diff --git a/src/asciidoc/aop-api.adoc b/src/asciidoc/aop-api.adoc new file mode 100644 index 000000000000..379520025243 --- /dev/null +++ b/src/asciidoc/aop-api.adoc @@ -0,0 +1,1751 @@ +[[aop-api]] +== Spring AOP APIs + + + + +[[aop-api-introduction]] +=== Introduction +The previous chapter described the Spring's support for AOP using +@AspectJ and schema-based aspect definitions. In this chapter we discuss the lower-level +Spring AOP APIs and the AOP support used in Spring 1.2 applications. For new +applications, we recommend the use of the Spring 2.0 and later AOP support described in +the previous chapter, but when working with existing applications, or when reading books +and articles, you may come across Spring 1.2 style examples. Spring 4.0 is backwards +compatible with Spring 1.2 and everything described in this chapter is fully supported +in Spring 4.0. + + + + +[[aop-api-pointcuts]] +=== Pointcut API in Spring +Let's look at how Spring handles the crucial pointcut concept. + + + +[[aop-api-concepts]] +==== Concepts +Spring's pointcut model enables pointcut reuse independent of advice types. It's +possible to target different advice using the same pointcut. + +The `org.springframework.aop.Pointcut` interface is the central interface, used to +target advices to particular classes and methods. The complete interface is shown below: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public interface Pointcut { + + ClassFilter getClassFilter(); + + MethodMatcher getMethodMatcher(); + + } +---- + +Splitting the `Pointcut` interface into two parts allows reuse of class and method +matching parts, and fine-grained composition operations (such as performing a "union" +with another method matcher). + +The `ClassFilter` interface is used to restrict the pointcut to a given set of target +classes. If the `matches()` method always returns true, all target classes will be +matched: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public interface ClassFilter { + + boolean matches(Class clazz); + } +---- + +The `MethodMatcher` interface is normally more important. The complete interface is +shown below: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public interface MethodMatcher { + + boolean matches(Method m, Class targetClass); + + boolean isRuntime(); + + boolean matches(Method m, Class targetClass, Object[] args); + } +---- + +The `matches(Method, Class)` method is used to test whether this pointcut will ever +match a given method on a target class. This evaluation can be performed when an AOP +proxy is created, to avoid the need for a test on every method invocation. If the +2-argument matches method returns true for a given method, and the `isRuntime()` method +for the MethodMatcher returns true, the 3-argument matches method will be invoked on +every method invocation. This enables a pointcut to look at the arguments passed to the +method invocation immediately before the target advice is to execute. + +Most MethodMatchers are static, meaning that their `isRuntime()` method returns false. +In this case, the 3-argument matches method will never be invoked. + +[TIP] +==== + +If possible, try to make pointcuts static, allowing the AOP framework to cache the +results of pointcut evaluation when an AOP proxy is created. +==== + + + +[[aop-api-pointcut-ops]] +==== Operations on pointcuts +Spring supports operations on pointcuts: notably, __union__ and __intersection__. + +* Union means the methods that either pointcut matches. +* Intersection means the methods that both pointcuts match. +* Union is usually more useful. +* Pointcuts can be composed using the static methods in the + __org.springframework.aop.support.Pointcuts__ class, or using the + __ComposablePointcut__ class in the same package. However, using AspectJ pointcut + expressions is usually a simpler approach. + + + +[[aop-api-pointcuts-aspectj]] +==== AspectJ expression pointcuts +Since 2.0, the most important type of pointcut used by Spring is +`org.springframework.aop.aspectj.AspectJExpressionPointcut`. This is a pointcut that +uses an AspectJ supplied library to parse an AspectJ pointcut expression string. + +See the previous chapter for a discussion of supported AspectJ pointcut primitives. + + + +[[aop-api-pointcuts-impls]] +==== Convenience pointcut implementations +Spring provides several convenient pointcut implementations. Some can be used out of the +box; others are intended to be subclassed in application-specific pointcuts. + + +[[aop-api-pointcuts-static]] +===== Static pointcuts +Static pointcuts are based on method and target class, and cannot take into account the +method's arguments. Static pointcuts are sufficient - __and best__ - for most usages. +It's possible for Spring to evaluate a static pointcut only once, when a method is first +invoked: after that, there is no need to evaluate the pointcut again with each method +invocation. + +Let's consider some static pointcut implementations included with Spring. + +[[aop-api-pointcuts-regex]] +====== Regular expression pointcuts +One obvious way to specify static pointcuts is regular expressions. Several AOP +frameworks besides Spring make this possible. +`org.springframework.aop.support.JdkRegexpMethodPointcut` is a generic regular +expression pointcut, using the regular expression support in JDK 1.4+. + +Using the `JdkRegexpMethodPointcut` class, you can provide a list of pattern Strings. If +any of these is a match, the pointcut will evaluate to true. (So the result is +effectively the union of these pointcuts.) + +The usage is shown below: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + .*set.* + .*absquatulate + + + +---- + +Spring provides a convenience class, `RegexpMethodPointcutAdvisor`, that allows us to +also reference an Advice (remember that an Advice can be an interceptor, before advice, +throws advice etc.). Behind the scenes, Spring will use a `JdkRegexpMethodPointcut`. +Using `RegexpMethodPointcutAdvisor` simplifies wiring, as the one bean encapsulates both +pointcut and advice, as shown below: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + .*set.* + .*absquatulate + + + +---- + +__RegexpMethodPointcutAdvisor__ can be used with any Advice type. + +[[aop-api-pointcuts-attribute-driven]] +====== Attribute-driven pointcuts +An important type of static pointcut is a __metadata-driven__ pointcut. This uses the +values of metadata attributes: typically, source-level metadata. + + +[[aop-api-pointcuts-dynamic]] +===== Dynamic pointcuts +Dynamic pointcuts are costlier to evaluate than static pointcuts. They take into account +method __arguments__, as well as static information. This means that they must be +evaluated with every method invocation; the result cannot be cached, as arguments will +vary. + +The main example is the `control flow` pointcut. + +[[aop-api-pointcuts-cflow]] +====== Control flow pointcuts +Spring control flow pointcuts are conceptually similar to AspectJ __cflow__ pointcuts, +although less powerful. (There is currently no way to specify that a pointcut executes +below a join point matched by another pointcut.) A control flow pointcut matches the +current call stack. For example, it might fire if the join point was invoked by a method +in the `com.mycompany.web` package, or by the `SomeCaller` class. Control flow pointcuts +are specified using the `org.springframework.aop.support.ControlFlowPointcut` class. +[NOTE] +==== +Control flow pointcuts are significantly more expensive to evaluate at runtime than even +other dynamic pointcuts. In Java 1.4, the cost is about 5 times that of other dynamic +pointcuts. +==== + + + +[[aop-api-pointcuts-superclasses]] +==== Pointcut superclasses +Spring provides useful pointcut superclasses to help you to implement your own pointcuts. + +Because static pointcuts are most useful, you'll probably subclass +StaticMethodMatcherPointcut, as shown below. This requires implementing just one +abstract method (although it's possible to override other methods to customize behavior): + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + class TestStaticPointcut extends StaticMethodMatcherPointcut { + + public boolean matches(Method m, Class targetClass) { + // return true if custom criteria match + } + } +---- + +There are also superclasses for dynamic pointcuts. + +You can use custom pointcuts with any advice type in Spring 1.0 RC2 and above. + + + +[[aop-api-pointcuts-custom]] +==== Custom pointcuts +Because pointcuts in Spring AOP are Java classes, rather than language features (as in +AspectJ) it's possible to declare custom pointcuts, whether static or dynamic. Custom +pointcuts in Spring can be arbitrarily complex. However, using the AspectJ pointcut +expression language is recommended if possible. + +[NOTE] +==== +Later versions of Spring may offer support for "semantic pointcuts" as offered by JAC: +for example, "all methods that change instance variables in the target object." +==== + + + + +[[aop-api-advice]] +=== Advice API in Spring +Let's now look at how Spring AOP handles advice. + + + +[[aop-api-advice-lifecycle]] +==== Advice lifecycles +Each advice is a Spring bean. An advice instance can be shared across all advised +objects, or unique to each advised object. This corresponds to __per-class__ or +__per-instance__ advice. + +Per-class advice is used most often. It is appropriate for generic advice such as +transaction advisors. These do not depend on the state of the proxied object or add new +state; they merely act on the method and arguments. + +Per-instance advice is appropriate for introductions, to support mixins. In this case, +the advice adds state to the proxied object. + +It's possible to use a mix of shared and per-instance advice in the same AOP proxy. + + + +[[aop-api-advice-types]] +==== Advice types in Spring +Spring provides several advice types out of the box, and is extensible to support +arbitrary advice types. Let us look at the basic concepts and standard advice types. + + +[[aop-api-advice-around]] +===== Interception around advice +The most fundamental advice type in Spring is __interception around advice__. + +Spring is compliant with the AOP Alliance interface for around advice using method +interception. MethodInterceptors implementing around advice should implement the +following interface: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public interface MethodInterceptor extends Interceptor { + + Object invoke(MethodInvocation invocation) throws Throwable; + } +---- + +The `MethodInvocation` argument to the `invoke()` method exposes the method being +invoked; the target join point; the AOP proxy; and the arguments to the method. The +`invoke()` method should return the invocation's result: the return value of the join +point. + +A simple `MethodInterceptor` implementation looks as follows: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class DebugInterceptor implements MethodInterceptor { + + public Object invoke(MethodInvocation invocation) throws Throwable { + System.out.println("Before: invocation=[" + invocation + "]"); + Object rval = invocation.proceed(); + System.out.println("Invocation returned"); + return rval; + } + } +---- + +Note the call to the MethodInvocation's `proceed()` method. This proceeds down the +interceptor chain towards the join point. Most interceptors will invoke this method, and +return its return value. However, a MethodInterceptor, like any around advice, can +return a different value or throw an exception rather than invoke the proceed method. +However, you don't want to do this without good reason! + +[NOTE] +==== +MethodInterceptors offer interoperability with other AOP Alliance-compliant AOP +implementations. The other advice types discussed in the remainder of this section +implement common AOP concepts, but in a Spring-specific way. While there is an advantage +in using the most specific advice type, stick with MethodInterceptor around advice if +you are likely to want to run the aspect in another AOP framework. Note that pointcuts +are not currently interoperable between frameworks, and the AOP Alliance does not +currently define pointcut interfaces. +==== + + +[[aop-api-advice-before]] +===== Before advice +A simpler advice type is a __before advice__. This does not need a `MethodInvocation` +object, since it will only be called before entering the method. + +The main advantage of a before advice is that there is no need to invoke the `proceed()` +method, and therefore no possibility of inadvertently failing to proceed down the +interceptor chain. + +The `MethodBeforeAdvice` interface is shown below. (Spring's API design would allow for +field before advice, although the usual objects apply to field interception and it's +unlikely that Spring will ever implement it). + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public interface MethodBeforeAdvice extends BeforeAdvice { + + void before(Method m, Object[] args, Object target) throws Throwable; + } +---- + +Note the return type is `void`. Before advice can insert custom behavior before the join +point executes, but cannot change the return value. If a before advice throws an +exception, this will abort further execution of the interceptor chain. The exception +will propagate back up the interceptor chain. If it is unchecked, or on the signature of +the invoked method, it will be passed directly to the client; otherwise it will be +wrapped in an unchecked exception by the AOP proxy. + +An example of a before advice in Spring, which counts all method invocations: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class CountingBeforeAdvice implements MethodBeforeAdvice { + + private int count; + + public void before(Method m, Object[] args, Object target) throws Throwable { + ++count; + } + + public int getCount() { + return count; + } + } +---- + +[TIP] +==== + +Before advice can be used with any pointcut. +==== + + +[[aop-api-advice-throws]] +===== Throws advice +__Throws advice__ is invoked after the return of the join point if the join point threw +an exception. Spring offers typed throws advice. Note that this means that the +`org.springframework.aop.ThrowsAdvice` interface does not contain any methods: It is a +tag interface identifying that the given object implements one or more typed throws +advice methods. These should be in the form of: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + afterThrowing([Method, args, target], subclassOfThrowable) +---- + +Only the last argument is required. The method signatures may have either one or four +arguments, depending on whether the advice method is interested in the method and +arguments. The following classes are examples of throws advice. + +The advice below is invoked if a `RemoteException` is thrown (including subclasses): + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class RemoteThrowsAdvice implements ThrowsAdvice { + + public void afterThrowing(RemoteException ex) throws Throwable { + // Do something with remote exception + } + } +---- + +The following advice is invoked if a `ServletException` is thrown. Unlike the above +advice, it declares 4 arguments, so that it has access to the invoked method, method +arguments and target object: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class ServletThrowsAdviceWithArguments implements ThrowsAdvice { + + public void afterThrowing(Method m, Object[] args, Object target, ServletException ex) { + // Do something with all arguments + } + } +---- + +The final example illustrates how these two methods could be used in a single class, +which handles both `RemoteException` and `ServletException`. Any number of throws advice +methods can be combined in a single class. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public static class CombinedThrowsAdvice implements ThrowsAdvice { + + public void afterThrowing(RemoteException ex) throws Throwable { + // Do something with remote exception + } + + public void afterThrowing(Method m, Object[] args, Object target, ServletException ex) { + // Do something with all arguments + } + } +---- + +[NOTE] +==== +If a throws-advice method throws an exception itself, it will override the +original exception (i.e. change the exception thrown to the user). The overriding +exception will typically be a RuntimeException; this is compatible with any method +signature. However, if a throws-advice method throws a checked exception, it will have +to match the declared exceptions of the target method and is hence to some degree +coupled to specific target method signatures. __Do not throw an undeclared checked +exception that is incompatible with the target method's signature!__ +==== + +[TIP] +==== + +Throws advice can be used with any pointcut. +==== + + +[[aop-api-advice-after-returning]] +===== After Returning advice +An after returning advice in Spring must implement the +__org.springframework.aop.AfterReturningAdvice__ interface, shown below: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public interface AfterReturningAdvice extends Advice { + + void afterReturning(Object returnValue, Method m, Object[] args, Object target) + throws Throwable; + } +---- + +An after returning advice has access to the return value (which it cannot modify), +invoked method, methods arguments and target. + +The following after returning advice counts all successful method invocations that have +not thrown exceptions: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class CountingAfterReturningAdvice implements AfterReturningAdvice { + + private int count; + + public void afterReturning(Object returnValue, Method m, Object[] args, Object target) + throws Throwable { + ++count; + } + + public int getCount() { + return count; + } + } +---- + +This advice doesn't change the execution path. If it throws an exception, this will be +thrown up the interceptor chain instead of the return value. + +[TIP] +==== + +After returning advice can be used with any pointcut. +==== + + +[[aop-api-advice-introduction]] +===== Introduction advice +Spring treats introduction advice as a special kind of interception advice. + +Introduction requires an `IntroductionAdvisor`, and an `IntroductionInterceptor`, +implementing the following interface: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public interface IntroductionInterceptor extends MethodInterceptor { + + boolean implementsInterface(Class intf); + } +---- + +The `invoke()` method inherited from the AOP Alliance `MethodInterceptor` interface must +implement the introduction: that is, if the invoked method is on an introduced +interface, the introduction interceptor is responsible for handling the method call - it +cannot invoke `proceed()`. + +Introduction advice cannot be used with any pointcut, as it applies only at class, +rather than method, level. You can only use introduction advice with the +`IntroductionAdvisor`, which has the following methods: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public interface IntroductionAdvisor extends Advisor, IntroductionInfo { + + ClassFilter getClassFilter(); + + void validateInterfaces() throws IllegalArgumentException; + } + + public interface IntroductionInfo { + + Class[] getInterfaces(); + } +---- + +There is no `MethodMatcher`, and hence no `Pointcut`, associated with introduction +advice. Only class filtering is logical. + +The `getInterfaces()` method returns the interfaces introduced by this advisor. + +The `validateInterfaces()` method is used internally to see whether or not the +introduced interfaces can be implemented by the configured `IntroductionInterceptor`. + +Let's look at a simple example from the Spring test suite. Let's suppose we want to +introduce the following interface to one or more objects: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public interface Lockable { + void lock(); + void unlock(); + boolean locked(); + } +---- + +This illustrates a __mixin__. We want to be able to cast advised objects to Lockable, +whatever their type, and call lock and unlock methods. If we call the lock() method, we +want all setter methods to throw a `LockedException`. Thus we can add an aspect that +provides the ability to make objects immutable, without them having any knowledge of it: +a good example of AOP. + +Firstly, we'll need an `IntroductionInterceptor` that does the heavy lifting. In this +case, we extend the `org.springframework.aop.support.DelegatingIntroductionInterceptor` +convenience class. We could implement IntroductionInterceptor directly, but using +`DelegatingIntroductionInterceptor` is best for most cases. + +The `DelegatingIntroductionInterceptor` is designed to delegate an introduction to an +actual implementation of the introduced interface(s), concealing the use of interception +to do so. The delegate can be set to any object using a constructor argument; the +default delegate (when the no-arg constructor is used) is this. Thus in the example +below, the delegate is the `LockMixin` subclass of `DelegatingIntroductionInterceptor`. +Given a delegate (by default itself), a `DelegatingIntroductionInterceptor` instance +looks for all interfaces implemented by the delegate (other than +IntroductionInterceptor), and will support introductions against any of them. It's +possible for subclasses such as `LockMixin` to call the `suppressInterface(Class intf)` +method to suppress interfaces that should not be exposed. However, no matter how many +interfaces an `IntroductionInterceptor` is prepared to support, the +`IntroductionAdvisor` used will control which interfaces are actually exposed. An +introduced interface will conceal any implementation of the same interface by the target. + +Thus `LockMixin` extends `DelegatingIntroductionInterceptor` and implements `Lockable` +itself. The superclass automatically picks up that Lockable can be supported for +introduction, so we don't need to specify that. We could introduce any number of +interfaces in this way. + +Note the use of the `locked` instance variable. This effectively adds additional state +to that held in the target object. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class LockMixin extends DelegatingIntroductionInterceptor implements Lockable { + + private boolean locked; + + public void lock() { + this.locked = true; + } + + public void unlock() { + this.locked = false; + } + + public boolean locked() { + return this.locked; + } + + public Object invoke(MethodInvocation invocation) throws Throwable { + if (locked() && invocation.getMethod().getName().indexOf("set") == 0) { + throw new LockedException(); + } + return super.invoke(invocation); + } + + } +---- + +Often it isn't necessary to override the `invoke()` method: the +`DelegatingIntroductionInterceptor` implementation - which calls the delegate method if +the method is introduced, otherwise proceeds towards the join point - is usually +sufficient. In the present case, we need to add a check: no setter method can be invoked +if in locked mode. + +The introduction advisor required is simple. All it needs to do is hold a distinct +`LockMixin` instance, and specify the introduced interfaces - in this case, just +`Lockable`. A more complex example might take a reference to the introduction +interceptor (which would be defined as a prototype): in this case, there's no +configuration relevant for a `LockMixin`, so we simply create it using `new`. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class LockMixinAdvisor extends DefaultIntroductionAdvisor { + + public LockMixinAdvisor() { + super(new LockMixin(), Lockable.class); + } + } +---- + +We can apply this advisor very simply: it requires no configuration. (However, it __is__ +necessary: It's impossible to use an `IntroductionInterceptor` without an +__IntroductionAdvisor__.) As usual with introductions, the advisor must be per-instance, +as it is stateful. We need a different instance of `LockMixinAdvisor`, and hence +`LockMixin`, for each advised object. The advisor comprises part of the advised object's +state. + +We can apply this advisor programmatically, using the `Advised.addAdvisor()` method, or +(the recommended way) in XML configuration, like any other advisor. All proxy creation +choices discussed below, including "auto proxy creators," correctly handle introductions +and stateful mixins. + + + + +[[aop-api-advisor]] +=== Advisor API in Spring +In Spring, an Advisor is an aspect that contains just a single advice object associated +with a pointcut expression. + +Apart from the special case of introductions, any advisor can be used with any advice. +`org.springframework.aop.support.DefaultPointcutAdvisor` is the most commonly used +advisor class. For example, it can be used with a `MethodInterceptor`, `BeforeAdvice` or +`ThrowsAdvice`. + +It is possible to mix advisor and advice types in Spring in the same AOP proxy. For +example, you could use a interception around advice, throws advice and before advice in +one proxy configuration: Spring will automatically create the necessary interceptor +chain. + + + + +[[aop-pfb]] +=== Using the ProxyFactoryBean to create AOP proxies +If you're using the Spring IoC container (an ApplicationContext or BeanFactory) for your +business objects - and you should be! - you will want to use one of Spring's AOP +FactoryBeans. (Remember that a factory bean introduces a layer of indirection, enabling +it to create objects of a different type.) + +[NOTE] +==== +The Spring AOP support also uses factory beans under the covers. +==== + +The basic way to create an AOP proxy in Spring is to use the +__org.springframework.aop.framework.ProxyFactoryBean__. This gives complete control over +the pointcuts and advice that will apply, and their ordering. However, there are simpler +options that are preferable if you don't need such control. + + + +[[aop-pfb-1]] +==== Basics +The `ProxyFactoryBean`, like other Spring `FactoryBean` implementations, introduces a +level of indirection. If you define a `ProxyFactoryBean` with name `foo`, what objects +referencing `foo` see is not the `ProxyFactoryBean` instance itself, but an object +created by the `ProxyFactoryBean`'s implementation of the `getObject()` method. This +method will create an AOP proxy wrapping a target object. + +One of the most important benefits of using a `ProxyFactoryBean` or another IoC-aware +class to create AOP proxies, is that it means that advices and pointcuts can also be +managed by IoC. This is a powerful feature, enabling certain approaches that are hard to +achieve with other AOP frameworks. For example, an advice may itself reference +application objects (besides the target, which should be available in any AOP +framework), benefiting from all the pluggability provided by Dependency Injection. + + + +[[aop-pfb-2]] +==== JavaBean properties +In common with most `FactoryBean` implementations provided with Spring, the +`ProxyFactoryBean` class is itself a JavaBean. Its properties are used to: + +* Specify the target you want to proxy. +* Specify whether to use CGLIB (see below and also <>). + +Some key properties are inherited from `org.springframework.aop.framework.ProxyConfig` +(the superclass for all AOP proxy factories in Spring). These key properties include: + +* `proxyTargetClass`: `true` if the target class is to be proxied, rather than the + target class' interfaces. If this property value is set to `true`, then CGLIB proxies + will be created (but see also <>). +* `optimize`: controls whether or not aggressive optimizations are applied to proxies + __created via CGLIB__. One should not blithely use this setting unless one fully + understands how the relevant AOP proxy handles optimization. This is currently used + only for CGLIB proxies; it has no effect with JDK dynamic proxies. +* `frozen`: if a proxy configuration is `frozen`, then changes to the configuration are + no longer allowed. This is useful both as a slight optimization and for those cases + when you don't want callers to be able to manipulate the proxy (via the `Advised` + interface) after the proxy has been created. The default value of this property is + `false`, so changes such as adding additional advice are allowed. +* `exposeProxy`: determines whether or not the current proxy should be exposed in a + `ThreadLocal` so that it can be accessed by the target. If a target needs to obtain + the proxy and the `exposeProxy` property is set to `true`, the target can use the + `AopContext.currentProxy()` method. + +Other properties specific to `ProxyFactoryBean` include: + +* `proxyInterfaces`: array of String interface names. If this isn't supplied, a CGLIB + proxy for the target class will be used (but see also <>). +* `interceptorNames`: String array of `Advisor`, interceptor or other advice names to + apply. Ordering is significant, on a first come-first served basis. That is to say + that the first interceptor in the list will be the first to be able to intercept the + invocation. + +The names are bean names in the current factory, including bean names from ancestor +factories. You can't mention bean references here since doing so would result in the +`ProxyFactoryBean` ignoring the singleton setting of the advice. + +You can append an interceptor name with an asterisk ( `*`). This will result in the +application of all advisor beans with names starting with the part before the asterisk +to be applied. An example of using this feature can be found in <>. + +* singleton: whether or not the factory should return a single object, no matter how + often the `getObject()` method is called. Several `FactoryBean` implementations offer + such a method. The default value is `true`. If you want to use stateful advice - for + example, for stateful mixins - use prototype advices along with a singleton value of + `false`. + + + +[[aop-pfb-proxy-types]] +==== JDK- and CGLIB-based proxies +This section serves as the definitive documentation on how the `ProxyFactoryBean` +chooses to create one of either a JDK- and CGLIB-based proxy for a particular target +object (that is to be proxied). + +[NOTE] +==== +The behavior of the `ProxyFactoryBean` with regard to creating JDK- or CGLIB-based +proxies changed between versions 1.2.x and 2.0 of Spring. The `ProxyFactoryBean` now +exhibits similar semantics with regard to auto-detecting interfaces as those of the +`TransactionProxyFactoryBean` class. +==== + +If the class of a target object that is to be proxied (hereafter simply referred to as +the target class) doesn't implement any interfaces, then a CGLIB-based proxy will be +created. This is the easiest scenario, because JDK proxies are interface based, and no +interfaces means JDK proxying isn't even possible. One simply plugs in the target bean, +and specifies the list of interceptors via the `interceptorNames` property. Note that a +CGLIB-based proxy will be created even if the `proxyTargetClass` property of the +`ProxyFactoryBean` has been set to `false`. (Obviously this makes no sense, and is best +removed from the bean definition because it is at best redundant, and at worst +confusing.) + +If the target class implements one (or more) interfaces, then the type of proxy that is +created depends on the configuration of the `ProxyFactoryBean`. + +If the `proxyTargetClass` property of the `ProxyFactoryBean` has been set to `true`, +then a CGLIB-based proxy will be created. This makes sense, and is in keeping with the +principle of least surprise. Even if the `proxyInterfaces` property of the +`ProxyFactoryBean` has been set to one or more fully qualified interface names, the fact +that the `proxyTargetClass` property is set to `true` __will__ cause CGLIB-based +proxying to be in effect. + +If the `proxyInterfaces` property of the `ProxyFactoryBean` has been set to one or more +fully qualified interface names, then a JDK-based proxy will be created. The created +proxy will implement all of the interfaces that were specified in the `proxyInterfaces` +property; if the target class happens to implement a whole lot more interfaces than +those specified in the `proxyInterfaces` property, that is all well and good but those +additional interfaces will not be implemented by the returned proxy. + +If the `proxyInterfaces` property of the `ProxyFactoryBean` has __not__ been set, but +the target class __does implement one (or more)__ interfaces, then the +`ProxyFactoryBean` will auto-detect the fact that the target class does actually +implement at least one interface, and a JDK-based proxy will be created. The interfaces +that are actually proxied will be __all__ of the interfaces that the target class +implements; in effect, this is the same as simply supplying a list of each and every +interface that the target class implements to the `proxyInterfaces` property. However, +it is significantly less work, and less prone to typos. + + + +[[aop-api-proxying-intf]] +==== Proxying interfaces +Let's look at a simple example of `ProxyFactoryBean` in action. This example involves: + +* A __target bean__ that will be proxied. This is the "personTarget" bean definition in + the example below. +* An Advisor and an Interceptor used to provide advice. +* An AOP proxy bean definition specifying the target object (the personTarget bean) and + the interfaces to proxy, along with the advices to apply. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + + + + + + + + + + + + myAdvisor + debugInterceptor + + + +---- + +Note that the `interceptorNames` property takes a list of String: the bean names of the +interceptor or advisors in the current factory. Advisors, interceptors, before, after +returning and throws advice objects can be used. The ordering of advisors is significant. + +[NOTE] +==== +You might be wondering why the list doesn't hold bean references. The reason for this is +that if the ProxyFactoryBean's singleton property is set to false, it must be able to +return independent proxy instances. If any of the advisors is itself a prototype, an +independent instance would need to be returned, so it's necessary to be able to obtain +an instance of the prototype from the factory; holding a reference isn't sufficient. +==== + +The "person" bean definition above can be used in place of a Person implementation, as +follows: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + Person person = (Person) factory.getBean("person"); +---- + +Other beans in the same IoC context can express a strongly typed dependency on it, as +with an ordinary Java object: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + +---- + +The `PersonUser` class in this example would expose a property of type Person. As far as +it's concerned, the AOP proxy can be used transparently in place of a "real" person +implementation. However, its class would be a dynamic proxy class. It would be possible +to cast it to the `Advised` interface (discussed below). + +It's possible to conceal the distinction between target and proxy using an anonymous +__inner bean__, as follows. Only the `ProxyFactoryBean` definition is different; the +advice is included only for completeness: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + + + + + + + + + + + myAdvisor + debugInterceptor + + + +---- + +This has the advantage that there's only one object of type `Person`: useful if we want +to prevent users of the application context from obtaining a reference to the un-advised +object, or need to avoid any ambiguity with Spring IoC __autowiring__. There's also +arguably an advantage in that the ProxyFactoryBean definition is self-contained. +However, there are times when being able to obtain the un-advised target from the +factory might actually be an __advantage__: for example, in certain test scenarios. + + + +[[aop-api-proxying-class]] +==== Proxying classes +What if you need to proxy a class, rather than one or more interfaces? + +Imagine that in our example above, there was no `Person` interface: we needed to advise +a class called `Person` that didn't implement any business interface. In this case, you +can configure Spring to use CGLIB proxying, rather than dynamic proxies. Simply set the +`proxyTargetClass` property on the ProxyFactoryBean above to true. While it's best to +program to interfaces, rather than classes, the ability to advise classes that don't +implement interfaces can be useful when working with legacy code. (In general, Spring +isn't prescriptive. While it makes it easy to apply good practices, it avoids forcing a +particular approach.) + +If you want to, you can force the use of CGLIB in any case, even if you do have +interfaces. + +CGLIB proxying works by generating a subclass of the target class at runtime. Spring +configures this generated subclass to delegate method calls to the original target: the +subclass is used to implement the __Decorator__ pattern, weaving in the advice. + +CGLIB proxying should generally be transparent to users. However, there are some issues +to consider: + +* `Final` methods can't be advised, as they can't be overridden. +* There is no need to add CGLIB to your classpath. As of Spring 3.2, CGLIB is repackaged + and included in the spring-core JAR. In other words, CGLIB-based AOP will work "out of + the box" just as do JDK dynamic proxies. + +There's little performance difference between CGLIB proxying and dynamic proxies. As of +Spring 1.0, dynamic proxies are slightly faster. However, this may change in the future. +Performance should not be a decisive consideration in this case. + + + +[[aop-global-advisors]] +==== Using 'global' advisors +By appending an asterisk to an interceptor name, all advisors with bean names matching +the part before the asterisk, will be added to the advisor chain. This can come in handy +if you need to add a standard set of 'global' advisors: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + global* + + + + + + +---- + + + + +[[aop-concise-proxy]] +=== Concise proxy definitions +Especially when defining transactional proxies, you may end up with many similar proxy +definitions. The use of parent and child bean definitions, along with inner bean +definitions, can result in much cleaner and more concise proxy definitions. + +First a parent, __template__, bean definition is created for the proxy: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + PROPAGATION_REQUIRED + + + +---- + +This will never be instantiated itself, so may actually be incomplete. Then each proxy +which needs to be created is just a child bean definition, which wraps the target of the +proxy as an inner bean definition, since the target will never be used on its own anyway. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + +---- + +It is of course possible to override properties from the parent template, such as in +this case, the transaction propagation settings: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + PROPAGATION_REQUIRED,readOnly + PROPAGATION_REQUIRED,readOnly + PROPAGATION_REQUIRED,readOnly + PROPAGATION_REQUIRED + + + +---- + +Note that in the example above, we have explicitly marked the parent bean definition as +__abstract__ by using the __abstract__ attribute, as described +<>, so that it may not actually ever be +instantiated. Application contexts (but not simple bean factories) will by default +pre-instantiate all singletons. It is therefore important (at least for singleton beans) +that if you have a (parent) bean definition which you intend to use only as a template, +and this definition specifies a class, you must make sure to set the __abstract__ +attribute to __true__, otherwise the application context will actually try to +pre-instantiate it. + + + + +[[aop-prog]] +=== Creating AOP proxies programmatically with the ProxyFactory +It's easy to create AOP proxies programmatically using Spring. This enables you to use +Spring AOP without dependency on Spring IoC. + +The following listing shows creation of a proxy for a target object, with one +interceptor and one advisor. The interfaces implemented by the target object will +automatically be proxied: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + ProxyFactory factory = new ProxyFactory(myBusinessInterfaceImpl); + factory.addAdvice(myMethodInterceptor); + factory.addAdvisor(myAdvisor); + MyBusinessInterface tb = (MyBusinessInterface) factory.getProxy(); +---- + +The first step is to construct an object of type +`org.springframework.aop.framework.ProxyFactory`. You can create this with a target +object, as in the above example, or specify the interfaces to be proxied in an alternate +constructor. + +You can add advices (with interceptors as a specialized kind of advice) and/or advisors, +and manipulate them for the life of the ProxyFactory. If you add an +IntroductionInterceptionAroundAdvisor, you can cause the proxy to implement additional +interfaces. + +There are also convenience methods on ProxyFactory (inherited from `AdvisedSupport`) +which allow you to add other advice types such as before and throws advice. +AdvisedSupport is the superclass of both ProxyFactory and ProxyFactoryBean. + +[TIP] +==== + +Integrating AOP proxy creation with the IoC framework is best practice in most +applications. We recommend that you externalize configuration from Java code with AOP, +as in general. +==== + + + + +[[aop-api-advised]] +=== Manipulating advised objects +However you create AOP proxies, you can manipulate them using the +`org.springframework.aop.framework.Advised` interface. Any AOP proxy can be cast to this +interface, whichever other interfaces it implements. This interface includes the +following methods: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + Advisor[] getAdvisors(); + + void addAdvice(Advice advice) throws AopConfigException; + + void addAdvice(int pos, Advice advice) throws AopConfigException; + + void addAdvisor(Advisor advisor) throws AopConfigException; + + void addAdvisor(int pos, Advisor advisor) throws AopConfigException; + + int indexOf(Advisor advisor); + + boolean removeAdvisor(Advisor advisor) throws AopConfigException; + + void removeAdvisor(int index) throws AopConfigException; + + boolean replaceAdvisor(Advisor a, Advisor b) throws AopConfigException; + + boolean isFrozen(); +---- + +The `getAdvisors()` method will return an Advisor for every advisor, interceptor or +other advice type that has been added to the factory. If you added an Advisor, the +returned advisor at this index will be the object that you added. If you added an +interceptor or other advice type, Spring will have wrapped this in an advisor with a +pointcut that always returns true. Thus if you added a `MethodInterceptor`, the advisor +returned for this index will be an `DefaultPointcutAdvisor` returning your +`MethodInterceptor` and a pointcut that matches all classes and methods. + +The `addAdvisor()` methods can be used to add any Advisor. Usually the advisor holding +pointcut and advice will be the generic `DefaultPointcutAdvisor`, which can be used with +any advice or pointcut (but not for introductions). + +By default, it's possible to add or remove advisors or interceptors even once a proxy +has been created. The only restriction is that it's impossible to add or remove an +introduction advisor, as existing proxies from the factory will not show the interface +change. (You can obtain a new proxy from the factory to avoid this problem.) + +A simple example of casting an AOP proxy to the `Advised` interface and examining and +manipulating its advice: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + Advised advised = (Advised) myObject; + Advisor[] advisors = advised.getAdvisors(); + int oldAdvisorCount = advisors.length; + System.out.println(oldAdvisorCount + " advisors"); + + // Add an advice like an interceptor without a pointcut + // Will match all proxied methods + // Can use for interceptors, before, after returning or throws advice + advised.addAdvice(new DebugInterceptor()); + + // Add selective advice using a pointcut + advised.addAdvisor(new DefaultPointcutAdvisor(mySpecialPointcut, myAdvice)); + + assertEquals("Added two advisors", oldAdvisorCount + 2, advised.getAdvisors().length); +---- + +[NOTE] +==== +It's questionable whether it's advisable (no pun intended) to modify advice on a +business object in production, although there are no doubt legitimate usage cases. +However, it can be very useful in development: for example, in tests. I have sometimes +found it very useful to be able to add test code in the form of an interceptor or other +advice, getting inside a method invocation I want to test. (For example, the advice can +get inside a transaction created for that method: for example, to run SQL to check that +a database was correctly updated, before marking the transaction for roll back.) +==== + +Depending on how you created the proxy, you can usually set a `frozen` flag, in which +case the `Advised` `isFrozen()` method will return true, and any attempts to modify +advice through addition or removal will result in an `AopConfigException`. The ability +to freeze the state of an advised object is useful in some cases, for example, to +prevent calling code removing a security interceptor. It may also be used in Spring 1.1 +to allow aggressive optimization if runtime advice modification is known not to be +required. + + + + +[[aop-autoproxy]] +=== Using the "auto-proxy" facility +So far we've considered explicit creation of AOP proxies using a `ProxyFactoryBean` or +similar factory bean. + +Spring also allows us to use "auto-proxy" bean definitions, which can automatically +proxy selected bean definitions. This is built on Spring "bean post processor" +infrastructure, which enables modification of any bean definition as the container loads. + +In this model, you set up some special bean definitions in your XML bean definition file +to configure the auto proxy infrastructure. This allows you just to declare the targets +eligible for auto-proxying: you don't need to use `ProxyFactoryBean`. + +There are two ways to do this: + +* Using an auto-proxy creator that refers to specific beans in the current context. +* A special case of auto-proxy creation that deserves to be considered separately; + auto-proxy creation driven by source-level metadata attributes. + + + +[[aop-autoproxy-choices]] +==== Autoproxy bean definitions +The `org.springframework.aop.framework.autoproxy` package provides the following +standard auto-proxy creators. + + +[[aop-api-autoproxy]] +===== BeanNameAutoProxyCreator +The `BeanNameAutoProxyCreator` class is a `BeanPostProcessor` that automatically creates +AOP proxies for beans with names matching literal values or wildcards. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + myInterceptor + + + +---- + +As with `ProxyFactoryBean`, there is an `interceptorNames` property rather than a list +of interceptors, to allow correct behavior for prototype advisors. Named "interceptors" +can be advisors or any advice type. + +As with auto proxying in general, the main point of using `BeanNameAutoProxyCreator` is +to apply the same configuration consistently to multiple objects, with minimal volume of +configuration. It is a popular choice for applying declarative transactions to multiple +objects. + +Bean definitions whose names match, such as "jdkMyBean" and "onlyJdk" in the above +example, are plain old bean definitions with the target class. An AOP proxy will be +created automatically by the `BeanNameAutoProxyCreator`. The same advice will be applied +to all matching beans. Note that if advisors are used (rather than the interceptor in +the above example), the pointcuts may apply differently to different beans. + + +[[aop-api-autoproxy-default]] +===== DefaultAdvisorAutoProxyCreator +A more general and extremely powerful auto proxy creator is +`DefaultAdvisorAutoProxyCreator`. This will automagically apply eligible advisors in the +current context, without the need to include specific bean names in the auto-proxy +advisor's bean definition. It offers the same merit of consistent configuration and +avoidance of duplication as `BeanNameAutoProxyCreator`. + +Using this mechanism involves: + +* Specifying a `DefaultAdvisorAutoProxyCreator` bean definition. +* Specifying any number of Advisors in the same or related contexts. Note that these + __must__ be Advisors, not just interceptors or other advices. This is necessary + because there must be a pointcut to evaluate, to check the eligibility of each advice + to candidate bean definitions. + +The `DefaultAdvisorAutoProxyCreator` will automatically evaluate the pointcut contained +in each advisor, to see what (if any) advice it should apply to each business object +(such as "businessObject1" and "businessObject2" in the example). + +This means that any number of advisors can be applied automatically to each business +object. If no pointcut in any of the advisors matches any method in a business object, +the object will not be proxied. As bean definitions are added for new business objects, +they will automatically be proxied if necessary. + +Autoproxying in general has the advantage of making it impossible for callers or +dependencies to obtain an un-advised object. Calling getBean("businessObject1") on this +ApplicationContext will return an AOP proxy, not the target business object. (The "inner +bean" idiom shown earlier also offers this benefit.) + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + + + + + + +---- + +The `DefaultAdvisorAutoProxyCreator` is very useful if you want to apply the same advice +consistently to many business objects. Once the infrastructure definitions are in place, +you can simply add new business objects without including specific proxy configuration. +You can also drop in additional aspects very easily - for example, tracing or +performance monitoring aspects - with minimal change to configuration. + +The DefaultAdvisorAutoProxyCreator offers support for filtering (using a naming +convention so that only certain advisors are evaluated, allowing use of multiple, +differently configured, AdvisorAutoProxyCreators in the same factory) and ordering. +Advisors can implement the `org.springframework.core.Ordered` interface to ensure +correct ordering if this is an issue. The TransactionAttributeSourceAdvisor used in the +above example has a configurable order value; the default setting is unordered. + + +[[aop-api-autoproxy-abstract]] +===== AbstractAdvisorAutoProxyCreator +This is the superclass of DefaultAdvisorAutoProxyCreator. You can create your own +auto-proxy creators by subclassing this class, in the unlikely event that advisor +definitions offer insufficient customization to the behavior of the framework +`DefaultAdvisorAutoProxyCreator`. + + + +[[aop-autoproxy-metadata]] +==== Using metadata-driven auto-proxying +A particularly important type of auto-proxying is driven by metadata. This produces a +similar programming model to .NET `ServicedComponents`. Instead of defining metadata in +XML descriptors, configuration for transaction management and other enterprise services +is held in source-level attributes. + +In this case, you use the `DefaultAdvisorAutoProxyCreator`, in combination with Advisors +that understand metadata attributes. The metadata specifics are held in the pointcut +part of the candidate advisors, rather than in the auto-proxy creation class itself. + +This is really a special case of the `DefaultAdvisorAutoProxyCreator`, but deserves +consideration on its own. (The metadata-aware code is in the pointcuts contained in the +advisors, not the AOP framework itself.) + +The `/attributes` directory of the JPetStore sample application shows the use of +attribute-driven auto-proxying. In this case, there's no need to use the +`TransactionProxyFactoryBean`. Simply defining transactional attributes on business +objects is sufficient, because of the use of metadata-aware pointcuts. The bean +definitions include the following code, in `/WEB-INF/declarativeServices.xml`. Note that +this is generic, and can be used outside the JPetStore: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + + + + + + + + + +---- + +The `DefaultAdvisorAutoProxyCreator` bean definition (the name is not significant, hence +it can even be omitted) will pick up all eligible pointcuts in the current application +context. In this case, the "transactionAdvisor" bean definition, of type +`TransactionAttributeSourceAdvisor`, will apply to classes or methods carrying a +transaction attribute. The TransactionAttributeSourceAdvisor depends on a +TransactionInterceptor, via constructor dependency. The example resolves this via +autowiring. The `AttributesTransactionAttributeSource` depends on an implementation of +the `org.springframework.metadata.Attributes` interface. In this fragment, the +"attributes" bean satisfies this, using the Jakarta Commons Attributes API to obtain +attribute information. (The application code must have been compiled using the Commons +Attributes compilation task.) + +The `/annotation` directory of the JPetStore sample application contains an analogous +example for auto-proxying driven by JDK 1.5+ annotations. The following configuration +enables automatic detection of Spring's `Transactional` annotation, leading to implicit +proxies for beans containing that annotation: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + + + + + +---- + +The `TransactionInterceptor` defined here depends on a `PlatformTransactionManager` +definition, which is not included in this generic file (although it could be) because it +will be specific to the application's transaction requirements (typically JTA, as in +this example, or Hibernate, JDO or JDBC): + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + +---- + +[TIP] +==== + +If you require only declarative transaction management, using these generic XML +definitions will result in Spring automatically proxying all classes or methods with +transaction attributes. You won't need to work directly with AOP, and the programming +model is similar to that of .NET ServicedComponents. +==== + +This mechanism is extensible. It's possible to do auto-proxying based on custom +attributes. You need to: + +* Define your custom attribute. +* Specify an Advisor with the necessary advice, including a pointcut that is triggered + by the presence of the custom attribute on a class or method. You may be able to use + an existing advice, merely implementing a static pointcut that picks up the custom + attribute. + +It's possible for such advisors to be unique to each advised class (for example, mixins): +they simply need to be defined as prototype, rather than singleton, bean definitions. +For example, the `LockMixin` introduction interceptor from the Spring test suite, +shown above, could be used in conjunction with a generic `DefaultIntroductionAdvisor`: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + +---- + +Note that both `lockMixin` and `lockableAdvisor` are defined as prototypes. + + + + +[[aop-targetsource]] +=== Using TargetSources +Spring offers the concept of a __TargetSource__, expressed in the +`org.springframework.aop.TargetSource` interface. This interface is responsible for +returning the "target object" implementing the join point. The `TargetSource` +implementation is asked for a target instance each time the AOP proxy handles a method +invocation. + +Developers using Spring AOP don't normally need to work directly with TargetSources, but +this provides a powerful means of supporting pooling, hot swappable and other +sophisticated targets. For example, a pooling TargetSource can return a different target +instance for each invocation, using a pool to manage instances. + +If you do not specify a TargetSource, a default implementation is used that wraps a +local object. The same target is returned for each invocation (as you would expect). + +Let's look at the standard target sources provided with Spring, and how you can use them. + +[TIP] +==== + +When using a custom target source, your target will usually need to be a prototype +rather than a singleton bean definition. This allows Spring to create a new target +instance when required. +==== + + + +[[aop-ts-swap]] +==== Hot swappable target sources +The `org.springframework.aop.target.HotSwappableTargetSource` exists to allow the target +of an AOP proxy to be switched while allowing callers to keep their references to it. + +Changing the target source's target takes effect immediately. The +`HotSwappableTargetSource` is threadsafe. + +You can change the target via the `swap()` method on HotSwappableTargetSource as follows: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + HotSwappableTargetSource swapper = (HotSwappableTargetSource) beanFactory.getBean("swapper"); + Object oldTarget = swapper.swap(newTarget); +---- + +The XML definitions required look as follows: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + + +---- + +The above `swap()` call changes the target of the swappable bean. Clients who hold a +reference to that bean will be unaware of the change, but will immediately start hitting +the new target. + +Although this example doesn't add any advice - and it's not necessary to add advice to +use a `TargetSource` - of course any `TargetSource` can be used in conjunction with +arbitrary advice. + + + +[[aop-ts-pool]] +==== Pooling target sources +Using a pooling target source provides a similar programming model to stateless session +EJBs, in which a pool of identical instances is maintained, with method invocations +going to free objects in the pool. + +A crucial difference between Spring pooling and SLSB pooling is that Spring pooling can +be applied to any POJO. As with Spring in general, this service can be applied in a +non-invasive way. + +Spring provides out-of-the-box support for Jakarta Commons Pool 1.3, which provides a +fairly efficient pooling implementation. You'll need the commons-pool Jar on your +application's classpath to use this feature. It's also possible to subclass +`org.springframework.aop.target.AbstractPoolingTargetSource` to support any other +pooling API. + +Sample configuration is shown below: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + ... properties omitted + + + + + + + + + + + +---- + +Note that the target object - "businessObjectTarget" in the example - __must__ be a +prototype. This allows the `PoolingTargetSource` implementation to create new instances +of the target to grow the pool as necessary. See the javadocs of +`AbstractPoolingTargetSource` and the concrete subclass you wish to use for information +about its properties: "maxSize" is the most basic, and always guaranteed to be present. + +In this case, "myInterceptor" is the name of an interceptor that would need to be +defined in the same IoC context. However, it isn't necessary to specify interceptors to +use pooling. If you want only pooling, and no other advice, don't set the +interceptorNames property at all. + +It's possible to configure Spring so as to be able to cast any pooled object to the +`org.springframework.aop.target.PoolingConfig` interface, which exposes information +about the configuration and current size of the pool through an introduction. You'll +need to define an advisor like this: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + +---- + +This advisor is obtained by calling a convenience method on the +`AbstractPoolingTargetSource` class, hence the use of MethodInvokingFactoryBean. This +advisor's name ("poolConfigAdvisor" here) must be in the list of interceptors names in +the ProxyFactoryBean exposing the pooled object. + +The cast will look as follows: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + PoolingConfig conf = (PoolingConfig) beanFactory.getBean("businessObject"); + System.out.println("Max pool size is " + conf.getMaxSize()); +---- + +[NOTE] +==== +Pooling stateless service objects is not usually necessary. We don't believe it should +be the default choice, as most stateless objects are naturally thread safe, and instance +pooling is problematic if resources are cached. +==== + +Simpler pooling is available using auto-proxying. It's possible to set the TargetSources +used by any auto-proxy creator. + + + +[[aop-ts-prototype]] +==== Prototype target sources +Setting up a "prototype" target source is similar to a pooling TargetSource. In this +case, a new instance of the target will be created on every method invocation. Although +the cost of creating a new object isn't high in a modern JVM, the cost of wiring up the +new object (satisfying its IoC dependencies) may be more expensive. Thus you shouldn't +use this approach without very good reason. + +To do this, you could modify the `poolTargetSource` definition shown above as follows. +(I've also changed the name, for clarity.) + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + +---- + +There's only one property: the name of the target bean. Inheritance is used in the +TargetSource implementations to ensure consistent naming. As with the pooling target +source, the target bean must be a prototype bean definition. + + + +[[aop-ts-threadlocal]] +==== ThreadLocal target sources + +`ThreadLocal` target sources are useful if you need an object to be created for each +incoming request (per thread that is). The concept of a `ThreadLocal` provide a JDK-wide +facility to transparently store resource alongside a thread. Setting up a +`ThreadLocalTargetSource` is pretty much the same as was explained for the other types +of target source: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + +---- + +[NOTE] +==== +ThreadLocals come with serious issues (potentially resulting in memory leaks) when +incorrectly using them in a multi-threaded and multi-classloader environments. One +should always consider wrapping a threadlocal in some other class and never directly use +the `ThreadLocal` itself (except of course in the wrapper class). Also, one should +always remember to correctly set and unset (where the latter simply involved a call to +`ThreadLocal.set(null)`) the resource local to the thread. Unsetting should be done in +any case since not unsetting it might result in problematic behavior. Spring's +ThreadLocal support does this for you and should always be considered in favor of using +ThreadLocals without other proper handling code. +==== + + + + +[[aop-extensibility]] +=== Defining new Advice types + +Spring AOP is designed to be extensible. While the interception implementation strategy +is presently used internally, it is possible to support arbitrary advice types in +addition to the out-of-the-box interception around advice, before, throws advice and +after returning advice. + +The `org.springframework.aop.framework.adapter` package is an SPI package allowing +support for new custom advice types to be added without changing the core framework. +The only constraint on a custom `Advice` type is that it must implement the +`org.aopalliance.aop.Advice` marker interface. + +Please refer to the `org.springframework.aop.framework.adapter` javadocs for further +information. + + + + +[[aop-api-resources]] +=== Further resources +Please refer to the Spring sample applications for further examples of Spring AOP: + +* The JPetStore's default configuration illustrates the use of the + `TransactionProxyFactoryBean` for declarative transaction management. +* The `/attributes` directory of the JPetStore illustrates the use of attribute-driven + declarative transaction management. + + + + + diff --git a/src/asciidoc/aop.adoc b/src/asciidoc/aop.adoc new file mode 100644 index 000000000000..805f33bcb284 --- /dev/null +++ b/src/asciidoc/aop.adoc @@ -0,0 +1,3544 @@ +[[aop]] +== Aspect Oriented Programming with Spring + + + + +[[aop-introduction]] +=== Introduction +__Aspect-Oriented Programming__ (AOP) complements Object-Oriented Programming (OOP) by +providing another way of thinking about program structure. The key unit of modularity in +OOP is the class, whereas in AOP the unit of modularity is the __aspect__. Aspects +enable the modularization of concerns such as transaction management that cut across +multiple types and objects. (Such concerns are often termed __crosscutting__ concerns in +AOP literature.) + +One of the key components of Spring is the __AOP framework__. While the Spring IoC +container does not depend on AOP, meaning you do not need to use AOP if you don't want +to, AOP complements Spring IoC to provide a very capable middleware solution. + +.Spring 2.0 AOP +**** +Spring 2.0 introduces a simpler and more powerful way of writing custom aspects using +either a <> or the <>. Both of these styles offer fully typed advice and use of the AspectJ pointcut +language, while still using Spring AOP for weaving. + +The Spring 2.0 schema- and @AspectJ-based AOP support is discussed in this chapter. +Spring 2.0 AOP remains fully backwards compatible with Spring 1.2 AOP, and the +lower-level AOP support offered by the Spring 1.2 APIs is discussed in <>. +**** + +AOP is used in the Spring Framework to... + +* ... provide declarative enterprise services, especially as a replacement for EJB + declarative services. The most important such service is + <>. +* ... allow users to implement custom aspects, complementing their use of OOP with AOP. + +[NOTE] +==== +If you are interested only in generic declarative services or other pre-packaged +declarative middleware services such as pooling, you do not need to work directly with +Spring AOP, and can skip most of this chapter. +==== + + + +[[aop-introduction-defn]] +==== AOP concepts +Let us begin by defining some central AOP concepts and terminology. These terms are not +Spring-specific... unfortunately, AOP terminology is not particularly intuitive; +however, it would be even more confusing if Spring used its own terminology. + +* __Aspect__: a modularization of a concern that cuts across multiple classes. + Transaction management is a good example of a crosscutting concern in enterprise Java + applications. In Spring AOP, aspects are implemented using regular classes + (the <>) or regular classes annotated with the + `@Aspect` annotation (the <>). +* __Join point__: a point during the execution of a program, such as the execution of a + method or the handling of an exception. In Spring AOP, a join point __always__ + represents a method execution. +* __Advice__: action taken by an aspect at a particular join point. Different types of + advice include "around," "before" and "after" advice. (Advice types are discussed + below.) Many AOP frameworks, including Spring, model an advice as an __interceptor__, + maintaining a chain of interceptors __around__ the join point. +* __Pointcut__: a predicate that matches join points. Advice is associated with a + pointcut expression and runs at any join point matched by the pointcut (for example, + the execution of a method with a certain name). The concept of join points as matched + by pointcut expressions is central to AOP, and Spring uses the AspectJ pointcut + expression language by default. +* __Introduction__: declaring additional methods or fields on behalf of a type. Spring + AOP allows you to introduce new interfaces (and a corresponding implementation) to any + advised object. For example, you could use an introduction to make a bean implement an + `IsModified` interface, to simplify caching. (An introduction is known as an + inter-type declaration in the AspectJ community.) +* __Target object__: object being advised by one or more aspects. Also referred to as + the __advised__ object. Since Spring AOP is implemented using runtime proxies, this + object will always be a __proxied__ object. +* __AOP proxy__: an object created by the AOP framework in order to implement the aspect + contracts (advise method executions and so on). In the Spring Framework, an AOP proxy + will be a JDK dynamic proxy or a CGLIB proxy. +* __Weaving__: linking aspects with other application types or objects to create an + advised object. This can be done at compile time (using the AspectJ compiler, for + example), load time, or at runtime. Spring AOP, like other pure Java AOP frameworks, + performs weaving at runtime. + +Types of advice: + +* __Before advice__: Advice that executes before a join point, but which does not have + the ability to prevent execution flow proceeding to the join point (unless it throws + an exception). +* __After returning advice__: Advice to be executed after a join point completes + normally: for example, if a method returns without throwing an exception. +* __After throwing advice__: Advice to be executed if a method exits by throwing an + exception. +* __After (finally) advice__: Advice to be executed regardless of the means by which a + join point exits (normal or exceptional return). +* __Around advice__: Advice that surrounds a join point such as a method invocation. + This is the most powerful kind of advice. Around advice can perform custom behavior + before and after the method invocation. It is also responsible for choosing whether to + proceed to the join point or to shortcut the advised method execution by returning its + own return value or throwing an exception. + +Around advice is the most general kind of advice. Since Spring AOP, like AspectJ, +provides a full range of advice types, we recommend that you use the least powerful +advice type that can implement the required behavior. For example, if you need only to +update a cache with the return value of a method, you are better off implementing an +after returning advice than an around advice, although an around advice can accomplish +the same thing. Using the most specific advice type provides a simpler programming model +with less potential for errors. For example, you do not need to invoke the `proceed()` +method on the `JoinPoint` used for around advice, and hence cannot fail to invoke it. + +In Spring 2.0, all advice parameters are statically typed, so that you work with advice +parameters of the appropriate type (the type of the return value from a method execution +for example) rather than `Object` arrays. + +The concept of join points, matched by pointcuts, is the key to AOP which distinguishes +it from older technologies offering only interception. Pointcuts enable advice to be +targeted independently of the Object-Oriented hierarchy. For example, an around advice +providing declarative transaction management can be applied to a set of methods spanning +multiple objects (such as all business operations in the service layer). + + + +[[aop-introduction-spring-defn]] +==== Spring AOP capabilities and goals +Spring AOP is implemented in pure Java. There is no need for a special compilation +process. Spring AOP does not need to control the class loader hierarchy, and is thus +suitable for use in a Servlet container or application server. + +Spring AOP currently supports only method execution join points (advising the execution +of methods on Spring beans). Field interception is not implemented, although support for +field interception could be added without breaking the core Spring AOP APIs. If you need +to advise field access and update join points, consider a language such as AspectJ. + +Spring AOP's approach to AOP differs from that of most other AOP frameworks. The aim is +not to provide the most complete AOP implementation (although Spring AOP is quite +capable); it is rather to provide a close integration between AOP implementation and +Spring IoC to help solve common problems in enterprise applications. + +Thus, for example, the Spring Framework's AOP functionality is normally used in +conjunction with the Spring IoC container. Aspects are configured using normal bean +definition syntax (although this allows powerful "autoproxying" capabilities): this is a +crucial difference from other AOP implementations. There are some things you cannot do +easily or efficiently with Spring AOP, such as advise very fine-grained objects (such as +domain objects typically): AspectJ is the best choice in such cases. However, our +experience is that Spring AOP provides an excellent solution to most problems in +enterprise Java applications that are amenable to AOP. + +Spring AOP will never strive to compete with AspectJ to provide a comprehensive AOP +solution. We believe that both proxy-based frameworks like Spring AOP and full-blown +frameworks such as AspectJ are valuable, and that they are complementary, rather than in +competition. Spring seamlessly integrates Spring AOP and IoC with AspectJ, to enable +all uses of AOP to be catered for within a consistent Spring-based application +architecture. This integration does not affect the Spring AOP API or the AOP Alliance +API: Spring AOP remains backward-compatible. See <> for a +discussion of the Spring AOP APIs. + +[NOTE] +==== +One of the central tenets of the Spring Framework is that of __non-invasiveness__; this +is the idea that you should not be forced to introduce framework-specific classes and +interfaces into your business/domain model. However, in some places the Spring Framework +does give you the option to introduce Spring Framework-specific dependencies into your +codebase: the rationale in giving you such options is because in certain scenarios it +might be just plain easier to read or code some specific piece of functionality in such +a way. The Spring Framework (almost) always offers you the choice though: you have the +freedom to make an informed decision as to which option best suits your particular use +case or scenario. + +One such choice that is relevant to this chapter is that of which AOP framework (and +which AOP style) to choose. You have the choice of AspectJ and/or Spring AOP, and you +also have the choice of either the @AspectJ annotation-style approach or the Spring XML +configuration-style approach. The fact that this chapter chooses to introduce the +@AspectJ-style approach first should not be taken as an indication that the Spring team +favors the @AspectJ annotation-style approach over the Spring XML configuration-style. + +See <> for a more complete discussion of the whys and wherefores of each +style. +==== + + + +[[aop-introduction-proxies]] +==== AOP Proxies +Spring AOP defaults to using standard JDK __dynamic proxies__ for AOP proxies. This +enables any interface (or set of interfaces) to be proxied. + +Spring AOP can also use CGLIB proxies. This is necessary to proxy classes, rather than +interfaces. CGLIB is used by default if a business object does not implement an +interface. As it is good practice to program to interfaces rather than classes, business +classes normally will implement one or more business interfaces. It is possible to +<>, in those (hopefully rare) cases +where you need to advise a method that is not declared on an interface, or where you +need to pass a proxied object to a method as a concrete type. + +It is important to grasp the fact that Spring AOP is __proxy-based__. See +<> for a thorough examination of exactly what this +implementation detail actually means. + + + + +[[aop-ataspectj]] +=== @AspectJ support +@AspectJ refers to a style of declaring aspects as regular Java classes annotated with +annotations. The @AspectJ style was introduced by the +http://www.eclipse.org/aspectj[AspectJ project] as part of the AspectJ 5 release. Spring +interprets the same annotations as AspectJ 5, using a library supplied by AspectJ +for pointcut parsing and matching. The AOP runtime is still pure Spring AOP though, and +there is no dependency on the AspectJ compiler or weaver. + +[NOTE] +==== +Using the AspectJ compiler and weaver enables use of the full AspectJ language, and is +discussed in <>. +==== + + + +[[aop-aspectj-support]] +==== Enabling @AspectJ Support +To use @AspectJ aspects in a Spring configuration you need to enable Spring support for +configuring Spring AOP based on @AspectJ aspects, and __autoproxying__ beans based on +whether or not they are advised by those aspects. By autoproxying we mean that if Spring +determines that a bean is advised by one or more aspects, it will automatically generate +a proxy for that bean to intercept method invocations and ensure that advice is executed +as needed. + +The @AspectJ support can be enabled with XML or Java style configuration. In either +case you will also need to ensure that AspectJ's `aspectjweaver.jar` library is on the +classpath of your application (version 1.6.8 or later). This library is available in the +`'lib'` directory of an AspectJ distribution or via the Maven Central repository. + + +[[aop-enable-aspectj-java]] +===== Enabling @AspectJ Support with Java configuration +To enable @AspectJ support with Java `@Configuration` add the `@EnableAspectJAutoProxy` +annotation: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Configuration + @EnableAspectJAutoProxy + public class AppConfig { + + } +---- + + +[[aop-enable-aspectj-xml]] +===== Enabling @AspectJ Support with XML configuration +To enable @AspectJ support with XML based configuration use the `aop:aspectj-autoproxy` +element: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + +---- + +This assumes that you are using schema support as described in <>. See +<> for how to import the tags in the aop namespace. + + + +[[aop-at-aspectj]] +==== Declaring an aspect + +With the @AspectJ support enabled, any bean defined in your application context with a +class that is an @AspectJ aspect (has the `@Aspect` annotation) will be automatically +detected by Spring and used to configure Spring AOP. The following example shows the +minimal definition required for a not-very-useful aspect: + +A regular bean definition in the application context, pointing to a bean class that has +the `@Aspect` annotation: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + +---- + +And the `NotVeryUsefulAspect` class definition, annotated with +`org.aspectj.lang.annotation.Aspect` annotation; + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + package org.xyz; + import org.aspectj.lang.annotation.Aspect; + + @Aspect + public class NotVeryUsefulAspect { + + } +---- + +Aspects (classes annotated with `@Aspect`) may have methods and fields just like any +other class. They may also contain pointcut, advice, and introduction (inter-type) +declarations. + +.Autodetecting aspects through component scanning +[NOTE] +==== +You may register aspect classes as regular beans in your Spring XML configuration, or +autodetect them through classpath scanning - just like any other Spring-managed bean. +However, note that the __@Aspect__ annotation is __not__ sufficient for autodetection in +the classpath: For that purpose, you need to add a separate __@Component__ annotation +(or alternatively a custom stereotype annotation that qualifies, as per the rules of +Spring's component scanner). +==== + +.Advising aspects with other aspects? +[NOTE] +==== +In Spring AOP, it is __not__ possible to have aspects themselves be the target of advice +from other aspects. The __@Aspect__ annotation on a class marks it as an aspect, and +hence excludes it from auto-proxying. +==== + + + +[[aop-pointcuts]] +==== Declaring a pointcut +Recall that pointcuts determine join points of interest, and thus enable us to control +when advice executes. __Spring AOP only supports method execution join points for Spring +beans__, so you can think of a pointcut as matching the execution of methods on Spring +beans. A pointcut declaration has two parts: a signature comprising a name and any +parameters, and a pointcut expression that determines __exactly__ which method +executions we are interested in. In the @AspectJ annotation-style of AOP, a pointcut +signature is provided by a regular method definition, and the pointcut expression is +indicated using the `@Pointcut` annotation (the method serving as the pointcut signature +__must__ have a `void` return type). + +An example will help make this distinction between a pointcut signature and a pointcut +expression clear. The following example defines a pointcut named `'anyOldTransfer'` that +will match the execution of any method named `'transfer'`: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Pointcut("execution(* transfer(..))")// the pointcut expression + private void anyOldTransfer() {}// the pointcut signature +---- + +The pointcut expression that forms the value of the `@Pointcut` annotation is a regular +AspectJ 5 pointcut expression. For a full discussion of AspectJ's pointcut language, see +the http://www.eclipse.org/aspectj/doc/released/progguide/index.html[AspectJ +Programming Guide] (and for extensions, the +http://www.eclipse.org/aspectj/doc/released/adk15notebook/index.html[AspectJ 5 +Developers Notebook]) or one of the books on AspectJ such as "Eclipse AspectJ" by Colyer +et. al. or "AspectJ in Action" by Ramnivas Laddad. + + +[[aop-pointcuts-designators]] +===== Supported Pointcut Designators +Spring AOP supports the following AspectJ pointcut designators (PCD) for use in pointcut +expressions: + +.Other pointcut types +**** +The full AspectJ pointcut language supports additional pointcut designators that are not +supported in Spring. These are: `call, get, set, preinitialization, +staticinitialization, initialization, handler, adviceexecution, withincode, cflow, +cflowbelow, if, @this`, and `@withincode`. Use of these pointcut designators in pointcut +expressions interpreted by Spring AOP will result in an `IllegalArgumentException` being +thrown. + +The set of pointcut designators supported by Spring AOP may be extended in future +releases to support more of the AspectJ pointcut designators. +**** + +* __execution__ - for matching method execution join points, this is the primary + pointcut designator you will use when working with Spring AOP +* __within__ - limits matching to join points within certain types (simply the execution + of a method declared within a matching type when using Spring AOP) +* __this__ - limits matching to join points (the execution of methods when using Spring + AOP) where the bean reference (Spring AOP proxy) is an instance of the given type +* __target__ - limits matching to join points (the execution of methods when using + Spring AOP) where the target object (application object being proxied) is an instance + of the given type +* __args__ - limits matching to join points (the execution of methods when using Spring + AOP) where the arguments are instances of the given types +* __@target__ - limits matching to join points (the execution of methods when using + Spring AOP) where the class of the executing object has an annotation of the given type +* __@args__ - limits matching to join points (the execution of methods when using Spring + AOP) where the runtime type of the actual arguments passed have annotations of the + given type(s) +* __@within__ - limits matching to join points within types that have the given + annotation (the execution of methods declared in types with the given annotation when + using Spring AOP) +* __@annotation__ - limits matching to join points where the subject of the join point + (method being executed in Spring AOP) has the given annotation + +Because Spring AOP limits matching to only method execution join points, the discussion +of the pointcut designators above gives a narrower definition than you will find in the +AspectJ programming guide. In addition, AspectJ itself has type-based semantics and at +an execution join point both '++this++' and '++target++' refer to the same object - the +object executing the method. Spring AOP is a proxy-based system and differentiates +between the proxy object itself (bound to '++this++') and the target object behind the +proxy (bound to '++target++'). + +[NOTE] +==== +Due to the proxy-based nature of Spring's AOP framework, protected methods are by +definition __not__ intercepted, neither for JDK proxies (where this isn't applicable) +nor for CGLIB proxies (where this is technically possible but not recommendable for AOP +purposes). As a consequence, any given pointcut will be matched against __public methods +only__! + +If your interception needs include protected/private methods or even constructors, +consider the use of Spring-driven <> instead of +Spring's proxy-based AOP framework. This constitutes a different mode of AOP usage with +different characteristics, so be sure to make yourself familiar with weaving first +before making a decision. +==== + +Spring AOP also supports an additional PCD named '++bean++'. This PCD allows you to limit +the matching of join points to a particular named Spring bean, or to a set of named +Spring beans (when using wildcards). The '++bean++' PCD has the following form: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + bean(idOrNameOfBean) +---- + +The '++idOrNameOfBean++' token can be the name of any Spring bean: limited wildcard +support using the '++*++' character is provided, so if you establish some naming +conventions for your Spring beans you can quite easily write a '++bean++' PCD expression +to pick them out. As is the case with other pointcut designators, the '++bean++' PCD can +be &&'ed, ||'ed, and ! (negated) too. + +[NOTE] +==== +Please note that the '++bean++' PCD is __only__ supported in Spring AOP - and __not__ in +native AspectJ weaving. It is a Spring-specific extension to the standard PCDs that +AspectJ defines. + +The '++bean++' PCD operates at the __instance__ level (building on the Spring bean name +concept) rather than at the type level only (which is what weaving-based AOP is limited +to). Instance-based pointcut designators are a special capability of Spring's +proxy-based AOP framework and its close integration with the Spring bean factory, where +it is natural and straightforward to identify specific beans by name. +==== + + +[[aop-pointcuts-combining]] +===== Combining pointcut expressions +Pointcut expressions can be combined using '&&', '||' and '!'. It is also possible to +refer to pointcut expressions by name. The following example shows three pointcut +expressions: `anyPublicOperation` (which matches if a method execution join point +represents the execution of any public method); `inTrading` (which matches if a method +execution is in the trading module), and `tradingOperation` (which matches if a method +execution represents any public method in the trading module). + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Pointcut("execution(public * *(..))") + private void anyPublicOperation() {} + + @Pointcut("within(com.xyz.someapp.trading..*)") + private void inTrading() {} + + @Pointcut("anyPublicOperation() && inTrading()") + private void tradingOperation() {} +---- + +It is a best practice to build more complex pointcut expressions out of smaller named +components as shown above. When referring to pointcuts by name, normal Java visibility +rules apply (you can see private pointcuts in the same type, protected pointcuts in the +hierarchy, public pointcuts anywhere and so on). Visibility does not affect pointcut +__matching__. + + +[[aop-common-pointcuts]] +===== Sharing common pointcut definitions +When working with enterprise applications, you often want to refer to modules of the +application and particular sets of operations from within several aspects. We recommend +defining a "SystemArchitecture" aspect that captures common pointcut expressions for +this purpose. A typical such aspect would look as follows: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + package com.xyz.someapp; + + import org.aspectj.lang.annotation.Aspect; + import org.aspectj.lang.annotation.Pointcut; + + @Aspect + public class SystemArchitecture { + + /** + * A join point is in the web layer if the method is defined + * in a type in the com.xyz.someapp.web package or any sub-package + * under that. + */ + @Pointcut("within(com.xyz.someapp.web..*)") + public void inWebLayer() {} + + /** + * A join point is in the service layer if the method is defined + * in a type in the com.xyz.someapp.service package or any sub-package + * under that. + */ + @Pointcut("within(com.xyz.someapp.service..*)") + public void inServiceLayer() {} + + /** + * A join point is in the data access layer if the method is defined + * in a type in the com.xyz.someapp.dao package or any sub-package + * under that. + */ + @Pointcut("within(com.xyz.someapp.dao..*)") + public void inDataAccessLayer() {} + + /** + * A business service is the execution of any method defined on a service + * interface. This definition assumes that interfaces are placed in the + * "service" package, and that implementation types are in sub-packages. + * + * If you group service interfaces by functional area (for example, + * in packages com.xyz.someapp.abc.service and com.xyz.someapp.def.service) then + * the pointcut expression "execution(* com.xyz.someapp..service.*.*(..))" + * could be used instead. + * + * Alternatively, you can write the expression using the 'bean' + * PCD, like so "bean(*Service)". (This assumes that you have + * named your Spring service beans in a consistent fashion.) + */ + @Pointcut("execution(* com.xyz.someapp..service.*.*(..))") + public void businessService() {} + + /** + * A data access operation is the execution of any method defined on a + * dao interface. This definition assumes that interfaces are placed in the + * "dao" package, and that implementation types are in sub-packages. + */ + @Pointcut("execution(* com.xyz.someapp.dao.*.*(..))") + public void dataAccessOperation() {} + + } +---- + +The pointcuts defined in such an aspect can be referred to anywhere that you need a +pointcut expression. For example, to make the service layer transactional, you could +write: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + + +---- + +The `` and `` elements are discussed in <>. The +transaction elements are discussed in <>. + + +[[aop-pointcuts-examples]] +===== Examples +Spring AOP users are likely to use the `execution` pointcut designator the most often. +The format of an execution expression is: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + execution(modifiers-pattern? ret-type-pattern declaring-type-pattern? name-pattern(param-pattern) + throws-pattern?) +---- + +All parts except the returning type pattern (ret-type-pattern in the snippet above), +name pattern, and parameters pattern are optional. The returning type pattern determines +what the return type of the method must be in order for a join point to be matched. Most +frequently you will use `*` as the returning type pattern, which matches any return +type. A fully-qualified type name will match only when the method returns the given +type. The name pattern matches the method name. You can use the `*` wildcard as all or +part of a name pattern. The parameters pattern is slightly more complex: `()` matches a +method that takes no parameters, whereas `(..)` matches any number of parameters (zero +or more). The pattern `(*)` matches a method taking one parameter of any type, +`(*,String)` matches a method taking two parameters, the first can be of any type, the +second must be a String. Consult the +http://www.eclipse.org/aspectj/doc/released/progguide/semantics-pointcuts.html[Language +Semantics] section of the AspectJ Programming Guide for more information. + +Some examples of common pointcut expressions are given below. + +* the execution of any public method: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + execution(public * *(..)) +---- + +* the execution of any method with a name beginning with "set": + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + execution(* set*(..)) +---- + +* the execution of any method defined by the `AccountService` interface: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + execution(* com.xyz.service.AccountService.*(..)) +---- + +* the execution of any method defined in the service package: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + execution(* com.xyz.service.*.*(..)) +---- + +* the execution of any method defined in the service package or a sub-package: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + execution(* com.xyz.service..*.*(..)) +---- + +* any join point (method execution only in Spring AOP) within the service package: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + within(com.xyz.service.*) +---- + +* any join point (method execution only in Spring AOP) within the service package or a + sub-package: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + within(com.xyz.service..*) +---- + +* any join point (method execution only in Spring AOP) where the proxy implements the + `AccountService` interface: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + this(com.xyz.service.AccountService) +---- + +[NOTE] +==== +'this' is more commonly used in a binding form :- see the following section on advice +for how to make the proxy object available in the advice body. +==== + +* any join point (method execution only in Spring AOP) where the target object + implements the `AccountService` interface: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + target(com.xyz.service.AccountService) +---- + +[NOTE] +==== +'target' is more commonly used in a binding form :- see the following section on advice +for how to make the target object available in the advice body. +==== + +* any join point (method execution only in Spring AOP) which takes a single parameter, + and where the argument passed at runtime is `Serializable`: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + args(java.io.Serializable) +---- + +[NOTE] +==== +'args' is more commonly used in a binding form :- see the following section on advice +for how to make the method arguments available in the advice body. +==== + +Note that the pointcut given in this example is different to `execution(* +*(java.io.Serializable))`: the args version matches if the argument passed at runtime is +Serializable, the execution version matches if the method signature declares a single +parameter of type `Serializable`. + +* any join point (method execution only in Spring AOP) where the target object has an + `@Transactional` annotation: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @target(org.springframework.transaction.annotation.Transactional) +---- + +[NOTE] +==== +'@target' can also be used in a binding form :- see the following section on advice for +how to make the annotation object available in the advice body. +==== + +* any join point (method execution only in Spring AOP) where the declared type of the + target object has an `@Transactional` annotation: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @within(org.springframework.transaction.annotation.Transactional) +---- + +[NOTE] +==== +'@within' can also be used in a binding form :- see the following section on advice for +how to make the annotation object available in the advice body. +==== + +* any join point (method execution only in Spring AOP) where the executing method has an + `@Transactional` annotation: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @annotation(org.springframework.transaction.annotation.Transactional) +---- + +[NOTE] +==== +'@annotation' can also be used in a binding form :- see the following section on advice +for how to make the annotation object available in the advice body. +==== + +* any join point (method execution only in Spring AOP) which takes a single parameter, + and where the runtime type of the argument passed has the `@Classified` annotation: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @args(com.xyz.security.Classified) +---- + +[NOTE] +==== +'@args' can also be used in a binding form :- see the following section on advice for +how to make the annotation object(s) available in the advice body. +==== + +* any join point (method execution only in Spring AOP) on a Spring bean named + '++tradeService++': + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + bean(tradeService) +---- + +* any join point (method execution only in Spring AOP) on Spring beans having names that + match the wildcard expression '++*Service++': + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + bean(*Service) +---- + + +[[writing-good-pointcuts]] +===== Writing good pointcuts +During compilation, AspectJ processes pointcuts in order to try and optimize matching +performance. Examining code and determining if each join point matches (statically or +dynamically) a given pointcut is a costly process. (A dynamic match means the match +cannot be fully determined from static analysis and a test will be placed in the code to +determine if there is an actual match when the code is running). On first encountering a +pointcut declaration, AspectJ will rewrite it into an optimal form for the matching +process. What does this mean? Basically pointcuts are rewritten in DNF (Disjunctive +Normal Form) and the components of the pointcut are sorted such that those components +that are cheaper to evaluate are checked first. This means you do not have to worry +about understanding the performance of various pointcut designators and may supply them +in any order in a pointcut declaration. + +However, AspectJ can only work with what it is told, and for optimal performance of +matching you should think about what they are trying to achieve and narrow the search +space for matches as much as possible in the definition. The existing designators +naturally fall into one of three groups: kinded, scoping and context: + +* Kinded designators are those which select a particular kind of join point. For + example: execution, get, set, call, handler +* Scoping designators are those which select a group of join points of interest (of + probably many kinds). For example: within, withincode +* Contextual designators are those that match (and optionally bind) based on context. + For example: this, target, @annotation + +A well written pointcut should try and include at least the first two types (kinded and +scoping), whilst the contextual designators may be included if wishing to match based on +join point context, or bind that context for use in the advice. Supplying either just a +kinded designator or just a contextual designator will work but could affect weaving +performance (time and memory used) due to all the extra processing and analysis. Scoping +designators are very fast to match and their usage means AspectJ can very quickly +dismiss groups of join points that should not be further processed - that is why a good +pointcut should always include one if possible. + + + +[[aop-advice]] +==== Declaring advice +Advice is associated with a pointcut expression, and runs before, after, or around +method executions matched by the pointcut. The pointcut expression may be either a +simple reference to a named pointcut, or a pointcut expression declared in place. + + +[[aop-advice-before]] +===== Before advice +Before advice is declared in an aspect using the `@Before` annotation: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + import org.aspectj.lang.annotation.Aspect; + import org.aspectj.lang.annotation.Before; + + @Aspect + public class BeforeExample { + + @Before("com.xyz.myapp.SystemArchitecture.dataAccessOperation()") + public void doAccessCheck() { + // ... + } + + } +---- + +If using an in-place pointcut expression we could rewrite the above example as: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + import org.aspectj.lang.annotation.Aspect; + import org.aspectj.lang.annotation.Before; + + @Aspect + public class BeforeExample { + + @Before("execution(* com.xyz.myapp.dao.*.*(..))") + public void doAccessCheck() { + // ... + } + + } +---- + + +[[aop-advice-after-returning]] +===== After returning advice +After returning advice runs when a matched method execution returns normally. It is +declared using the `@AfterReturning` annotation: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + import org.aspectj.lang.annotation.Aspect; + import org.aspectj.lang.annotation.AfterReturning; + + @Aspect + public class AfterReturningExample { + + @AfterReturning("com.xyz.myapp.SystemArchitecture.dataAccessOperation()") + public void doAccessCheck() { + // ... + } + + } +---- + +[NOTE] +==== +Note: it is of course possible to have multiple advice declarations, and other members +as well, all inside the same aspect. We're just showing a single advice declaration in +these examples to focus on the issue under discussion at the time. +==== + +Sometimes you need access in the advice body to the actual value that was returned. You +can use the form of `@AfterReturning` that binds the return value for this: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + import org.aspectj.lang.annotation.Aspect; + import org.aspectj.lang.annotation.AfterReturning; + + @Aspect + public class AfterReturningExample { + + @AfterReturning( + pointcut="com.xyz.myapp.SystemArchitecture.dataAccessOperation()", + returning="retVal") + public void doAccessCheck(Object retVal) { + // ... + } + + } +---- + +The name used in the `returning` attribute must correspond to the name of a parameter in +the advice method. When a method execution returns, the return value will be passed to +the advice method as the corresponding argument value. A `returning` clause also +restricts matching to only those method executions that return a value of the specified +type ( `Object` in this case, which will match any return value). + +Please note that it is __not__ possible to return a totally different reference when +using after-returning advice. + + +[[aop-advice-after-throwing]] +===== After throwing advice +After throwing advice runs when a matched method execution exits by throwing an +exception. It is declared using the `@AfterThrowing` annotation: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + import org.aspectj.lang.annotation.Aspect; + import org.aspectj.lang.annotation.AfterThrowing; + + @Aspect + public class AfterThrowingExample { + + @AfterThrowing("com.xyz.myapp.SystemArchitecture.dataAccessOperation()") + public void doRecoveryActions() { + // ... + } + + } +---- + +Often you want the advice to run only when exceptions of a given type are thrown, and +you also often need access to the thrown exception in the advice body. Use the +`throwing` attribute to both restrict matching (if desired, use `Throwable` as the +exception type otherwise) and bind the thrown exception to an advice parameter. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + import org.aspectj.lang.annotation.Aspect; + import org.aspectj.lang.annotation.AfterThrowing; + + @Aspect + public class AfterThrowingExample { + + @AfterThrowing( + pointcut="com.xyz.myapp.SystemArchitecture.dataAccessOperation()", + throwing="ex") + public void doRecoveryActions(DataAccessException ex) { + // ... + } + + } +---- + +The name used in the `throwing` attribute must correspond to the name of a parameter in +the advice method. When a method execution exits by throwing an exception, the exception +will be passed to the advice method as the corresponding argument value. A `throwing` +clause also restricts matching to only those method executions that throw an exception +of the specified type ( `DataAccessException` in this case). + + +[[aop-advice-after-finally]] +===== After (finally) advice +After (finally) advice runs however a matched method execution exits. It is declared +using the `@After` annotation. After advice must be prepared to handle both normal and +exception return conditions. It is typically used for releasing resources, etc. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + import org.aspectj.lang.annotation.Aspect; + import org.aspectj.lang.annotation.After; + + @Aspect + public class AfterFinallyExample { + + @After("com.xyz.myapp.SystemArchitecture.dataAccessOperation()") + public void doReleaseLock() { + // ... + } + + } +---- + + +[[aop-ataspectj-around-advice]] +===== Around advice +The final kind of advice is around advice. Around advice runs "around" a matched method +execution. It has the opportunity to do work both before and after the method executes, +and to determine when, how, and even if, the method actually gets to execute at all. +Around advice is often used if you need to share state before and after a method +execution in a thread-safe manner (starting and stopping a timer for example). Always +use the least powerful form of advice that meets your requirements (i.e. don't use +around advice if simple before advice would do). + +Around advice is declared using the `@Around` annotation. The first parameter of the +advice method must be of type `ProceedingJoinPoint`. Within the body of the advice, +calling `proceed()` on the `ProceedingJoinPoint` causes the underlying method to +execute. The `proceed` method may also be called passing in an `Object[]` - the values +in the array will be used as the arguments to the method execution when it proceeds. + +[NOTE] +==== +The behavior of proceed when called with an Object[] is a little different than the +behavior of proceed for around advice compiled by the AspectJ compiler. For around +advice written using the traditional AspectJ language, the number of arguments passed to +proceed must match the number of arguments passed to the around advice (not the number +of arguments taken by the underlying join point), and the value passed to proceed in a +given argument position supplants the original value at the join point for the entity +the value was bound to (Don't worry if this doesn't make sense right now!). The approach +taken by Spring is simpler and a better match to its proxy-based, execution only +semantics. You only need to be aware of this difference if you are compiling @AspectJ +aspects written for Spring and using proceed with arguments with the AspectJ compiler +and weaver. There is a way to write such aspects that is 100% compatible across both +Spring AOP and AspectJ, and this is discussed in the following section on advice +parameters. +==== + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + import org.aspectj.lang.annotation.Aspect; + import org.aspectj.lang.annotation.Around; + import org.aspectj.lang.ProceedingJoinPoint; + + @Aspect + public class AroundExample { + + @Around("com.xyz.myapp.SystemArchitecture.businessService()") + public Object doBasicProfiling(ProceedingJoinPoint pjp) throws Throwable { + // start stopwatch + Object retVal = pjp.proceed(); + // stop stopwatch + return retVal; + } + + } +---- + +The value returned by the around advice will be the return value seen by the caller of +the method. A simple caching aspect for example could return a value from a cache if it +has one, and invoke proceed() if it does not. Note that proceed may be invoked once, +many times, or not at all within the body of the around advice, all of these are quite +legal. + + +[[aop-ataspectj-advice-params]] +===== Advice parameters +Spring offers fully typed advice - meaning that you declare the parameters you need +in the advice signature (as we saw for the returning and throwing examples above) rather +than work with `Object[]` arrays all the time. We'll see how to make argument and other +contextual values available to the advice body in a moment. First let's take a look at +how to write generic advice that can find out about the method the advice is currently +advising. + +[[aop-ataspectj-advice-params-the-joinpoint]] +====== Access to the current JoinPoint + +Any advice method may declare as its first parameter, a parameter of type +`org.aspectj.lang.JoinPoint` (please note that around advice is __required__ to declare +a first parameter of type `ProceedingJoinPoint`, which is a subclass of `JoinPoint`. The +`JoinPoint` interface provides a number of useful methods such as `getArgs()` (returns +the method arguments), `getThis()` (returns the proxy object), `getTarget()` (returns +the target object), `getSignature()` (returns a description of the method that is being +advised) and `toString()` (prints a useful description of the method being advised). +Please do consult the javadocs for full details. + +[[aop-ataspectj-advice-params-passing]] +====== Passing parameters to advice +We've already seen how to bind the returned value or exception value (using after +returning and after throwing advice). To make argument values available to the advice +body, you can use the binding form of `args`. If a parameter name is used in place of a +type name in an args expression, then the value of the corresponding argument will be +passed as the parameter value when the advice is invoked. An example should make this +clearer. Suppose you want to advise the execution of dao operations that take an Account +object as the first parameter, and you need access to the account in the advice body. +You could write the following: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Before("com.xyz.myapp.SystemArchitecture.dataAccessOperation() && args(account,..)") + public void validateAccount(Account account) { + // ... + } +---- + +The `args(account,..)` part of the pointcut expression serves two purposes: firstly, it +restricts matching to only those method executions where the method takes at least one +parameter, and the argument passed to that parameter is an instance of `Account`; +secondly, it makes the actual `Account` object available to the advice via the `account` +parameter. + +Another way of writing this is to declare a pointcut that "provides" the `Account` +object value when it matches a join point, and then just refer to the named pointcut +from the advice. This would look as follows: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Pointcut("com.xyz.myapp.SystemArchitecture.dataAccessOperation() && args(account,..)") + private void accountDataAccessOperation(Account account) {} + + @Before("accountDataAccessOperation(account)") + public void validateAccount(Account account) { + // ... + } +---- + +The interested reader is once more referred to the AspectJ programming guide for more +details. + +The proxy object ( `this`), target object ( `target`), and annotations ( `@within, +@target, @annotation, @args`) can all be bound in a similar fashion. The following +example shows how you could match the execution of methods annotated with an +`@Auditable` annotation, and extract the audit code. + +First the definition of the `@Auditable` annotation: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Retention(RetentionPolicy.RUNTIME) + @Target(ElementType.METHOD) + public @interface Auditable { + AuditCode value(); + } +---- + +And then the advice that matches the execution of `@Auditable` methods: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Before("com.xyz.lib.Pointcuts.anyPublicMethod() && @annotation(auditable)") + public void audit(Auditable auditable) { + AuditCode code = auditable.value(); + // ... + } +---- + +[[aop-ataspectj-advice-params-generics]] +====== Advice parameters and generics +Spring AOP can handle generics used in class declarations and method parameters. Suppose +you have a generic type like this: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public interface Sample { + void sampleGenericMethod(T param); + void sampleGenericCollectionMethod(Collection>T> param); + } +---- + +You can restrict interception of method types to certain parameter types by simply +typing the advice parameter to the parameter type you want to intercept the method for: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Before("execution(* ..Sample+.sampleGenericMethod(*)) && args(param)") + public void beforeSampleMethod(MyType param) { + // Advice implementation + } +---- + +That this works is pretty obvious as we already discussed above. However, it's worth +pointing out that this won't work for generic collections. So you cannot define a +pointcut like this: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Before("execution(* ..Sample+.sampleGenericCollectionMethod(*)) && args(param)") + public void beforeSampleMethod(Collection param) { + // Advice implementation + } +---- + +To make this work we would have to inspect every element of the collection, which is not +reasonable as we also cannot decide how to treat `null` values in general. To achieve +something similar to this you have to type the parameter to `Collection` and manually +check the type of the elements. + +[[aop-ataspectj-advice-params-names]] +====== Determining argument names +The parameter binding in advice invocations relies on matching names used in pointcut +expressions to declared parameter names in (advice and pointcut) method signatures. +Parameter names are __not__ available through Java reflection, so Spring AOP uses the +following strategies to determine parameter names: + +* If the parameter names have been specified by the user explicitly, then the specified + parameter names are used: both the advice and the pointcut annotations have + an optional "argNames" attribute which can be used to specify the argument names of + the annotated method - these argument names __are__ available at runtime. For example: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Before(value="com.xyz.lib.Pointcuts.anyPublicMethod() && target(bean) && @annotation(auditable)", + argNames="bean,auditable") + public void audit(Object bean, Auditable auditable) { + AuditCode code = auditable.value(); + // ... use code and bean + } +---- + +If the first parameter is of the `JoinPoint`, `ProceedingJoinPoint`, or +`JoinPoint.StaticPart` type, you may leave out the name of the parameter from the value +of the "argNames" attribute. For example, if you modify the preceding advice to receive +the join point object, the "argNames" attribute need not include it: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Before(value="com.xyz.lib.Pointcuts.anyPublicMethod() && target(bean) && @annotation(auditable)", + argNames="bean,auditable") + public void audit(JoinPoint jp, Object bean, Auditable auditable) { + AuditCode code = auditable.value(); + // ... use code, bean, and jp + } +---- + +The special treatment given to the first parameter of the `JoinPoint`, +`ProceedingJoinPoint`, and `JoinPoint.StaticPart` types is particularly convenient for +advice that do not collect any other join point context. In such situations, you may +simply omit the "argNames" attribute. For example, the following advice need not declare +the "argNames" attribute: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Before("com.xyz.lib.Pointcuts.anyPublicMethod()") + public void audit(JoinPoint jp) { + // ... use jp + } +---- + +* Using the `'argNames'` attribute is a little clumsy, so if the `'argNames'` attribute + has not been specified, then Spring AOP will look at the debug information for the + class and try to determine the parameter names from the local variable table. This + information will be present as long as the classes have been compiled with debug + information ( `'-g:vars'` at a minimum). The consequences of compiling with this flag + on are: (1) your code will be slightly easier to understand (reverse engineer), (2) + the class file sizes will be very slightly bigger (typically inconsequential), (3) the + optimization to remove unused local variables will not be applied by your compiler. In + other words, you should encounter no difficulties building with this flag on. + +[NOTE] +==== +If an @AspectJ aspect has been compiled by the AspectJ compiler (ajc) even without the +debug information then there is no need to add the argNames attribute as the compiler +will retain the needed information. +==== + +* If the code has been compiled without the necessary debug information, then Spring AOP + will attempt to deduce the pairing of binding variables to parameters (for example, if + only one variable is bound in the pointcut expression, and the advice method only + takes one parameter, the pairing is obvious!). If the binding of variables is + ambiguous given the available information, then an `AmbiguousBindingException` will be + thrown. +* If all of the above strategies fail then an `IllegalArgumentException` will be thrown. + +[[aop-ataspectj-advice-proceeding-with-the-call]] +====== Proceeding with arguments +We remarked earlier that we would describe how to write a proceed call __with +arguments__ that works consistently across Spring AOP and AspectJ. The solution is +simply to ensure that the advice signature binds each of the method parameters in order. +For example: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Around("execution(List find*(..)) && " + + "com.xyz.myapp.SystemArchitecture.inDataAccessLayer() && " + + "args(accountHolderNamePattern)") + public Object preProcessQueryPattern(ProceedingJoinPoint pjp, + String accountHolderNamePattern) throws Throwable { + String newPattern = preProcess(accountHolderNamePattern); + return pjp.proceed(new Object[] {newPattern}); + } +---- + +In many cases you will be doing this binding anyway (as in the example above). + + +[[aop-ataspectj-advice-ordering]] +===== Advice ordering +What happens when multiple pieces of advice all want to run at the same join point? +Spring AOP follows the same precedence rules as AspectJ to determine the order of advice +execution. The highest precedence advice runs first "on the way in" (so given two pieces +of before advice, the one with highest precedence runs first). "On the way out" from a +join point, the highest precedence advice runs last (so given two pieces of after +advice, the one with the highest precedence will run second). + +When two pieces of advice defined in __different__ aspects both need to run at the same +join point, unless you specify otherwise the order of execution is undefined. You can +control the order of execution by specifying precedence. This is done in the normal +Spring way by either implementing the `org.springframework.core.Ordered` interface in +the aspect class or annotating it with the `Order` annotation. Given two aspects, the +aspect returning the lower value from `Ordered.getValue()` (or the annotation value) has +the higher precedence. + +When two pieces of advice defined in __the same__ aspect both need to run at the same +join point, the ordering is undefined (since there is no way to retrieve the declaration +order via reflection for javac-compiled classes). Consider collapsing such advice +methods into one advice method per join point in each aspect class, or refactor the +pieces of advice into separate aspect classes - which can be ordered at the aspect level. + + + +[[aop-introductions]] +==== Introductions +Introductions (known as inter-type declarations in AspectJ) enable an aspect to declare +that advised objects implement a given interface, and to provide an implementation of +that interface on behalf of those objects. + +An introduction is made using the `@DeclareParents` annotation. This annotation is used +to declare that matching types have a new parent (hence the name). For example, given an +interface `UsageTracked`, and an implementation of that interface `DefaultUsageTracked`, +the following aspect declares that all implementors of service interfaces also implement +the `UsageTracked` interface. (In order to expose statistics via JMX for example.) + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Aspect + public class UsageTracking { + + @DeclareParents(value="com.xzy.myapp.service.*+", defaultImpl=DefaultUsageTracked.class) + public static UsageTracked mixin; + + @Before("com.xyz.myapp.SystemArchitecture.businessService() && this(usageTracked)") + public void recordUsage(UsageTracked usageTracked) { + usageTracked.incrementUseCount(); + } + + } +---- + +The interface to be implemented is determined by the type of the annotated field. The +`value` attribute of the `@DeclareParents` annotation is an AspectJ type pattern :- any +bean of a matching type will implement the UsageTracked interface. Note that in the +before advice of the above example, service beans can be directly used as +implementations of the `UsageTracked` interface. If accessing a bean programmatically +you would write the following: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + UsageTracked usageTracked = (UsageTracked) context.getBean("myService"); +---- + + + +[[aop-instantiation-models]] +==== Aspect instantiation models +[NOTE] +==== +(This is an advanced topic, so if you are just starting out with AOP you can safely skip +it until later.) +==== + +By default there will be a single instance of each aspect within the application +context. AspectJ calls this the singleton instantiation model. It is possible to define +aspects with alternate lifecycles :- Spring supports AspectJ's `perthis` and `pertarget` +instantiation models ( `percflow, percflowbelow,` and `pertypewithin` are not currently +supported). + +A "perthis" aspect is declared by specifying a `perthis` clause in the `@Aspect` +annotation. Let's look at an example, and then we'll explain how it works. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Aspect("perthis(com.xyz.myapp.SystemArchitecture.businessService())") + public class MyAspect { + + private int someState; + + @Before(com.xyz.myapp.SystemArchitecture.businessService()) + public void recordServiceUsage() { + // ... + } + + } +---- + +The effect of the `'perthis'` clause is that one aspect instance will be created for +each unique service object executing a business service (each unique object bound to +'this' at join points matched by the pointcut expression). The aspect instance is +created the first time that a method is invoked on the service object. The aspect goes +out of scope when the service object goes out of scope. Before the aspect instance is +created, none of the advice within it executes. As soon as the aspect instance has been +created, the advice declared within it will execute at matched join points, but only +when the service object is the one this aspect is associated with. See the AspectJ +programming guide for more information on per-clauses. + +The `'pertarget'` instantiation model works in exactly the same way as perthis, but +creates one aspect instance for each unique target object at matched join points. + + + +[[aop-ataspectj-example]] +==== Example +Now that you have seen how all the constituent parts work, let's put them together to do +something useful! + +The execution of business services can sometimes fail due to concurrency issues (for +example, deadlock loser). If the operation is retried, it is quite likely to succeed +next time round. For business services where it is appropriate to retry in such +conditions (idempotent operations that don't need to go back to the user for conflict +resolution), we'd like to transparently retry the operation to avoid the client seeing a +`PessimisticLockingFailureException`. This is a requirement that clearly cuts across +multiple services in the service layer, and hence is ideal for implementing via an +aspect. + +Because we want to retry the operation, we will need to use around advice so that we can +call proceed multiple times. Here's how the basic aspect implementation looks: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Aspect + public class ConcurrentOperationExecutor implements Ordered { + + private static final int DEFAULT_MAX_RETRIES = 2; + + private int maxRetries = DEFAULT_MAX_RETRIES; + private int order = 1; + + public void setMaxRetries(int maxRetries) { + this.maxRetries = maxRetries; + } + + public int getOrder() { + return this.order; + } + + public void setOrder(int order) { + this.order = order; + } + + @Around("com.xyz.myapp.SystemArchitecture.businessService()") + public Object doConcurrentOperation(ProceedingJoinPoint pjp) throws Throwable { + int numAttempts = 0; + PessimisticLockingFailureException lockFailureException; + do { + numAttempts++; + try { + return pjp.proceed(); + } + catch(PessimisticLockingFailureException ex) { + lockFailureException = ex; + } + } while(numAttempts <= this.maxRetries); + throw lockFailureException; + } + + } +---- + +Note that the aspect implements the `Ordered` interface so we can set the precedence of +the aspect higher than the transaction advice (we want a fresh transaction each time we +retry). The `maxRetries` and `order` properties will both be configured by Spring. The +main action happens in the `doConcurrentOperation` around advice. Notice that for the +moment we're applying the retry logic to all `businessService()s`. We try to proceed, +and if we fail with an `PessimisticLockingFailureException` we simply try again unless +we have exhausted all of our retry attempts. + +The corresponding Spring configuration is: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + +---- + +To refine the aspect so that it only retries idempotent operations, we might define an +`Idempotent` annotation: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Retention(RetentionPolicy.RUNTIME) + public @interface Idempotent { + // marker annotation + } +---- + +and use the annotation to annotate the implementation of service operations. The change +to the aspect to only retry idempotent operations simply involves refining the pointcut +expression so that only `@Idempotent` operations match: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Around("com.xyz.myapp.SystemArchitecture.businessService() && " + + "@annotation(com.xyz.myapp.service.Idempotent)") + public Object doConcurrentOperation(ProceedingJoinPoint pjp) throws Throwable { + ... + } +---- + + + + +[[aop-schema]] +=== Schema-based AOP support +If you prefer an XML-based format, then Spring also offers support for defining aspects +using the new "aop" namespace tags. The exact same pointcut expressions and advice kinds +are supported as when using the @AspectJ style, hence in this section we will focus on +the new __syntax__ and refer the reader to the discussion in the previous section +(<>) for an understanding of writing pointcut expressions and the binding +of advice parameters. + +To use the aop namespace tags described in this section, you need to import the +spring-aop schema as described in <>. See <> +for how to import the tags in the aop namespace. + +Within your Spring configurations, all aspect and advisor elements must be placed within +an `` element (you can have more than one `` element in an +application context configuration). An `` element can contain pointcut, +advisor, and aspect elements (note these must be declared in that order). + +[WARNING] +==== + +The `` style of configuration makes heavy use of Spring's +<> mechanism. This can cause issues (such as advice not +being woven) if you are already using explicit auto-proxying via the use of +`BeanNameAutoProxyCreator` or suchlike. The recommended usage pattern is to use either +just the `` style, or just the `AutoProxyCreator` style. +==== + + + +[[aop-schema-declaring-an-aspect]] +==== Declaring an aspect +Using the schema support, an aspect is simply a regular Java object defined as a bean in +your Spring application context. The state and behavior is captured in the fields and +methods of the object, and the pointcut and advice information is captured in the XML. + +An aspect is declared using the element, and the backing bean is referenced +using the `ref` attribute: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + ... + + + + + ... + +---- + +The bean backing the aspect (" `aBean`" in this case) can of course be configured and +dependency injected just like any other Spring bean. + + + +[[aop-schema-pointcuts]] +==== Declaring a pointcut +A named pointcut can be declared inside an element, enabling the pointcut +definition to be shared across several aspects and advisors. + +A pointcut representing the execution of any business service in the service layer could +be defined as follows: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + +---- + +Note that the pointcut expression itself is using the same AspectJ pointcut expression +language as described in <>. If you are using the schema based +declaration style, you can refer to named pointcuts defined in types +(@Aspects) within the pointcut expression. Another way of defining the above pointcut +would be: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + +---- + +Assuming you have a `SystemArchitecture` aspect as described in <>. + +Declaring a pointcut inside an aspect is very similar to declaring a top-level pointcut: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + ... + + + + +---- + +Much the same way in an @AspectJ aspect, pointcuts declared using the schema based +definition style may collect join point context. For example, the following pointcut +collects the 'this' object as the join point context and passes it to advice: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + + ... + + + + +---- + +The advice must be declared to receive the collected join point context by including +parameters of the matching names: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public void monitor(Object service) { + ... + } +---- + +When combining pointcut sub-expressions, '&&' is awkward within an XML document, and so +the keywords 'and', 'or' and 'not' can be used in place of '&&', '||' and '!' +respectively. For example, the previous pointcut may be better written as: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + + ... + + +---- + +Note that pointcuts defined in this way are referred to by their XML id and cannot be +used as named pointcuts to form composite pointcuts. The named pointcut support in the +schema based definition style is thus more limited than that offered by the @AspectJ +style. + + + +[[aop-schema-advice]] +==== Declaring advice +The same five advice kinds are supported as for the @AspectJ style, and they have +exactly the same semantics. + + +[[aop-schema-advice-before]] +===== Before advice +Before advice runs before a matched method execution. It is declared inside an +`` using the element. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + ... + + +---- + +Here `dataAccessOperation` is the id of a pointcut defined at the top ( ``) +level. To define the pointcut inline instead, replace the `pointcut-ref` attribute with +a `pointcut` attribute: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + ... + + +---- + +As we noted in the discussion of the @AspectJ style, using named pointcuts can +significantly improve the readability of your code. + +The method attribute identifies a method ( `doAccessCheck`) that provides the body of +the advice. This method must be defined for the bean referenced by the aspect element +containing the advice. Before a data access operation is executed (a method execution +join point matched by the pointcut expression), the "doAccessCheck" method on the aspect +bean will be invoked. + + +[[aop-schema-advice-after-returning]] +===== After returning advice +After returning advice runs when a matched method execution completes normally. It is +declared inside an `` in the same way as before advice. For example: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + ... + + +---- + +Just as in the @AspectJ style, it is possible to get hold of the return value within the +advice body. Use the returning attribute to specify the name of the parameter to which +the return value should be passed: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + ... + + +---- + +The doAccessCheck method must declare a parameter named `retVal`. The type of this +parameter constrains matching in the same way as described for @AfterReturning. For +example, the method signature may be declared as: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public void doAccessCheck(Object retVal) {... +---- + + +[[aop-schema-advice-after-throwing]] +===== After throwing advice +After throwing advice executes when a matched method execution exits by throwing an +exception. It is declared inside an `` using the after-throwing element: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + ... + + +---- + +Just as in the @AspectJ style, it is possible to get hold of the thrown exception within +the advice body. Use the throwing attribute to specify the name of the parameter to +which the exception should be passed: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + ... + + +---- + +The doRecoveryActions method must declare a parameter named `dataAccessEx`. The type of +this parameter constrains matching in the same way as described for @AfterThrowing. For +example, the method signature may be declared as: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public void doRecoveryActions(DataAccessException dataAccessEx) {... +---- + + +[[aop-schema-advice-after-finally]] +===== After (finally) advice +After (finally) advice runs however a matched method execution exits. It is declared +using the `after` element: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + ... + + +---- + + +[[aop-schema-advice-around]] +===== Around advice +The final kind of advice is around advice. Around advice runs "around" a matched method +execution. It has the opportunity to do work both before and after the method executes, +and to determine when, how, and even if, the method actually gets to execute at all. +Around advice is often used if you need to share state before and after a method +execution in a thread-safe manner (starting and stopping a timer for example). Always +use the least powerful form of advice that meets your requirements; don't use around +advice if simple before advice would do. + +Around advice is declared using the `aop:around` element. The first parameter of the +advice method must be of type `ProceedingJoinPoint`. Within the body of the advice, +calling `proceed()` on the `ProceedingJoinPoint` causes the underlying method to +execute. The `proceed` method may also be calling passing in an `Object[]` - the values +in the array will be used as the arguments to the method execution when it proceeds. See +<> for notes on calling proceed with an `Object[]`. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + ... + + +---- + +The implementation of the `doBasicProfiling` advice would be exactly the same as in the +@AspectJ example (minus the annotation of course): + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public Object doBasicProfiling(ProceedingJoinPoint pjp) throws Throwable { + // start stopwatch + Object retVal = pjp.proceed(); + // stop stopwatch + return retVal; + } +---- + + +[[aop-schema-params]] +===== Advice parameters +The schema based declaration style supports fully typed advice in the same way as +described for the @AspectJ support - by matching pointcut parameters by name against +advice method parameters. See <> for details. If you wish +to explicitly specify argument names for the advice methods (not relying on the +detection strategies previously described) then this is done using the `arg-names` +attribute of the advice element, which is treated in the same manner to the "argNames" +attribute in an advice annotation as described in <>. +For example: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + +---- + +The `arg-names` attribute accepts a comma-delimited list of parameter names. + +Find below a slightly more involved example of the XSD-based approach that illustrates +some around advice used in conjunction with a number of strongly typed parameters. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + package x.y.service; + + public interface FooService { + + Foo getFoo(String fooName, int age); + } + + public class DefaultFooService implements FooService { + + public Foo getFoo(String name, int age) { + return new Foo(name, age); + } + } +---- + +Next up is the aspect. Notice the fact that the `profile(..)` method accepts a number of +strongly-typed parameters, the first of which happens to be the join point used to +proceed with the method call: the presence of this parameter is an indication that the +`profile(..)` is to be used as `around` advice: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + package x.y; + + import org.aspectj.lang.ProceedingJoinPoint; + import org.springframework.util.StopWatch; + + public class SimpleProfiler { + + public Object profile(ProceedingJoinPoint call, String name, int age) throws Throwable { + StopWatch clock = new StopWatch("Profiling for '" + name + "' and '" + age + "'"); + try { + clock.start(call.toShortString()); + return call.proceed(); + } finally { + clock.stop(); + System.out.println(clock.prettyPrint()); + } + } + } +---- + +Finally, here is the XML configuration that is required to effect the execution of the +above advice for a particular join point: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + + + + + + + + + + + + +---- + +If we had the following driver script, we would get output something like this on +standard output: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + import org.springframework.beans.factory.BeanFactory; + import org.springframework.context.support.ClassPathXmlApplicationContext; + import x.y.service.FooService; + + public final class Boot { + + public static void main(final String[] args) throws Exception { + BeanFactory ctx = new ClassPathXmlApplicationContext("x/y/plain.xml"); + FooService foo = (FooService) ctx.getBean("fooService"); + foo.getFoo("Pengo", 12); + } + } +---- + +[literal] +[subs="verbatim,quotes"] +---- +StopWatch 'Profiling for 'Pengo' and '12'': running time (millis) = 0 +----------------------------------------- +ms % Task name +----------------------------------------- +00000 ? execution(getFoo) +---- + + +[[aop-ordering]] +===== Advice ordering +When multiple advice needs to execute at the same join point (executing method) the +ordering rules are as described in <>. The precedence +between aspects is determined by either adding the `Order` annotation to the bean +backing the aspect or by having the bean implement the `Ordered` interface. + + + +[[aop-schema-introductions]] +==== Introductions +Introductions (known as inter-type declarations in AspectJ) enable an aspect to declare +that advised objects implement a given interface, and to provide an implementation of +that interface on behalf of those objects. + +An introduction is made using the `aop:declare-parents` element inside an `aop:aspect` +This element is used to declare that matching types have a new parent (hence the name). +For example, given an interface `UsageTracked`, and an implementation of that interface +`DefaultUsageTracked`, the following aspect declares that all implementors of service +interfaces also implement the `UsageTracked` interface. (In order to expose statistics +via JMX for example.) + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + +---- + +The class backing the `usageTracking` bean would contain the method: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public void recordUsage(UsageTracked usageTracked) { + usageTracked.incrementUseCount(); + } +---- + +The interface to be implemented is determined by `implement-interface` attribute. The +value of the `types-matching` attribute is an AspectJ type pattern :- any bean of a +matching type will implement the `UsageTracked` interface. Note that in the before +advice of the above example, service beans can be directly used as implementations of +the `UsageTracked` interface. If accessing a bean programmatically you would write the +following: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + UsageTracked usageTracked = (UsageTracked) context.getBean("myService"); +---- + + + +[[aop-schema-instatiation-models]] +==== Aspect instantiation models +The only supported instantiation model for schema-defined aspects is the singleton +model. Other instantiation models may be supported in future releases. + + + +[[aop-schema-advisors]] +==== Advisors +The concept of "advisors" is brought forward from the AOP support defined in Spring 1.2 +and does not have a direct equivalent in AspectJ. An advisor is like a small +self-contained aspect that has a single piece of advice. The advice itself is +represented by a bean, and must implement one of the advice interfaces described in +<>. Advisors can take advantage of AspectJ pointcut expressions +though. + +Spring supports the advisor concept with the `` element. You will most +commonly see it used in conjunction with transactional advice, which also has its own +namespace support in Spring. Here's how it looks: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + + + + + + +---- + +As well as the `pointcut-ref` attribute used in the above example, you can also use the +`pointcut` attribute to define a pointcut expression inline. + +To define the precedence of an advisor so that the advice can participate in ordering, +use the `order` attribute to define the `Ordered` value of the advisor. + + + +[[aop-schema-example]] +==== Example +Let's see how the concurrent locking failure retry example from +<> looks when rewritten using the schema support. + +The execution of business services can sometimes fail due to concurrency issues (for +example, deadlock loser). If the operation is retried, it is quite likely it will +succeed next time round. For business services where it is appropriate to retry in such +conditions (idempotent operations that don't need to go back to the user for conflict +resolution), we'd like to transparently retry the operation to avoid the client seeing a +`PessimisticLockingFailureException`. This is a requirement that clearly cuts across +multiple services in the service layer, and hence is ideal for implementing via an +aspect. + +Because we want to retry the operation, we'll need to use around advice so that we can +call proceed multiple times. Here's how the basic aspect implementation looks (it's just +a regular Java class using the schema support): + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class ConcurrentOperationExecutor implements Ordered { + + private static final int DEFAULT_MAX_RETRIES = 2; + + private int maxRetries = DEFAULT_MAX_RETRIES; + private int order = 1; + + public void setMaxRetries(int maxRetries) { + this.maxRetries = maxRetries; + } + + public int getOrder() { + return this.order; + } + + public void setOrder(int order) { + this.order = order; + } + + public Object doConcurrentOperation(ProceedingJoinPoint pjp) throws Throwable { + int numAttempts = 0; + PessimisticLockingFailureException lockFailureException; + do { + numAttempts++; + try { + return pjp.proceed(); + } + catch(PessimisticLockingFailureException ex) { + lockFailureException = ex; + } + } while(numAttempts <= this.maxRetries); + throw lockFailureException; + } + + } +---- + +Note that the aspect implements the `Ordered` interface so we can set the precedence of +the aspect higher than the transaction advice (we want a fresh transaction each time we +retry). The `maxRetries` and `order` properties will both be configured by Spring. The +main action happens in the `doConcurrentOperation` around advice method. We try to +proceed, and if we fail with a `PessimisticLockingFailureException` we simply try again +unless we have exhausted all of our retry attempts. + +[NOTE] +==== +This class is identical to the one used in the @AspectJ example, but with the +annotations removed. +==== + +The corresponding Spring configuration is: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + + + + + + + + + +---- + +Notice that for the time being we assume that all business services are idempotent. If +this is not the case we can refine the aspect so that it only retries genuinely +idempotent operations, by introducing an `Idempotent` annotation: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Retention(RetentionPolicy.RUNTIME) + public @interface Idempotent { + // marker annotation + } +---- + +and using the annotation to annotate the implementation of service operations. The +change to the aspect to retry only idempotent operations simply involves refining the +pointcut expression so that only `@Idempotent` operations match: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + +---- + + + + +[[aop-choosing]] +=== Choosing which AOP declaration style to use +Once you have decided that an aspect is the best approach for implementing a given +requirement, how do you decide between using Spring AOP or AspectJ, and between the +Aspect language (code) style, @AspectJ annotation style, or the Spring XML style? These +decisions are influenced by a number of factors including application requirements, +development tools, and team familiarity with AOP. + + + +[[aop-spring-or-aspectj]] +==== Spring AOP or full AspectJ? +Use the simplest thing that can work. Spring AOP is simpler than using full AspectJ as +there is no requirement to introduce the AspectJ compiler / weaver into your development +and build processes. If you only need to advise the execution of operations on Spring +beans, then Spring AOP is the right choice. If you need to advise objects not managed by +the Spring container (such as domain objects typically), then you will need to use +AspectJ. You will also need to use AspectJ if you wish to advise join points other than +simple method executions (for example, field get or set join points, and so on). + +When using AspectJ, you have the choice of the AspectJ language syntax (also known as +the "code style") or the @AspectJ annotation style. Clearly, if you are not using Java +5+ then the choice has been made for you... use the code style. If aspects play a large +role in your design, and you are able to use the http://www.eclipse.org/ajdt/[AspectJ +Development Tools (AJDT)] plugin for Eclipse, then the AspectJ language syntax is the +preferred option: it is cleaner and simpler because the language was purposefully +designed for writing aspects. If you are not using Eclipse, or have only a few aspects +that do not play a major role in your application, then you may want to consider using +the @AspectJ style and sticking with a regular Java compilation in your IDE, and adding +an aspect weaving phase to your build script. + + + +[[aop-ataspectj-or-xml]] +==== @AspectJ or XML for Spring AOP? +If you have chosen to use Spring AOP, then you have a choice of @AspectJ or XML style. +There are various tradeoffs to consider. + +The XML style will be most familiar to existing Spring users and it is backed by genuine +POJOs. When using AOP as a tool to configure enterprise services then XML can be a good +choice (a good test is whether you consider the pointcut expression to be a part of your +configuration you might want to change independently). With the XML style arguably it is +clearer from your configuration what aspects are present in the system. + +The XML style has two disadvantages. Firstly it does not fully encapsulate the +implementation of the requirement it addresses in a single place. The DRY principle says +that there should be a single, unambiguous, authoritative representation of any piece of +knowledge within a system. When using the XML style, the knowledge of __how__ a +requirement is implemented is split across the declaration of the backing bean class, +and the XML in the configuration file. When using the @AspectJ style there is a single +module - the aspect - in which this information is encapsulated. Secondly, the XML style +is slightly more limited in what it can express than the @AspectJ style: only the +"singleton" aspect instantiation model is supported, and it is not possible to combine +named pointcuts declared in XML. For example, in the @AspectJ style you can write +something like: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Pointcut(execution(* get*())) + public void propertyAccess() {} + + @Pointcut(execution(org.xyz.Account+ *(..)) + public void operationReturningAnAccount() {} + + @Pointcut(propertyAccess() && operationReturningAnAccount()) + public void accountPropertyAccess() {} +---- + +In the XML style I can declare the first two pointcuts: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + +---- + +The downside of the XML approach is that you cannot define the +'++accountPropertyAccess++' pointcut by combining these definitions. + +The @AspectJ style supports additional instantiation models, and richer pointcut +composition. It has the advantage of keeping the aspect as a modular unit. It also has +the advantage the @AspectJ aspects can be understood (and thus consumed) both by Spring +AOP and by AspectJ - so if you later decide you need the capabilities of AspectJ to +implement additional requirements then it is very easy to migrate to an AspectJ-based +approach. On balance the Spring team prefer the @AspectJ style whenever you have aspects +that do more than simple "configuration" of enterprise services. + + + + +[[aop-mixing-styles]] +=== Mixing aspect types +It is perfectly possible to mix @AspectJ style aspects using the autoproxying support, +schema-defined `` aspects, `` declared advisors and even +proxies and interceptors defined using the Spring 1.2 style in the same configuration. +All of these are implemented using the same underlying support mechanism and will +co-exist without any difficulty. + + + + +[[aop-proxying]] +=== Proxying mechanisms +Spring AOP uses either JDK dynamic proxies or CGLIB to create the proxy for a given +target object. (JDK dynamic proxies are preferred whenever you have a choice). + +If the target object to be proxied implements at least one interface then a JDK dynamic +proxy will be used. All of the interfaces implemented by the target type will be +proxied. If the target object does not implement any interfaces then a CGLIB proxy will +be created. + +If you want to force the use of CGLIB proxying (for example, to proxy every method +defined for the target object, not just those implemented by its interfaces) you can do +so. However, there are some issues to consider: + +* `final` methods cannot be advised, as they cannot be overridden. +* As of Spring 3.2, it is no longer necessary to add CGLIB to your project classpath, as + CGLIB classes are repackaged under org.springframework and included directly in the + spring-core JAR. This means that CGLIB-based proxy support 'just works' in the same + way that JDK dynamic proxies always have. +* The constructor of your proxied object will be called twice. This is a natural + consequence of the CGLIB proxy model whereby a subclass is generated for each proxied + object. For each proxied instance, two objects are created: the actual proxied object + and an instance of the subclass that implements the advice. This behavior is not + exhibited when using JDK proxies. Usually, calling the constructor of the proxied type + twice, is not an issue, as there are usually only assignments taking place and no real + logic is implemented in the constructor. + +To force the use of CGLIB proxies set the value of the `proxy-target-class` attribute of +the `` element to true: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + +---- + +To force CGLIB proxying when using the @AspectJ autoproxy support, set the +`'proxy-target-class'` attribute of the `` element to `true`: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + +---- + +[NOTE] +==== +Multiple `` sections are collapsed into a single unified auto-proxy creator +at runtime, which applies the __strongest__ proxy settings that any of the +`` sections (typically from different XML bean definition files) specified. +This also applies to the `` and `` +elements. + +To be clear: using '++proxy-target-class="true"++' on ``, +`` or `` elements will force the use of CGLIB +proxies __for all three of them__. +==== + + + +[[aop-understanding-aop-proxies]] +==== Understanding AOP proxies +Spring AOP is __proxy-based__. It is vitally important that you grasp the semantics of +what that last statement actually means before you write your own aspects or use any of +the Spring AOP-based aspects supplied with the Spring Framework. + +Consider first the scenario where you have a plain-vanilla, un-proxied, +nothing-special-about-it, straight object reference, as illustrated by the following +code snippet. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class SimplePojo implements Pojo { + + public void foo() { + // this next method invocation is a direct call on the 'this' reference + this.bar(); + } + + public void bar() { + // some logic... + } + } +---- + +If you invoke a method on an object reference, the method is invoked __directly__ on +that object reference, as can be seen below. + +image::images/aop-proxy-plain-pojo-call.png[width=400] + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class Main { + + public static void main(String[] args) { + + Pojo pojo = new SimplePojo(); + + // this is a direct method call on the 'pojo' reference + pojo.foo(); + } + } +---- + +Things change slightly when the reference that client code has is a proxy. Consider the +following diagram and code snippet. + +image::images/aop-proxy-call.png[width=400] + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class Main { + + public static void main(String[] args) { + + ProxyFactory factory = new ProxyFactory(new SimplePojo()); + factory.addInterface(Pojo.class); + factory.addAdvice(new RetryAdvice()); + + Pojo pojo = (Pojo) factory.getProxy(); + + // this is a method call on the proxy! + pojo.foo(); + } + } +---- + +The key thing to understand here is that the client code inside the `main(..)` of the +`Main` class __has a reference to the proxy__. This means that method calls on that +object reference will be calls on the proxy, and as such the proxy will be able to +delegate to all of the interceptors (advice) that are relevant to that particular method +call. However, once the call has finally reached the target object, the `SimplePojo` +reference in this case, any method calls that it may make on itself, such as +`this.bar()` or `this.foo()`, are going to be invoked against the __this__ reference, +and __not__ the proxy. This has important implications. It means that self-invocation is +__not__ going to result in the advice associated with a method invocation getting a +chance to execute. + +Okay, so what is to be done about this? The best approach (the term best is used loosely +here) is to refactor your code such that the self-invocation does not happen. For sure, +this does entail some work on your part, but it is the best, least-invasive approach. +The next approach is absolutely horrendous, and I am almost reticent to point it out +precisely because it is so horrendous. You can (choke!) totally tie the logic within +your class to Spring AOP by doing this: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class SimplePojo implements Pojo { + + public void foo() { + // this works, but... gah! + ((Pojo) AopContext.currentProxy()).bar(); + } + + public void bar() { + // some logic... + } + } +---- + +This totally couples your code to Spring AOP, __and__ it makes the class itself aware of +the fact that it is being used in an AOP context, which flies in the face of AOP. It +also requires some additional configuration when the proxy is being created: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class Main { + + public static void main(String[] args) { + + ProxyFactory factory = new ProxyFactory(new SimplePojo()); + factory.adddInterface(Pojo.class); + factory.addAdvice(new RetryAdvice()); + factory.setExposeProxy(true); + + Pojo pojo = (Pojo) factory.getProxy(); + + // this is a method call on the proxy! + pojo.foo(); + } + } +---- + +Finally, it must be noted that AspectJ does not have this self-invocation issue because +it is not a proxy-based AOP framework. + + + + +[[aop-aspectj-programmatic]] +=== Programmatic creation of @AspectJ Proxies +In addition to declaring aspects in your configuration using either `` or +``, it is also possible programmatically to create proxies that +advise target objects. For the full details of Spring's AOP API, see the next chapter. +Here we want to focus on the ability to automatically create proxies using @AspectJ +aspects. + +The class `org.springframework.aop.aspectj.annotation.AspectJProxyFactory` can be used +to create a proxy for a target object that is advised by one or more @AspectJ aspects. +Basic usage for this class is very simple, as illustrated below. See the javadocs for +full information. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + // create a factory that can generate a proxy for the given target object + AspectJProxyFactory factory = new AspectJProxyFactory(targetObject); + + // add an aspect, the class must be an @AspectJ aspect + // you can call this as many times as you need with different aspects + factory.addAspect(SecurityManager.class); + + // you can also add existing aspect instances, the type of the object supplied must be an @AspectJ aspect + factory.addAspect(usageTracker); + + // now get the proxy object... + MyInterfaceType proxy = factory.getProxy(); +---- + + + + +[[aop-using-aspectj]] +=== Using AspectJ with Spring applications +Everything we've covered so far in this chapter is pure Spring AOP. In this section, +we're going to look at how you can use the AspectJ compiler/weaver instead of, or in +addition to, Spring AOP if your needs go beyond the facilities offered by Spring AOP +alone. + +Spring ships with a small AspectJ aspect library, which is available standalone in your +distribution as `spring-aspects.jar`; you'll need to add this to your classpath in order +to use the aspects in it. <> and <> discuss the +content of this library and how you can use it. <> discusses how to +dependency inject AspectJ aspects that are woven using the AspectJ compiler. Finally, +<> provides an introduction to load-time weaving for Spring applications +using AspectJ. + + + +[[aop-atconfigurable]] +==== Using AspectJ to dependency inject domain objects with Spring +The Spring container instantiates and configures beans defined in your application +context. It is also possible to ask a bean factory to configure a __pre-existing__ +object given the name of a bean definition containing the configuration to be applied. +The `spring-aspects.jar` contains an annotation-driven aspect that exploits this +capability to allow dependency injection of __any object__. The support is intended to +be used for objects created __outside of the control of any container__. Domain objects +often fall into this category because they are often created programmatically using the +`new` operator, or by an ORM tool as a result of a database query. + +The `@Configurable` annotation marks a class as eligible for Spring-driven +configuration. In the simplest case it can be used just as a marker annotation: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + package com.xyz.myapp.domain; + + import org.springframework.beans.factory.annotation.Configurable; + + @Configurable + public class Account { + // ... + } +---- + +When used as a marker interface in this way, Spring will configure new instances of the +annotated type ( `Account` in this case) using a bean definition (typically +prototype-scoped) with the same name as the fully-qualified type name ( +`com.xyz.myapp.domain.Account`). Since the default name for a bean is the +fully-qualified name of its type, a convenient way to declare the prototype definition +is simply to omit the `id` attribute: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + +---- + +If you want to explicitly specify the name of the prototype bean definition to use, you +can do so directly in the annotation: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + package com.xyz.myapp.domain; + + import org.springframework.beans.factory.annotation.Configurable; + + @Configurable("account") + public class Account { + // ... + } +---- + +Spring will now look for a bean definition named " `account`" and use that as the +definition to configure new `Account` instances. + +You can also use autowiring to avoid having to specify a dedicated bean definition at +all. To have Spring apply autowiring use the '++autowire++' property of the +`@Configurable` annotation: specify either `@Configurable(autowire=Autowire.BY_TYPE)` or +`@Configurable(autowire=Autowire.BY_NAME` for autowiring by type or by name +respectively. As an alternative, as of Spring 2.5 it is preferable to specify explicit, +annotation-driven dependency injection for your `@Configurable` beans by using +`@Autowired` or `@Inject` at the field or method level (see <> +for further details). + +Finally you can enable Spring dependency checking for the object references in the newly +created and configured object by using the `dependencyCheck` attribute (for example: +`@Configurable(autowire=Autowire.BY_NAME,dependencyCheck=true)`). If this attribute is +set to true, then Spring will validate after configuration that all properties (__which +are not primitives or collections__) have been set. + +Using the annotation on its own does nothing of course. It is the +`AnnotationBeanConfigurerAspect` in `spring-aspects.jar` that acts on the presence of +the annotation. In essence the aspect says "after returning from the initialization of a +new object of a type annotated with `@Configurable`, configure the newly created object +using Spring in accordance with the properties of the annotation". In this context, +__initialization__ refers to newly instantiated objects (e.g., objects instantiated with +the '++new++' operator) as well as to `Serializable` objects that are undergoing +deserialization (e.g., via +http://docs.oracle.com/javase/6/docs/api/java/io/Serializable.html[readResolve()]). + +[NOTE] +==== +One of the key phrases in the above paragraph is '__in essence__'. For most cases, the +exact semantics of '__after returning from the initialization of a new object__' will be +fine... in this context, '__after initialization__' means that the dependencies will be +injected __after__ the object has been constructed - this means that the dependencies +will not be available for use in the constructor bodies of the class. If you want the +dependencies to be injected __before__ the constructor bodies execute, and thus be +available for use in the body of the constructors, then you need to define this on the +`@Configurable` declaration like so: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Configurable(preConstruction=true) +---- + +You can find out more information about the language semantics of the various pointcut +types in AspectJ +http://www.eclipse.org/aspectj/doc/next/progguide/semantics-joinPoints.html[in this +appendix] of the http://www.eclipse.org/aspectj/doc/next/progguide/index.html[AspectJ +Programming Guide]. +==== + +For this to work the annotated types must be woven with the AspectJ weaver - you can +either use a build-time Ant or Maven task to do this (see for example the +http://www.eclipse.org/aspectj/doc/released/devguide/antTasks.html[AspectJ Development +Environment Guide]) or load-time weaving (see <>). The +`AnnotationBeanConfigurerAspect` itself needs configuring by Spring (in order to obtain +a reference to the bean factory that is to be used to configure new objects). If you are +using Java based configuration simply add `@EnableSpringConfigured` to any +`@Configuration` class. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Configuration + @EnableSpringConfigured + public class AppConfig { + + } +---- + +If you prefer XML based configuration, the Spring <> defines a convenient `context:spring-configured` element: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + +---- + +Instances of `@Configurable` objects created __before__ the aspect has been configured +will result in a message being issued to the debug log and no configuration of the +object taking place. An example might be a bean in the Spring configuration that creates +domain objects when it is initialized by Spring. In this case you can use the +"depends-on" bean attribute to manually specify that the bean depends on the +configuration aspect. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + +---- + +[NOTE] +==== +Do not activate `@Configurable` processing through the bean configurer aspect unless you +really mean to rely on its semantics at runtime. In particular, make sure that you do +not use `@Configurable` on bean classes which are registered as regular Spring beans +with the container: You would get double initialization otherwise, once through the +container and once through the aspect. +==== + + +[[aop-configurable-testing]] +===== Unit testing @Configurable objects + +One of the goals of the `@Configurable` support is to enable independent unit testing of +domain objects without the difficulties associated with hard-coded lookups. If +`@Configurable` types have not been woven by AspectJ then the annotation has no affect +during unit testing, and you can simply set mock or stub property references in the +object under test and proceed as normal. If `@Configurable` types __have__ been woven by +AspectJ then you can still unit test outside of the container as normal, but you will +see a warning message each time that you construct an `@Configurable` object indicating +that it has not been configured by Spring. + + +[[aop-configurable-container]] +===== Working with multiple application contexts +The `AnnotationBeanConfigurerAspect` used to implement the `@Configurable` support is an +AspectJ singleton aspect. The scope of a singleton aspect is the same as the scope of +`static` members, that is to say there is one aspect instance per classloader that +defines the type. This means that if you define multiple application contexts within the +same classloader hierarchy you need to consider where to define the +`@EnableSpringConfigured` bean and where to place `spring-aspects.jar` on the classpath. + +Consider a typical Spring web-app configuration with a shared parent application context +defining common business services and everything needed to support them, and one child +application context per servlet containing definitions particular to that servlet. All +of these contexts will co-exist within the same classloader hierarchy, and so the +`AnnotationBeanConfigurerAspect` can only hold a reference to one of them. In this case +we recommend defining the `@EnableSpringConfigured` bean in the shared (parent) +application context: this defines the services that you are likely to want to inject +into domain objects. A consequence is that you cannot configure domain objects with +references to beans defined in the child (servlet-specific) contexts using the +@Configurable mechanism (probably not something you want to do anyway!). + +When deploying multiple web-apps within the same container, ensure that each +web-application loads the types in `spring-aspects.jar` using its own classloader (for +example, by placing `spring-aspects.jar` in `'WEB-INF/lib'`). If `spring-aspects.jar` is +only added to the container wide classpath (and hence loaded by the shared parent +classloader), all web applications will share the same aspect instance which is probably +not what you want. + + + +[[aop-ajlib-other]] +==== Other Spring aspects for AspectJ +In addition to the `@Configurable` aspect, `spring-aspects.jar` contains an AspectJ +aspect that can be used to drive Spring's transaction management for types and methods +annotated with the `@Transactional` annotation. This is primarily intended for users who +want to use the Spring Framework's transaction support outside of the Spring container. + +The aspect that interprets `@Transactional` annotations is the +`AnnotationTransactionAspect`. When using this aspect, you must annotate the +__implementation__ class (and/or methods within that class), __not__ the interface (if +any) that the class implements. AspectJ follows Java's rule that annotations on +interfaces are __not inherited__. + +A `@Transactional` annotation on a class specifies the default transaction semantics for +the execution of any __public__ operation in the class. + +A `@Transactional` annotation on a method within the class overrides the default +transaction semantics given by the class annotation (if present). Methods with `public`, +`protected`, and default visibility may all be annotated. Annotating `protected` and +default visibility methods directly is the only way to get transaction demarcation for +the execution of such methods. + +For AspectJ programmers that want to use the Spring configuration and transaction +management support but don't want to (or cannot) use annotations, `spring-aspects.jar` +also contains `abstract` aspects you can extend to provide your own pointcut +definitions. See the sources for the `AbstractBeanConfigurerAspect` and +`AbstractTransactionAspect` aspects for more information. As an example, the following +excerpt shows how you could write an aspect to configure all instances of objects +defined in the domain model using prototype bean definitions that match the +fully-qualified class names: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public aspect DomainObjectConfiguration extends AbstractBeanConfigurerAspect { + + public DomainObjectConfiguration() { + setBeanWiringInfoResolver(new ClassNameBeanWiringInfoResolver()); + } + + // the creation of a new bean (any object in the domain model) + protected pointcut beanCreation(Object beanInstance) : + initialization(new(..)) && + SystemArchitecture.inDomainModel() && + this(beanInstance); + + } +---- + + + +[[aop-aj-configure]] +==== Configuring AspectJ aspects using Spring IoC +When using AspectJ aspects with Spring applications, it is natural to both want and +expect to be able to configure such aspects using Spring. The AspectJ runtime itself is +responsible for aspect creation, and the means of configuring the AspectJ created +aspects via Spring depends on the AspectJ instantiation model (the '++per-xxx++' clause) +used by the aspect. + +The majority of AspectJ aspects are __singleton__ aspects. Configuration of these +aspects is very easy: simply create a bean definition referencing the aspect type as +normal, and include the bean attribute `'factory-method="aspectOf"'`. This ensures that +Spring obtains the aspect instance by asking AspectJ for it rather than trying to create +an instance itself. For example: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + +---- + +Non-singleton aspects are harder to configure: however it is possible to do so by +creating prototype bean definitions and using the `@Configurable` support from +`spring-aspects.jar` to configure the aspect instances once they have bean created by +the AspectJ runtime. + +If you have some @AspectJ aspects that you want to weave with AspectJ (for example, +using load-time weaving for domain model types) and other @AspectJ aspects that you want +to use with Spring AOP, and these aspects are all configured using Spring, then you will +need to tell the Spring AOP @AspectJ autoproxying support which exact subset of the +@AspectJ aspects defined in the configuration should be used for autoproxying. You can +do this by using one or more `` elements inside the `` +declaration. Each `` element specifies a name pattern, and only beans with +names matched by at least one of the patterns will be used for Spring AOP autoproxy +configuration: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + +---- + +[NOTE] +==== +Do not be misled by the name of the `` element: using it will +result in the creation of __Spring AOP proxies__. The @AspectJ style of aspect +declaration is just being used here, but the AspectJ runtime is __not__ involved. +==== + + + +[[aop-aj-ltw]] +==== Load-time weaving with AspectJ in the Spring Framework +Load-time weaving (LTW) refers to the process of weaving AspectJ aspects into an +application's class files as they are being loaded into the Java virtual machine (JVM). +The focus of this section is on configuring and using LTW in the specific context of the +Spring Framework: this section is not an introduction to LTW though. For full details on +the specifics of LTW and configuring LTW with just AspectJ (with Spring not being +involved at all), see the +http://www.eclipse.org/aspectj/doc/released/devguide/ltw.html[LTW section of the AspectJ +Development Environment Guide]. + +The value-add that the Spring Framework brings to AspectJ LTW is in enabling much +finer-grained control over the weaving process. 'Vanilla' AspectJ LTW is effected using +a Java (5+) agent, which is switched on by specifying a VM argument when starting up a +JVM. It is thus a JVM-wide setting, which may be fine in some situations, but often is a +little too coarse. Spring-enabled LTW enables you to switch on LTW on a +__per-ClassLoader__ basis, which obviously is more fine-grained and which can make more +sense in a 'single-JVM-multiple-application' environment (such as is found in a typical +application server environment). + +Further, <>, this support enables +load-time weaving __without making any modifications to the application server's launch +script__ that will be needed to add `-javaagent:path/to/aspectjweaver.jar` or (as we +describe later in this section) +`-javaagent:path/to/org.springframework.instrument-{version}.jar` (previously named +`spring-agent.jar`). Developers simply modify one or more files that form the +application context to enable load-time weaving instead of relying on administrators who +typically are in charge of the deployment configuration such as the launch script. + +Now that the sales pitch is over, let us first walk through a quick example of AspectJ +LTW using Spring, followed by detailed specifics about elements introduced in the +following example. For a complete example, please see the +https://github.com/spring-projects/spring-petclinic[Petclinic sample application]. + + +[[aop-aj-ltw-first-example]] +===== A first example +Let us assume that you are an application developer who has been tasked with diagnosing +the cause of some performance problems in a system. Rather than break out a profiling +tool, what we are going to do is switch on a simple profiling aspect that will enable us +to very quickly get some performance metrics, so that we can then apply a finer-grained +profiling tool to that specific area immediately afterwards. + +[NOTE] +==== +The example presented here uses XML style configuration, it is also possible to +configure and use @AspectJ with <>. Specifically the +`@EnableLoadTimeWeaving` annotation can be used as an alternative to +`` (see <> for details). +==== + +Here is the profiling aspect. Nothing too fancy, just a quick-and-dirty time-based +profiler, using the @AspectJ-style of aspect declaration. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + package foo; + + import org.aspectj.lang.ProceedingJoinPoint; + import org.aspectj.lang.annotation.Aspect; + import org.aspectj.lang.annotation.Around; + import org.aspectj.lang.annotation.Pointcut; + import org.springframework.util.StopWatch; + import org.springframework.core.annotation.Order; + + @Aspect + public class ProfilingAspect { + + @Around("methodsToBeProfiled()") + public Object profile(ProceedingJoinPoint pjp) throws Throwable { + StopWatch sw = new StopWatch(getClass().getSimpleName()); + try { + sw.start(pjp.getSignature().getName()); + return pjp.proceed(); + } finally { + sw.stop(); + System.out.println(sw.prettyPrint()); + } + } + + @Pointcut("execution(public * foo..*.*(..))") + public void methodsToBeProfiled(){} + } +---- + +We will also need to create an '++META-INF/aop.xml++' file, to inform the AspectJ weaver +that we want to weave our `ProfilingAspect` into our classes. This file convention, +namely the presence of a file (or files) on the Java classpath called +'++META-INF/aop.xml++' is standard AspectJ. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + + + + + + + +---- + +Now to the Spring-specific portion of the configuration. We need to configure a +`LoadTimeWeaver` (all explained later, just take it on trust for now). This load-time +weaver is the essential component responsible for weaving the aspect configuration in +one or more '++META-INF/aop.xml++' files into the classes in your application. The good +thing is that it does not require a lot of configuration, as can be seen below (there +are some more options that you can specify, but these are detailed later). + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + **** + +---- + +Now that all the required artifacts are in place - the aspect, the '++META-INF/aop.xml++' +file, and the Spring configuration -, let us create a simple driver class with a +`main(..)` method to demonstrate the LTW in action. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + package foo; + + import org.springframework.context.support.ClassPathXmlApplicationContext; + + public final class Main { + + public static void main(String[] args) { + + ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml", Main.class); + + EntitlementCalculationService entitlementCalculationService + = (EntitlementCalculationService) ctx.getBean("entitlementCalculationService"); + + // the profiling aspect is 'woven' around this method execution + entitlementCalculationService.calculateEntitlement(); + } + } +---- + +There is one last thing to do. The introduction to this section did say that one could +switch on LTW selectively on a per- `ClassLoader` basis with Spring, and this is true. +However, just for this example, we are going to use a Java agent (supplied with Spring) +to switch on the LTW. This is the command line we will use to run the above `Main` class: + +[literal] +[subs="verbatim,quotes"] +---- +java -javaagent:C:/projects/foo/lib/global/spring-instrument.jar foo.Main +---- + +The '++-javaagent++' is a flag for specifying and enabling +http://docs.oracle.com/javase/6/docs/api/java/lang/instrument/package-summary.html[agents +to instrument programs running on the JVM]. The Spring Framework ships with such an +agent, the `InstrumentationSavingAgent`, which is packaged in the +`spring-instrument.jar` that was supplied as the value of the `-javaagent` argument in +the above example. + +The output from the execution of the `Main` program will look something like that below. +(I have introduced a `Thread.sleep(..)` statement into the `calculateEntitlement()` +implementation so that the profiler actually captures something other than 0 +milliseconds - the `01234` milliseconds is __not__ an overhead introduced by the AOP :) ) + +[literal] +[subs="verbatim,quotes"] +---- +Calculating entitlement + +StopWatch 'ProfilingAspect': running time (millis) = 1234 +------ ----- ---------------------------- +ms % Task name +------ ----- ---------------------------- +01234 100% calculateEntitlement +---- + +Since this LTW is effected using full-blown AspectJ, we are not just limited to advising +Spring beans; the following slight variation on the `Main` program will yield the same +result. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + package foo; + + import org.springframework.context.support.ClassPathXmlApplicationContext; + + public final class Main { + + public static void main(String[] args) { + + new ClassPathXmlApplicationContext("beans.xml", Main.class); + + EntitlementCalculationService entitlementCalculationService = + new StubEntitlementCalculationService(); + + // the profiling aspect will be 'woven' around this method execution + entitlementCalculationService.calculateEntitlement(); + } + } +---- + +Notice how in the above program we are simply bootstrapping the Spring container, and +then creating a new instance of the `StubEntitlementCalculationService` totally outside +the context of Spring... the profiling advice still gets woven in. + +The example admittedly is simplistic... however the basics of the LTW support in Spring +have all been introduced in the above example, and the rest of this section will explain +the 'why' behind each bit of configuration and usage in detail. + +[NOTE] +==== +The `ProfilingAspect` used in this example may be basic, but it is quite useful. It is a +nice example of a development-time aspect that developers can use during development (of +course), and then quite easily exclude from builds of the application being deployed +into UAT or production. +==== + + +[[aop-aj-ltw-the-aspects]] +===== Aspects +The aspects that you use in LTW have to be AspectJ aspects. They can be written in +either the AspectJ language itself or you can write your aspects in the @AspectJ-style. +It means that your aspects are then both valid AspectJ __and__ Spring AOP aspects. +Furthermore, the compiled aspect classes need to be available on the classpath. + + +[[aop-aj-ltw-aop_dot_xml]] +===== 'META-INF/aop.xml' + +The AspectJ LTW infrastructure is configured using one or more '++META-INF/aop.xml++' +files, that are on the Java classpath (either directly, or more typically in jar files). + +The structure and contents of this file is detailed in the main AspectJ reference +documentation, and the interested reader is +http://www.eclipse.org/aspectj/doc/released/devguide/ltw-configuration.html[referred to +that resource]. (I appreciate that this section is brief, but the '++aop.xml++' file is +100% AspectJ - there is no Spring-specific information or semantics that apply to it, +and so there is no extra value that I can contribute either as a result), so rather than +rehash the quite satisfactory section that the AspectJ developers wrote, I am just +directing you there.) + + +[[aop-aj-ltw-libraries]] +===== Required libraries (JARS) +At a minimum you will need the following libraries to use the Spring Framework's support +for AspectJ LTW: + +* `spring-aop.jar` (version 2.5 or later, plus all mandatory dependencies) +* `aspectjweaver.jar` (version 1.6.8 or later) + +If you are using the <>, you will also need: + +* `spring-instrument.jar` + + +[[aop-aj-ltw-spring]] +===== Spring configuration +The key component in Spring's LTW support is the `LoadTimeWeaver` interface (in the +`org.springframework.instrument.classloading` package), and the numerous implementations +of it that ship with the Spring distribution. A `LoadTimeWeaver` is responsible for +adding one or more `java.lang.instrument.ClassFileTransformers` to a `ClassLoader` at +runtime, which opens the door to all manner of interesting applications, one of which +happens to be the LTW of aspects. + +[TIP] +==== + +If you are unfamiliar with the idea of runtime class file transformation, you are +encouraged to read the javadoc API documentation for the `java.lang.instrument` package +before continuing. This is not a huge chore because there is - rather annoyingly - +precious little documentation there... the key interfaces and classes will at least be +laid out in front of you for reference as you read through this section. +==== + +Configuring a `LoadTimeWeaver` for a particular `ApplicationContext` can be as easy as +adding one line. (Please note that you almost certainly will need to be using an +`ApplicationContext` as your Spring container - typically a `BeanFactory` will not be +enough because the LTW support makes use of `BeanFactoryPostProcessors`.) + +To enable the Spring Framework's LTW support, you need to configure a `LoadTimeWeaver`, +which typically is done using the `@EnableLoadTimeWeaving` annotation. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Configuration + @EnableLoadTimeWeaving + public class AppConfig { + + } +---- + +Alternatively, if you prefer XML based configuration, use the +`` element. Note that the element is defined in the +'++context++' namespace. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + +---- + +The above configuration will define and register a number of LTW-specific infrastructure +beans for you automatically, such as a `LoadTimeWeaver` and an `AspectJWeavingEnabler`. +The default `LoadTimeWeaver` is the `DefaultContextLoadTimeWeaver` class, which attempts +to decorate an automatically detected `LoadTimeWeaver`: the exact type of +`LoadTimeWeaver` that will be 'automatically detected' is dependent upon your runtime +environment (summarized in the following table). + +[[aop-aj-ltw-spring-env-impls]] +.DefaultContextLoadTimeWeaver LoadTimeWeavers +|=== +| Runtime Environment| `LoadTimeWeaver` implementation + +| Running in + http://www.bea.com/framework.jsp?CNT=index.htm&FP=/content/products/weblogic/server[BEA's + Weblogic 10] +| `WebLogicLoadTimeWeaver` + +| Running in http://www-01.ibm.com/software/webservers/appserv/was/[IBM WebSphere + Application Server 7] +| `WebSphereLoadTimeWeaver` + +| Running in http://glassfish.dev.java.net/[GlassFish] +| `GlassFishLoadTimeWeaver` + +| Running in http://www.jboss.org/jbossas/[JBoss AS] +| `JBossLoadTimeWeaver` + +| JVM started with Spring `InstrumentationSavingAgent` __(java + -javaagent:path/to/spring-instrument.jar)__ +| `InstrumentationLoadTimeWeaver` + +| Fallback, expecting the underlying ClassLoader to follow common conventions (e.g. + applicable to `TomcatInstrumentableClassLoader` and http://www.caucho.com/[Resin]) +| `ReflectiveLoadTimeWeaver` +|=== + +Note that these are just the `LoadTimeWeavers` that are autodetected when using the +`DefaultContextLoadTimeWeaver`: it is of course possible to specify exactly which +`LoadTimeWeaver` implementation that you wish to use. + +To specify a specific `LoadTimeWeaver` with Java configuration implement the +`LoadTimeWeavingConfigurer` interface and override the `getLoadTimeWeaver()` method: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Configuration + @EnableLoadTimeWeaving + public class AppConfig implements LoadTimeWeavingConfigurer { + + @Override + public LoadTimeWeaver getLoadTimeWeaver() { + return new ReflectiveLoadTimeWeaver(); + } + } +---- + +If you are using XML based configuration you can specify the fully-qualified classname +as the value of the '++weaver-class++' attribute on the `` +element: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + +---- + +The `LoadTimeWeaver` that is defined and registered by the configuration can be later +retrieved from the Spring container using the well-known name '++loadTimeWeaver++'. +Remember that the `LoadTimeWeaver` exists just as a mechanism for Spring's LTW +infrastructure to add one or more `ClassFileTransformers`. The actual +`ClassFileTransformer` that does the LTW is the `ClassPreProcessorAgentAdapter` (from +the `org.aspectj.weaver.loadtime` package) class. See the class-level javadocs of the +`ClassPreProcessorAgentAdapter` class for further details, because the specifics of how +the weaving is actually effected is beyond the scope of this section. + +There is one final attribute of the configuration left to discuss: the +'++aspectjWeaving++' attribute (or '++aspectj-weaving++' if you are using XML). This is a +simple attribute that controls whether LTW is enabled or not; it is as simple as that. +It accepts one of three possible values, summarized below, with the default value being +'++autodetect++' if the attribute is not present. + +[[aop-aj-ltw-ltw-tag-attrs]] +.AspectJ weaving attribute values +|=== +| Annotation Value| XML Value| Explanation + +| `ENABLED` +| `on` +| AspectJ weaving is on, and aspects will be woven at load-time as appropriate. + +| `DISABLED` +| `off` +| LTW is off... no aspect will be woven at load-time. + +| `AUTODETECT` +| `autodetect` +| If the Spring LTW infrastructure can find at least one '++META-INF/aop.xml++' file, + then AspectJ weaving is on, else it is off. This is the default value. +|=== + + +[[aop-aj-ltw-environments]] +===== Environment-specific configuration +This last section contains any additional settings and configuration that you will need +when using Spring's LTW support in environments such as application servers and web +containers. + +[[aop-aj-ltw-environment-tomcat]] +====== Tomcat +http://tomcat.apache.org/[Apache Tomcat]'s default class loader does not support class +transformation which is why Spring provides an enhanced implementation that addresses +this need. Named `TomcatInstrumentableClassLoader`, the loader works on Tomcat 5.0 and +above and can be registered individually for __each__ web application as follows: + +* Tomcat 6.0.x or higher +* Copy `org.springframework.instrument.tomcat.jar` into __$CATALINA_HOME__/lib, where + __$CATALINA_HOME__ represents the root of the Tomcat installation) +* Instruct Tomcat to use the custom class loader (instead of the default) by editing the + web application context file: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + +---- + +Apache Tomcat (6.0+) supports several context locations: + +* server configuration file - __$CATALINA_HOME/conf/server.xml__ +* default context configuration - __$CATALINA_HOME/conf/context.xml__ - that affects all + deployed web applications +* per-web application configuration which can be deployed either on the server-side at + __$CATALINA_HOME/conf/[enginename]/[hostname]/[webapp]-context.xml__ or embedded + inside the web-app archive at __META-INF/context.xml__ + +For efficiency, the embedded per-web-app configuration style is recommended because it +will impact only applications that use the custom class loader and does not require any +changes to the server configuration. See the Tomcat 6.0.x +http://tomcat.apache.org/tomcat-6.0-doc/config/context.html[documentation] for more +details about available context locations. + +Alternatively, consider the use of the Spring-provided generic VM agent, to be specified +in Tomcat's launch script (see above). This will make instrumentation available to all +deployed web applications, no matter what ClassLoader they happen to run on. + +[[aop-aj-ltw-environments-weblogic-oc4j-resin-glassfish-jboss]] +====== WebLogic, WebSphere, Resin, GlassFish, JBoss +Recent versions of WebLogic Server (version 10 and above), IBM WebSphere Application +Server (version 7 and above), Resin (3.1 and above) and JBoss (6.x or above) provide a +ClassLoader that is capable of local instrumentation. Spring's native LTW leverages such +ClassLoaders to enable AspectJ weaving. You can enable LTW by simply activating +load-time weaving as described earlier. Specifically, you do __not__ need to modify the +launch script to add `-javaagent:path/to/spring-instrument.jar`. + +Note that GlassFish instrumentation-capable ClassLoader is available only in its EAR +environment. For GlassFish web applications, follow the Tomcat setup instructions as +outlined above. + +Note that on JBoss 6.x, the app server scanning needs to be disabled to prevent it from +loading the classes before the application actually starts. A quick workaround is to add +to your artifact a file named `WEB-INF/jboss-scanning.xml` with the following content: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + +---- + +[[aop-aj-ltw-environment-generic]] +====== Generic Java applications +When class instrumentation is required in environments that do not support or are not +supported by the existing `LoadTimeWeaver` implementations, a JDK agent can be the only +solution. For such cases, Spring provides `InstrumentationLoadTimeWeaver`, which +requires a Spring-specific (but very general) VM agent, +`org.springframework.instrument-{version}.jar` (previously named `spring-agent.jar`). + +To use it, you must start the virtual machine with the Spring agent, by supplying the +following JVM options: + +[literal] +[subs="verbatim,quotes"] +---- +-javaagent:/path/to/org.springframework.instrument-{version}.jar +---- + +Note that this requires modification of the VM launch script which may prevent you from +using this in application server environments (depending on your operation policies). +Additionally, the JDK agent will instrument the __entire__ VM which can prove expensive. + +For performance reasons, it is recommended to use this configuration only if your target +environment (such as http://www.eclipse.org/jetty/[Jetty]) does not have (or does not +support) a dedicated LTW. + + + + +[[aop-resources]] +=== Further Resources +More information on AspectJ can be found on the http://www.eclipse.org/aspectj[AspectJ +website]. + +The book __Eclipse AspectJ__ by Adrian Colyer et. al. (Addison-Wesley, 2005) provides a +comprehensive introduction and reference for the AspectJ language. + +The book __AspectJ in Action__ by Ramnivas Laddad (Manning, 2003) comes highly +recommended; the focus of the book is on AspectJ, but a lot of general AOP themes are +explored (in some depth). diff --git a/src/asciidoc/appendix.adoc b/src/asciidoc/appendix.adoc deleted file mode 100644 index cf46a041655e..000000000000 --- a/src/asciidoc/appendix.adoc +++ /dev/null @@ -1,6628 +0,0 @@ -[[spring-appendices]] -= Appendices - - - - - -[[migration-4.0]] -== Migrating to Spring Framework 4.0 -Migration guides for upgrading from previous releases of the Spring Framework are now -provided as a Wiki page. For details please refer to -https://github.com/spring-projects/spring-framework/wiki/Migrating-from-earlier-versions-of-the-spring-framework - - - - - -[[classic-spring]] -== Classic Spring Usage -This appendix discusses some classic Spring usage patterns as a reference for developers -maintaining legacy Spring applications. These usage patterns no longer reflect the -recommended way of using these features and the current recommended usage is covered in -the respective sections of the reference manual. - - - - -[[classic-spring-orm]] -=== Classic ORM usage -This section documents the classic usage patterns that you might encounter in a legacy -Spring application. For the currently recommended usage patterns, please refer to the -<> chapter. - - - -[[classic-spring-hibernate]] -==== Hibernate -For the currently recommended usage patterns for Hibernate see <> - - -[[orm-hibernate-template]] -===== the HibernateTemplate - -The basic programming model for templating looks as follows, for methods that can be -part of any custom data access object or business service. There are no restrictions on -the implementation of the surrounding object at all, it just needs to provide a -Hibernate `SessionFactory`. It can get the latter from anywhere, but preferably as bean -reference from a Spring IoC container - via a simple `setSessionFactory(..)` bean -property setter. The following snippets show a DAO definition in a Spring container, -referencing the above defined `SessionFactory`, and an example for a DAO method -implementation. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - ----- - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class ProductDaoImpl implements ProductDao { - - private HibernateTemplate hibernateTemplate; - - public void setSessionFactory(SessionFactory sessionFactory) { - this.hibernateTemplate = new HibernateTemplate(sessionFactory); - } - - public Collection loadProductsByCategory(String category) throws DataAccessException { - return this.hibernateTemplate.find("from test.Product product where product.category=?", category); - } - } ----- - -The `HibernateTemplate` class provides many methods that mirror the methods exposed on -the Hibernate `Session` interface, in addition to a number of convenience methods such -as the one shown above. If you need access to the `Session` to invoke methods that are -not exposed on the `HibernateTemplate`, you can always drop down to a callback-based -approach like so. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class ProductDaoImpl implements ProductDao { - - private HibernateTemplate hibernateTemplate; - - public void setSessionFactory(SessionFactory sessionFactory) { - this.hibernateTemplate = new HibernateTemplate(sessionFactory); - } - - public Collection loadProductsByCategory(final String category) throws DataAccessException { - return this.hibernateTemplate.execute(new HibernateCallback() { - public Object doInHibernate(Session session) { - Criteria criteria = session.createCriteria(Product.class); - criteria.add(Expression.eq("category", category)); - criteria.setMaxResults(6); - return criteria.list(); - } - }; - } - - } ----- - -A callback implementation effectively can be used for any Hibernate data access. -`HibernateTemplate` will ensure that `Session` instances are properly opened and closed, -and automatically participate in transactions. The template instances are thread-safe -and reusable, they can thus be kept as instance variables of the surrounding class. For -simple single step actions like a single find, load, saveOrUpdate, or delete call, -`HibernateTemplate` offers alternative convenience methods that can replace such one -line callback implementations. Furthermore, Spring provides a convenient -`HibernateDaoSupport` base class that provides a `setSessionFactory(..)` method for -receiving a `SessionFactory`, and `getSessionFactory()` and `getHibernateTemplate()` for -use by subclasses. In combination, this allows for very simple DAO implementations for -typical requirements: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class ProductDaoImpl extends HibernateDaoSupport implements ProductDao { - - public Collection loadProductsByCategory(String category) throws DataAccessException { - return this.getHibernateTemplate().find( - "from test.Product product where product.category=?", category); - } - - } ----- - - -[[orm-hibernate-daos]] -===== Implementing Spring-based DAOs without callbacks -As alternative to using Spring's `HibernateTemplate` to implement DAOs, data access code -can also be written in a more traditional fashion, without wrapping the Hibernate access -code in a callback, while still respecting and participating in Spring's generic -`DataAccessException` hierarchy. The `HibernateDaoSupport` base class offers methods to -access the current transactional `Session` and to convert exceptions in such a scenario; -similar methods are also available as static helpers on the `SessionFactoryUtils` class. -Note that such code will usually pass ' `false`' as the value of the `getSession(..)` -methods ' `allowCreate`' argument, to enforce running within a transaction (which avoids -the need to close the returned `Session`, as its lifecycle is managed by the -transaction). - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class HibernateProductDao extends HibernateDaoSupport implements ProductDao { - - public Collection loadProductsByCategory(String category) throws DataAccessException, MyException { - Session session = getSession(false); - try { - Query query = session.createQuery("from test.Product product where product.category=?"); - query.setString(0, category); - List result = query.list(); - if (result == null) { - throw new MyException("No search results."); - } - return result; - } - catch (HibernateException ex) { - throw convertHibernateAccessException(ex); - } - } - } ----- - -The advantage of such direct Hibernate access code is that it allows __any__ checked -application exception to be thrown within the data access code; contrast this to the -`HibernateTemplate` class which is restricted to throwing only unchecked exceptions -within the callback. Note that you can often defer the corresponding checks and the -throwing of application exceptions to after the callback, which still allows working -with `HibernateTemplate`. In general, the `HibernateTemplate` class' convenience methods -are simpler and more convenient for many scenarios. - - - -[[classic-spring-jdo]] -==== JDO -For the currently recommended usage patterns for JDO see <> - - -[[orm-jdo-template]] -===== JdoTemplate and `JdoDaoSupport` - -Each JDO-based DAO will then receive the `PersistenceManagerFactory` through dependency -injection. Such a DAO could be coded against plain JDO API, working with the given -`PersistenceManagerFactory`, but will usually rather be used with the Spring Framework's -`JdoTemplate`: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - ----- - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class ProductDaoImpl implements ProductDao { - - private JdoTemplate jdoTemplate; - - public void setPersistenceManagerFactory(PersistenceManagerFactory pmf) { - this.jdoTemplate = new JdoTemplate(pmf); - } - - public Collection loadProductsByCategory(final String category) throws DataAccessException { - return (Collection) this.jdoTemplate.execute(new JdoCallback() { - public Object doInJdo(PersistenceManager pm) throws JDOException { - Query query = pm.newQuery(Product.class, "category = pCategory"); - query.declareParameters("String pCategory"); - List result = query.execute(category); - // do some further stuff with the result list - return result; - } - }); - } - - } ----- - -A callback implementation can effectively be used for any JDO data access. `JdoTemplate` -will ensure that `PersistenceManager` s are properly opened and closed, and -automatically participate in transactions. The template instances are thread-safe and -reusable, they can thus be kept as instance variables of the surrounding class. For -simple single-step actions such as a single `find`, `load`, `makePersistent`, or -`delete` call, `JdoTemplate` offers alternative convenience methods that can replace -such one line callback implementations. Furthermore, Spring provides a convenient -`JdoDaoSupport` base class that provides a `setPersistenceManagerFactory(..)` method for -receiving a `PersistenceManagerFactory`, and `getPersistenceManagerFactory()` and -`getJdoTemplate()` for use by subclasses. In combination, this allows for very simple -DAO implementations for typical requirements: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class ProductDaoImpl extends JdoDaoSupport implements ProductDao { - - public Collection loadProductsByCategory(String category) throws DataAccessException { - return getJdoTemplate().find(Product.class, - "category = pCategory", "String category", new Object[] {category}); - } - - } ----- - -As alternative to working with Spring's `JdoTemplate`, you can also code Spring-based -DAOs at the JDO API level, explicitly opening and closing a `PersistenceManager`. As -elaborated in the corresponding Hibernate section, the main advantage of this approach -is that your data access code is able to throw checked exceptions. `JdoDaoSupport` -offers a variety of support methods for this scenario, for fetching and releasing a -transactional `PersistenceManager` as well as for converting exceptions. - - - -[[classic-spring-jpa]] -==== JPA -For the currently recommended usage patterns for JPA see <> - - -[[orm-jpa-template]] -===== JpaTemplate and `JpaDaoSupport` - -Each JPA-based DAO will then receive a `EntityManagerFactory` via dependency injection. -Such a DAO can be coded against plain JPA and work with the given `EntityManagerFactory` -or through Spring's `JpaTemplate`: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - ----- - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class JpaProductDao implements ProductDao { - - private JpaTemplate jpaTemplate; - - public void setEntityManagerFactory(EntityManagerFactory emf) { - this.jpaTemplate = new JpaTemplate(emf); - } - - public Collection loadProductsByCategory(final String category) throws DataAccessException { - return (Collection) this.jpaTemplate.execute(new JpaCallback() { - public Object doInJpa(EntityManager em) throws PersistenceException { - Query query = em.createQuery("from Product as p where p.category = :category"); - query.setParameter("category", category); - List result = query.getResultList(); - // do some further processing with the result list - return result; - } - }); - } - - } ----- - -The `JpaCallback` implementation allows any type of JPA data access. The `JpaTemplate` -will ensure that `EntityManager` s are properly opened and closed and automatically -participate in transactions. Moreover, the `JpaTemplate` properly handles exceptions, -making sure resources are cleaned up and the appropriate transactions rolled back. The -template instances are thread-safe and reusable and they can be kept as instance -variable of the enclosing class. Note that `JpaTemplate` offers single-step actions such -as find, load, merge, etc along with alternative convenience methods that can replace -one line callback implementations. - -Furthermore, Spring provides a convenient `JpaDaoSupport` base class that provides the -`get/setEntityManagerFactory` and `getJpaTemplate()` to be used by subclasses: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class ProductDaoImpl extends JpaDaoSupport implements ProductDao { - - public Collection loadProductsByCategory(String category) throws DataAccessException { - Map params = new HashMap(); - params.put("category", category); - return getJpaTemplate().findByNamedParams("from Product as p where p.category = :category", params); - } - - } ----- - -Besides working with Spring's `JpaTemplate`, one can also code Spring-based DAOs against -the JPA, doing one's own explicit `EntityManager` handling. As also elaborated in the -corresponding Hibernate section, the main advantage of this approach is that your data -access code is able to throw checked exceptions. `JpaDaoSupport` offers a variety of -support methods for this scenario, for retrieving and releasing a transaction -`EntityManager`, as well as for converting exceptions. - -__JpaTemplate mainly exists as a sibling of JdoTemplate and HibernateTemplate, offering -the same style for people used to it.__ - - - - -[[clasic-spring-mvc]] -=== Classic Spring MVC -... - - - - -[[classic-spring-jms]] -=== JMS Usage - -One of the benefits of Spring's JMS support is to shield the user from differences -between the JMS 1.0.2 and 1.1 APIs. (For a description of the differences between the -two APIs see sidebar on Domain Unification). Since it is now common to encounter only -the JMS 1.1 API the use of classes that are based on the JMS 1.0.2 API has been -deprecated in Spring 3.0. This section describes Spring JMS support for the JMS 1.0.2 -deprecated classes. - -.Domain Unification -**** -There are two major releases of the JMS specification, 1.0.2 and 1.1. - -JMS 1.0.2 defined two types of messaging domains, point-to-point (Queues) and -publish/subscribe (Topics). The 1.0.2 API reflected these two messaging domains by -providing a parallel class hierarchy for each domain. As a result, a client application -became domain specific in its use of the JMS API. JMS 1.1 introduced the concept of -domain unification that minimized both the functional differences and client API -differences between the two domains. As an example of a functional difference that was -removed, if you use a JMS 1.1 provider you can transactionally consume a message from -one domain and produce a message on the other using the same `Session`. - -[NOTE] -==== -The JMS 1.1 specification was released in April 2002 and incorporated as part of J2EE -1.4 in November 2003. As a result, common J2EE 1.3 application servers which are still -in widespread use (such as BEA WebLogic 8.1 and IBM WebSphere 5.1) are based on JMS -1.0.2. -==== -**** - - - -[[classic-spring-jms-template]] -==== JmsTemplate -Located in the package `org.springframework.jms.core` the class `JmsTemplate102` -provides all of the features of the `JmsTemplate` described the JMS chapter, but is -based on the JMS 1.0.2 API instead of the JMS 1.1 API. As a consequence, if you are -using JmsTemplate102 you need to set the boolean property `pubSubDomain` to configure -the `JmsTemplate` with knowledge of what JMS domain is being used. By default the value -of this property is false, indicating that the point-to-point domain, Queues, will be -used. - - - -[[classic-spring-aysnc-messages]] -==== Asynchronous Message Reception -<> are used in -conjunction with Spring's <> to support -asynchronous message reception by exposing almost any class as a Message-driven POJO. If -you are using the JMS 1.0.2 API, you will want to use the 1.0.2 specific classes such as -`MessageListenerAdapter102`, `SimpleMessageListenerContainer102`, and -`DefaultMessageListenerContainer102`. These classes provide the same functionality as -the JMS 1.1 based counterparts but rely only on the JMS 1.0.2 API. - - - -[[classic-spring-jms-connections]] -==== Connections -The `ConnectionFactory` interface is part of the JMS specification and serves as the -entry point for working with JMS. Spring provides an implementation of the -`ConnectionFactory` interface, `SingleConnectionFactory102`, based on the JMS 1.0.2 API -that will return the same `Connection` on all `createConnection()` calls and ignore -calls to `close()`. You will need to set the boolean property `pubSubDomain` to indicate -which messaging domain is used as `SingleConnectionFactory102` will always explicitly -differentiate between a `javax.jms.QueueConnection` and a `javax.jmsTopicConnection`. - - - -[[classic-spring-jms-tx-management]] -==== Transaction Management -In a JMS 1.0.2 environment the class `JmsTransactionManager102` provides support for -managing JMS transactions for a single Connection Factory. Please refer to the reference -documentation on <> for more information on this -functionality. - - - - - -[[classic-aop-spring]] -== Classic Spring AOP Usage -In this appendix we discuss the lower-level Spring AOP APIs and the AOP support used in -Spring 1.2 applications. For new applications, we recommend the use of the Spring 2.0 -AOP support described in the <> chapter, but when working with existing -applications, or when reading books and articles, you may come across Spring 1.2 style -examples. Spring 2.0 is fully backwards compatible with Spring 1.2 and everything -described in this appendix is fully supported in Spring 2.0. - - - - -[[classic-aop-api-pointcuts]] -=== Pointcut API in Spring -Let's look at how Spring handles the crucial pointcut concept. - - - -[[classic-aop-api-concepts]] -==== Concepts -Spring's pointcut model enables pointcut reuse independent of advice types. It's -possible to target different advice using the same pointcut. - -The `org.springframework.aop.Pointcut` interface is the central interface, used to -target advices to particular classes and methods. The complete interface is shown below: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public interface Pointcut { - - ClassFilter getClassFilter(); - - MethodMatcher getMethodMatcher(); - - } ----- - -Splitting the `Pointcut` interface into two parts allows reuse of class and method -matching parts, and fine-grained composition operations (such as performing a "union" -with another method matcher). - -The `ClassFilter` interface is used to restrict the pointcut to a given set of target -classes. If the `matches()` method always returns true, all target classes will be -matched: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public interface ClassFilter { - - boolean matches(Class clazz); - - } ----- - -The `MethodMatcher` interface is normally more important. The complete interface is -shown below: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public interface MethodMatcher { - - boolean matches(Method m, Class targetClass); - - boolean isRuntime(); - - boolean matches(Method m, Class targetClass, Object[] args); - - } ----- - -The `matches(Method, Class)` method is used to test whether this pointcut will ever -match a given method on a target class. This evaluation can be performed when an AOP -proxy is created, to avoid the need for a test on every method invocation. If the -2-argument matches method returns true for a given method, and the `isRuntime()` method -for the MethodMatcher returns true, the 3-argument matches method will be invoked on -every method invocation. This enables a pointcut to look at the arguments passed to the -method invocation immediately before the target advice is to execute. - -Most MethodMatchers are static, meaning that their `isRuntime()` method returns false. -In this case, the 3-argument matches method will never be invoked. - -[TIP] -==== - -If possible, try to make pointcuts static, allowing the AOP framework to cache the -results of pointcut evaluation when an AOP proxy is created. -==== - - - -[[classic-aop-api-pointcut-ops]] -==== Operations on pointcuts -Spring supports operations on pointcuts: notably, __union__ and __intersection__. - -* Union means the methods that either pointcut matches. -* Intersection means the methods that both pointcuts match. -* Union is usually more useful. -* Pointcuts can be composed using the static methods in the - __org.springframework.aop.support.Pointcuts__ class, or using the - __ComposablePointcut__ class in the same package. However, using AspectJ pointcut - expressions is usually a simpler approach. - - - -[[classic-aop-api-pointcuts-aspectj]] -==== AspectJ expression pointcuts -Since 2.0, the most important type of pointcut used by Spring is -`org.springframework.aop.aspectj.AspectJExpressionPointcut`. This is a pointcut that -uses an AspectJ supplied library to parse an AspectJ pointcut expression string. - -See the previous chapter for a discussion of supported AspectJ pointcut primitives. - - - -[[classic-aop-api-pointcuts-impls]] -==== Convenience pointcut implementations -Spring provides several convenient pointcut implementations. Some can be used out of the -box; others are intended to be subclassed in application-specific pointcuts. - - -[[classic-aop-api-pointcuts-static]] -===== Static pointcuts -Static pointcuts are based on method and target class, and cannot take into account the -method's arguments. Static pointcuts are sufficient - __and best__ - for most usages. -It's possible for Spring to evaluate a static pointcut only once, when a method is first -invoked: after that, there is no need to evaluate the pointcut again with each method -invocation. - -Let's consider some static pointcut implementations included with Spring. - -[[classic-aop-api-pointcuts-regex]] -====== Regular expression pointcuts -One obvious way to specify static pointcuts is regular expressions. Several AOP -frameworks besides Spring make this possible. -`org.springframework.aop.support.Perl5RegexpMethodPointcut` is a generic regular -expression pointcut, using Perl 5 regular expression syntax. The -`Perl5RegexpMethodPointcut` class depends on Jakarta ORO for regular expression -matching. Spring also provides the `JdkRegexpMethodPointcut` class that uses the regular -expression support in JDK 1.4+. - -Using the `Perl5RegexpMethodPointcut` class, you can provide a list of pattern Strings. -If any of these is a match, the pointcut will evaluate to true. (So the result is -effectively the union of these pointcuts.) - -The usage is shown below: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - .*set.* - .*absquatulate - - - ----- - -Spring provides a convenience class, `RegexpMethodPointcutAdvisor`, that allows us to -also reference an Advice (remember that an Advice can be an interceptor, before advice, -throws advice etc.). Behind the scenes, Spring will use a `JdkRegexpMethodPointcut`. -Using `RegexpMethodPointcutAdvisor` simplifies wiring, as the one bean encapsulates both -pointcut and advice, as shown below: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - .*set.* - .*absquatulate - - - ----- - -__RegexpMethodPointcutAdvisor__ can be used with any Advice type. - -[[classic-aop-api-pointcuts-attribute-driven]] -====== Attribute-driven pointcuts -An important type of static pointcut is a __metadata-driven__ pointcut. This uses the -values of metadata attributes: typically, source-level metadata. - - -[[classic-aop-api-pointcuts-dynamic]] -===== Dynamic pointcuts -Dynamic pointcuts are costlier to evaluate than static pointcuts. They take into account -method__arguments__, as well as static information. This means that they must be -evaluated with every method invocation; the result cannot be cached, as arguments will -vary. - -The main example is the `control flow` pointcut. - -[[classic-aop-api-pointcuts-cflow]] -====== Control flow pointcuts -Spring control flow pointcuts are conceptually similar to AspectJ __cflow__ pointcuts, -although less powerful. (There is currently no way to specify that a pointcut executes -below a join point matched by another pointcut.) A control flow pointcut matches the -current call stack. For example, it might fire if the join point was invoked by a method -in the `com.mycompany.web` package, or by the `SomeCaller` class. Control flow pointcuts -are specified using the `org.springframework.aop.support.ControlFlowPointcut` class. -[NOTE] -==== -Control flow pointcuts are significantly more expensive to evaluate at runtime than even -other dynamic pointcuts. In Java 1.4, the cost is about 5 times that of other dynamic -pointcuts. -==== - - - -[[classic-aop-api-pointcuts-superclasses]] -==== Pointcut superclasses -Spring provides useful pointcut superclasses to help you to implement your own pointcuts. - -Because static pointcuts are most useful, you'll probably subclass -StaticMethodMatcherPointcut, as shown below. This requires implementing just one -abstract method (although it's possible to override other methods to customize behavior): - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - class TestStaticPointcut extends StaticMethodMatcherPointcut { - - public boolean matches(Method m, Class targetClass) { - // return true if custom criteria match - } - - } ----- - -There are also superclasses for dynamic pointcuts. - -You can use custom pointcuts with any advice type in Spring 1.0 RC2 and above. - - - -[[classic-aop-api-pointcuts-custom]] -==== Custom pointcuts -Because pointcuts in Spring AOP are Java classes, rather than language features (as in -AspectJ) it's possible to declare custom pointcuts, whether static or dynamic. Custom -pointcuts in Spring can be arbitrarily complex. However, using the AspectJ pointcut -expression language is recommended if possible. - -[NOTE] -==== -Later versions of Spring may offer support for "semantic pointcuts" as offered by JAC: -for example, "all methods that change instance variables in the target object." -==== - - - - -[[classic-aop-api-advice]] -=== Advice API in Spring -Let's now look at how Spring AOP handles advice. - - - -[[classic-aop-api-advice-lifecycle]] -==== Advice lifecycles -Each advice is a Spring bean. An advice instance can be shared across all advised -objects, or unique to each advised object. This corresponds to __per-class__ or -__per-instance__ advice. - -Per-class advice is used most often. It is appropriate for generic advice such as -transaction advisors. These do not depend on the state of the proxied object or add new -state; they merely act on the method and arguments. - -Per-instance advice is appropriate for introductions, to support mixins. In this case, -the advice adds state to the proxied object. - -It's possible to use a mix of shared and per-instance advice in the same AOP proxy. - - - -[[classic-aop-api-advice-types]] -==== Advice types in Spring -Spring provides several advice types out of the box, and is extensible to support -arbitrary advice types. Let us look at the basic concepts and standard advice types. - - -[[classic-aop-api-advice-around]] -===== Interception around advice -The most fundamental advice type in Spring is __interception around advice__. - -Spring is compliant with the AOP Alliance interface for around advice using method -interception. MethodInterceptors implementing around advice should implement the -following interface: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public interface MethodInterceptor extends Interceptor { - - Object invoke(MethodInvocation invocation) throws Throwable; - - } ----- - -The `MethodInvocation` argument to the `invoke()` method exposes the method being -invoked; the target join point; the AOP proxy; and the arguments to the method. The -`invoke()` method should return the invocation's result: the return value of the join -point. - -A simple `MethodInterceptor` implementation looks as follows: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class DebugInterceptor implements MethodInterceptor { - - public Object invoke(MethodInvocation invocation) throws Throwable { - System.out.println("Before: invocation=[" + invocation + "]"); - Object rval = invocation.proceed(); - System.out.println("Invocation returned"); - return rval; - } - - } ----- - -Note the call to the MethodInvocation's `proceed()` method. This proceeds down the -interceptor chain towards the join point. Most interceptors will invoke this method, and -return its return value. However, a MethodInterceptor, like any around advice, can -return a different value or throw an exception rather than invoke the proceed method. -However, you don't want to do this without good reason! - -[NOTE] -==== -MethodInterceptors offer interoperability with other AOP Alliance-compliant AOP -implementations. The other advice types discussed in the remainder of this section -implement common AOP concepts, but in a Spring-specific way. While there is an advantage -in using the most specific advice type, stick with MethodInterceptor around advice if -you are likely to want to run the aspect in another AOP framework. Note that pointcuts -are not currently interoperable between frameworks, and the AOP Alliance does not -currently define pointcut interfaces. -==== - - -[[classic-aop-api-advice-before]] -===== Before advice -A simpler advice type is a __before advice__. This does not need a `MethodInvocation` -object, since it will only be called before entering the method. - -The main advantage of a before advice is that there is no need to invoke the `proceed()` -method, and therefore no possibility of inadvertently failing to proceed down the -interceptor chain. - -The `MethodBeforeAdvice` interface is shown below. (Spring's API design would allow for -field before advice, although the usual objects apply to field interception and it's -unlikely that Spring will ever implement it). - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public interface MethodBeforeAdvice extends BeforeAdvice { - - void before(Method m, Object[] args, Object target) throws Throwable; - - } ----- - -Note the return type is `void`. Before advice can insert custom behavior before the join -point executes, but cannot change the return value. If a before advice throws an -exception, this will abort further execution of the interceptor chain. The exception -will propagate back up the interceptor chain. If it is unchecked, or on the signature of -the invoked method, it will be passed directly to the client; otherwise it will be -wrapped in an unchecked exception by the AOP proxy. - -An example of a before advice in Spring, which counts all method invocations: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class CountingBeforeAdvice implements MethodBeforeAdvice { - - private int count; - - public void before(Method m, Object[] args, Object target) throws Throwable { - ++count; - } - - public int getCount() { - return count; - } - } ----- - -[TIP] -==== - -Before advice can be used with any pointcut. -==== - - -[[classic-aop-api-advice-throws]] -===== Throws advice -__Throws advice__ is invoked after the return of the join point if the join point threw -an exception. Spring offers typed throws advice. Note that this means that the -`org.springframework.aop.ThrowsAdvice` interface does not contain any methods: It is a -tag interface identifying that the given object implements one or more typed throws -advice methods. These should be in the form of: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - afterThrowing([Method, args, target], subclassOfThrowable) ----- - -Only the last argument is required. The method signatures may have either one or four -arguments, depending on whether the advice method is interested in the method and -arguments. The following classes are examples of throws advice. - -The advice below is invoked if a `RemoteException` is thrown (including subclasses): - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class RemoteThrowsAdvice implements ThrowsAdvice { - - public void afterThrowing(RemoteException ex) throws Throwable { - // Do something with remote exception - } - - } ----- - -The following advice is invoked if a `ServletException` is thrown. Unlike the above -advice, it declares 4 arguments, so that it has access to the invoked method, method -arguments and target object: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class ServletThrowsAdviceWithArguments implements ThrowsAdvice { - - public void afterThrowing(Method m, Object[] args, Object target, ServletException ex) { - // Do something with all arguments - } - - } ----- - -The final example illustrates how these two methods could be used in a single class, -which handles both `RemoteException` and `ServletException`. Any number of throws advice -methods can be combined in a single class. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public static class CombinedThrowsAdvice implements ThrowsAdvice { - - public void afterThrowing(RemoteException ex) throws Throwable { - // Do something with remote exception - } - - public void afterThrowing(Method m, Object[] args, Object target, ServletException ex) { - // Do something with all arguments - } - } ----- - -__Note:__ If a throws-advice method throws an exception itself, it will override the -original exception (i.e. change the exception thrown to the user). The overriding -exception will typically be a RuntimeException; this is compatible with any method -signature. However, if a throws-advice method throws a checked exception, it will have -to match the declared exceptions of the target method and is hence to some degree -coupled to specific target method signatures. __Do not throw an undeclared checked -exception that is incompatible with the target method's signature!__ - -[TIP] -==== - -Throws advice can be used with any pointcut. -==== - - -[[classic-aop-api-advice-after-returning]] -===== After Returning advice -An after returning advice in Spring must implement the -__org.springframework.aop.AfterReturningAdvice__ interface, shown below: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public interface AfterReturningAdvice extends Advice { - - void afterReturning(Object returnValue, Method m, Object[] args, - Object target) throws Throwable; - - } ----- - -An after returning advice has access to the return value (which it cannot modify), -invoked method, methods arguments and target. - -The following after returning advice counts all successful method invocations that have -not thrown exceptions: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class CountingAfterReturningAdvice implements AfterReturningAdvice { - - private int count; - - public void afterReturning(Object returnValue, Method m, Object[] args, - Object target) throws Throwable { - ++count; - } - - public int getCount() { - return count; - } - - } ----- - -This advice doesn't change the execution path. If it throws an exception, this will be -thrown up the interceptor chain instead of the return value. - -[TIP] -==== - -After returning advice can be used with any pointcut. -==== - - -[[classic-aop-api-advice-introduction]] -===== Introduction advice -Spring treats introduction advice as a special kind of interception advice. - -Introduction requires an `IntroductionAdvisor`, and an `IntroductionInterceptor`, -implementing the following interface: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public interface IntroductionInterceptor extends MethodInterceptor { - - boolean implementsInterface(Class intf); - - } ----- - -The `invoke()` method inherited from the AOP Alliance `MethodInterceptor` interface must -implement the introduction: that is, if the invoked method is on an introduced -interface, the introduction interceptor is responsible for handling the method call - it -cannot invoke `proceed()`. - -Introduction advice cannot be used with any pointcut, as it applies only at class, -rather than method, level. You can only use introduction advice with the -`IntroductionAdvisor`, which has the following methods: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public interface IntroductionAdvisor extends Advisor, IntroductionInfo { - - ClassFilter getClassFilter(); - - void validateInterfaces() throws IllegalArgumentException; - - } - - public interface IntroductionInfo { - - Class[] getInterfaces(); - - } ----- - -There is no `MethodMatcher`, and hence no `Pointcut`, associated with introduction -advice. Only class filtering is logical. - -The `getInterfaces()` method returns the interfaces introduced by this advisor. - -The `validateInterfaces()` method is used internally to see whether or not the -introduced interfaces can be implemented by the configured `IntroductionInterceptor`. - -Let's look at a simple example from the Spring test suite. Let's suppose we want to -introduce the following interface to one or more objects: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public interface Lockable { - - void lock(); - - void unlock(); - - boolean locked(); - - } ----- - -This illustrates a __mixin__. We want to be able to cast advised objects to Lockable, -whatever their type, and call lock and unlock methods. If we call the lock() method, we -want all setter methods to throw a `LockedException`. Thus we can add an aspect that -provides the ability to make objects immutable, without them having any knowledge of it: -a good example of AOP. - -Firstly, we'll need an `IntroductionInterceptor` that does the heavy lifting. In this -case, we extend the `org.springframework.aop.support.DelegatingIntroductionInterceptor` -convenience class. We could implement IntroductionInterceptor directly, but using -`DelegatingIntroductionInterceptor` is best for most cases. - -The `DelegatingIntroductionInterceptor` is designed to delegate an introduction to an -actual implementation of the introduced interface(s), concealing the use of interception -to do so. The delegate can be set to any object using a constructor argument; the -default delegate (when the no-arg constructor is used) is this. Thus in the example -below, the delegate is the `LockMixin` subclass of `DelegatingIntroductionInterceptor`. -Given a delegate (by default itself), a `DelegatingIntroductionInterceptor` instance -looks for all interfaces implemented by the delegate (other than -IntroductionInterceptor), and will support introductions against any of them. It's -possible for subclasses such as `LockMixin` to call the `suppressInterface(Class intf)` -method to suppress interfaces that should not be exposed. However, no matter how many -interfaces an `IntroductionInterceptor` is prepared to support, the -`IntroductionAdvisor` used will control which interfaces are actually exposed. An -introduced interface will conceal any implementation of the same interface by the target. - -Thus LockMixin subclasses `DelegatingIntroductionInterceptor` and implements Lockable -itself. The superclass automatically picks up that Lockable can be supported for -introduction, so we don't need to specify that. We could introduce any number of -interfaces in this way. - -Note the use of the `locked` instance variable. This effectively adds additional state -to that held in the target object. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class LockMixin extends DelegatingIntroductionInterceptor implements Lockable { - - private boolean locked; - - public void lock() { - this.locked = true; - } - - public void unlock() { - this.locked = false; - } - - public boolean locked() { - return this.locked; - } - - public Object invoke(MethodInvocation invocation) throws Throwable { - if (locked() && invocation.getMethod().getName().indexOf("set") == 0) { - throw new LockedException(); - } - return super.invoke(invocation); - } - - } ----- - -Often it isn't necessary to override the `invoke()` method: the -`DelegatingIntroductionInterceptor` implementation - which calls the delegate method if -the method is introduced, otherwise proceeds towards the join point - is usually -sufficient. In the present case, we need to add a check: no setter method can be invoked -if in locked mode. - -The introduction advisor required is simple. All it needs to do is hold a distinct -`LockMixin` instance, and specify the introduced interfaces - in this case, just -`Lockable`. A more complex example might take a reference to the introduction -interceptor (which would be defined as a prototype): in this case, there's no -configuration relevant for a `LockMixin`, so we simply create it using `new`. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class LockMixinAdvisor extends DefaultIntroductionAdvisor { - - public LockMixinAdvisor() { - super(new LockMixin(), Lockable.class); - } - - } ----- - -We can apply this advisor very simply: it requires no configuration. (However, it __is__ -necessary: It's impossible to use an `IntroductionInterceptor` without an -__IntroductionAdvisor__.) As usual with introductions, the advisor must be per-instance, -as it is stateful. We need a different instance of `LockMixinAdvisor`, and hence -`LockMixin`, for each advised object. The advisor comprises part of the advised object's -state. - -We can apply this advisor programmatically, using the `Advised.addAdvisor()` method, or -(the recommended way) in XML configuration, like any other advisor. All proxy creation -choices discussed below, including "auto proxy creators," correctly handle introductions -and stateful mixins. - - - - -[[classic-aop-api-advisor]] -=== Advisor API in Spring -In Spring, an Advisor is an aspect that contains just a single advice object associated -with a pointcut expression. - -Apart from the special case of introductions, any advisor can be used with any advice. -`org.springframework.aop.support.DefaultPointcutAdvisor` is the most commonly used -advisor class. For example, it can be used with a `MethodInterceptor`, `BeforeAdvice` or -`ThrowsAdvice`. - -It is possible to mix advisor and advice types in Spring in the same AOP proxy. For -example, you could use a interception around advice, throws advice and before advice in -one proxy configuration: Spring will automatically create the necessary interceptor -chain. - - - - -[[classic-aop-pfb]] -=== Using the ProxyFactoryBean to create AOP proxies -If you're using the Spring IoC container (an ApplicationContext or BeanFactory) for your -business objects - and you should be! - you will want to use one of Spring's AOP -FactoryBeans. (Remember that a factory bean introduces a layer of indirection, enabling -it to create objects of a different type.) - -[NOTE] -==== -The Spring 2.0 AOP support also uses factory beans under the covers. -==== - -The basic way to create an AOP proxy in Spring is to use the -__org.springframework.aop.framework.ProxyFactoryBean__. This gives complete control over -the pointcuts and advice that will apply, and their ordering. However, there are simpler -options that are preferable if you don't need such control. - - - -[[classic-aop-pfb-1]] -==== Basics -The `ProxyFactoryBean`, like other Spring `FactoryBean` implementations, introduces a -level of indirection. If you define a `ProxyFactoryBean` with name `foo`, what objects -referencing `foo` see is not the `ProxyFactoryBean` instance itself, but an object -created by the `ProxyFactoryBean`'s implementation of the `getObject()` method. This -method will create an AOP proxy wrapping a target object. - -One of the most important benefits of using a `ProxyFactoryBean` or another IoC-aware -class to create AOP proxies, is that it means that advices and pointcuts can also be -managed by IoC. This is a powerful feature, enabling certain approaches that are hard to -achieve with other AOP frameworks. For example, an advice may itself reference -application objects (besides the target, which should be available in any AOP -framework), benefiting from all the pluggability provided by Dependency Injection. - - - -[[classic-aop-pfb-2]] -==== JavaBean properties -In common with most `FactoryBean` implementations provided with Spring, the -`ProxyFactoryBean` class is itself a JavaBean. Its properties are used to: - -* Specify the target you want to proxy. -* Specify whether to use CGLIB (see below and also <>). - -Some key properties are inherited from `org.springframework.aop.framework.ProxyConfig` -(the superclass for all AOP proxy factories in Spring). These key properties include: - -* `proxyTargetClass`: `true` if the target class is to be proxied, rather than the - target class' interfaces. If this property value is set to `true`, then CGLIB proxies - will be created (but see also below <>). -* `optimize`: controls whether or not aggressive optimizations are applied to proxies - __created via CGLIB__. One should not blithely use this setting unless one fully - understands how the relevant AOP proxy handles optimization. This is currently used - only for CGLIB proxies; it has no effect with JDK dynamic proxies. -* `frozen`: if a proxy configuration is `frozen`, then changes to the configuration are - no longer allowed. This is useful both as a slight optimization and for those cases - when you don't want callers to be able to manipulate the proxy (via the `Advised` - interface) after the proxy has been created. The default value of this property is - `false`, so changes such as adding additional advice are allowed. -* `exposeProxy`: determines whether or not the current proxy should be exposed in a - `ThreadLocal` so that it can be accessed by the target. If a target needs to obtain - the proxy and the `exposeProxy` property is set to `true`, the target can use the - `AopContext.currentProxy()` method. -* `aopProxyFactory`: the implementation of `AopProxyFactory` to use. Offers a way of - customizing whether to use dynamic proxies, CGLIB or any other proxy strategy. The - default implementation will choose dynamic proxies or CGLIB appropriately. There - should be no need to use this property; it is intended to allow the addition of new - proxy types in Spring 1.1. - -Other properties specific to `ProxyFactoryBean` include: - -* `proxyInterfaces`: array of String interface names. If this isn't supplied, a CGLIB - proxy for the target class will be used (but see also below <>). -* `interceptorNames`: String array of `Advisor`, interceptor or other advice names to - apply. Ordering is significant, on a first come-first served basis. That is to say - that the first interceptor in the list will be the first to be able to intercept the - invocation. - -The names are bean names in the current factory, including bean names from ancestor -factories. You can't mention bean references here since doing so would result in the -`ProxyFactoryBean` ignoring the singleton setting of the advice. - -You can append an interceptor name with an asterisk ( `*`). This will result in the -application of all advisor beans with names starting with the part before the asterisk -to be applied. An example of using this feature can be found in <>. - -* singleton: whether or not the factory should return a single object, no matter how - often the `getObject()` method is called. Several `FactoryBean` implementations offer - such a method. The default value is `true`. If you want to use stateful advice - for - example, for stateful mixins - use prototype advices along with a singleton value of - `false`. - - - -[[classic-aop-pfb-proxy-types]] -==== JDK- and CGLIB-based proxies -This section serves as the definitive documentation on how the `ProxyFactoryBean` -chooses to create one of either a JDK- and CGLIB-based proxy for a particular target -object (that is to be proxied). - -[NOTE] -==== -The behavior of the `ProxyFactoryBean` with regard to creating JDK- or CGLIB-based -proxies changed between versions 1.2.x and 2.0 of Spring. The `ProxyFactoryBean` now -exhibits similar semantics with regard to auto-detecting interfaces as those of the -`TransactionProxyFactoryBean` class. -==== - -If the class of a target object that is to be proxied (hereafter simply referred to as -the target class) doesn't implement any interfaces, then a CGLIB-based proxy will be -created. This is the easiest scenario, because JDK proxies are interface based, and no -interfaces means JDK proxying isn't even possible. One simply plugs in the target bean, -and specifies the list of interceptors via the `interceptorNames` property. Note that a -CGLIB-based proxy will be created even if the `proxyTargetClass` property of the -`ProxyFactoryBean` has been set to `false`. (Obviously this makes no sense, and is best -removed from the bean definition because it is at best redundant, and at worst -confusing.) - -If the target class implements one (or more) interfaces, then the type of proxy that is -created depends on the configuration of the `ProxyFactoryBean`. - -If the `proxyTargetClass` property of the `ProxyFactoryBean` has been set to `true`, -then a CGLIB-based proxy will be created. This makes sense, and is in keeping with the -principle of least surprise. Even if the `proxyInterfaces` property of the -`ProxyFactoryBean` has been set to one or more fully qualified interface names, the fact -that the `proxyTargetClass` property is set to `true` __will__ cause CGLIB-based -proxying to be in effect. - -If the `proxyInterfaces` property of the `ProxyFactoryBean` has been set to one or more -fully qualified interface names, then a JDK-based proxy will be created. The created -proxy will implement all of the interfaces that were specified in the `proxyInterfaces` -property; if the target class happens to implement a whole lot more interfaces than -those specified in the `proxyInterfaces` property, that is all well and good but those -additional interfaces will not be implemented by the returned proxy. - -If the `proxyInterfaces` property of the `ProxyFactoryBean` has __not__ been set, but -the target class __does implement one (or more)__ interfaces, then the -`ProxyFactoryBean` will auto-detect the fact that the target class does actually -implement at least one interface, and a JDK-based proxy will be created. The interfaces -that are actually proxied will be __all__ of the interfaces that the target class -implements; in effect, this is the same as simply supplying a list of each and every -interface that the target class implements to the `proxyInterfaces` property. However, -it is significantly less work, and less prone to typos. - - - -[[classic-aop-api-proxying-intf]] -==== Proxying interfaces -Let's look at a simple example of `ProxyFactoryBean` in action. This example involves: - -* A __target bean__ that will be proxied. This is the "personTarget" bean definition in - the example below. -* An Advisor and an Interceptor used to provide advice. -* An AOP proxy bean definition specifying the target object (the personTarget bean) and - the interfaces to proxy, along with the advices to apply. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - Tony - 51 - - - - Custom string property value - - - - - - - com.mycompany.Person - - - - myAdvisor - debugInterceptor - - - ----- - -Note that the `interceptorNames` property takes a list of String: the bean names of the -interceptor or advisors in the current factory. Advisors, interceptors, before, after -returning and throws advice objects can be used. The ordering of advisors is significant. - -[NOTE] -==== -You might be wondering why the list doesn't hold bean references. The reason for this is -that if the ProxyFactoryBean's singleton property is set to false, it must be able to -return independent proxy instances. If any of the advisors is itself a prototype, an -independent instance would need to be returned, so it's necessary to be able to obtain -an instance of the prototype from the factory; holding a reference isn't sufficient. -==== - -The "person" bean definition above can be used in place of a Person implementation, as -follows: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - Person person = (Person) factory.getBean("person"); ----- - -Other beans in the same IoC context can express a strongly typed dependency on it, as -with an ordinary Java object: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - ----- - -The `PersonUser` class in this example would expose a property of type Person. As far as -it's concerned, the AOP proxy can be used transparently in place of a "real" person -implementation. However, its class would be a dynamic proxy class. It would be possible -to cast it to the `Advised` interface (discussed below). - -It's possible to conceal the distinction between target and proxy using an anonymous -__inner bean__, as follows. Only the `ProxyFactoryBean` definition is different; the -advice is included only for completeness: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - Custom string property value - - - - - - com.mycompany.Person - - - - Tony - 51 - - - - - myAdvisor - debugInterceptor - - - ----- - -This has the advantage that there's only one object of type `Person`: useful if we want -to prevent users of the application context from obtaining a reference to the un-advised -object, or need to avoid any ambiguity with Spring IoC __autowiring__. There's also -arguably an advantage in that the ProxyFactoryBean definition is self-contained. -However, there are times when being able to obtain the un-advised target from the -factory might actually be an __advantage__: for example, in certain test scenarios. - - - -[[classic-aop-api-proxying-class]] -==== Proxying classes -What if you need to proxy a class, rather than one or more interfaces? - -Imagine that in our example above, there was no `Person` interface: we needed to advise -a class called `Person` that didn't implement any business interface. In this case, you -can configure Spring to use CGLIB proxying, rather than dynamic proxies. Simply set the -`proxyTargetClass` property on the ProxyFactoryBean above to true. While it's best to -program to interfaces, rather than classes, the ability to advise classes that don't -implement interfaces can be useful when working with legacy code. (In general, Spring -isn't prescriptive. While it makes it easy to apply good practices, it avoids forcing a -particular approach.) - -If you want to, you can force the use of CGLIB in any case, even if you do have -interfaces. - -CGLIB proxying works by generating a subclass of the target class at runtime. Spring -configures this generated subclass to delegate method calls to the original target: the -subclass is used to implement the __Decorator__ pattern, weaving in the advice. - -CGLIB proxying should generally be transparent to users. However, there are some issues -to consider: - -* `Final` methods can't be advised, as they can't be overridden. -* As of Spring 3.2 it is no longer required to add CGLIB to your project classpath. - CGLIB classes have been repackaged under org.springframework and included directly in - the spring-core JAR. This is both for user convenience as well as to avoid potential - conflicts with other projects that have dependence on a differing version of CGLIB. - -There's little performance difference between CGLIB proxying and dynamic proxies. As of -Spring 1.0, dynamic proxies are slightly faster. However, this may change in the future. -Performance should not be a decisive consideration in this case. - - - -[[classic-aop-global-advisors]] -==== Using 'global' advisors -By appending an asterisk to an interceptor name, all advisors with bean names matching -the part before the asterisk, will be added to the advisor chain. This can come in handy -if you need to add a standard set of 'global' advisors: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - global* - - - - - - ----- - - - - -[[classic-aop-concise-proxy]] -=== Concise proxy definitions -Especially when defining transactional proxies, you may end up with many similar proxy -definitions. The use of parent and child bean definitions, along with inner bean -definitions, can result in much cleaner and more concise proxy definitions. - -First a parent, __template__, bean definition is created for the proxy: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - PROPAGATION_REQUIRED - - - ----- - -This will never be instantiated itself, so may actually be incomplete. Then each proxy -which needs to be created is just a child bean definition, which wraps the target of the -proxy as an inner bean definition, since the target will never be used on its own anyway. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - ----- - -It is of course possible to override properties from the parent template, such as in -this case, the transaction propagation settings: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - PROPAGATION_REQUIRED,readOnly - PROPAGATION_REQUIRED,readOnly - PROPAGATION_REQUIRED,readOnly - PROPAGATION_REQUIRED - - - ----- - -Note that in the example above, we have explicitly marked the parent bean definition as -__abstract__ by using the __abstract__ attribute, as described -<>, so that it may not actually ever be -instantiated. Application contexts (but not simple bean factories) will by default -pre-instantiate all singletons. It is therefore important (at least for singleton beans) -that if you have a (parent) bean definition which you intend to use only as a template, -and this definition specifies a class, you must make sure to set the__abstract__ -attribute to __true__, otherwise the application context will actually try to -pre-instantiate it. - - - - -[[classic-aop-prog]] -=== Creating AOP proxies programmatically with the ProxyFactory -It's easy to create AOP proxies programmatically using Spring. This enables you to use -Spring AOP without dependency on Spring IoC. - -The following listing shows creation of a proxy for a target object, with one -interceptor and one advisor. The interfaces implemented by the target object will -automatically be proxied: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - ProxyFactory factory = new ProxyFactory(myBusinessInterfaceImpl); - factory.addInterceptor(myMethodInterceptor); - factory.addAdvisor(myAdvisor); - MyBusinessInterface tb = (MyBusinessInterface) factory.getProxy(); ----- - -The first step is to construct an object of type -`org.springframework.aop.framework.ProxyFactory`. You can create this with a target -object, as in the above example, or specify the interfaces to be proxied in an alternate -constructor. - -You can add interceptors or advisors, and manipulate them for the life of the -ProxyFactory. If you add an IntroductionInterceptionAroundAdvisor you can cause the -proxy to implement additional interfaces. - -There are also convenience methods on ProxyFactory (inherited from `AdvisedSupport`) -which allow you to add other advice types such as before and throws advice. -AdvisedSupport is the superclass of both ProxyFactory and ProxyFactoryBean. - -[TIP] -==== - -Integrating AOP proxy creation with the IoC framework is best practice in most -applications. We recommend that you externalize configuration from Java code with AOP, -as in general. -==== - - - - -[[classic-aop-api-advised]] -=== Manipulating advised objects -However you create AOP proxies, you can manipulate them using the -`org.springframework.aop.framework.Advised` interface. Any AOP proxy can be cast to this -interface, whichever other interfaces it implements. This interface includes the -following methods: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - Advisor[] getAdvisors(); - - void addAdvice(Advice advice) throws AopConfigException; - - void addAdvice(int pos, Advice advice) throws AopConfigException; - - void addAdvisor(Advisor advisor) throws AopConfigException; - - void addAdvisor(int pos, Advisor advisor) throws AopConfigException; - - int indexOf(Advisor advisor); - - boolean removeAdvisor(Advisor advisor) throws AopConfigException; - - void removeAdvisor(int index) throws AopConfigException; - - boolean replaceAdvisor(Advisor a, Advisor b) throws AopConfigException; - - boolean isFrozen(); ----- - -The `getAdvisors()` method will return an Advisor for every advisor, interceptor or -other advice type that has been added to the factory. If you added an Advisor, the -returned advisor at this index will be the object that you added. If you added an -interceptor or other advice type, Spring will have wrapped this in an advisor with a -pointcut that always returns true. Thus if you added a `MethodInterceptor`, the advisor -returned for this index will be an `DefaultPointcutAdvisor` returning your -`MethodInterceptor` and a pointcut that matches all classes and methods. - -The `addAdvisor()` methods can be used to add any Advisor. Usually the advisor holding -pointcut and advice will be the generic `DefaultPointcutAdvisor`, which can be used with -any advice or pointcut (but not for introductions). - -By default, it's possible to add or remove advisors or interceptors even once a proxy -has been created. The only restriction is that it's impossible to add or remove an -introduction advisor, as existing proxies from the factory will not show the interface -change. (You can obtain a new proxy from the factory to avoid this problem.) - -A simple example of casting an AOP proxy to the `Advised` interface and examining and -manipulating its advice: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - Advised advised = (Advised) myObject; - Advisor[] advisors = advised.getAdvisors(); - int oldAdvisorCount = advisors.length; - System.out.println(oldAdvisorCount + " advisors"); - - // Add an advice like an interceptor without a pointcut - // Will match all proxied methods - // Can use for interceptors, before, after returning or throws advice - advised.addAdvice(new DebugInterceptor()); - - // Add selective advice using a pointcut - advised.addAdvisor(new DefaultPointcutAdvisor(mySpecialPointcut, myAdvice)); - - assertEquals("Added two advisors", oldAdvisorCount + 2, advised.getAdvisors().length); ----- - -[NOTE] -==== -It's questionable whether it's advisable (no pun intended) to modify advice on a -business object in production, although there are no doubt legitimate usage cases. -However, it can be very useful in development: for example, in tests. I have sometimes -found it very useful to be able to add test code in the form of an interceptor or other -advice, getting inside a method invocation I want to test. (For example, the advice can -get inside a transaction created for that method: for example, to run SQL to check that -a database was correctly updated, before marking the transaction for roll back.) -==== - -Depending on how you created the proxy, you can usually set a `frozen` flag, in which -case the `Advised` `isFrozen()` method will return true, and any attempts to modify -advice through addition or removal will result in an `AopConfigException`. The ability -to freeze the state of an advised object is useful in some cases, for example, to -prevent calling code removing a security interceptor. It may also be used in Spring 1.1 -to allow aggressive optimization if runtime advice modification is known not to be -required. - - - - -[[classic-aop-autoproxy]] -=== Using the "autoproxy" facility -So far we've considered explicit creation of AOP proxies using a `ProxyFactoryBean` or -similar factory bean. - -Spring also allows us to use "autoproxy" bean definitions, which can automatically proxy -selected bean definitions. This is built on Spring "bean post processor" infrastructure, -which enables modification of any bean definition as the container loads. - -In this model, you set up some special bean definitions in your XML bean definition file -to configure the auto proxy infrastructure. This allows you just to declare the targets -eligible for autoproxying: you don't need to use `ProxyFactoryBean`. - -There are two ways to do this: - -* Using an autoproxy creator that refers to specific beans in the current context. -* A special case of autoproxy creation that deserves to be considered separately; - autoproxy creation driven by source-level metadata attributes. - - - -[[classic-aop-autoproxy-choices]] -==== Autoproxy bean definitions -The `org.springframework.aop.framework.autoproxy` package provides the following -standard autoproxy creators. - - -[[classic-aop-api-autoproxy]] -===== BeanNameAutoProxyCreator -The `BeanNameAutoProxyCreator` class is a `BeanPostProcessor` that automatically creates -AOP proxies for beans with names matching literal values or wildcards. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - jdk*,onlyJdk - - - myInterceptor - - - ----- - -As with `ProxyFactoryBean`, there is an `interceptorNames` property rather than a list -of interceptors, to allow correct behavior for prototype advisors. Named "interceptors" -can be advisors or any advice type. - -As with auto proxying in general, the main point of using `BeanNameAutoProxyCreator` is -to apply the same configuration consistently to multiple objects, with minimal volume of -configuration. It is a popular choice for applying declarative transactions to multiple -objects. - -Bean definitions whose names match, such as "jdkMyBean" and "onlyJdk" in the above -example, are plain old bean definitions with the target class. An AOP proxy will be -created automatically by the `BeanNameAutoProxyCreator`. The same advice will be applied -to all matching beans. Note that if advisors are used (rather than the interceptor in -the above example), the pointcuts may apply differently to different beans. - - -[[classic-aop-api-autoproxy-default]] -===== DefaultAdvisorAutoProxyCreator -A more general and extremely powerful auto proxy creator is -`DefaultAdvisorAutoProxyCreator`. This will automagically apply eligible advisors in the -current context, without the need to include specific bean names in the autoproxy -advisor's bean definition. It offers the same merit of consistent configuration and -avoidance of duplication as `BeanNameAutoProxyCreator`. - -Using this mechanism involves: - -* Specifying a `DefaultAdvisorAutoProxyCreator` bean definition. -* Specifying any number of Advisors in the same or related contexts. Note that these - __must__ be Advisors, not just interceptors or other advices. This is necessary - because there must be a pointcut to evaluate, to check the eligibility of each advice - to candidate bean definitions. - -The `DefaultAdvisorAutoProxyCreator` will automatically evaluate the pointcut contained -in each advisor, to see what (if any) advice it should apply to each business object -(such as "businessObject1" and "businessObject2" in the example). - -This means that any number of advisors can be applied automatically to each business -object. If no pointcut in any of the advisors matches any method in a business object, -the object will not be proxied. As bean definitions are added for new business objects, -they will automatically be proxied if necessary. - -Autoproxying in general has the advantage of making it impossible for callers or -dependencies to obtain an un-advised object. Calling getBean("businessObject1") on this -ApplicationContext will return an AOP proxy, not the target business object. (The "inner -bean" idiom shown earlier also offers this benefit.) - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - - - - - - ----- - -The `DefaultAdvisorAutoProxyCreator` is very useful if you want to apply the same advice -consistently to many business objects. Once the infrastructure definitions are in place, -you can simply add new business objects without including specific proxy configuration. -You can also drop in additional aspects very easily - for example, tracing or -performance monitoring aspects - with minimal change to configuration. - -The DefaultAdvisorAutoProxyCreator offers support for filtering (using a naming -convention so that only certain advisors are evaluated, allowing use of multiple, -differently configured, AdvisorAutoProxyCreators in the same factory) and ordering. -Advisors can implement the `org.springframework.core.Ordered` interface to ensure -correct ordering if this is an issue. The TransactionAttributeSourceAdvisor used in the -above example has a configurable order value; the default setting is unordered. - - -[[classic-aop-api-autoproxy-abstract]] -===== AbstractAdvisorAutoProxyCreator -This is the superclass of DefaultAdvisorAutoProxyCreator. You can create your own -autoproxy creators by subclassing this class, in the unlikely event that advisor -definitions offer insufficient customization to the behavior of the framework -`DefaultAdvisorAutoProxyCreator`. - - - -[[classic-aop-autoproxy-metadata]] -==== Using metadata-driven auto-proxying -A particularly important type of autoproxying is driven by metadata. This produces a -similar programming model to .NET `ServicedComponents`. Instead of using XML deployment -descriptors as in EJB, configuration for transaction management and other enterprise -services is held in source-level attributes. - -In this case, you use the `DefaultAdvisorAutoProxyCreator`, in combination with Advisors -that understand metadata attributes. The metadata specifics are held in the pointcut -part of the candidate advisors, rather than in the autoproxy creation class itself. - -This is really a special case of the `DefaultAdvisorAutoProxyCreator`, but deserves -consideration on its own. (The metadata-aware code is in the pointcuts contained in the -advisors, not the AOP framework itself.) - -The `/attributes` directory of the JPetStore sample application shows the use of -attribute-driven autoproxying. In this case, there's no need to use the -`TransactionProxyFactoryBean`. Simply defining transactional attributes on business -objects is sufficient, because of the use of metadata-aware pointcuts. The bean -definitions include the following code, in `/WEB-INF/declarativeServices.xml`. Note that -this is generic, and can be used outside the JPetStore: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - - - - - - - - - ----- - -The `DefaultAdvisorAutoProxyCreator` bean definition (the name is not significant, hence -it can even be omitted) will pick up all eligible pointcuts in the current application -context. In this case, the "transactionAdvisor" bean definition, of type -`TransactionAttributeSourceAdvisor`, will apply to classes or methods carrying a -transaction attribute. The TransactionAttributeSourceAdvisor depends on a -TransactionInterceptor, via constructor dependency. The example resolves this via -autowiring. The `AttributesTransactionAttributeSource` depends on an implementation of -the `org.springframework.metadata.Attributes` interface. In this fragment, the -"attributes" bean satisfies this, using the Jakarta Commons Attributes API to obtain -attribute information. (The application code must have been compiled using the Commons -Attributes compilation task.) - -The `/annotation` directory of the JPetStore sample application contains an analogous -example for auto-proxying driven by JDK 1.5+ annotations. The following configuration -enables automatic detection of Spring's `Transactional` annotation, leading to implicit -proxies for beans containing that annotation: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - - - - - ----- - -The `TransactionInterceptor` defined here depends on a `PlatformTransactionManager` -definition, which is not included in this generic file (although it could be) because it -will be specific to the application's transaction requirements (typically JTA, as in -this example, or Hibernate, JDO or JDBC): - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - ----- - -[TIP] -==== - -If you require only declarative transaction management, using these generic XML -definitions will result in Spring automatically proxying all classes or methods with -transaction attributes. You won't need to work directly with AOP, and the programming -model is similar to that of .NET ServicedComponents. -==== - -This mechanism is extensible. It's possible to do autoproxying based on custom -attributes. You need to: - -* Define your custom attribute. -* Specify an Advisor with the necessary advice, including a pointcut that is triggered - by the presence of the custom attribute on a class or method. You may be able to use - an existing advice, merely implementing a static pointcut that picks up the custom - attribute. - -It's possible for such advisors to be unique to each advised class (for example, -mixins): they simply need to be defined as prototype, rather than singleton, bean -definitions. For example, the `LockMixin` introduction interceptor from the Spring test -suite, shown above, could be used in conjunction with an attribute-driven pointcut to -target a mixin, as shown here. We use the generic `DefaultPointcutAdvisor`, configured -using JavaBean properties: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - - - - - - - - - ----- - -The above `swap()` call changes the target of the swappable bean. Clients who hold a -reference to that bean will be unaware of the change, but will immediately start hitting -the new target. - -Although this example doesn't add any advice - and it's not necessary to add advice to -use a `TargetSource` - of course any `TargetSource` can be used in conjunction with -arbitrary advice. - - - -[[classic-aop-ts-pool]] -==== Pooling target sources -Using a pooling target source provides a similar programming model to stateless session -EJBs, in which a pool of identical instances is maintained, with method invocations -going to free objects in the pool. - -A crucial difference between Spring pooling and SLSB pooling is that Spring pooling can -be applied to any POJO. As with Spring in general, this service can be applied in a -non-invasive way. - -Spring provides out-of-the-box support for Jakarta Commons Pool 1.3, which provides a -fairly efficient pooling implementation. You'll need the commons-pool Jar on your -application's classpath to use this feature. It's also possible to subclass -`org.springframework.aop.target.AbstractPoolingTargetSource` to support any other -pooling API. - -Sample configuration is shown below: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - ... properties omitted - - - - - - - - - - - ----- - -Note that the target object - "businessObjectTarget" in the example - __must__ be a -prototype. This allows the `PoolingTargetSource` implementation to create new instances -of the target to grow the pool as necessary. See the Javadoc for -`AbstractPoolingTargetSource` and the concrete subclass you wish to use for information -about its properties: "maxSize" is the most basic, and always guaranteed to be present. - -In this case, "myInterceptor" is the name of an interceptor that would need to be -defined in the same IoC context. However, it isn't necessary to specify interceptors to -use pooling. If you want only pooling, and no other advice, don't set the -interceptorNames property at all. - -It's possible to configure Spring so as to be able to cast any pooled object to the -`org.springframework.aop.target.PoolingConfig` interface, which exposes information -about the configuration and current size of the pool through an introduction. You'll -need to define an advisor like this: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - ----- - -This advisor is obtained by calling a convenience method on the -`AbstractPoolingTargetSource` class, hence the use of MethodInvokingFactoryBean. This -advisor's name ("poolConfigAdvisor" here) must be in the list of interceptors names in -the ProxyFactoryBean exposing the pooled object. - -The cast will look as follows: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - PoolingConfig conf = (PoolingConfig) beanFactory.getBean("businessObject"); - System.out.println("Max pool size is " + conf.getMaxSize()); ----- - -[NOTE] -==== -Pooling stateless service objects is not usually necessary. We don't believe it should -be the default choice, as most stateless objects are naturally thread safe, and instance -pooling is problematic if resources are cached. -==== - -Simpler pooling is available using autoproxying. It's possible to set the TargetSources -used by any autoproxy creator. - - - -[[classic-aop-ts-prototype]] -==== Prototype target sources -Setting up a "prototype" target source is similar to a pooling TargetSource. In this -case, a new instance of the target will be created on every method invocation. Although -the cost of creating a new object isn't high in a modern JVM, the cost of wiring up the -new object (satisfying its IoC dependencies) may be more expensive. Thus you shouldn't -use this approach without very good reason. - -To do this, you could modify the `poolTargetSource` definition shown above as follows. -(I've also changed the name, for clarity.) - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - ----- - -There's only one property: the name of the target bean. Inheritance is used in the -TargetSource implementations to ensure consistent naming. As with the pooling target -source, the target bean must be a prototype bean definition. - - - -[[classic-aop-ts-threadlocal]] -==== ThreadLocal target sources - -`ThreadLocal` target sources are useful if you need an object to be created for each -incoming request (per thread that is). The concept of a `ThreadLocal` provide a JDK-wide -facility to transparently store resource alongside a thread. Setting up a -`ThreadLocalTargetSource` is pretty much the same as was explained for the other types -of target source: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - ----- - -[NOTE] -==== -ThreadLocals come with serious issues (potentially resulting in memory leaks) when -incorrectly using them in a multi-threaded and multi-classloader environments. One -should always consider wrapping a threadlocal in some other class and never directly use -the `ThreadLocal` itself (except of course in the wrapper class). Also, one should -always remember to correctly set and unset (where the latter simply involved a call to -`ThreadLocal.set(null)`) the resource local to the thread. Unsetting should be done in -any case since not unsetting it might result in problematic behavior. Spring's -ThreadLocal support does this for you and should always be considered in favor of using -ThreadLocals without other proper handling code. -==== - - - - -[[classic-aop-extensibility]] -=== Defining new Advice types - -Spring AOP is designed to be extensible. While the interception implementation strategy -is presently used internally, it is possible to support arbitrary advice types in -addition to the out-of-the-box interception around advice, before, throws advice and -after returning advice. - -The `org.springframework.aop.framework.adapter` package is an SPI package allowing -support for new custom advice types to be added without changing the core framework. The -only constraint on a custom `Advice` type is that it must implement the -`org.aopalliance.aop.Advice` tag interface. - -Please refer to the `org.springframework.aop.framework.adapter` package's Javadocs for -further information. - - - - -[[classic-aop-api-resources]] -=== Further resources -Please refer to the Spring sample applications for further examples of Spring AOP: - -* The JPetStore's default configuration illustrates the use of the - `TransactionProxyFactoryBean` for declarative transaction management. -* The `/attributes` directory of the JPetStore illustrates the use of attribute-driven - declarative transaction management. - - -[[xsd-config]] -== XML Schema-based configuration - - -[[xsd-config-introduction]] -=== Introduction -This appendix details the XML Schema-based configuration introduced in Spring 2.0 and -enhanced and extended in Spring 2.5 and 3.0. - -.DTD support? -**** -Authoring Spring configuration files using the older DTD style is still fully supported. - -Nothing will break if you forego the use of the new XML Schema-based approach to -authoring Spring XML configuration files. All that you lose out on is the opportunity to -have more succinct and clearer configuration. Regardless of whether the XML -configuration is DTD- or Schema-based, in the end it all boils down to the same object -model in the container (namely one or more `BeanDefinition` instances). -**** - -The central motivation for moving to XML Schema based configuration files was to make -Spring XML configuration easier. The __'classic'__ ``-based approach is good, but -its generic-nature comes with a price in terms of configuration overhead. - -From the Spring IoC containers point-of-view, __everything__ is a bean. That's great -news for the Spring IoC container, because if everything is a bean then everything can -be treated in the exact same fashion. The same, however, is not true from a developer's -point-of-view. The objects defined in a Spring XML configuration file are not all -generic, vanilla beans. Usually, each bean requires some degree of specific -configuration. - -Spring 2.0's new XML Schema-based configuration addresses this issue. The `` -element is still present, and if you wanted to, you could continue to write the __exact -same__ style of Spring XML configuration using only `` elements. The new XML -Schema-based configuration does, however, make Spring XML configuration files -substantially clearer to read. In addition, it allows you to express the intent of a -bean definition. - -The key thing to remember is that the new custom tags work best for infrastructure or -integration beans: for example, AOP, collections, transactions, integration with -3rd-party frameworks such as Mule, etc., while the existing bean tags are best suited to -application-specific beans, such as DAOs, service layer objects, validators, etc. - -The examples included below will hopefully convince you that the inclusion of XML Schema -support in Spring 2.0 was a good idea. The reception in the community has been -encouraging; also, please note the fact that this new configuration mechanism is totally -customisable and extensible. This means you can write your own domain-specific -configuration tags that would better represent your application's domain; the process -involved in doing so is covered in the appendix entitled <>. - - - - -[[xsd-config-body]] -=== XML Schema-based configuration - - - -[[xsd-config-body-referencing]] -==== Referencing the schemas -To switch over from the DTD-style to the new XML Schema-style, you need to make the -following change. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - ----- - -The equivalent file in the XML Schema-style would be... - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - ----- - -[NOTE] -==== -The `'xsi:schemaLocation'` fragment is not actually required, but can be included to -reference a local copy of a schema (which can be useful during development). -==== - -The above Spring XML configuration fragment is boilerplate that you can copy and paste -(!) and then plug `` definitions into like you have always done. However, the -entire point of switching over is to take advantage of the new Spring 2.0 XML tags since -they make configuration easier. The section entitled <> -demonstrates how you can start immediately by using some of the more common utility tags. - -The rest of this chapter is devoted to showing examples of the new Spring XML Schema -based configuration, with at least one example for every new tag. The format follows a -before and after style, with a __before__ snippet of XML showing the old (but still 100% -legal and supported) style, followed immediately by an __after__ example showing the -equivalent in the new XML Schema-based style. - - - -[[xsd-config-body-schemas-util]] -==== the util schema - -First up is coverage of the `util` tags. As the name implies, the `util` tags deal with -common, __utility__ configuration issues, such as configuring collections, referencing -constants, and suchlike. - -To use the tags in the `util` schema, you need to have the following preamble at the top -of your Spring XML configuration file; the text in the snippet below references the -correct schema so that the tags in the `util` namespace are available to you. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - ----- - - -[[xsd-config-body-schemas-util-constant]] -===== - -Before... - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - ----- - -The above configuration uses a Spring `FactoryBean` implementation, the -`FieldRetrievingFactoryBean`, to set the value of the `'isolation'` property on a bean -to the value of the `'java.sql.Connection.TRANSACTION_SERIALIZABLE'` constant. This is -all well and good, but it is a tad verbose and (unnecessarily) exposes Spring's internal -plumbing to the end user. - -The following XML Schema-based version is more concise and clearly expresses the -developer's intent (__'inject this constant value'__), and it just reads better. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - ----- - -[[xsd-config-body-schemas-util-frfb]] -====== Setting a bean property or constructor arg from a field value -http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/beans/factory/config/FieldRetrievingFactoryBean.html[`FieldRetrievingFactoryBean`] -is a `FactoryBean` which retrieves a `static` or non-static field value. It is typically -used for retrieving `public` `static` `final` constants, which may then be used to set a -property value or constructor arg for another bean. - -Find below an example which shows how a `static` field is exposed, by using the -http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/beans/factory/config/FieldRetrievingFactoryBean.html#setStaticField(java.lang.String)[`staticField`] -property: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - ----- - -There is also a convenience usage form where the `static` field is specified as the bean -name: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - ----- - -This does mean that there is no longer any choice in what the bean id is (so any other -bean that refers to it will also have to use this longer name), but this form is very -concise to define, and very convenient to use as an inner bean since the id doesn't have -to be specified for the bean reference: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - ----- - -It is also possible to access a non-static (instance) field of another bean, as -described in the API documentation for the -http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/beans/factory/config/FieldRetrievingFactoryBean.html[`FieldRetrievingFactoryBean`] -class. - -Injecting enum values into beans as either property or constructor arguments is very -easy to do in Spring, in that you don't actually have to __do__ anything or know -anything about the Spring internals (or even about classes such as the -`FieldRetrievingFactoryBean`). Let's look at an example to see how easy injecting an -enum value is; consider this JDK 5 enum: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - package javax.persistence; - - public enum PersistenceContextType { - - TRANSACTION, - EXTENDED - - } ----- - -Now consider a setter of type `PersistenceContextType`: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - package example; - - public class Client { - - private PersistenceContextType persistenceContextType; - - public void setPersistenceContextType(PersistenceContextType type) { - this.persistenceContextType = type; - } - - } ----- - -.. and the corresponding bean definition: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - ----- - -This works for classic type-safe emulated enums (on JDK 1.4 and JDK 1.3) as well; Spring -will automatically attempt to match the string property value to a constant on the enum -class. - - -[[xsd-config-body-schemas-util-property-path]] -===== - -Before... - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - - - - - ----- - -The above configuration uses a Spring `FactoryBean` implementation, the -`PropertyPathFactoryBean`, to create a bean (of type `int`) called `'testBean.age'` that -has a value equal to the `'age'` property of the `'testBean'` bean. - -After... - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - - - - - ----- - -The value of the `'path'` attribute of the `` tag follows the form -`'beanName.beanProperty'`. - -[[xsd-config-body-schemas-util-property-path-dependency]] -====== Using to set a bean property or constructor-argument - -`PropertyPathFactoryBean` is a `FactoryBean` that evaluates a property path on a given -target object. The target object can be specified directly or via a bean name. This -value may then be used in another bean definition as a property value or constructor -argument. - -Here's an example where a path is used against another bean, by name: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - // target bean to be referenced by name - - - - - - - - - - // will result in 11, which is the value of property 'spouse.age' of bean 'person' - - - - ----- - -In this example, a path is evaluated against an inner bean: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - - ----- - -There is also a shortcut form, where the bean name is the property path. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - ----- - -This form does mean that there is no choice in the name of the bean. Any reference to it -will also have to use the same id, which is the path. Of course, if used as an inner -bean, there is no need to refer to it at all: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - ----- - -The result type may be specifically set in the actual definition. This is not necessary -for most use cases, but can be of use for some. Please see the Javadocs for more info on -this feature. - - -[[xsd-config-body-schemas-util-properties]] -===== - -Before... - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - ----- - -The above configuration uses a Spring `FactoryBean` implementation, the -`PropertiesFactoryBean`, to instantiate a `java.util.Properties` instance with values -loaded from the supplied <> location). - -After... - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - ----- - - -[[xsd-config-body-schemas-util-list]] -===== - -Before... - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - pechorin@hero.org - raskolnikov@slums.org - stavrogin@gov.org - porfiry@gov.org - - - ----- - -The above configuration uses a Spring `FactoryBean` implementation, the -`ListFactoryBean`, to create a `java.util.List` instance initialized with values taken -from the supplied `'sourceList'`. - -After... - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - pechorin@hero.org - raskolnikov@slums.org - stavrogin@gov.org - porfiry@gov.org - ----- - -You can also explicitly control the exact type of `List` that will be instantiated and -populated via the use of the `'list-class'` attribute on the `` element. For -example, if we really need a `java.util.LinkedList` to be instantiated, we could use the -following configuration: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - jackshaftoe@vagabond.org - eliza@thinkingmanscrumpet.org - vanhoek@pirate.org - d'Arcachon@nemesis.org - ----- - -If no `'list-class'` attribute is supplied, a `List` implementation will be chosen by -the container. - - -[[xsd-config-body-schemas-util-map]] -===== - -Before... - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - - - - ----- - -The above configuration uses a Spring `FactoryBean` implementation, the -`MapFactoryBean`, to create a `java.util.Map` instance initialized with key-value pairs -taken from the supplied `'sourceMap'`. - -After... - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - ----- - -You can also explicitly control the exact type of `Map` that will be instantiated and -populated via the use of the `'map-class'` attribute on the `` element. For -example, if we really need a `java.util.TreeMap` to be instantiated, we could use the -following configuration: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - ----- - -If no `'map-class'` attribute is supplied, a `Map` implementation will be chosen by the -container. - - -[[xsd-config-body-schemas-util-set]] -===== - -Before... - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - pechorin@hero.org - raskolnikov@slums.org - stavrogin@gov.org - porfiry@gov.org - - - ----- - -The above configuration uses a Spring `FactoryBean` implementation, the -`SetFactoryBean`, to create a `java.util.Set` instance initialized with values taken -from the supplied `'sourceSet'`. - -After... - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - pechorin@hero.org - raskolnikov@slums.org - stavrogin@gov.org - porfiry@gov.org - ----- - -You can also explicitly control the exact type of `Set` that will be instantiated and -populated via the use of the `'set-class'` attribute on the `` element. For -example, if we really need a `java.util.TreeSet` to be instantiated, we could use the -following configuration: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - pechorin@hero.org - raskolnikov@slums.org - stavrogin@gov.org - porfiry@gov.org - ----- - -If no `'set-class'` attribute is supplied, a `Set` implementation will be chosen by the -container. - - - -[[xsd-config-body-schemas-jee]] -==== the jee schema - -The `jee` tags deal with Java EE (Java Enterprise Edition)-related configuration issues, -such as looking up a JNDI object and defining EJB references. - -To use the tags in the `jee` schema, you need to have the following preamble at the top -of your Spring XML configuration file; the text in the following snippet references the -correct schema so that the tags in the `jee` namespace are available to you. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - ----- - - -[[xsd-config-body-schemas-jee-jndi-lookup]] -===== (simple) - -Before... - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - ----- - -After... - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - ----- - - -[[xsd-config-body-schemas-jee-jndi-lookup-environment-single]] -===== (with single JNDI environment setting) - -Before... - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - bar - - - ----- - -After... - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - foo=bar - ----- - - -[[xsd-config-body-schemas-jee-jndi-lookup-evironment-multiple]] -===== (with multiple JNDI environment settings) - -Before... - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - bar - pong - - - ----- - -After... - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - foo=bar - ping=pong - - ----- - - -[[xsd-config-body-schemas-jee-jndi-lookup-complex]] -===== (complex) - -Before... - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - ----- - -After... - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - ----- - - -[[xsd-config-body-schemas-jee-local-slsb]] -===== (simple) - -The `` tag configures a reference to an EJB Stateless SessionBean. - -Before... - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - ----- - -After... - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - ----- - - -[[xsd-config-body-schemas-jee-local-slsb-complex]] -===== (complex) - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - ----- - -After... - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - ----- - - -[[xsd-config-body-schemas-jee-remote-slsb]] -===== - -The `` tag configures a reference to a `remote` EJB Stateless -SessionBean. - -Before... - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - - ----- - -After... - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - ----- - - - -[[xsd-config-body-schemas-lang]] -==== the lang schema - -The `lang` tags deal with exposing objects that have been written in a dynamic language -such as JRuby or Groovy as beans in the Spring container. - -These tags (and the dynamic language support) are comprehensively covered in the chapter -entitled <>. Please do consult that chapter for full details on this -support and the `lang` tags themselves. - -In the interest of completeness, to use the tags in the `lang` schema, you need to have -the following preamble at the top of your Spring XML configuration file; the text in the -following snippet references the correct schema so that the tags in the `lang` namespace -are available to you. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - ----- - - - -[[xsd-config-body-schemas-jms]] -==== the jms schema - -The `jms` tags deal with configuring JMS-related beans such as Spring's -<>. These tags are detailed in the section of the -<> entitled <>. Please do consult that chapter for full -details on this support and the `jms` tags themselves. - -In the interest of completeness, to use the tags in the `jms` schema, you need to have -the following preamble at the top of your Spring XML configuration file; the text in the -following snippet references the correct schema so that the tags in the `jms` namespace -are available to you. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - ----- - - - -[[xsd-config-body-schemas-tx]] -==== the tx (transaction) schema - -The `tx` tags deal with configuring all of those beans in Spring's comprehensive support -for transactions. These tags are covered in the chapter entitled <>. - -[TIP] -==== - -You are strongly encouraged to look at the `'spring-tx.xsd'` file that ships with the -Spring distribution. This file is (of course), the XML Schema for Spring's transaction -configuration, and covers all of the various tags in the `tx` namespace, including -attribute defaults and suchlike. This file is documented inline, and thus the -information is not repeated here in the interests of adhering to the DRY (Don't Repeat -Yourself) principle. -==== - -In the interest of completeness, to use the tags in the `tx` schema, you need to have -the following preamble at the top of your Spring XML configuration file; the text in the -following snippet references the correct schema so that the tags in the `tx` namespace -are available to you. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - ----- - -[NOTE] -==== -Often when using the tags in the `tx` namespace you will also be using the tags from the -`aop` namespace (since the declarative transaction support in Spring is implemented -using AOP). The above XML snippet contains the relevant lines needed to reference the -`aop` schema so that the tags in the `aop` namespace are available to you. -==== - - - -[[xsd-config-body-schemas-aop]] -==== the aop schema - -The `aop` tags deal with configuring all things AOP in Spring: this includes Spring's -own proxy-based AOP framework and Spring's integration with the AspectJ AOP framework. -These tags are comprehensively covered in the chapter entitled <>. - -In the interest of completeness, to use the tags in the `aop` schema, you need to have -the following preamble at the top of your Spring XML configuration file; the text in the -following snippet references the correct schema so that the tags in the `aop` namespace -are available to you. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - ----- - - - -[[xsd-config-body-schemas-context]] -==== the context schema - -The `context` tags deal with `ApplicationContext` configuration that relates to plumbing -- that is, not usually beans that are important to an end-user but rather beans that do -a lot of grunt work in Spring, such as `BeanfactoryPostProcessors`. The following -snippet references the correct schema so that the tags in the `context` namespace are -available to you. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - ----- - -[NOTE] -==== -The `context` schema was only introduced in Spring 2.5. -==== - - -[[xsd-config-body-schemas-context-pphc]] -===== - -This element activates the replacement of `${...}` placeholders, resolved against the -specified properties file (as a <>). This element is -a convenience mechanism that sets up a<> for you; if you need more control over the -`PropertyPlaceholderConfigurer`, just define one yourself explicitly. - - -[[xsd-config-body-schemas-context-ac]] -===== - -Activates the Spring infrastructure for various annotations to be detected in bean -classes: Spring's <> and -<>, as well as JSR 250's `@PostConstruct`, -`@PreDestroy` and `@Resource` (if available), and JPA's `@PersistenceContext` and -`@PersistenceUnit` (if available). Alternatively, you can choose to activate the -individual `BeanPostProcessors` for those annotations explicitly. - -[NOTE] -==== -This element does __not__ activate processing of Spring's -<> annotation. Use the -<`>> element for that purpose. -==== - - -[[xsd-config-body-schemas-context-component-scan]] -===== - -This element is detailed in <>. - - -[[xsd-config-body-schemas-context-ltw]] -===== - -This element is detailed in <>. - - -[[xsd-config-body-schemas-context-sc]] -===== - -This element is detailed in <>. - - -[[xsd-config-body-schemas-context-mbe]] -===== - -This element is detailed in <>. - - - -[[xsd-config-body-schemas-tool]] -==== the tool schema - -The `tool` tags are for use when you want to add tooling-specific metadata to your -custom configuration elements. This metadata can then be consumed by tools that are -aware of this metadata, and the tools can then do pretty much whatever they want with it -(validation, etc.). - -The `tool` tags are not documented in this release of Spring as they are currently -undergoing review. If you are a third party tool vendor and you would like to contribute -to this review process, then do mail the Spring mailing list. The currently supported -`tool` tags can be found in the file `'spring-tool.xsd'` in the -`'src/org/springframework/beans/factory/xml'` directory of the Spring source -distribution. - - - -[[xsd-config-body-schemas-jdbc]] -==== the jdbc schema - -The `jdbc` tags allow you to quickly configure an embedded database or initialize an -existing data source. These tags are documented in <> -and <> respectively. - -To use the tags in the `jdbc` schema, you need to have the following preamble at the top -of your Spring XML configuration file; the text in the following snippet references the -correct schema so that the tags in the `jdbc` namespace are available to you. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - ----- - - - -[[xsd-config-body-schemas-cache]] -==== the cache schema - -The `cache` tags can be used to enable support for Spring's `@CacheEvict`, `@CachePut` -and `@Caching` annotations. It it also supports declarative XML-based caching. See -<> and <> for details. - -To use the tags in the `cache` schema, you need to have the following preamble at the -top of your Spring XML configuration file; the text in the following snippet references -the correct schema so that the tags in the `cache` namespace are available to you. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - ----- - - - -[[xsd-config-body-schemas-beans]] -==== the beans schema - -Last but not least we have the tags in the `beans` schema. These are the same tags that -have been in Spring since the very dawn of the framework. Examples of the various tags -in the `beans` schema are not shown here because they are quite comprehensively covered -in <> (and indeed in that entire <>). - -One thing that is new to the beans tags themselves in Spring 2.0 is the idea of -arbitrary bean metadata. In Spring 2.0 it is now possible to add zero or more key / -value pairs to `` XML definitions. What, if anything, is done with this extra -metadata is totally up to your own custom logic (and so is typically only of use if you -are writing your own custom tags as described in the appendix entitled -<>). - -Find below an example of the `` tag in the context of a surrounding `` -(please note that without any logic to interpret it the metadata is effectively useless -as-is). - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - ____ - - - - ----- - -In the case of the above example, you would assume that there is some logic that will -consume the bean definition and set up some caching infrastructure using the supplied -metadata. - - - - - -[[extensible-xml]] -== Extensible XML authoring - - - - -[[extensible-xml-introduction]] -=== Introduction -Since version 2.0, Spring has featured a mechanism for schema-based extensions to the -basic Spring XML format for defining and configuring beans. This section is devoted to -detailing how you would go about writing your own custom XML bean definition parsers and -integrating such parsers into the Spring IoC container. - -To facilitate the authoring of configuration files using a schema-aware XML editor, -Spring's extensible XML configuration mechanism is based on XML Schema. If you are not -familiar with Spring's current XML configuration extensions that come with the standard -Spring distribution, please first read the appendix entitled<>. - -Creating new XML configuration extensions can be done by following these (relatively) -simple steps: - -* <> an XML schema to describe your custom element(s). -* <> a custom `NamespaceHandler` implementation - (this is an easy step, don't worry). -* <> one or more `BeanDefinitionParser` implementations - (this is where the real work is done). -* <> the above artifacts with Spring (this too - is an easy step). - -What follows is a description of each of these steps. For the example, we will create an -XML extension (a custom XML element) that allows us to configure objects of the type -`SimpleDateFormat` (from the `java.text` package) in an easy manner. When we are done, -we will be able to define bean definitions of type `SimpleDateFormat` like this: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - ----- - -__(Don't worry about the fact that this example is very simple; much more detailed -examples follow afterwards. The intent in this first simple example is to walk you -through the basic steps involved.)__ - - - - -[[extensible-xml-schema]] -=== Authoring the schema -Creating an XML configuration extension for use with Spring's IoC container starts with -authoring an XML Schema to describe the extension. What follows is the schema we'll use -to configure `SimpleDateFormat` objects. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - - - - - - - - - - - ----- - -(The emphasized line contains an extension base for all tags that will be identifiable -(meaning they have an `id` attribute that will be used as the bean identifier in the -container). We are able to use this attribute because we imported the Spring-provided -`'beans'` namespace.) - -The above schema will be used to configure `SimpleDateFormat` objects, directly in an -XML application context file using the `` element. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - ----- - -Note that after we've created the infrastructure classes, the above snippet of XML will -essentially be exactly the same as the following XML snippet. In other words, we're just -creating a bean in the container, identified by the name `'dateFormat'` of type -`SimpleDateFormat`, with a couple of properties set. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - ----- - -[NOTE] -==== -The schema-based approach to creating configuration format allows for tight integration -with an IDE that has a schema-aware XML editor. Using a properly authored schema, you -can use autocompletion to have a user choose between several configuration options -defined in the enumeration. -==== - - - - -[[extensible-xml-namespacehandler]] -=== Coding a NamespaceHandler - -In addition to the schema, we need a `NamespaceHandler` that will parse all elements of -this specific namespace Spring encounters while parsing configuration files. The -`NamespaceHandler` should in our case take care of the parsing of the `myns:dateformat` -element. - -The `NamespaceHandler` interface is pretty simple in that it features just three methods: - -* `init()` - allows for initialization of the `NamespaceHandler` and will be called by - Spring before the handler is used -* `BeanDefinition parse(Element, ParserContext)` - called when Spring encounters a - top-level element (not nested inside a bean definition or a different namespace). This - method can register bean definitions itself and/or return a bean definition. -* `BeanDefinitionHolder decorate(Node, BeanDefinitionHolder, ParserContext)` - called - when Spring encounters an attribute or nested element of a different namespace. The - decoration of one or more bean definitions is used for example with - the<>. We'll start by - highlighting a simple example, without using decoration, after which we will show - decoration in a somewhat more advanced example. - -Although it is perfectly possible to code your own `NamespaceHandler` for the entire -namespace (and hence provide code that parses each and every element in the namespace), -it is often the case that each top-level XML element in a Spring XML configuration file -results in a single bean definition (as in our case, where a single `` -element results in a single `SimpleDateFormat` bean definition). Spring features a -number of convenience classes that support this scenario. In this example, we'll make -use the `NamespaceHandlerSupport` class: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - package org.springframework.samples.xml; - - import org.springframework.beans.factory.xml.NamespaceHandlerSupport; - - public class MyNamespaceHandler extends NamespaceHandlerSupport { - - public void init() { - **registerBeanDefinitionParser("dateformat", new SimpleDateFormatBeanDefinitionParser());** - } - - } ----- - -The observant reader will notice that there isn't actually a whole lot of parsing logic -in this class. Indeed... the `NamespaceHandlerSupport` class has a built in notion of -delegation. It supports the registration of any number of `BeanDefinitionParser` -instances, to which it will delegate to when it needs to parse an element in its -namespace. This clean separation of concerns allows a `NamespaceHandler` to handle the -orchestration of the parsing of __all__ of the custom elements in its namespace, while -delegating to `BeanDefinitionParsers` to do the grunt work of the XML parsing; this -means that each `BeanDefinitionParser` will contain just the logic for parsing a single -custom element, as we can see in the next step - - - - -[[extensible-xml-parser]] -=== BeanDefinitionParser - -A `BeanDefinitionParser` will be used if the `NamespaceHandler` encounters an XML -element of the type that has been mapped to the specific bean definition parser (which -is `'dateformat'` in this case). In other words, the `BeanDefinitionParser` is -responsible for parsing __one__ distinct top-level XML element defined in the schema. In -the parser, we'll have access to the XML element (and thus its subelements too) so that -we can parse our custom XML content, as can be seen in the following example: - -[source,java,indent=0] ----- - package org.springframework.samples.xml; - - import org.springframework.beans.factory.support.BeanDefinitionBuilder; - import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser; - import org.springframework.util.StringUtils; - import org.w3c.dom.Element; - - import java.text.SimpleDateFormat; - - public class SimpleDateFormatBeanDefinitionParser extends AbstractSingleBeanDefinitionParser { // <1> - - protected Class getBeanClass(Element element) { - return SimpleDateFormat.class; // <2> - } - - protected void doParse(Element element, BeanDefinitionBuilder bean) { - // this will never be null since the schema explicitly requires that a value be supplied - String pattern = element.getAttribute("pattern"); - bean.addConstructorArg(pattern); - - // this however is an optional property - String lenient = element.getAttribute("lenient"); - if (StringUtils.hasText(lenient)) { - bean.addPropertyValue("lenient", Boolean.valueOf(lenient)); - } - } - - } ----- - -<1> We use the Spring-provided `AbstractSingleBeanDefinitionParser` to handle a lot of -the basic grunt work of creating a __single__ `BeanDefinition`. - -<2> We supply the `AbstractSingleBeanDefinitionParser` superclass with the type that our -single `BeanDefinition` will represent. - -In this simple case, this is all that we need to do. The creation of our single -`BeanDefinition` is handled by the `AbstractSingleBeanDefinitionParser` superclass, as -is the extraction and setting of the bean definition's unique identifier. - - - - -[[extensible-xml-registration]] -=== Registering the handler and the schema -The coding is finished! All that remains to be done is to somehow make the Spring XML -parsing infrastructure aware of our custom element; we do this by registering our custom -`namespaceHandler` and custom XSD file in two special purpose properties files. These -properties files are both placed in a `'META-INF'` directory in your application, and -can, for example, be distributed alongside your binary classes in a JAR file. The Spring -XML parsing infrastructure will automatically pick up your new extension by consuming -these special properties files, the formats of which are detailed below. - - - -[[extensible-xml-registration-spring-handlers]] -==== 'META-INF/spring.handlers' - -The properties file called `'spring.handlers'` contains a mapping of XML Schema URIs to -namespace handler classes. So for our example, we need to write the following: - -[literal] -[subs="verbatim,quotes"] ----- -http\://www.mycompany.com/schema/myns=org.springframework.samples.xml.MyNamespaceHandler ----- - -__(The `':'` character is a valid delimiter in the Java properties format, and so the -`':'` character in the URI needs to be escaped with a backslash.)__ - -The first part (the key) of the key-value pair is the URI associated with your custom -namespace extension, and needs to __match exactly__ the value of the `'targetNamespace'` -attribute as specified in your custom XSD schema. - - - -[[extensible-xml-registration-spring-schemas]] -==== 'META-INF/spring.schemas' - -The properties file called `'spring.schemas'` contains a mapping of XML Schema locations -(referred to along with the schema declaration in XML files that use the schema as part -of the `'xsi:schemaLocation'` attribute) to __classpath__ resources. This file is needed -to prevent Spring from absolutely having to use a default `EntityResolver` that requires -Internet access to retrieve the schema file. If you specify the mapping in this -properties file, Spring will search for the schema on the classpath (in this case -`'myns.xsd'` in the `'org.springframework.samples.xml'` package): - -[literal] -[subs="verbatim,quotes"] ----- -http\://www.mycompany.com/schema/myns/myns.xsd=org/springframework/samples/xml/myns.xsd ----- - -The upshot of this is that you are encouraged to deploy your XSD file(s) right alongside -the `NamespaceHandler` and `BeanDefinitionParser` classes on the classpath. - - - - -[[extensible-xml-using]] -=== Using a custom extension in your Spring XML configuration -Using a custom extension that you yourself have implemented is no different from using -one of the 'custom' extensions that Spring provides straight out of the box. Find below -an example of using the custom `` element developed in the previous steps -in a Spring XML configuration file. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - - - - - - - ----- - - - - -[[extensible-xml-meat]] -=== Meatier examples -Find below some much meatier examples of custom XML extensions. - - - -[[extensible-xml-custom-nested]] -==== Nesting custom tags within custom tags -This example illustrates how you might go about writing the various artifacts required -to satisfy a target of the following configuration: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - - - - - ----- - -The above configuration actually nests custom extensions within each other. The class -that is actually configured by the above `` element is the `Component` -class (shown directly below). Notice how the `Component` class does __not__ expose a -setter method for the `'components'` property; this makes it hard (or rather impossible) -to configure a bean definition for the `Component` class using setter injection. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - package com.foo; - - import java.util.ArrayList; - import java.util.List; - - public class Component { - - private String name; - private List components = new ArrayList (); - - // mmm, there is no setter method for the 'components' - public void addComponent(Component component) { - this.components.add(component); - } - - public List getComponents() { - return components; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - } ----- - -The typical solution to this issue is to create a custom `FactoryBean` that exposes a -setter property for the `'components'` property. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - package com.foo; - - import org.springframework.beans.factory.FactoryBean; - - import java.util.List; - - public class ComponentFactoryBean implements FactoryBean { - - private Component parent; - private List children; - - public void setParent(Component parent) { - this.parent = parent; - } - - public void setChildren(List children) { - this.children = children; - } - - public Component getObject() throws Exception { - if (this.children != null && this.children.size() > 0) { - for (Component child : children) { - this.parent.addComponent(child); - } - } - return this.parent; - } - - public Class getObjectType() { - return Component.class; - } - - public boolean isSingleton() { - return true; - } - - } ----- - -This is all very well, and does work nicely, but exposes a lot of Spring plumbing to the -end user. What we are going to do is write a custom extension that hides away all of -this Spring plumbing. If we stick to <>, we'll start off by creating the XSD schema to define the structure of our -custom tag. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - - - - - - - - ----- - -We'll then create a custom `NamespaceHandler`. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - package com.foo; - - import org.springframework.beans.factory.xml.NamespaceHandlerSupport; - - public class ComponentNamespaceHandler extends NamespaceHandlerSupport { - - public void init() { - registerBeanDefinitionParser("component", new ComponentBeanDefinitionParser()); - } - - } ----- - -Next up is the custom `BeanDefinitionParser`. Remember that what we are creating is a -`BeanDefinition` describing a `ComponentFactoryBean`. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - package com.foo; - - import org.springframework.beans.factory.config.BeanDefinition; - import org.springframework.beans.factory.support.AbstractBeanDefinition; - import org.springframework.beans.factory.support.BeanDefinitionBuilder; - import org.springframework.beans.factory.support.ManagedList; - import org.springframework.beans.factory.xml.AbstractBeanDefinitionParser; - import org.springframework.beans.factory.xml.ParserContext; - import org.springframework.util.xml.DomUtils; - import org.w3c.dom.Element; - - import java.util.List; - - public class ComponentBeanDefinitionParser extends AbstractBeanDefinitionParser { - - protected AbstractBeanDefinition parseInternal(Element element, ParserContext parserContext) { - return parseComponentElement(element); - } - - private static AbstractBeanDefinition parseComponentElement(Element element) { - BeanDefinitionBuilder factory = BeanDefinitionBuilder.rootBeanDefinition(ComponentFactoryBean.class); - factory.addPropertyValue("parent", parseComponent(element)); - - List childElements = DomUtils.getChildElementsByTagName(element, "component"); - if (childElements != null && childElements.size() > 0) { - parseChildComponents(childElements, factory); - } - - return factory.getBeanDefinition(); - } - - private static BeanDefinition parseComponent(Element element) { - BeanDefinitionBuilder component = BeanDefinitionBuilder.rootBeanDefinition(Component.class); - component.addPropertyValue("name", element.getAttribute("name")); - return component.getBeanDefinition(); - } - - private static void parseChildComponents(List childElements, BeanDefinitionBuilder factory) { - ManagedList children = new ManagedList(childElements.size()); - for (Element element : childElements) { - children.add(parseComponentElement(element)); - } - factory.addPropertyValue("children", children); - } - - } ----- - -Lastly, the various artifacts need to be registered with the Spring XML infrastructure. - -[literal] -[subs="verbatim,quotes"] ----- -# in 'META-INF/spring.handlers' -http\://www.foo.com/schema/component=com.foo.ComponentNamespaceHandler ----- - -[literal] -[subs="verbatim,quotes"] ----- -# in 'META-INF/spring.schemas' -http\://www.foo.com/schema/component/component.xsd=com/foo/component.xsd ----- - - - -[[extensible-xml-custom-just-attributes]] -==== Custom attributes on 'normal' elements -Writing your own custom parser and the associated artifacts isn't hard, but sometimes it -is not the right thing to do. Consider the scenario where you need to add metadata to -already existing bean definitions. In this case you certainly don't want to have to go -off and write your own entire custom extension; rather you just want to add an -additional attribute to the existing bean definition element. - -By way of another example, let's say that the service class that you are defining a bean -definition for a service object that will (unknown to it) be accessing a clustered -http://jcp.org/en/jsr/detail?id=107[JCache], and you want to ensure that the named -JCache instance is eagerly started within the surrounding cluster: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - ----- - -What we are going to do here is create another `BeanDefinition` when the -`'jcache:cache-name'` attribute is parsed; this `BeanDefinition` will then initialize -the named JCache for us. We will also modify the existing `BeanDefinition` for the -`'checkingAccountService'` so that it will have a dependency on this new -JCache-initializing `BeanDefinition`. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - package com.foo; - - public class JCacheInitializer { - - private String name; - - public JCacheInitializer(String name) { - this.name = name; - } - - public void initialize() { - // lots of JCache API calls to initialize the named cache... - } - - } ----- - -Now onto the custom extension. Firstly, the authoring of the XSD schema describing the -custom attribute (quite easy in this case). - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - ----- - -Next, the associated `NamespaceHandler`. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - package com.foo; - - import org.springframework.beans.factory.xml.NamespaceHandlerSupport; - - public class JCacheNamespaceHandler extends NamespaceHandlerSupport { - - public void init() { - super.registerBeanDefinitionDecoratorForAttribute("cache-name", - new JCacheInitializingBeanDefinitionDecorator()); - } - - } ----- - -Next, the parser. Note that in this case, because we are going to be parsing an XML -attribute, we write a `BeanDefinitionDecorator` rather than a `BeanDefinitionParser`. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - package com.foo; - - import org.springframework.beans.factory.config.BeanDefinitionHolder; - import org.springframework.beans.factory.support.AbstractBeanDefinition; - import org.springframework.beans.factory.support.BeanDefinitionBuilder; - import org.springframework.beans.factory.xml.BeanDefinitionDecorator; - import org.springframework.beans.factory.xml.ParserContext; - import org.w3c.dom.Attr; - import org.w3c.dom.Node; - - import java.util.ArrayList; - import java.util.Arrays; - import java.util.List; - - public class JCacheInitializingBeanDefinitionDecorator implements BeanDefinitionDecorator { - - private static final String[] EMPTY_STRING_ARRAY = new String[0]; - - public BeanDefinitionHolder decorate(Node source, BeanDefinitionHolder holder, - ParserContext ctx) { - String initializerBeanName = registerJCacheInitializer(source, ctx); - createDependencyOnJCacheInitializer(holder, initializerBeanName); - return holder; - } - - private void createDependencyOnJCacheInitializer(BeanDefinitionHolder holder, - String initializerBeanName) { - AbstractBeanDefinition definition = ((AbstractBeanDefinition) holder.getBeanDefinition()); - String[] dependsOn = definition.getDependsOn(); - if (dependsOn == null) { - dependsOn = new String[]{initializerBeanName}; - } else { - List dependencies = new ArrayList(Arrays.asList(dependsOn)); - dependencies.add(initializerBeanName); - dependsOn = (String[]) dependencies.toArray(EMPTY_STRING_ARRAY); - } - definition.setDependsOn(dependsOn); - } - - private String registerJCacheInitializer(Node source, ParserContext ctx) { - String cacheName = ((Attr) source).getValue(); - String beanName = cacheName + "-initializer"; - if (!ctx.getRegistry().containsBeanDefinition(beanName)) { - BeanDefinitionBuilder initializer = BeanDefinitionBuilder.rootBeanDefinition(JCacheInitializer.class); - initializer.addConstructorArg(cacheName); - ctx.getRegistry().registerBeanDefinition(beanName, initializer.getBeanDefinition()); - } - return beanName; - } - - } ----- - -Lastly, the various artifacts need to be registered with the Spring XML infrastructure. - -[literal] -[subs="verbatim,quotes"] ----- -# in 'META-INF/spring.handlers' -http\://www.foo.com/schema/jcache=com.foo.JCacheNamespaceHandler ----- - -[literal] -[subs="verbatim,quotes"] ----- -# in 'META-INF/spring.schemas' -http\://www.foo.com/schema/jcache/jcache.xsd=com/foo/jcache.xsd ----- - - - - -[[extensible-xml-resources]] -=== Further Resources -Find below links to further resources concerning XML Schema and the extensible XML -support described in this chapter. - -* The http://www.w3.org/TR/2004/REC-xmlschema-1-20041028/[XML Schema Part 1: Structures - Second Edition] -* The http://www.w3.org/TR/2004/REC-xmlschema-2-20041028/[XML Schema Part 2: Datatypes - Second Edition] - - - - - -[[spring.tld]] -== spring.tld - - - - -[[spring.tld-intro]] -=== Introduction -One of the view technologies you can use with the Spring Framework is Java Server Pages -(JSPs). To help you implement views using Java Server Pages the Spring Framework -provides you with some tags for evaluating errors, setting themes and outputting -internationalized messages. - -Please note that the various tags generated by this form tag library are compliant with -the http://www.w3.org/TR/xhtml1/[XHTML-1.0-Strict specification] and attendant -http://www.w3.org/TR/xhtml1/dtds.html#a_dtd_XHTML-1.0-Strict[DTD]. - -This appendix describes the `spring.tld` tag library. - -* <> -* <> -* <> -* <> -* <> -* <> -* <> -* <> -* <> -* <> - - - - -[[spring.tld.bind]] -=== the bind tag - -Provides BindStatus object for the given bind path. The HTML escaping flag participates -in a page-wide or application-wide setting (i.e. by HtmlEscapeTag or a -"defaultHtmlEscape" context-param in web.xml). - -[[spring.tld.bind.table]] -.Attributes -[cols="1,1,1,3"] -|=== -| Attribute| Required?| Runtime Expression?| Description - -| htmlEscape -| false -| true -| Set HTML escaping for this tag, as boolean value. Overrides the default HTML escaping - setting for the current page. - -| ignoreNestedPath -| false -| true -| Set whether to ignore a nested path, if any. Default is to not ignore. - -| path -| true -| true -| The path to the bean or bean property to bind status information for. For instance - account.name, company.address.zipCode or just employee. The status object will - exported to the page scope, specifically for this bean or bean property -|=== - - - - -[[spring.tld.escapeBody]] -=== the escapeBody tag - -Escapes its enclosed body content, applying HTML escaping and/or JavaScript escaping. -The HTML escaping flag participates in a page-wide or application-wide setting (i.e. by -HtmlEscapeTag or a "defaultHtmlEscape" context-param in web.xml). - -[[spring.tld.escapeBody.table]] -.Attributes -[cols="1,1,1,3"] -|=== -| Attribute| Required?| Runtime Expression?| Description - -| htmlEscape -| false -| true -| Set HTML escaping for this tag, as boolean value. Overrides the default HTML escaping - setting for the current page. - -| javaScriptEscape -| false -| true -| Set JavaScript escaping for this tag, as boolean value. Default is false. -|=== - - - - -[[spring.tld.hasBindErrors]] -=== the hasBindErrors tag - -Provides Errors instance in case of bind errors. The HTML escaping flag participates in -a page-wide or application-wide setting (i.e. by HtmlEscapeTag or a "defaultHtmlEscape" -context-param in web.xml). - -[[spring.tld.hasBindErrors.table]] -.Attributes -[cols="1,1,1,3"] -|=== -| Attribute| Required?| Runtime Expression?| Description - -| htmlEscape -| false -| true -| Set HTML escaping for this tag, as boolean value. Overrides the default HTML escaping - setting for the current page. - -| name -| true -| true -| The name of the bean in the request, that needs to be inspected for errors. If errors - are available for this bean, they will be bound under the 'errors' key. -|=== - - - - -[[spring.tld.htmlEscape]] -=== the htmlEscape tag - -Sets default HTML escape value for the current page. Overrides a "defaultHtmlEscape" -context-param in web.xml, if any. - -[[spring.tld.htmlEscape.table]] -.Attributes -[cols="1,1,1,3"] -|=== -| Attribute| Required?| Runtime Expression?| Description - -| defaultHtmlEscape -| true -| true -| Set the default value for HTML escaping, to be put into the current PageContext. -|=== - - - - -[[spring.tld.message]] -=== the message tag - -Retrieves the message with the given code, or text if code isn't resolvable. The HTML -escaping flag participates in a page-wide or application-wide setting (i.e. by -HtmlEscapeTag or a "defaultHtmlEscape" context-param in web.xml). - -[[spring.tld.message.table]] -.Attributes -[cols="1,1,1,3"] -|=== -| Attribute| Required?| Runtime Expression?| Description - -| arguments -| false -| true -| Set optional message arguments for this tag, as a (comma-)delimited String (each - String argument can contain JSP EL), an Object array (used as argument array), or a - single Object (used as single argument). - -| argumentSeparator -| false -| true -| The separator character to be used for splitting the arguments string value; defaults - to a 'comma' (','). - -| code -| false -| true -| The code (key) to use when looking up the message. If code is not provided, the text - attribute will be used. - -| htmlEscape -| false -| true -| Set HTML escaping for this tag, as boolean value. Overrides the default HTML escaping - setting for the current page. - -| javaScriptEscape -| false -| true -| Set JavaScript escaping for this tag, as boolean value. Default is false. - -| message -| false -| true -| A MessageSourceResolvable argument (direct or through JSP EL). Fits nicely when used - in conjunction with Spring's own validation error classes which all implement the - MessageSourceResolvable interface. For example, this allows you to iterate over all of - the errors in a form, passing each error (using a runtime expression) as the value of - this 'message' attribute, thus effecting the easy display of such error messages. - -| scope -| false -| true -| The scope to use when exporting the result to a variable. This attribute is only used - when var is also set. Possible values are page, request, session and application. - -| text -| false -| true -| Default text to output when a message for the given code could not be found. If both - text and code are not set, the tag will output null. - -| var -| false -| true -| The string to use when binding the result to the page, request, session or application - scope. If not specified, the result gets outputted to the writer (i.e. typically - directly to the JSP). -|=== - - - - -[[spring.tld.nestedPath]] -=== the nestedPath tag - -Sets a nested path to be used by the bind tag's path. - -[[spring.tld.nestedPath.table]] -.Attributes -[cols="1,1,1,3"] -|=== -| Attribute| Required?| Runtime Expression?| Description - -| path -| true -| true -| Set the path that this tag should apply. E.g. 'customer' to allow bind paths like - 'address.street' rather than 'customer.address.street'. -|=== - - - - -[[spring.tld.theme]] -=== the theme tag - -Retrieves the theme message with the given code, or text if code isn't resolvable. The -HTML escaping flag participates in a page-wide or application-wide setting (i.e. by -HtmlEscapeTag or a "defaultHtmlEscape" context-param in web.xml). - -[[spring.tld.theme.table]] -.Attributes -[cols="1,1,1,3"] -|=== -| Attribute| Required?| Runtime Expression?| Description - -| arguments -| false -| true -| Set optional message arguments for this tag, as a (comma-)delimited String (each - String argument can contain JSP EL), an Object array (used as argument array), or a - single Object (used as single argument). - -| argumentSeparator -| false -| true -| The separator character to be used for splitting the arguments string value; defaults - to a 'comma' (','). - -| code -| false -| true -| The code (key) to use when looking up the message. If code is not provided, the text - attribute will be used. - -| htmlEscape -| false -| true -| Set HTML escaping for this tag, as boolean value. Overrides the default HTML escaping - setting for the current page. - -| javaScriptEscape -| false -| true -| Set JavaScript escaping for this tag, as boolean value. Default is false. - -| message -| false -| true -| A MessageSourceResolvable argument (direct or through JSP EL). - -| scope -| false -| true -| The scope to use when exporting the result to a variable. This attribute is only used - when var is also set. Possible values are page, request, session and application. - -| text -| false -| true -| Default text to output when a message for the given code could not be found. If both - text and code are not set, the tag will output null. - -| var -| false -| true -| The string to use when binding the result to the page, request, session or application - scope. If not specified, the result gets outputted to the writer (i.e. typically - directly to the JSP). -|=== - - - - -[[spring.tld.transform]] -=== the transform tag - -Provides transformation of variables to Strings, using an appropriate custom -PropertyEditor from BindTag (can only be used inside BindTag). The HTML escaping flag -participates in a page-wide or application-wide setting (i.e. by HtmlEscapeTag or a -'defaultHtmlEscape' context-param in web.xml). - -[[spring.tld.transform.table]] -.Attributes -[cols="1,1,1,3"] -|=== -| Attribute| Required?| Runtime Expression?| Description - -| htmlEscape -| false -| true -| Set HTML escaping for this tag, as boolean value. Overrides the default HTML escaping - setting for the current page. - -| scope -| false -| true -| The scope to use when exported the result to a variable. This attribute is only used - when var is also set. Possible values are page, request, session and application. - -| value -| true -| true -| The value to transform. This is the actual object you want to have transformed (for - instance a Date). Using the PropertyEditor that is currently in use by the - 'spring:bind' tag. - -| var -| false -| true -| The string to use when binding the result to the page, request, session or application - scope. If not specified, the result gets outputted to the writer (i.e. typically - directly to the JSP). -|=== - - - - -[[spring.tld.url]] -=== the url tag - -Creates URLs with support for URI template variables, HTML/XML escaping, and Javascript -escaping. Modeled after the JSTL c:url tag with backwards compatibility in mind. - -[[spring.tld.url.table]] -.Attributes -[cols="1,1,1,3"] -|=== -| Attribute| Required?| Runtime Expression?| Description - -| url -| true -| true -| The URL to build. This value can include template {placeholders} that are replaced - with the URL encoded value of the named parameter. Parameters must be defined using - the param tag inside the body of this tag. - -| context -| false -| true -| Specifies a remote application context path. The default is the current application - context path. - -| var -| false -| true -| The name of the variable to export the URL value to. If not specified the URL is - written as output. - -| scope -| false -| true -| The scope for the var. 'application', 'session', 'request' and 'page' scopes are - supported. Defaults to page scope. This attribute has no effect unless the var - attribute is also defined. - -| htmlEscape -| false -| true -| Set HTML escaping for this tag, as a boolean value. Overrides the default HTML - escaping setting for the current page. - -| javaScriptEscape -| false -| true -| Set JavaScript escaping for this tag, as a boolean value. Default is false. -|=== - - - - -[[spring.tld.eval]] -=== the eval tag - -Evaluates a Spring expression (SpEL) and either prints the result or assigns it to a -variable. - -[[spring.tld.eval.table]] -[cols="1,1,1,3"] -.Attributes -|=== -| Attribute| Required?| Runtime Expression?| Description - -| expression -| true -| true -| The expression to evaluate. - -| var -| false -| true -| The name of the variable to export the evaluation result to. If not specified the - evaluation result is converted to a String and written as output. - -| scope -| false -| true -| The scope for the var. 'application', 'session', 'request' and 'page' scopes are - supported. Defaults to page scope. This attribute has no effect unless the var - attribute is also defined. - -| htmlEscape -| false -| true -| Set HTML escaping for this tag, as a boolean value. Overrides the default HTML - escaping setting for the current page. - -| javaScriptEscape -| false -| true -| Set JavaScript escaping for this tag, as a boolean value. Default is false. -|=== - - - - - -[[spring-form.tld]] -== spring-form.tld - - - - -[[spring-form.tld-intro]] -=== Introduction -One of the view technologies you can use with the Spring Framework is Java Server Pages -(JSPs). To help you implement views using Java Server Pages the Spring Framework -provides you with some tags for evaluating errors, setting themes and outputting -internationalized messages. - -Please note that the various tags generated by this form tag library are compliant with -the http://www.w3.org/TR/xhtml1/[XHTML-1.0-Strict specification] and attendant -http://www.w3.org/TR/xhtml1/dtds.html#a_dtd_XHTML-1.0-Strict[DTD]. - -This appendix describes the `spring-form.tld` tag library. - -* <> -* <> -* <> -* <> -* <> -* <> -* <> -* <> -* <> -* <> -* <> -* <> -* <> -* <> - - - - -[[spring-form.tld.checkbox]] -=== the checkbox tag - -Renders an HTML 'input' tag with type 'checkbox'. - -[[spring-form.tld.checkbox.attrs.tbl]] -.Attributes -[cols="1,1,1,3"] -|=== -| Attribute| Required?| Runtime Expression?| Description - -| accesskey -| false -| true -| HTML Standard Attribute - -| cssClass -| false -| true -| Equivalent to "class" - HTML Optional Attribute - -| cssErrorClass -| false -| true -| Equivalent to "class" - HTML Optional Attribute. Used when the bound field has errors. - -| cssStyle -| false -| true -| Equivalent to "style" - HTML Optional Attribute - -| dir -| false -| true -| HTML Standard Attribute - -| disabled -| false -| true -| HTML Optional Attribute. Setting the value of this attribute to 'true' (without the - quotes) will disable the HTML element. - -| htmlEscape -| false -| true -| Enable/disable HTML escaping of rendered values. - -| id -| false -| true -| HTML Standard Attribute - -| label -| false -| true -| Value to be displayed as part of the tag - -| lang -| false -| true -| HTML Standard Attribute - -| onblur -| false -| true -| HTML Event Attribute - -| onchange -| false -| true -| HTML Event Attribute - -| onclick -| false -| true -| HTML Event Attribute - -| ondblclick -| false -| true -| HTML Event Attribute - -| onfocus -| false -| true -| HTML Event Attribute - -| onkeydown -| false -| true -| HTML Event Attribute - -| onkeypress -| false -| true -| HTML Event Attribute - -| onkeyup -| false -| true -| HTML Event Attribute - -| onmousedown -| false -| true -| HTML Event Attribute - -| onmousemove -| false -| true -| HTML Event Attribute - -| onmouseout -| false -| true -| HTML Event Attribute - -| onmouseover -| false -| true -| HTML Event Attribute - -| onmouseup -| false -| true -| HTML Event Attribute - -| path -| true -| true -| Path to property for data binding - -| tabindex -| false -| true -| HTML Standard Attribute - -| title -| false -| true -| HTML Standard Attribute - -| value -| false -| true -| HTML Optional Attribute -|=== - - - - -[[spring-form.tld.checkboxes]] -=== the checkboxes tag - -Renders multiple HTML 'input' tags with type 'checkbox'. - -[[spring-form.tld.checkboxes.table]] -.Attributes -[cols="1,1,1,3"] -|=== -| Attribute| Required?| Runtime Expression?| Description - -| accesskey -| false -| true -| HTML Standard Attribute - -| cssClass -| false -| true -| Equivalent to "class" - HTML Optional Attribute - -| cssErrorClass -| false -| true -| Equivalent to "class" - HTML Optional Attribute. Used when the bound field has errors. - -| cssStyle -| false -| true -| Equivalent to "style" - HTML Optional Attribute - -| delimiter -| false -| true -| Delimiter to use between each 'input' tag with type 'checkbox'. There is no delimiter - by default. - -| dir -| false -| true -| HTML Standard Attribute - -| disabled -| false -| true -| HTML Optional Attribute. Setting the value of this attribute to 'true' (without the - quotes) will disable the HTML element. - -| element -| false -| true -| Specifies the HTML element that is used to enclose each 'input' tag with type - 'checkbox'. Defaults to 'span'. - -| htmlEscape -| false -| true -| Enable/disable HTML escaping of rendered values. - -| id -| false -| true -| HTML Standard Attribute - -| itemLabel -| false -| true -| Value to be displayed as part of the 'input' tags with type 'checkbox' - -| items -| true -| true -| The Collection, Map or array of objects used to generate the 'input' tags with type - 'checkbox' - -| itemValue -| false -| true -| Name of the property mapped to 'value' attribute of the 'input' tags with type - 'checkbox' - -| lang -| false -| true -| HTML Standard Attribute - -| onblur -| false -| true -| HTML Event Attribute - -| onchange -| false -| true -| HTML Event Attribute - -| onclick -| false -| true -| HTML Event Attribute - -| ondblclick -| false -| true -| HTML Event Attribute - -| onfocus -| false -| true -| HTML Event Attribute - -| onkeydown -| false -| true -| HTML Event Attribute - -| onkeypress -| false -| true -| HTML Event Attribute - -| onkeyup -| false -| true -| HTML Event Attribute - -| onmousedown -| false -| true -| HTML Event Attribute - -| onmousemove -| false -| true -| HTML Event Attribute - -| onmouseout -| false -| true -| HTML Event Attribute - -| onmouseover -| false -| true -| HTML Event Attribute - -| onmouseup -| false -| true -| HTML Event Attribute - -| path -| true -| true -| Path to property for data binding - -| tabindex -| false -| true -| HTML Standard Attribute - -| title -| false -| true -| HTML Standard Attribute -|=== - - - - -[[spring-form.tld.errors]] -=== the errors tag - -Renders field errors in an HTML 'span' tag. - -[[spring-form.tld.errors.table]] -.Attributes -[cols="1,1,1,3"] -|=== -| Attribute| Required?| Runtime Expression?| Description - -| cssClass -| false -| true -| Equivalent to "class" - HTML Optional Attribute - -| cssStyle -| false -| true -| Equivalent to "style" - HTML Optional Attribute - -| delimiter -| false -| true -| Delimiter for displaying multiple error messages. Defaults to the br tag. - -| dir -| false -| true -| HTML Standard Attribute - -| element -| false -| true -| Specifies the HTML element that is used to render the enclosing errors. - -| htmlEscape -| false -| true -| Enable/disable HTML escaping of rendered values. - -| id -| false -| true -| HTML Standard Attribute - -| lang -| false -| true -| HTML Standard Attribute - -| onclick -| false -| true -| HTML Event Attribute - -| ondblclick -| false -| true -| HTML Event Attribute - -| onkeydown -| false -| true -| HTML Event Attribute - -| onkeypress -| false -| true -| HTML Event Attribute - -| onkeyup -| false -| true -| HTML Event Attribute - -| onmousedown -| false -| true -| HTML Event Attribute - -| onmousemove -| false -| true -| HTML Event Attribute - -| onmouseout -| false -| true -| HTML Event Attribute - -| onmouseover -| false -| true -| HTML Event Attribute - -| onmouseup -| false -| true -| HTML Event Attribute - -| path -| false -| true -| Path to errors object for data binding - -| tabindex -| false -| true -| HTML Standard Attribute - -| title -| false -| true -| HTML Standard Attribute -|=== - - - - -[[spring-form.tld.form]] -=== the form tag - -Renders an HTML 'form' tag and exposes a binding path to inner tags for binding. - -[[spring-form.tld.form.table]] -.Attributes -[cols="1,1,1,3"] -|=== -| Attribute| Required?| Runtime Expression?| Description - -| acceptCharset -| false -| true -| Specifies the list of character encodings for input data that is accepted by the - server processing this form. The value is a space- and/or comma-delimited list of - charset values. The client must interpret this list as an exclusive-or list, i.e., the - server is able to accept any single character encoding per entity received. - -| action -| false -| true -| HTML Required Attribute - -| commandName -| false -| true -| Name of the model attribute under which the form object is exposed. Defaults to - 'command'. - -| cssClass -| false -| true -| Equivalent to "class" - HTML Optional Attribute - -| cssStyle -| false -| true -| Equivalent to "style" - HTML Optional Attribute - -| dir -| false -| true -| HTML Standard Attribute - -| enctype -| false -| true -| HTML Optional Attribute - -| htmlEscape -| false -| true -| Enable/disable HTML escaping of rendered values. - -| id -| false -| true -| HTML Standard Attribute - -| lang -| false -| true -| HTML Standard Attribute - -| method -| false -| true -| HTML Optional Attribute - -| modelAttribute -| false -| true -| Name of the model attribute under which the form object is exposed. Defaults to - 'command'. - -| name -| false -| true -| HTML Standard Attribute - added for backwards compatibility cases - -| onclick -| false -| true -| HTML Event Attribute - -| ondblclick -| false -| true -| HTML Event Attribute - -| onkeydown -| false -| true -| HTML Event Attribute - -| onkeypress -| false -| true -| HTML Event Attribute - -| onkeyup -| false -| true -| HTML Event Attribute - -| onmousedown -| false -| true -| HTML Event Attribute - -| onmousemove -| false -| true -| HTML Event Attribute - -| onmouseout -| false -| true -| HTML Event Attribute - -| onmouseover -| false -| true -| HTML Event Attribute - -| onmouseup -| false -| true -| HTML Event Attribute - -| onreset -| false -| true -| HTML Event Attribute - -| onsubmit -| false -| true -| HTML Event Attribute - -| target -| false -| true -| HTML Optional Attribute - -| title -| false -| true -| HTML Standard Attribute -|=== - - - - -[[spring-form.tld.hidden]] -=== the hidden tag - -Renders an HTML 'input' tag with type 'hidden' using the bound value. - -[[spring-form.tld.hidden.table]] -.Attributes -[cols="1,1,1,3"] -|=== -| Attribute| Required?| Runtime Expression?| Description - -| htmlEscape -| false -| true -| Enable/disable HTML escaping of rendered values. - -| id -| false -| true -| HTML Standard Attribute - -| path -| true -| true -| Path to property for data binding -|=== - - - - -[[spring-form.tld.input]] -=== the input tag - -Renders an HTML 'input' tag with type 'text' using the bound value. - -[[spring-form.tld.input.table]] -.Attributes -[cols="1,1,1,3"] -|=== -| Attribute| Required?| Runtime Expression?| Description - -| accesskey -| false -| true -| HTML Standard Attribute - -| alt -| false -| true -| HTML Optional Attribute - -| autocomplete -| false -| true -| Common Optional Attribute - -| cssClass -| false -| true -| Equivalent to "class" - HTML Optional Attribute - -| cssErrorClass -| false -| true -| Equivalent to "class" - HTML Optional Attribute. Used when the bound field has errors. - -| cssStyle -| false -| true -| Equivalent to "style" - HTML Optional Attribute - -| dir -| false -| true -| HTML Standard Attribute - -| disabled -| false -| true -| HTML Optional Attribute. Setting the value of this attribute to 'true' (without the - quotes) will disable the HTML element. - -| htmlEscape -| false -| true -| Enable/disable HTML escaping of rendered values. - -| id -| false -| true -| HTML Standard Attribute - -| lang -| false -| true -| HTML Standard Attribute - -| maxlength -| false -| true -| HTML Optional Attribute - -| onblur -| false -| true -| HTML Event Attribute - -| onchange -| false -| true -| HTML Event Attribute - -| onclick -| false -| true -| HTML Event Attribute - -| ondblclick -| false -| true -| HTML Event Attribute - -| onfocus -| false -| true -| HTML Event Attribute - -| onkeydown -| false -| true -| HTML Event Attribute - -| onkeypress -| false -| true -| HTML Event Attribute - -| onkeyup -| false -| true -| HTML Event Attribute - -| onmousedown -| false -| true -| HTML Event Attribute - -| onmousemove -| false -| true -| HTML Event Attribute - -| onmouseout -| false -| true -| HTML Event Attribute - -| onmouseover -| false -| true -| HTML Event Attribute - -| onmouseup -| false -| true -| HTML Event Attribute - -| onselect -| false -| true -| HTML Event Attribute - -| path -| true -| true -| Path to property for data binding - -| readonly -| false -| true -| HTML Optional Attribute. Setting the value of this attribute to 'true' (without the - quotes) will make the HTML element readonly. - -| size -| false -| true -| HTML Optional Attribute - -| tabindex -| false -| true -| HTML Standard Attribute - -| title -| false -| true -| HTML Standard Attribute -|=== - - - - -[[spring-form.tld.label]] -=== the label tag - -Renders a form field label in an HTML 'label' tag. - -[[spring-form.tld.label.table]] -[cols="1,1,1,3"] -.Attributes -|=== -| Attribute| Required?| Runtime Expression?| Description - -| cssClass -| false -| true -| Equivalent to "class" - HTML Optional Attribute. - -| cssErrorClass -| false -| true -| Equivalent to "class" - HTML Optional Attribute. Used only when errors are present. - -| cssStyle -| false -| true -| Equivalent to "style" - HTML Optional Attribute - -| dir -| false -| true -| HTML Standard Attribute - -| for -| false -| true -| HTML Standard Attribute - -| htmlEscape -| false -| true -| Enable/disable HTML escaping of rendered values. - -| id -| false -| true -| HTML Standard Attribute - -| lang -| false -| true -| HTML Standard Attribute - -| onclick -| false -| true -| HTML Event Attribute - -| ondblclick -| false -| true -| HTML Event Attribute - -| onkeydown -| false -| true -| HTML Event Attribute - -| onkeypress -| false -| true -| HTML Event Attribute - -| onkeyup -| false -| true -| HTML Event Attribute - -| onmousedown -| false -| true -| HTML Event Attribute - -| onmousemove -| false -| true -| HTML Event Attribute - -| onmouseout -| false -| true -| HTML Event Attribute - -| onmouseover -| false -| true -| HTML Event Attribute - -| onmouseup -| false -| true -| HTML Event Attribute - -| path -| true -| true -| Path to errors object for data binding - -| tabindex -| false -| true -| HTML Standard Attribute - -| title -| false -| true -| HTML Standard Attribute -|=== - - - - -[[spring-form.tld.option]] -=== the option tag - -Renders a single HTML 'option'. Sets 'selected' as appropriate based on bound value. - -[[spring-form.tld.option.table]] -.Attributes -[cols="1,1,1,3"] -|=== -| Attribute| Required?| Runtime Expression?| Description - -| cssClass -| false -| true -| Equivalent to "class" - HTML Optional Attribute - -| cssErrorClass -| false -| true -| Equivalent to "class" - HTML Optional Attribute. Used when the bound field has errors. - -| cssStyle -| false -| true -| Equivalent to "style" - HTML Optional Attribute - -| dir -| false -| true -| HTML Standard Attribute - -| disabled -| false -| true -| HTML Optional Attribute. Setting the value of this attribute to 'true' (without the - quotes) will disable the HTML element. - -| htmlEscape -| false -| true -| Enable/disable HTML escaping of rendered values. - -| id -| false -| true -| HTML Standard Attribute - -| label -| false -| true -| HTML Optional Attribute - -| lang -| false -| true -| HTML Standard Attribute - -| onclick -| false -| true -| HTML Event Attribute - -| ondblclick -| false -| true -| HTML Event Attribute - -| onkeydown -| false -| true -| HTML Event Attribute - -| onkeypress -| false -| true -| HTML Event Attribute - -| onkeyup -| false -| true -| HTML Event Attribute - -| onmousedown -| false -| true -| HTML Event Attribute - -| onmousemove -| false -| true -| HTML Event Attribute - -| onmouseout -| false -| true -| HTML Event Attribute - -| onmouseover -| false -| true -| HTML Event Attribute - -| onmouseup -| false -| true -| HTML Event Attribute - -| tabindex -| false -| true -| HTML Standard Attribute - -| title -| false -| true -| HTML Standard Attribute - -| value -| true -| true -| HTML Optional Attribute -|=== - - - - -[[spring-form.tld.options]] -=== the options tag - -Renders a list of HTML 'option' tags. Sets 'selected' as appropriate based on bound value. - -[[spring-form.tld.options.table]] -.Attributes -[cols="1,1,1,3"] -|=== -| Attribute| Required?| Runtime Expression?| Description - -| cssClass -| false -| true -| Equivalent to "class" - HTML Optional Attribute - -| cssErrorClass -| false -| true -| Equivalent to "class" - HTML Optional Attribute. Used when the bound field has errors. - -| cssStyle -| false -| true -| Equivalent to "style" - HTML Optional Attribute - -| dir -| false -| true -| HTML Standard Attribute - -| disabled -| false -| true -| HTML Optional Attribute. Setting the value of this attribute to 'true' (without the - quotes) will disable the HTML element. - -| htmlEscape -| false -| true -| Enable/disable HTML escaping of rendered values. - -| id -| false -| true -| HTML Standard Attribute - -| itemLabel -| false -| true -| Name of the property mapped to the inner text of the 'option' tag - -| items -| true -| true -| The Collection, Map or array of objects used to generate the inner 'option' tags - -| itemValue -| false -| true -| Name of the property mapped to 'value' attribute of the 'option' tag - -| lang -| false -| true -| HTML Standard Attribute - -| onclick -| false -| true -| HTML Event Attribute - -| ondblclick -| false -| true -| HTML Event Attribute - -| onkeydown -| false -| true -| HTML Event Attribute - -| onkeypress -| false -| true -| HTML Event Attribute - -| onkeyup -| false -| true -| HTML Event Attribute - -| onmousedown -| false -| true -| HTML Event Attribute - -| onmousemove -| false -| true -| HTML Event Attribute - -| onmouseout -| false -| true -| HTML Event Attribute - -| onmouseover -| false -| true -| HTML Event Attribute - -| onmouseup -| false -| true -| HTML Event Attribute - -| tabindex -| false -| true -| HTML Standard Attribute - -| title -| false -| true -| HTML Standard Attribute -|=== - - - - -[[spring-form.tld.password]] -=== the password tag - -Renders an HTML 'input' tag with type 'password' using the bound value. - -[[spring-form.tld.password.table]] -.Attributes -[cols="1,1,1,3"] -|=== -| Attribute| Required?| Runtime Expression?| Description - -| accesskey -| false -| true -| HTML Standard Attribute - -| alt -| false -| true -| HTML Optional Attribute - -| autocomplete -| false -| true -| Common Optional Attribute - -| cssClass -| false -| true -| Equivalent to "class" - HTML Optional Attribute - -| cssErrorClass -| false -| true -| Equivalent to "class" - HTML Optional Attribute. Used when the bound field has errors. - -| cssStyle -| false -| true -| Equivalent to "style" - HTML Optional Attribute - -| dir -| false -| true -| HTML Standard Attribute - -| disabled -| false -| true -| HTML Optional Attribute. Setting the value of this attribute to 'true' (without the - quotes) will disable the HTML element. - -| htmlEscape -| false -| true -| Enable/disable HTML escaping of rendered values. - -| id -| false -| true -| HTML Standard Attribute - -| lang -| false -| true -| HTML Standard Attribute - -| maxlength -| false -| true -| HTML Optional Attribute - -| onblur -| false -| true -| HTML Event Attribute - -| onchange -| false -| true -| HTML Event Attribute - -| onclick -| false -| true -| HTML Event Attribute - -| ondblclick -| false -| true -| HTML Event Attribute - -| onfocus -| false -| true -| HTML Event Attribute - -| onkeydown -| false -| true -| HTML Event Attribute - -| onkeypress -| false -| true -| HTML Event Attribute - -| onkeyup -| false -| true -| HTML Event Attribute - -| onmousedown -| false -| true -| HTML Event Attribute - -| onmousemove -| false -| true -| HTML Event Attribute - -| onmouseout -| false -| true -| HTML Event Attribute - -| onmouseover -| false -| true -| HTML Event Attribute - -| onmouseup -| false -| true -| HTML Event Attribute - -| onselect -| false -| true -| HTML Event Attribute - -| path -| true -| true -| Path to property for data binding - -| readonly -| false -| true -| HTML Optional Attribute. Setting the value of this attribute to 'true' (without the - quotes) will make the HTML element readonly. - -| showPassword -| false -| true -| Is the password value to be shown? Defaults to false. - -| size -| false -| true -| HTML Optional Attribute - -| tabindex -| false -| true -| HTML Standard Attribute - -| title -| false -| true -| HTML Standard Attribute -|=== - - - - -[[spring-form.tld.radiobutton]] -=== the radiobutton tag - -Renders an HTML 'input' tag with type 'radio'. - -[[spring-form.tld.radiobutton.table]] -.Attributes -[cols="1,1,1,3"] -|=== -| Attribute| Required?| Runtime Expression?| Description - -| accesskey -| false -| true -| HTML Standard Attribute - -| cssClass -| false -| true -| Equivalent to "class" - HTML Optional Attribute - -| cssErrorClass -| false -| true -| Equivalent to "class" - HTML Optional Attribute. Used when the bound field has errors. - -| cssStyle -| false -| true -| Equivalent to "style" - HTML Optional Attribute - -| dir -| false -| true -| HTML Standard Attribute - -| disabled -| false -| true -| HTML Optional Attribute. Setting the value of this attribute to 'true' (without the - quotes) will disable the HTML element. - -| htmlEscape -| false -| true -| Enable/disable HTML escaping of rendered values. - -| id -| false -| true -| HTML Standard Attribute - -| label -| false -| true -| Value to be displayed as part of the tag - -| lang -| false -| true -| HTML Standard Attribute - -| onblur -| false -| true -| HTML Event Attribute - -| onchange -| false -| true -| HTML Event Attribute - -| onclick -| false -| true -| HTML Event Attribute - -| ondblclick -| false -| true -| HTML Event Attribute - -| onfocus -| false -| true -| HTML Event Attribute - -| onkeydown -| false -| true -| HTML Event Attribute - -| onkeypress -| false -| true -| HTML Event Attribute - -| onkeyup -| false -| true -| HTML Event Attribute - -| onmousedown -| false -| true -| HTML Event Attribute - -| onmousemove -| false -| true -| HTML Event Attribute - -| onmouseout -| false -| true -| HTML Event Attribute - -| onmouseover -| false -| true -| HTML Event Attribute - -| onmouseup -| false -| true -| HTML Event Attribute - -| path -| true -| true -| Path to property for data binding - -| tabindex -| false -| true -| HTML Standard Attribute - -| title -| false -| true -| HTML Standard Attribute - -| value -| false -| true -| HTML Optional Attribute -|=== - - - - -[[spring-form.tld.radiobuttons]] -=== the radiobuttons tag - -Renders multiple HTML 'input' tags with type 'radio'. - -[[spring-form.tld.radiobuttons.table]] -.Attributes -[cols="1,1,1,3"] -|=== -| Attribute| Required?| Runtime Expression?| Description - -| accesskey -| false -| true -| HTML Standard Attribute - -| cssClass -| false -| true -| Equivalent to "class" - HTML Optional Attribute - -| cssErrorClass -| false -| true -| Equivalent to "class" - HTML Optional Attribute. Used when the bound field has errors. - -| cssStyle -| false -| true -| Equivalent to "style" - HTML Optional Attribute - -| delimiter -| false -| true -| Delimiter to use between each 'input' tag with type 'radio'. There is no delimiter by - default. - -| dir -| false -| true -| HTML Standard Attribute - -| disabled -| false -| true -| HTML Optional Attribute. Setting the value of this attribute to 'true' (without the - quotes) will disable the HTML element. - -| element -| false -| true -| Specifies the HTML element that is used to enclose each 'input' tag with type 'radio'. - Defaults to 'span'. - -| htmlEscape -| false -| true -| Enable/disable HTML escaping of rendered values. - -| id -| false -| true -| HTML Standard Attribute - -| itemLabel -| false -| true -| Value to be displayed as part of the 'input' tags with type 'radio' - -| items -| true -| true -| The Collection, Map or array of objects used to generate the 'input' tags with type - 'radio' - -| itemValue -| false -| true -| Name of the property mapped to 'value' attribute of the 'input' tags with type 'radio' - -| lang -| false -| true -| HTML Standard Attribute - -| onblur -| false -| true -| HTML Event Attribute - -| onchange -| false -| true -| HTML Event Attribute - -| onclick -| false -| true -| HTML Event Attribute - -| ondblclick -| false -| true -| HTML Event Attribute - -| onfocus -| false -| true -| HTML Event Attribute - -| onkeydown -| false -| true -| HTML Event Attribute - -| onkeypress -| false -| true -| HTML Event Attribute - -| onkeyup -| false -| true -| HTML Event Attribute - -| onmousedown -| false -| true -| HTML Event Attribute - -| onmousemove -| false -| true -| HTML Event Attribute - -| onmouseout -| false -| true -| HTML Event Attribute - -| onmouseover -| false -| true -| HTML Event Attribute - -| onmouseup -| false -| true -| HTML Event Attribute - -| path -| true -| true -| Path to property for data binding - -| tabindex -| false -| true -| HTML Standard Attribute - -| title -| false -| true -| HTML Standard Attribute -|=== - - - - -[[spring-form.tld.select]] -=== the select tag - -Renders an HTML 'select' element. Supports databinding to the selected option. - -[[spring-form.tld.select.table]] -.Attributes -[cols="1,1,1,3"] -|=== -| Attribute| Required?| Runtime Expression?| Description - -| accesskey -| false -| true -| HTML Standard Attribute - -| cssClass -| false -| true -| Equivalent to "class" - HTML Optional Attribute - -| cssErrorClass -| false -| true -| Equivalent to "class" - HTML Optional Attribute. Used when the bound field has errors. - -| cssStyle -| false -| true -| Equivalent to "style" - HTML Optional Attribute - -| dir -| false -| true -| HTML Standard Attribute - -| disabled -| false -| true -| HTML Optional Attribute. Setting the value of this attribute to 'true' (without the - quotes) will disable the HTML element. - -| htmlEscape -| false -| true -| Enable/disable HTML escaping of rendered values. - -| id -| false -| true -| HTML Standard Attribute - -| itemLabel -| false -| true -| Name of the property mapped to the inner text of the 'option' tag - -| items -| false -| true -| The Collection, Map or array of objects used to generate the inner 'option' tags - -| itemValue -| false -| true -| Name of the property mapped to 'value' attribute of the 'option' tag - -| lang -| false -| true -| HTML Standard Attribute - -| multiple -| false -| true -| HTML Optional Attribute - -| onblur -| false -| true -| HTML Event Attribute - -| onchange -| false -| true -| HTML Event Attribute - -| onclick -| false -| true -| HTML Event Attribute - -| ondblclick -| false -| true -| HTML Event Attribute - -| onfocus -| false -| true -| HTML Event Attribute - -| onkeydown -| false -| true -| HTML Event Attribute - -| onkeypress -| false -| true -| HTML Event Attribute - -| onkeyup -| false -| true -| HTML Event Attribute - -| onmousedown -| false -| true -| HTML Event Attribute - -| onmousemove -| false -| true -| HTML Event Attribute - -| onmouseout -| false -| true -| HTML Event Attribute - -| onmouseover -| false -| true -| HTML Event Attribute - -| onmouseup -| false -| true -| HTML Event Attribute - -| path -| true -| true -| Path to property for data binding - -| size -| false -| true -| HTML Optional Attribute - -| tabindex -| false -| true -| HTML Standard Attribute - -| title -| false -| true -| HTML Standard Attribute -|=== - - - - -[[spring-form.tld.textarea]] -=== the textarea tag - -Renders an HTML 'textarea'. - -[[spring-form.tld.textarea.table]] -.Attributes -[cols="1,1,1,3"] -|=== -| Attribute| Required?| Runtime Expression?| Description - -| accesskey -| false -| true -| HTML Standard Attribute - -| cols -| false -| true -| HTML Required Attribute - -| cssClass -| false -| true -| Equivalent to "class" - HTML Optional Attribute - -| cssErrorClass -| false -| true -| Equivalent to "class" - HTML Optional Attribute. Used when the bound field has errors. - -| cssStyle -| false -| true -| Equivalent to "style" - HTML Optional Attribute - -| dir -| false -| true -| HTML Standard Attribute - -| disabled -| false -| true -| HTML Optional Attribute. Setting the value of this attribute to 'true' (without the - quotes) will disable the HTML element. - -| htmlEscape -| false -| true -| Enable/disable HTML escaping of rendered values. - -| id -| false -| true -| HTML Standard Attribute - -| lang -| false -| true -| HTML Standard Attribute - -| onblur -| false -| true -| HTML Event Attribute - -| onchange -| false -| true -| HTML Event Attribute - -| onclick -| false -| true -| HTML Event Attribute - -| ondblclick -| false -| true -| HTML Event Attribute - -| onfocus -| false -| true -| HTML Event Attribute - -| onkeydown -| false -| true -| HTML Event Attribute - -| onkeypress -| false -| true -| HTML Event Attribute - -| onkeyup -| false -| true -| HTML Event Attribute - -| onmousedown -| false -| true -| HTML Event Attribute - -| onmousemove -| false -| true -| HTML Event Attribute - -| onmouseout -| false -| true -| HTML Event Attribute - -| onmouseover -| false -| true -| HTML Event Attribute - -| onmouseup -| false -| true -| HTML Event Attribute - -| onselect -| false -| true -| HTML Event Attribute - -| path -| true -| true -| Path to property for data binding - -| readonly -| false -| true -| HTML Optional Attribute. Setting the value of this attribute to 'true' (without the - quotes) will make the HTML element readonly. - -| rows -| false -| true -| HTML Required Attribute - -| tabindex -| false -| true -| HTML Standard Attribute - -| title -| false -| true -| HTML Standard Attribute -|=== diff --git a/src/asciidoc/beans.adoc b/src/asciidoc/beans.adoc new file mode 100644 index 000000000000..445d3a63fef8 --- /dev/null +++ b/src/asciidoc/beans.adoc @@ -0,0 +1,7892 @@ +[[beans]] +== The IoC container + + + + +[[beans-introduction]] +=== Introduction to the Spring IoC container and beans +This chapter covers the Spring Framework implementation of the Inversion of Control +(IoC) footnote:[See pass:specialcharacters,macros[<>] ] principle. IoC +is also known as __dependency injection__ (DI). It is a process whereby objects define +their dependencies, that is, the other objects they work with, only through constructor +arguments, arguments to a factory method, or properties that are set on the object +instance after it is constructed or returned from a factory method. The container then +__injects__ those dependencies when it creates the bean. This process is fundamentally +the inverse, hence the name __Inversion of Control__ (IoC), of the bean itself +controlling the instantiation or location of its dependencies by using direct +construction of classes, or a mechanism such as the __Service Locator__ pattern. + +The `org.springframework.beans` and `org.springframework.context` packages are the basis +for Spring Framework's IoC container. The +{javadoc-baseurl}/org/springframework/beans/factory/BeanFactory.html[`BeanFactory`] +interface provides an advanced configuration mechanism capable of managing any type of +object. +{javadoc-baseurl}/org/springframework/context/ApplicationContext.html[`ApplicationContext`] +is a sub-interface of `BeanFactory`. It adds easier integration with Spring's AOP +features; message resource handling (for use in internationalization), event +publication; and application-layer specific contexts such as the `WebApplicationContext` +for use in web applications. + +In short, the `BeanFactory` provides the configuration framework and basic +functionality, and the `ApplicationContext` adds more enterprise-specific functionality. +The `ApplicationContext` is a complete superset of the `BeanFactory`, and is used +exclusively in this chapter in descriptions of Spring's IoC container. For more +information on using the `BeanFactory` instead of the `ApplicationContext,` refer to +<>. + +In Spring, the objects that form the backbone of your application and that are managed +by the Spring IoC __container__ are called __beans__. A bean is an object that is +instantiated, assembled, and otherwise managed by a Spring IoC container. Otherwise, a +bean is simply one of many objects in your application. Beans, and the __dependencies__ +among them, are reflected in the __configuration metadata__ used by a container. + + + + +[[beans-basics]] +=== Container overview +The interface `org.springframework.context.ApplicationContext` represents the Spring IoC +container and is responsible for instantiating, configuring, and assembling the +aforementioned beans. The container gets its instructions on what objects to +instantiate, configure, and assemble by reading configuration metadata. The +configuration metadata is represented in XML, Java annotations, or Java code. It allows +you to express the objects that compose your application and the rich interdependencies +between such objects. + +Several implementations of the `ApplicationContext` interface are supplied +out-of-the-box with Spring. In standalone applications it is common to create an +instance of +{javadoc-baseurl}/org/springframework/context/support/ClassPathXmlApplicationContext.html[`ClassPathXmlApplicationContext`] +or {javadoc-baseurl}/org/springframework/context/support/FileSystemXmlApplicationContext.html[`FileSystemXmlApplicationContext`]. + While XML has been the traditional format for defining configuration metadata you can +instruct the container to use Java annotations or code as the metadata format by +providing a small amount of XML configuration to declaratively enable support for these +additional metadata formats. + +In most application scenarios, explicit user code is not required to instantiate one or +more instances of a Spring IoC container. For example, in a web application scenario, a +simple eight (or so) lines of boilerplate web descriptor XML in the `web.xml` file +of the application will typically suffice (see <>). If you are using the +https://spring.io/tools/sts[Spring Tool Suite] Eclipse-powered development +environment this boilerplate configuration can be easily created with few mouse clicks or +keystrokes. + +The following diagram is a high-level view of how Spring works. Your application classes +are combined with configuration metadata so that after the `ApplicationContext` is +created and initialized, you have a fully configured and executable system or +application. + +.The Spring IoC container +image::images/container-magic.png[width=250] + + + +[[beans-factory-metadata]] +==== Configuration metadata +As the preceding diagram shows, the Spring IoC container consumes a form of +__configuration metadata__; this configuration metadata represents how you as an +application developer tell the Spring container to instantiate, configure, and assemble +the objects in your application. + +Configuration metadata is traditionally supplied in a simple and intuitive XML format, +which is what most of this chapter uses to convey key concepts and features of the +Spring IoC container. + +[NOTE] +==== +XML-based metadata is __not__ the only allowed form of configuration metadata. The +Spring IoC container itself is __totally__ decoupled from the format in which this +configuration metadata is actually written. These days many developers choose +<> for their Spring applications. +==== + +For information about using other forms of metadata with the Spring container, see: + +* <>: Spring 2.5 introduced + support for annotation-based configuration metadata. +* <>: Starting with Spring 3.0, many features + provided by the Spring JavaConfig project became part of the core Spring Framework. + Thus you can define beans external to your application classes by using Java rather + than XML files. To use these new features, see the `@Configuration`, `@Bean`, `@Import` + and `@DependsOn` annotations. + +Spring configuration consists of at least one and typically more than one bean +definition that the container must manage. XML-based configuration metadata shows these +beans configured as `` elements inside a top-level `` element. Java +configuration typically uses `@Bean` annotated methods within a `@Configuration` class. + +These bean definitions correspond to the actual objects that make up your application. +Typically you define service layer objects, data access objects (DAOs), presentation +objects such as Struts `Action` instances, infrastructure objects such as Hibernate +`SessionFactories`, JMS `Queues`, and so forth. Typically one does not configure +fine-grained domain objects in the container, because it is usually the responsibility +of DAOs and business logic to create and load domain objects. However, you can use +Spring's integration with AspectJ to configure objects that have been created outside +the control of an IoC container. See <>. + +The following example shows the basic structure of XML-based configuration metadata: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + + + + + + + +---- + +The `id` attribute is a string that you use to identify the individual bean definition. +The `class` attribute defines the type of the bean and uses the fully qualified +classname. The value of the id attribute refers to collaborating objects. The XML for +referring to collaborating objects is not shown in this example; see +<> for more information. + + + +[[beans-factory-instantiation]] +==== Instantiating a container +Instantiating a Spring IoC container is straightforward. The location path or paths +supplied to an `ApplicationContext` constructor are actually resource strings that allow +the container to load configuration metadata from a variety of external resources such +as the local file system, from the Java `CLASSPATH`, and so on. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + ApplicationContext context = + new ClassPathXmlApplicationContext(new String[] {"services.xml", "daos.xml"}); +---- + +[NOTE] +==== +After you learn about Spring's IoC container, you may want to know more about Spring's +`Resource` abstraction, as described in <>, which provides a convenient +mechanism for reading an InputStream from locations defined in a URI syntax. In +particular, `Resource` paths are used to construct applications contexts as described in +<>. +==== + +The following example shows the service layer objects `(services.xml)` configuration file: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + + + + + + + +---- + +The following example shows the data access objects `daos.xml` file: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + + + + + + + +---- + +In the preceding example, the service layer consists of the class `PetStoreServiceImpl`, +and two data access objects of the type `JpaAccountDao` and `JpaItemDao` (based +on the JPA Object/Relational mapping standard). The `property name` element refers to the +name of the JavaBean property, and the `ref` element refers to the name of another bean +definition. This linkage between `id` and `ref` elements expresses the dependency between +collaborating objects. For details of configuring an object's dependencies, see +<>. + + +[[beans-factory-xml-import]] +===== Composing XML-based configuration metadata +It can be useful to have bean definitions span multiple XML files. Often each individual +XML configuration file represents a logical layer or module in your architecture. + +You can use the application context constructor to load bean definitions from all these +XML fragments. This constructor takes multiple `Resource` locations, as was shown in the +previous section. Alternatively, use one or more occurrences of the `` element +to load bean definitions from another file or files. For example: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + +---- + +In the preceding example, external bean definitions are loaded from three files: +`services.xml`, `messageSource.xml`, and `themeSource.xml`. All location paths are +relative to the definition file doing the importing, so `services.xml` must be in the +same directory or classpath location as the file doing the importing, while +`messageSource.xml` and `themeSource.xml` must be in a `resources` location below the +location of the importing file. As you can see, a leading slash is ignored, but given +that these paths are relative, it is better form not to use the slash at all. The +contents of the files being imported, including the top level `` element, must +be valid XML bean definitions according to the Spring Schema. + +[NOTE] +==== +It is possible, but not recommended, to reference files in parent directories using a +relative "../" path. Doing so creates a dependency on a file that is outside the current +application. In particular, this reference is not recommended for "classpath:" URLs (for +example, "classpath:../services.xml"), where the runtime resolution process chooses the +"nearest" classpath root and then looks into its parent directory. Classpath +configuration changes may lead to the choice of a different, incorrect directory. + +You can always use fully qualified resource locations instead of relative paths: for +example, "file:C:/config/services.xml" or "classpath:/config/services.xml". However, be +aware that you are coupling your application's configuration to specific absolute +locations. It is generally preferable to keep an indirection for such absolute +locations, for example, through "${...}" placeholders that are resolved against JVM +system properties at runtime. +==== + + + +[[beans-factory-client]] +==== Using the container +The `ApplicationContext` is the interface for an advanced factory capable of maintaining +a registry of different beans and their dependencies. Using the method `T getBean(String +name, Class requiredType)` you can retrieve instances of your beans. + +The `ApplicationContext` enables you to read bean definitions and access them as follows: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + // create and configure beans + ApplicationContext context = + new ClassPathXmlApplicationContext(new String[] {"services.xml", "daos.xml"}); + + // retrieve configured instance + PetStoreService service = context.getBean("petStore", PetStoreService.class); + + // use configured instance + List userList = service.getUsernameList(); +---- + +You use `getBean()` to retrieve instances of your beans. The `ApplicationContext` +interface has a few other methods for retrieving beans, but ideally your application +code should never use them. Indeed, your application code should have no calls to the +`getBean()` method at all, and thus no dependency on Spring APIs at all. For example, +Spring's integration with web frameworks provides for dependency injection for various +web framework classes such as controllers and JSF-managed beans. + + + + +[[beans-definition]] +=== Bean overview +A Spring IoC container manages one or more __beans__. These beans are created with the +configuration metadata that you supply to the container, for example, in the form of XML +`` definitions. + +Within the container itself, these bean definitions are represented as `BeanDefinition` +objects, which contain (among other information) the following metadata: + +* __A package-qualified class name:__ typically the actual implementation class of the + bean being defined. +* Bean behavioral configuration elements, which state how the bean should behave in the + container (scope, lifecycle callbacks, and so forth). +* References to other beans that are needed for the bean to do its work; these + references are also called __collaborators__ or __dependencies__. +* Other configuration settings to set in the newly created object, for example, the + number of connections to use in a bean that manages a connection pool, or the size + limit of the pool. + +This metadata translates to a set of properties that make up each bean definition. + +[[beans-factory-bean-definition-tbl]] +.The bean definition +|=== +| Property| Explained in... + +| class +| <> + +| name +| <> + +| scope +| <> + +| constructor arguments +| <> + +| properties +| <> + +| autowiring mode +| <> + +| lazy-initialization mode +| <> + +| initialization method +| <> + +| destruction method +| <> +|=== + +In addition to bean definitions that contain information on how to create a specific +bean, the `ApplicationContext` implementations also permit the registration of existing +objects that are created outside the container, by users. This is done by accessing the +ApplicationContext's BeanFactory via the method `getBeanFactory()` which returns the +BeanFactory implementation `DefaultListableBeanFactory`. `DefaultListableBeanFactory` +supports this registration through the methods `registerSingleton(..)` and +`registerBeanDefinition(..)`. However, typical applications work solely with beans +defined through metadata bean definitions. + + + +[[beans-beanname]] +==== Naming beans +Every bean has one or more identifiers. These identifiers must be unique within the +container that hosts the bean. A bean usually has only one identifier, but if it +requires more than one, the extra ones can be considered aliases. + +In XML-based configuration metadata, you use the `id` and/or `name` attributes +to specify the bean identifier(s). The `id` attribute allows you to specify +exactly one id. Conventionally these names are alphanumeric ('myBean', +'fooService', etc.), but may contain special characters as well. If you want to +introduce other aliases to the bean, you can also specify them in the `name` +attribute, separated by a comma (`,`), semicolon (`;`), or white space. As a +historical note, in versions prior to Spring 3.1, the `id` attribute was +defined as an `xsd:ID` type, which constrained possible characters. As of 3.1, +it is defined as an `xsd:string` type. Note that bean `id` uniqueness is still +enforced by the container, though no longer by XML parsers. + +You are not required to supply a name or id for a bean. If no name or id is supplied +explicitly, the container generates a unique name for that bean. However, if you want to +refer to that bean by name, through the use of the `ref` element or +<> style lookup, you must provide a name. +Motivations for not supplying a name are related to using <> and <>. + +.Bean Naming Conventions +**** +The convention is to use the standard Java convention for instance field names when +naming beans. That is, bean names start with a lowercase letter, and are camel-cased +from then on. Examples of such names would be (without quotes) `'accountManager'`, +`'accountService'`, `'userDao'`, `'loginController'`, and so forth. + +Naming beans consistently makes your configuration easier to read and understand, and if +you are using Spring AOP it helps a lot when applying advice to a set of beans related +by name. +**** + + +[[beans-beanname-alias]] +===== Aliasing a bean outside the bean definition +In a bean definition itself, you can supply more than one name for the bean, by using a +combination of up to one name specified by the `id` attribute, and any number of other +names in the `name` attribute. These names can be equivalent aliases to the same bean, +and are useful for some situations, such as allowing each component in an application to +refer to a common dependency by using a bean name that is specific to that component +itself. + +Specifying all aliases where the bean is actually defined is not always adequate, +however. It is sometimes desirable to introduce an alias for a bean that is defined +elsewhere. This is commonly the case in large systems where configuration is split +amongst each subsystem, each subsystem having its own set of object definitions. In +XML-based configuration metadata, you can use the `` element to accomplish this. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + +---- + +In this case, a bean in the same container which is named `fromName`, may also, +after the use of this alias definition, be referred to as `toName`. + +For example, the configuration metadata for subsystem A may refer to a DataSource via +the name `subsystemA-dataSource`. The configuration metadata for subsystem B may refer to +a DataSource via the name `subsystemB-dataSource`. When composing the main application +that uses both these subsystems the main application refers to the DataSource via the +name `myApp-dataSource`. To have all three names refer to the same object you add to the +MyApp configuration metadata the following aliases definitions: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + +---- + +Now each component and the main application can refer to the dataSource through a name +that is unique and guaranteed not to clash with any other definition (effectively +creating a namespace), yet they refer to the same bean. + +.Java-configuration +**** +If you are using Java-configuration, the `@Bean` annotation can be used to provide aliases +see <> for details. +**** + +[[beans-factory-class]] +==== Instantiating beans +A bean definition essentially is a recipe for creating one or more objects. The +container looks at the recipe for a named bean when asked, and uses the configuration +metadata encapsulated by that bean definition to create (or acquire) an actual object. + +If you use XML-based configuration metadata, you specify the type (or class) of object +that is to be instantiated in the `class` attribute of the `` element. This +`class` attribute, which internally is a `Class` property on a `BeanDefinition` +instance, is usually mandatory. (For exceptions, see +<> and <>.) +You use the `Class` property in one of two ways: + +* Typically, to specify the bean class to be constructed in the case where the container + itself directly creates the bean by calling its constructor reflectively, somewhat + equivalent to Java code using the `new` operator. +* To specify the actual class containing the `static` factory method that will be + invoked to create the object, in the less common case where the container invokes a + `static` __factory__ method on a class to create the bean. The object type returned + from the invocation of the `static` factory method may be the same class or another + class entirely. + +**** +.Inner class names +If you want to configure a bean definition for a `static` nested class, you have to use +the __binary__ name of the inner class. + +For example, if you have a class called `Foo` in the `com.example` package, and this +`Foo` class has a `static` inner class called `Bar`, the value of the `'class'` +attribute on a bean definition would be... + +`com.example.Foo$Bar` + +Notice the use of the `$` character in the name to separate the inner class name from +the outer class name. +**** + + +[[beans-factory-class-ctor]] +===== Instantiation with a constructor +When you create a bean by the constructor approach, all normal classes are usable by and +compatible with Spring. That is, the class being developed does not need to implement +any specific interfaces or to be coded in a specific fashion. Simply specifying the bean +class should suffice. However, depending on what type of IoC you use for that specific +bean, you may need a default (empty) constructor. + +The Spring IoC container can manage virtually __any__ class you want it to manage; it is +not limited to managing true JavaBeans. Most Spring users prefer actual JavaBeans with +only a default (no-argument) constructor and appropriate setters and getters modeled +after the properties in the container. You can also have more exotic non-bean-style +classes in your container. If, for example, you need to use a legacy connection pool +that absolutely does not adhere to the JavaBean specification, Spring can manage it as +well. + +With XML-based configuration metadata you can specify your bean class as follows: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + +---- + +For details about the mechanism for supplying arguments to the constructor (if required) +and setting object instance properties after the object is constructed, see +<>. + + +[[beans-factory-class-static-factory-method]] +===== Instantiation with a static factory method +When defining a bean that you create with a static factory method, you use the `class` +attribute to specify the class containing the `static` factory method and an attribute +named `factory-method` to specify the name of the factory method itself. You should be +able to call this method (with optional arguments as described later) and return a live +object, which subsequently is treated as if it had been created through a constructor. +One use for such a bean definition is to call `static` factories in legacy code. + +The following bean definition specifies that the bean will be created by calling a +factory-method. The definition does not specify the type (class) of the returned object, +only the class containing the factory method. In this example, the `createInstance()` +method must be a __static__ method. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + +---- + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class ClientService { + private static ClientService clientService = new ClientService(); + private ClientService() {} + + public static ClientService createInstance() { + return clientService; + } + } +---- + +For details about the mechanism for supplying (optional) arguments to the factory method +and setting object instance properties after the object is returned from the factory, +see <>. + + +[[beans-factory-class-instance-factory-method]] +===== Instantiation using an instance factory method +Similar to instantiation through a <>, instantiation with an instance factory method invokes a non-static +method of an existing bean from the container to create a new bean. To use this +mechanism, leave the `class` attribute empty, and in the `factory-bean` attribute, +specify the name of a bean in the current (or parent/ancestor) container that contains +the instance method that is to be invoked to create the object. Set the name of the +factory method itself with the `factory-method` attribute. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + +---- + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class DefaultServiceLocator { + + private static ClientService clientService = new ClientServiceImpl(); + private DefaultServiceLocator() {} + + public ClientService createClientServiceInstance() { + return clientService; + } + } +---- + +One factory class can also hold more than one factory method as shown here: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + +---- + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class DefaultServiceLocator { + + private static ClientService clientService = new ClientServiceImpl(); + private static AccountService accountService = new AccountServiceImpl(); + + private DefaultServiceLocator() {} + + public ClientService createClientServiceInstance() { + return clientService; + } + + public AccountService createAccountServiceInstance() { + return accountService; + } + + } +---- + +This approach shows that the factory bean itself can be managed and configured through +dependency injection (DI). See <>. + +[NOTE] +==== +In Spring documentation,__ factory bean__ refers to a bean that is configured in the +Spring container that will create objects through an +<> or +<> factory method. By contrast, +`FactoryBean` (notice the capitalization) refers to a Spring-specific +<>. +==== + + + + +[[beans-dependencies]] +=== Dependencies +A typical enterprise application does not consist of a single object (or bean in the +Spring parlance). Even the simplest application has a few objects that work together to +present what the end-user sees as a coherent application. This next section explains how +you go from defining a number of bean definitions that stand alone to a fully realized +application where objects collaborate to achieve a goal. + + + +[[beans-factory-collaborators]] +==== Dependency injection +__Dependency injection__ (DI) is a process whereby objects define their dependencies, +that is, the other objects they work with, only through constructor arguments, arguments +to a factory method, or properties that are set on the object instance after it is +constructed or returned from a factory method. The container then __injects__ those +dependencies when it creates the bean. This process is fundamentally the inverse, hence +the name __Inversion of Control__ (IoC), of the bean itself controlling the instantiation +or location of its dependencies on its own by using direct construction of classes, or +the __Service Locator__ pattern. + +Code is cleaner with the DI principle and decoupling is more effective when objects are +provided with their dependencies. The object does not look up its dependencies, and does +not know the location or class of the dependencies. As such, your classes become easier +to test, in particular when the dependencies are on interfaces or abstract base classes, +which allow for stub or mock implementations to be used in unit tests. + +DI exists in two major variants, <> and <>. + + +[[beans-constructor-injection]] +===== Constructor-based dependency injection +__Constructor-based__ DI is accomplished by the container invoking a constructor with a +number of arguments, each representing a dependency. Calling a `static` factory method +with specific arguments to construct the bean is nearly equivalent, and this discussion +treats arguments to a constructor and to a `static` factory method similarly. The +following example shows a class that can only be dependency-injected with constructor +injection. Notice that there is nothing __special__ about this class, it is a POJO that +has no dependencies on container specific interfaces, base classes or annotations. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class SimpleMovieLister { + + // the SimpleMovieLister has a dependency on a MovieFinder + private MovieFinder movieFinder; + + // a constructor so that the Spring container can inject a MovieFinder + public SimpleMovieLister(MovieFinder movieFinder) { + this.movieFinder = movieFinder; + } + + // business logic that actually uses the injected MovieFinder is omitted... + + } +---- + +[[beans-factory-ctor-arguments-resolution]] +====== Constructor argument resolution +Constructor argument resolution matching occurs using the argument's type. If no +potential ambiguity exists in the constructor arguments of a bean definition, then the +order in which the constructor arguments are defined in a bean definition is the order +in which those arguments are supplied to the appropriate constructor when the bean is +being instantiated. Consider the following class: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + package x.y; + + public class Foo { + + public Foo(Bar bar, Baz baz) { + // ... + } + + } +---- + +No potential ambiguity exists, assuming that `Bar` and `Baz` classes are not related by +inheritance. Thus the following configuration works fine, and you do not need to specify +the constructor argument indexes and/or types explicitly in the `` +element. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + + + +---- + +When another bean is referenced, the type is known, and matching can occur (as was the +case with the preceding example). When a simple type is used, such as +`true`, Spring cannot determine the type of the value, and so cannot match +by type without help. Consider the following class: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + package examples; + + public class ExampleBean { + + // Number of years to calculate the Ultimate Answer + private int years; + + // The Answer to Life, the Universe, and Everything + private String ultimateAnswer; + + public ExampleBean(int years, String ultimateAnswer) { + this.years = years; + this.ultimateAnswer = ultimateAnswer; + } + + } +---- + +.[[beans-factory-ctor-arguments-type]]Constructor argument type matching +-- +In the preceding scenario, the container __can__ use type matching with simple types if +you explicitly specify the type of the constructor argument using the `type` attribute. +For example: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + +---- +-- + +.[[beans-factory-ctor-arguments-index]]Constructor argument index +-- +Use the `index` attribute to specify explicitly the index of constructor arguments. For +example: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + +---- + +In addition to resolving the ambiguity of multiple simple values, specifying an index +resolves ambiguity where a constructor has two arguments of the same type. Note that the +__index is 0 based__. +-- + +.[[beans-factory-ctor-arguments-name]]Constructor argument name +-- +You can also use the constructor parameter name for value disambiguation: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + +---- + +Keep in mind that to make this work out of the box your code must be compiled with the +debug flag enabled so that Spring can look up the parameter name from the constructor. +If you can't compile your code with debug flag (or don't want to) you can use +http://download.oracle.com/javase/6/docs/api/java/beans/ConstructorProperties.html[@ConstructorProperties] +JDK annotation to explicitly name your constructor arguments. The sample class would +then have to look as follows: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + package examples; + + public class ExampleBean { + + // Fields omitted + + @ConstructorProperties({"years", "ultimateAnswer"}) + public ExampleBean(int years, String ultimateAnswer) { + this.years = years; + this.ultimateAnswer = ultimateAnswer; + } + + } +---- +-- + + +[[beans-setter-injection]] +===== Setter-based dependency injection +__Setter-based__ DI is accomplished by the container calling setter methods on your +beans after invoking a no-argument constructor or no-argument `static` factory method to +instantiate your bean. + +The following example shows a class that can only be dependency-injected using pure +setter injection. This class is conventional Java. It is a POJO that has no dependencies +on container specific interfaces, base classes or annotations. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class SimpleMovieLister { + + // the SimpleMovieLister has a dependency on the MovieFinder + private MovieFinder movieFinder; + + // a setter method so that the Spring container can inject a MovieFinder + public void setMovieFinder(MovieFinder movieFinder) { + this.movieFinder = movieFinder; + } + + // business logic that actually uses the injected MovieFinder is omitted... + + } +---- + +The `ApplicationContext` supports constructor-based and setter-based DI for the beans it +manages. It also supports setter-based DI after some dependencies have already been +injected through the constructor approach. You configure the dependencies in the form of +a `BeanDefinition`, which you use in conjunction with `PropertyEditor` instances to +convert properties from one format to another. However, most Spring users do not work +with these classes directly (i.e., programmatically) but rather with XML `bean` +definitions, annotated components (i.e., classes annotated with `@Component`, +`@Controller`, etc.), or `@Bean` methods in Java-based `@Configuration` classes. These +sources are then converted internally into instances of `BeanDefinition` and used to +load an entire Spring IoC container instance. + +.Constructor-based or setter-based DI? +**** +Since you can mix constructor-based and setter-based DI, it is a good rule of thumb to +use constructors for _mandatory dependencies_ and setter methods or configuration methods +for _optional dependencies_. Note that use of the <> +annotation on a setter method can be used to make the property a required dependency. + +The Spring team generally advocates constructor injection as it enables one to implement +application components as _immutable objects_ and to ensure that required dependencies +are not `null`. Furthermore constructor-injected components are always returned to client +(calling) code in a fully initialized state. As a side note, a large number of constructor +arguments is a _bad code smell_, implying that the class likely has too many +responsibilities and should be refactored to better address proper separation of concerns. + +Setter injection should primarily only be used for optional dependencies that can be +assigned reasonable default values within the class. Otherwise, not-null checks must be +performed everywhere the code uses the dependency. One benefit of setter injection is that +setter methods make objects of that class amenable to reconfiguration or re-injection +later. Management through <> is therefore a compelling use case for setter +injection. + +Use the DI style that makes the most sense for a particular class. Sometimes, when dealing +with third-party classes for which you do not have the source, the choice is made for you. +For example, if a third-party class does not expose any setter methods, then constructor +injection may be the only available form of DI. +**** + + +[[beans-dependency-resolution]] +===== Dependency resolution process +The container performs bean dependency resolution as follows: + +* The `ApplicationContext` is created and initialized with configuration metadata that + describes all the beans. Configuration metadata can be specified via XML, Java code, or + annotations. +* For each bean, its dependencies are expressed in the form of properties, constructor + arguments, or arguments to the static-factory method if you are using that instead of + a normal constructor. These dependencies are provided to the bean, __when the bean is + actually created__. +* Each property or constructor argument is an actual definition of the value to set, or + a reference to another bean in the container. +* Each property or constructor argument which is a value is converted from its specified + format to the actual type of that property or constructor argument. By default Spring + can convert a value supplied in string format to all built-in types, such as `int`, + `long`, `String`, `boolean`, etc. + +The Spring container validates the configuration of each bean as the container is created. +However, the bean properties themselves are not set until the bean __is actually created__. +Beans that are singleton-scoped and set to be pre-instantiated (the default) are created +when the container is created. Scopes are defined in <>. Otherwise, +the bean is created only when it is requested. Creation of a bean potentially causes a +graph of beans to be created, as the bean's dependencies and its dependencies' +dependencies (and so on) are created and assigned. Note that resolution mismatches among +those dependencies may show up late, i.e. on first creation of the affected bean. + +.Circular dependencies +**** +If you use predominantly constructor injection, it is possible to create an unresolvable +circular dependency scenario. + +For example: Class A requires an instance of class B through constructor injection, and +class B requires an instance of class A through constructor injection. If you configure +beans for classes A and B to be injected into each other, the Spring IoC container +detects this circular reference at runtime, and throws a +`BeanCurrentlyInCreationException`. + +One possible solution is to edit the source code of some classes to be configured by +setters rather than constructors. Alternatively, avoid constructor injection and use +setter injection only. In other words, although it is not recommended, you can configure +circular dependencies with setter injection. + +Unlike the __typical__ case (with no circular dependencies), a circular dependency +between bean A and bean B forces one of the beans to be injected into the other prior to +being fully initialized itself (a classic chicken/egg scenario). +**** + +You can generally trust Spring to do the right thing. It detects configuration problems, +such as references to non-existent beans and circular dependencies, at container +load-time. Spring sets properties and resolves dependencies as late as possible, when +the bean is actually created. This means that a Spring container which has loaded +correctly can later generate an exception when you request an object if there is a +problem creating that object or one of its dependencies. For example, the bean throws an +exception as a result of a missing or invalid property. This potentially delayed +visibility of some configuration issues is why `ApplicationContext` implementations by +default pre-instantiate singleton beans. At the cost of some upfront time and memory to +create these beans before they are actually needed, you discover configuration issues +when the `ApplicationContext` is created, not later. You can still override this default +behavior so that singleton beans will lazy-initialize, rather than be pre-instantiated. + +If no circular dependencies exist, when one or more collaborating beans are being +injected into a dependent bean, each collaborating bean is __totally__ configured prior +to being injected into the dependent bean. This means that if bean A has a dependency on +bean B, the Spring IoC container completely configures bean B prior to invoking the +setter method on bean A. In other words, the bean is instantiated (if not a +pre-instantiated singleton), its dependencies are set, and the relevant lifecycle +methods (such as a <> +or the <>) +are invoked. + + +[[beans-some-examples]] +===== Examples of dependency injection +The following example uses XML-based configuration metadata for setter-based DI. A small +part of a Spring XML configuration file specifies some bean definitions: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + + + + + + +---- + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class ExampleBean { + + private AnotherBean beanOne; + private YetAnotherBean beanTwo; + private int i; + + public void setBeanOne(AnotherBean beanOne) { + this.beanOne = beanOne; + } + + public void setBeanTwo(YetAnotherBean beanTwo) { + this.beanTwo = beanTwo; + } + + public void setIntegerProperty(int i) { + this.i = i; + } + + } +---- + +In the preceding example, setters are declared to match against the properties specified +in the XML file. The following example uses constructor-based DI: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + + + + + + + +---- + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class ExampleBean { + + private AnotherBean beanOne; + private YetAnotherBean beanTwo; + private int i; + + public ExampleBean( + AnotherBean anotherBean, YetAnotherBean yetAnotherBean, int i) { + this.beanOne = anotherBean; + this.beanTwo = yetAnotherBean; + this.i = i; + } + + } +---- + +The constructor arguments specified in the bean definition will be used as arguments to +the constructor of the `ExampleBean`. + +Now consider a variant of this example, where instead of using a constructor, Spring is +told to call a `static` factory method to return an instance of the object: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + +---- + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class ExampleBean { + + // a private constructor + private ExampleBean(...) { + ... + } + + // a static factory method; the arguments to this method can be + // considered the dependencies of the bean that is returned, + // regardless of how those arguments are actually used. + public static ExampleBean createInstance ( + AnotherBean anotherBean, YetAnotherBean yetAnotherBean, int i) { + + ExampleBean eb = new ExampleBean (...); + // some other operations... + return eb; + } + + } +---- + +Arguments to the `static` factory method are supplied via `` elements, +exactly the same as if a constructor had actually been used. The type of the class being +returned by the factory method does not have to be of the same type as the class that +contains the `static` factory method, although in this example it is. An instance +(non-static) factory method would be used in an essentially identical fashion (aside +from the use of the `factory-bean` attribute instead of the `class` attribute), so +details will not be discussed here. + + + +[[beans-factory-properties-detailed]] +==== Dependencies and configuration in detail +As mentioned in the previous section, you can define bean properties and constructor +arguments as references to other managed beans (collaborators), or as values defined +inline. Spring's XML-based configuration metadata supports sub-element types within its +`` and `` elements for this purpose. + + +[[beans-value-element]] +===== Straight values (primitives, Strings, and so on) + +The `value` attribute of the `` element specifies a property or constructor +argument as a human-readable string representation. Spring's +<> is used to convert these +values from a `String` to the actual type of the property or argument. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + +---- + +The following example uses the <> for even more succinct +XML configuration. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + +---- + +The preceding XML is more succinct; however, typos are discovered at runtime rather than +design time, unless you use an IDE such as http://www.jetbrains.com/idea/[IntelliJ +IDEA] or the https://spring.io/tools/sts[Spring Tool Suite] (STS) +that support automatic property completion when you create bean definitions. Such IDE +assistance is highly recommended. + +You can also configure a `java.util.Properties` instance as: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + jdbc.driver.className=com.mysql.jdbc.Driver + jdbc.url=jdbc:mysql://localhost:3306/mydb + + + +---- + +The Spring container converts the text inside the `` element into a +`java.util.Properties` instance by using the JavaBeans `PropertyEditor` mechanism. This +is a nice shortcut, and is one of a few places where the Spring team do favor the use of +the nested `` element over the `value` attribute style. + +[[beans-idref-element]] +====== The idref element + +The `idref` element is simply an error-proof way to pass the __id__ (string value - not +a reference) of another bean in the container to a `` or `` +element. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + +---- + +The above bean definition snippet is __exactly__ equivalent (at runtime) to the +following snippet: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + +---- + +The first form is preferable to the second, because using the `idref` tag allows the +container to validate __at deployment time__ that the referenced, named bean actually +exists. In the second variation, no validation is performed on the value that is passed +to the `targetName` property of the `client` bean. Typos are only discovered (with most +likely fatal results) when the `client` bean is actually instantiated. If the `client` +bean is a <> bean, this typo and the resulting exception +may only be discovered long after the container is deployed. + +[NOTE] +==== +The `local` attribute on the `idref` element is no longer supported in the 4.0 beans xsd +since it does not provide value over a regular `bean` reference anymore. Simply change +your existing `idref local` references to `idref bean` when upgrading to the 4.0 schema. +==== + +A common place (at least in versions earlier than Spring 2.0) where the `` element +brings value is in the configuration of <> in a +`ProxyFactoryBean` bean definition. Using `` elements when you specify the +interceptor names prevents you from misspelling an interceptor id. + + +[[beans-ref-element]] +===== References to other beans (collaborators) +The `ref` element is the final element inside a `` or `` +definition element. Here you set the value of the specified property of a bean to be a +reference to another bean (a collaborator) managed by the container. The referenced bean +is a dependency of the bean whose property will be set, and it is initialized on demand +as needed before the property is set. (If the collaborator is a singleton bean, it may +be initialized already by the container.) All references are ultimately a reference to +another object. Scoping and validation depend on whether you specify the id/name of the +other object through the `bean`, `local,` or `parent` attributes. + +Specifying the target bean through the `bean` attribute of the `` tag is the most +general form, and allows creation of a reference to any bean in the same container or +parent container, regardless of whether it is in the same XML file. The value of the +`bean` attribute may be the same as the `id` attribute of the target bean, or as one of +the values in the `name` attribute of the target bean. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + +---- + +Specifying the target bean through the `parent` attribute creates a reference to a bean +that is in a parent container of the current container. The value of the `parent` +attribute may be the same as either the `id` attribute of the target bean, or one of the +values in the `name` attribute of the target bean, and the target bean must be in a +parent container of the current one. You use this bean reference variant mainly when you +have a hierarchy of containers and you want to wrap an existing bean in a parent +container with a proxy that will have the same name as the parent bean. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + +---- + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + class="org.springframework.aop.framework.ProxyFactoryBean"> + + + + + +---- + +[NOTE] +==== +The `local` attribute on the `ref` element is no longer supported in the 4.0 beans xsd +since it does not provide value over a regular `bean` reference anymore. Simply change +your existing `ref local` references to `ref bean` when upgrading to the 4.0 schema. +==== + + +[[beans-inner-beans]] +===== Inner beans +A `` element inside the `` or `` elements defines a +so-called __inner bean__. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + + +---- + +An inner bean definition does not require a defined id or name; the container ignores +these values. It also ignores the `scope` flag. Inner beans are __always__ anonymous and +they are __always__ created with the outer bean. It is __not__ possible to inject inner +beans into collaborating beans other than into the enclosing bean. + + +[[beans-collection-elements]] +===== Collections +In the ``, ``, ``, and `` elements, you set the properties +and arguments of the Java `Collection` types `List`, `Set`, `Map`, and `Properties`, +respectively. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + administrator@example.org + support@example.org + development@example.org + + + + + + a list element followed by a reference + + + + + + + + + + + + + + just some string + + + + +---- + +__The value of a map key or value, or a set value, can also again be any of the +following elements:__ + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + bean | ref | idref | list | set | map | props | value | null +---- + +[[beans-collection-elements-merging]] +====== Collection merging +The Spring container also supports the __merging__ of collections. An application +developer can define a parent-style ``, ``, `` or `` element, +and have child-style ``, ``, `` or `` elements inherit and +override values from the parent collection. That is, the child collection's values are +the result of merging the elements of the parent and child collections, with the child's +collection elements overriding values specified in the parent collection. + +__This section on merging discusses the parent-child bean mechanism. Readers unfamiliar +with parent and child bean definitions may wish to read the +<> before continuing.__ + +The following example demonstrates collection merging: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + administrator@example.com + support@example.com + + + + + + + + sales@example.com + support@example.co.uk + + + + +---- + +Notice the use of the `merge=true` attribute on the `` element of the +`adminEmails` property of the `child` bean definition. When the `child` bean is resolved +and instantiated by the container, the resulting instance has an `adminEmails` +`Properties` collection that contains the result of the merging of the child's +`adminEmails` collection with the parent's `adminEmails` collection. + +[literal] +[subs="verbatim,quotes"] +---- +administrator=administrator@example.com +sales=sales@example.com +support=support@example.co.uk +---- + +The child `Properties` collection's value set inherits all property elements from the +parent ``, and the child's value for the `support` value overrides the value in +the parent collection. + +This merging behavior applies similarly to the ``, ``, and `` +collection types. In the specific case of the `` element, the semantics +associated with the `List` collection type, that is, the notion of an `ordered` +collection of values, is maintained; the parent's values precede all of the child list's +values. In the case of the `Map`, `Set`, and `Properties` collection types, no ordering +exists. Hence no ordering semantics are in effect for the collection types that underlie +the associated `Map`, `Set`, and `Properties` implementation types that the container +uses internally. + +[[beans-collection-merge-limitations]] +====== Limitations of collection merging +You cannot merge different collection types (such as a `Map` and a `List`), and if you +do attempt to do so an appropriate `Exception` is thrown. The `merge` attribute must be +specified on the lower, inherited, child definition; specifying the `merge` attribute on +a parent collection definition is redundant and will not result in the desired merging. + +[[beans-collection-elements-strongly-typed]] +====== Strongly-typed collection +With the introduction of generic types in Java 5, you can use strongly typed collections. +That is, it is possible to declare a `Collection` type such that it can only contain +`String` elements (for example). If you are using Spring to dependency-inject a +strongly-typed `Collection` into a bean, you can take advantage of Spring's +type-conversion support such that the elements of your strongly-typed `Collection` +instances are converted to the appropriate type prior to being added to the `Collection`. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class Foo { + + private Map accounts; + + public void setAccounts(Map accounts) { + this.accounts = accounts; + } + } +---- + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + + + + +---- + +When the `accounts` property of the `foo` bean is prepared for injection, the generics +information about the element type of the strongly-typed `Map` is +available by reflection. Thus Spring's type conversion infrastructure recognizes the +various value elements as being of type `Float`, and the string values `9.99, 2.75`, and +`3.99` are converted into an actual `Float` type. + + +[[beans-null-element]] +===== Null and empty string values +Spring treats empty arguments for properties and the like as empty `Strings`. The +following XML-based configuration metadata snippet sets the email property to the empty +`String` value (""). + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + +---- + +The preceding example is equivalent to the following Java code: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + exampleBean.setEmail("") +---- + +The `` element handles `null` values. For example: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + +---- + +The above configuration is equivalent to the following Java code: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + exampleBean.setEmail(null) +---- + + +[[beans-p-namespace]] +===== XML shortcut with the p-namespace +The p-namespace enables you to use the `bean` element's attributes, instead of nested +`` elements, to describe your property values and/or collaborating beans. + +Spring supports extensible configuration formats <>, which are +based on an XML Schema definition. The `beans` configuration format discussed in this +chapter is defined in an XML Schema document. However, the p-namespace is not defined in +an XSD file and exists only in the core of Spring. + +The following example shows two XML snippets that resolve to the same result: The first +uses standard XML format and the second uses the p-namespace. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + +---- + +The example shows an attribute in the p-namespace called email in the bean definition. +This tells Spring to include a property declaration. As previously mentioned, the +p-namespace does not have a schema definition, so you can set the name of the attribute +to the property name. + +This next example includes two more bean definitions that both have a reference to +another bean: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + + + + + + +---- + +As you can see, this example includes not only a property value using the p-namespace, +but also uses a special format to declare property references. Whereas the first bean +definition uses `` to create a reference from bean +`john` to bean `jane`, the second bean definition uses `p:spouse-ref="jane"` as an +attribute to do the exact same thing. In this case `spouse` is the property name, +whereas the `-ref` part indicates that this is not a straight value but rather a +reference to another bean. + +[NOTE] +==== +The p-namespace is not as flexible as the standard XML format. For example, the format +for declaring property references clashes with properties that end in `Ref`, whereas the +standard XML format does not. We recommend that you choose your approach carefully and +communicate this to your team members, to avoid producing XML documents that use all +three approaches at the same time. +==== + + +[[beans-c-namespace]] +===== XML shortcut with the c-namespace +Similar to the <>, the __c-namespace__, newly introduced in Spring +3.1, allows usage of inlined attributes for configuring the constructor arguments rather +then nested `constructor-arg` elements. + +Let's review the examples from <> with the `c:` namespace: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + + + + + + + + + +---- + +The `c:` namespace uses the same conventions as the `p:` one (trailing `-ref` for bean +references) for setting the constructor arguments by their names. And just as well, it +needs to be declared even though it is not defined in an XSD schema (but it exists +inside the Spring core). + +For the rare cases where the constructor argument names are not available (usually if +the bytecode was compiled without debugging information), one can use fallback to the +argument indexes: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + + +---- + +[NOTE] +==== +Due to the XML grammar, the index notation requires the presence of the leading `_` as +XML attribute names cannot start with a number (even though some IDE allow it). +==== + +In practice, the constructor resolution +<> is quite efficient in matching +arguments so unless one really needs to, we recommend using the name notation +through-out your configuration. + + +[[beans-compound-property-names]] +===== Compound property names +You can use compound or nested property names when you set bean properties, as long as +all components of the path except the final property name are not `null`. Consider the +following bean definition. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + +---- + +The `foo` bean has a `fred` property, which has a `bob` property, which has a `sammy` +property, and that final `sammy` property is being set to the value `123`. In order for +this to work, the `fred` property of `foo`, and the `bob` property of `fred` must not be +`null` after the bean is constructed, or a `NullPointerException` is thrown. + + + +[[beans-factory-dependson]] +==== Using depends-on + +If a bean is a dependency of another that usually means that one bean is set as a +property of another. Typically you accomplish this with the <` +element>> in XML-based configuration metadata. However, sometimes dependencies between +beans are less direct; for example, a static initializer in a class needs to be +triggered, such as database driver registration. The `depends-on` attribute can +explicitly force one or more beans to be initialized before the bean using this element +is initialized. The following example uses the `depends-on` attribute to express a +dependency on a single bean: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + +---- + +To express a dependency on multiple beans, supply a list of bean names as the value of +the `depends-on` attribute, with commas, whitespace and semicolons, used as valid +delimiters: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + +---- + +[NOTE] +==== +The `depends-on` attribute in the bean definition can specify both an initialization +time dependency and, in the case of <> beans +only, a corresponding destroy time dependency. Dependent beans that define a +`depends-on` relationship with a given bean are destroyed first, prior to the given bean +itself being destroyed. Thus `depends-on` can also control shutdown order. +==== + + + +[[beans-factory-lazy-init]] +==== Lazy-initialized beans +By default, `ApplicationContext` implementations eagerly create and configure all +<> beans as part of the initialization +process. Generally, this pre-instantiation is desirable, because errors in the +configuration or surrounding environment are discovered immediately, as opposed to hours +or even days later. When this behavior is __not__ desirable, you can prevent +pre-instantiation of a singleton bean by marking the bean definition as +lazy-initialized. A lazy-initialized bean tells the IoC container to create a bean +instance when it is first requested, rather than at startup. + +In XML, this behavior is controlled by the `lazy-init` attribute on the `` +element; for example: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + +---- + +When the preceding configuration is consumed by an `ApplicationContext`, the bean named +`lazy` is not eagerly pre-instantiated when the `ApplicationContext` is starting up, +whereas the `not.lazy` bean is eagerly pre-instantiated. + +However, when a lazy-initialized bean is a dependency of a singleton bean that is +__not__ lazy-initialized, the `ApplicationContext` creates the lazy-initialized bean at +startup, because it must satisfy the singleton's dependencies. The lazy-initialized bean +is injected into a singleton bean elsewhere that is not lazy-initialized. + +You can also control lazy-initialization at the container level by using the +`default-lazy-init` attribute on the `` element; for example: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + +---- + + + +[[beans-factory-autowire]] +==== Autowiring collaborators +The Spring container can __autowire__ relationships between collaborating beans. You can +allow Spring to resolve collaborators (other beans) automatically for your bean by +inspecting the contents of the `ApplicationContext`. Autowiring has the following +advantages: + +* Autowiring can significantly reduce the need to specify properties or constructor + arguments. (Other mechanisms such as a bean template + <> are also valuable + in this regard.) +* Autowiring can update a configuration as your objects evolve. For example, if you need + to add a dependency to a class, that dependency can be satisfied automatically without + you needing to modify the configuration. Thus autowiring can be especially useful + during development, without negating the option of switching to explicit wiring when + the code base becomes more stable. + +When using XML-based configuration metadata footnote:[See +pass:specialcharacters,macros[<>]], you specify autowire +mode for a bean definition with the `autowire` attribute of the `` element. The +autowiring functionality has five modes. You specify autowiring __per__ bean and thus +can choose which ones to autowire. + +[[beans-factory-autowiring-modes-tbl]] +.Autowiring modes +|=== +| Mode| Explanation + +| no +| (Default) No autowiring. Bean references must be defined via a `ref` element. Changing + the default setting is not recommended for larger deployments, because specifying + collaborators explicitly gives greater control and clarity. To some extent, it + documents the structure of a system. + +| byName +| Autowiring by property name. Spring looks for a bean with the same name as the + property that needs to be autowired. For example, if a bean definition is set to + autowire by name, and it contains a __master__ property (that is, it has a + __setMaster(..)__ method), Spring looks for a bean definition named `master`, and uses + it to set the property. + +| byType +| Allows a property to be autowired if exactly one bean of the property type exists in + the container. If more than one exists, a fatal exception is thrown, which indicates + that you may not use __byType__ autowiring for that bean. If there are no matching + beans, nothing happens; the property is not set. + +| constructor +| Analogous to __byType__, but applies to constructor arguments. If there is not exactly + one bean of the constructor argument type in the container, a fatal error is raised. +|=== + +With __byType__ or __constructor__ autowiring mode, you can wire arrays and +typed-collections. In such cases __all__ autowire candidates within the container that +match the expected type are provided to satisfy the dependency. You can autowire +strongly-typed Maps if the expected key type is `String`. An autowired Maps values will +consist of all bean instances that match the expected type, and the Maps keys will +contain the corresponding bean names. + +You can combine autowire behavior with dependency checking, which is performed after +autowiring completes. + + +[[beans-autowired-exceptions]] +===== Limitations and disadvantages of autowiring +Autowiring works best when it is used consistently across a project. If autowiring is +not used in general, it might be confusing to developers to use it to wire only one or +two bean definitions. + +Consider the limitations and disadvantages of autowiring: + +* Explicit dependencies in `property` and `constructor-arg` settings always override + autowiring. You cannot autowire so-called __simple__ properties such as primitives, + `Strings`, and `Classes` (and arrays of such simple properties). This limitation is + by-design. +* Autowiring is less exact than explicit wiring. Although, as noted in the above table, + Spring is careful to avoid guessing in case of ambiguity that might have unexpected + results, the relationships between your Spring-managed objects are no longer + documented explicitly. +* Wiring information may not be available to tools that may generate documentation from + a Spring container. +* Multiple bean definitions within the container may match the type specified by the + setter method or constructor argument to be autowired. For arrays, collections, or + Maps, this is not necessarily a problem. However for dependencies that expect a single + value, this ambiguity is not arbitrarily resolved. If no unique bean definition is + available, an exception is thrown. + +In the latter scenario, you have several options: + +* Abandon autowiring in favor of explicit wiring. +* Avoid autowiring for a bean definition by setting its `autowire-candidate` attributes + to `false` as described in the next section. +* Designate a single bean definition as the __primary__ candidate by setting the + `primary` attribute of its `` element to `true`. +* Implement the more fine-grained control available + with annotation-based configuration, as described in <>. + + +[[beans-factory-autowire-candidate]] +===== Excluding a bean from autowiring +On a per-bean basis, you can exclude a bean from autowiring. In Spring's XML format, set +the `autowire-candidate` attribute of the `` element to `false`; the container +makes that specific bean definition unavailable to the autowiring infrastructure +(including annotation style configurations such as <>). + +You can also limit autowire candidates based on pattern-matching against bean names. The +top-level `` element accepts one or more patterns within its +`default-autowire-candidates` attribute. For example, to limit autowire candidate status +to any bean whose name ends with __Repository,__ provide a value of *Repository. To +provide multiple patterns, define them in a comma-separated list. An explicit value of +`true` or `false` for a bean definitions `autowire-candidate` attribute always takes +precedence, and for such beans, the pattern matching rules do not apply. + +These techniques are useful for beans that you never want to be injected into other +beans by autowiring. It does not mean that an excluded bean cannot itself be configured +using autowiring. Rather, the bean itself is not a candidate for autowiring other beans. + + + +[[beans-factory-method-injection]] +==== Method injection +In most application scenarios, most beans in the container are +<>. When a singleton bean needs to +collaborate with another singleton bean, or a non-singleton bean needs to collaborate +with another non-singleton bean, you typically handle the dependency by defining one +bean as a property of the other. A problem arises when the bean lifecycles are +different. Suppose singleton bean A needs to use non-singleton (prototype) bean B, +perhaps on each method invocation on A. The container only creates the singleton bean A +once, and thus only gets one opportunity to set the properties. The container cannot +provide bean A with a new instance of bean B every time one is needed. + +A solution is to forego some inversion of control. You can <> by implementing the `ApplicationContextAware` interface, +and by <> ask for (a +typically new) bean B instance every time bean A needs it. The following is an example +of this approach: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + // a class that uses a stateful Command-style class to perform some processing + package fiona.apple; + + // Spring-API imports + import org.springframework.beans.BeansException; + import org.springframework.context.ApplicationContext; + import org.springframework.context.ApplicationContextAware; + + public class CommandManager implements ApplicationContextAware { + + private ApplicationContext applicationContext; + + public Object process(Map commandState) { + // grab a new instance of the appropriate Command + Command command = createCommand(); + // set the state on the (hopefully brand new) Command instance + command.setState(commandState); + return command.execute(); + } + + protected Command createCommand() { + // notice the Spring API dependency! + return this.applicationContext.getBean("command", Command.class); + } + + public void setApplicationContext( + ApplicationContext applicationContext) throws BeansException { + this.applicationContext = applicationContext; + } + } +---- + +The preceding is not desirable, because the business code is aware of and coupled to the +Spring Framework. Method Injection, a somewhat advanced feature of the Spring IoC +container, allows this use case to be handled in a clean fashion. + +**** +You can read more about the motivation for Method Injection in +https://spring.io/blog/2004/08/06/method-injection/[this blog entry]. +**** + + +[[beans-factory-lookup-method-injection]] +===== Lookup method injection +Lookup method injection is the ability of the container to override methods on +__container managed beans__, to return the lookup result for another named bean in the +container. The lookup typically involves a prototype bean as in the scenario described +in the preceding section. The Spring Framework implements this method injection by using +bytecode generation from the CGLIB library to generate dynamically a subclass that +overrides the method. + +[NOTE] +==== +For this dynamic subclassing to work, the class that the Spring container will subclass +cannot be `final`, and the method to be overridden cannot be `final` either. Also, +testing a class that has an `abstract` method requires you to subclass the class +yourself and to supply a stub implementation of the `abstract` method. Finally, objects +that have been the target of method injection cannot be serialized. As of Spring 3.2 it +is no longer necessary to add CGLIB to your classpath, because CGLIB classes are +repackaged under org.springframework and distributed within the spring-core JAR. This is +done both for convenience as well as to avoid potential conflicts with other projects +that use differing versions of CGLIB. +==== + +Looking at the `CommandManager` class in the previous code snippet, you see that the +Spring container will dynamically override the implementation of the `createCommand()` +method. Your `CommandManager` class will not have any Spring dependencies, as can be +seen in the reworked example: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + package fiona.apple; + + // no more Spring imports! + + public abstract class CommandManager { + + public Object process(Object commandState) { + // grab a new instance of the appropriate Command interface + Command command = createCommand(); + // set the state on the (hopefully brand new) Command instance + command.setState(commandState); + return command.execute(); + } + + // okay... but where is the implementation of this method? + protected abstract Command createCommand(); + } +---- + +In the client class containing the method to be injected (the `CommandManager` in this +case), the method to be injected requires a signature of the following form: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + [abstract] theMethodName(no-arguments); +---- + +If the method is `abstract`, the dynamically-generated subclass implements the method. +Otherwise, the dynamically-generated subclass overrides the concrete method defined in +the original class. For example: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + + +---- + +The bean identified as __commandManager__ calls its own method `createCommand()` +whenever it needs a new instance of the __command__ bean. You must be careful to deploy +the `command` bean as a prototype, if that is actually what is needed. If it is deployed +as a <>, the same instance of the `command` +bean is returned each time. + +[TIP] +==== +The interested reader may also find the `ServiceLocatorFactoryBean` (in the +`org.springframework.beans.factory.config` package) to be of use. The approach used in +ServiceLocatorFactoryBean is similar to that of another utility class, +`ObjectFactoryCreatingFactoryBean`, but it allows you to specify your own lookup +interface as opposed to a Spring-specific lookup interface. Consult the javadocs of +these classes for additional information. +==== + + +[[beans-factory-arbitrary-method-replacement]] +===== Arbitrary method replacement +A less useful form of method injection than lookup method Injection is the ability to +replace arbitrary methods in a managed bean with another method implementation. Users +may safely skip the rest of this section until the functionality is actually needed. + +With XML-based configuration metadata, you can use the `replaced-method` element to +replace an existing method implementation with another, for a deployed bean. Consider +the following class, with a method computeValue, which we want to override: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class MyValueCalculator { + + public String computeValue(String input) { + // some real code... + } + + // some other methods... + + } +---- + +A class implementing the `org.springframework.beans.factory.support.MethodReplacer` +interface provides the new method definition. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + /** + * meant to be used to override the existing computeValue(String) + * implementation in MyValueCalculator + */ + public class ReplacementComputeValue implements MethodReplacer { + + public Object reimplement(Object o, Method m, Object[] args) throws Throwable { + // get the input value, work with it, and return a computed result + String input = (String) args[0]; + ... + return ...; + } + } +---- + +The bean definition to deploy the original class and specify the method override would +look like this: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + String + + + + +---- + +You can use one or more contained `` elements within the `` +element to indicate the method signature of the method being overridden. The signature +for the arguments is necessary only if the method is overloaded and multiple variants +exist within the class. For convenience, the type string for an argument may be a +substring of the fully qualified type name. For example, the following all match +`java.lang.String`: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + java.lang.String + String + Str +---- + +Because the number of arguments is often enough to distinguish between each possible +choice, this shortcut can save a lot of typing, by allowing you to type only the +shortest string that will match an argument type. + + + + +[[beans-factory-scopes]] +=== Bean scopes +When you create a bean definition, you create a __recipe__ for creating actual instances +of the class defined by that bean definition. The idea that a bean definition is a +recipe is important, because it means that, as with a class, you can create many object +instances from a single recipe. + +You can control not only the various dependencies and configuration values that are to +be plugged into an object that is created from a particular bean definition, but also +the __scope__ of the objects created from a particular bean definition. This approach is +powerful and flexible in that you can __choose__ the scope of the objects you create +through configuration instead of having to bake in the scope of an object at the Java +class level. Beans can be defined to be deployed in one of a number of scopes: out of +the box, the Spring Framework supports five scopes, three of which are available only if +you use a web-aware `ApplicationContext`. + +The following scopes are supported out of the box. You can also create +<> + +[[beans-factory-scopes-tbl]] +.Bean scopes +|=== +| Scope| Description + +| <> +| (Default) Scopes a single bean definition to a single object instance per Spring IoC + container. + +| <> +| Scopes a single bean definition to any number of object instances. + +| <> +| Scopes a single bean definition to the lifecycle of a single HTTP request; that is, + each HTTP request has its own instance of a bean created off the back of a single bean + definition. Only valid in the context of a web-aware Spring `ApplicationContext`. + +| <> +| Scopes a single bean definition to the lifecycle of an HTTP `Session`. Only valid in + the context of a web-aware Spring `ApplicationContext`. + +| <> +| Scopes a single bean definition to the lifecycle of a global HTTP `Session`. Typically + only valid when used in a portlet context. Only valid in the context of a web-aware + Spring `ApplicationContext`. + +| <> +| Scopes a single bean definition to the lifecycle of a `ServletContext`. Only valid in + the context of a web-aware Spring `ApplicationContext`. +|=== + +[NOTE] +==== +As of Spring 3.0, a __thread scope__ is available, but is not registered by default. For +more information, see the documentation for +{javadoc-baseurl}/org/springframework/context/support/SimpleThreadScope.html[`SimpleThreadScope`]. +For instructions on how to register this or any other custom scope, see +<>. +==== + + + +[[beans-factory-scopes-singleton]] +==== The singleton scope +Only one __shared__ instance of a singleton bean is managed, and all requests for beans +with an id or ids matching that bean definition result in that one specific bean +instance being returned by the Spring container. + +To put it another way, when you define a bean definition and it is scoped as a +singleton, the Spring IoC container creates __exactly one__ instance of the object +defined by that bean definition. This single instance is stored in a cache of such +singleton beans, and __all subsequent requests and references__ for that named bean +return the cached object. + +image::images/singleton.png[width=400] + +Spring's concept of a singleton bean differs from the Singleton pattern as defined in +the Gang of Four (GoF) patterns book. The GoF Singleton hard-codes the scope of an +object such that one __and only one__ instance of a particular class is created __per +ClassLoader__. The scope of the Spring singleton is best described as __per container +and per bean__. This means that if you define one bean for a particular class in a +single Spring container, then the Spring container creates one __and only one__ instance +of the class defined by that bean definition. __The singleton scope is the default scope +in Spring__. To define a bean as a singleton in XML, you would write, for example: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + +---- + + + +[[beans-factory-scopes-prototype]] +==== The prototype scope +The non-singleton, prototype scope of bean deployment results in the __creation of a new +bean instance__ every time a request for that specific bean is made. That is, the bean +is injected into another bean or you request it through a `getBean()` method call on the +container. As a rule, use the prototype scope for all stateful beans and the singleton +scope for stateless beans. + +The following diagram illustrates the Spring prototype scope. __A data access object +(DAO) is not typically configured as a prototype, because a typical DAO does not hold +any conversational state; it was just easier for this author to reuse the core of the +singleton diagram.__ + +image::images/prototype.png[width=400] + +The following example defines a bean as a prototype in XML: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + +---- + +In contrast to the other scopes, Spring does not manage the complete lifecycle of a +prototype bean: the container instantiates, configures, and otherwise assembles a +prototype object, and hands it to the client, with no further record of that prototype +instance. Thus, although__ initialization__ lifecycle callback methods are called on all +objects regardless of scope, in the case of prototypes, configured __destruction__ +lifecycle callbacks are __not__ called. The client code must clean up prototype-scoped +objects and release expensive resources that the prototype bean(s) are holding. To get +the Spring container to release resources held by prototype-scoped beans, try using a +custom <>, which holds a reference to +beans that need to be cleaned up. + +In some respects, the Spring container's role in regard to a prototype-scoped bean is a +replacement for the Java `new` operator. All lifecycle management past that point must +be handled by the client. (For details on the lifecycle of a bean in the Spring +container, see <>.) + + + +[[beans-factory-scopes-sing-prot-interaction]] +==== Singleton beans with prototype-bean dependencies +When you use singleton-scoped beans with dependencies on prototype beans, be aware that +__dependencies are resolved at instantiation time__. Thus if you dependency-inject a +prototype-scoped bean into a singleton-scoped bean, a new prototype bean is instantiated +and then dependency-injected into the singleton bean. The prototype instance is the sole +instance that is ever supplied to the singleton-scoped bean. + +However, suppose you want the singleton-scoped bean to acquire a new instance of the +prototype-scoped bean repeatedly at runtime. You cannot dependency-inject a +prototype-scoped bean into your singleton bean, because that injection occurs only +__once__, when the Spring container is instantiating the singleton bean and resolving +and injecting its dependencies. If you need a new instance of a prototype bean at +runtime more than once, see <> + + + +[[beans-factory-scopes-other]] +==== Request, session, and global session scopes +The `request`, `session`, and `global session` scopes are __only__ available if you use +a web-aware Spring `ApplicationContext` implementation (such as +`XmlWebApplicationContext`). If you use these scopes with regular Spring IoC containers +such as the `ClassPathXmlApplicationContext`, you get an `IllegalStateException` +complaining about an unknown bean scope. + + +[[beans-factory-scopes-other-web-configuration]] +===== Initial web configuration +To support the scoping of beans at the `request`, `session`, and `global session` levels +(web-scoped beans), some minor initial configuration is required before you define your +beans. (This initial setup is __not__ required for the standard scopes, singleton and +prototype.) + +How you accomplish this initial setup depends on your particular Servlet environment.. + +If you access scoped beans within Spring Web MVC, in effect, within a request that is +processed by the Spring `DispatcherServlet`, or `DispatcherPortlet`, then no special +setup is necessary: `DispatcherServlet` and `DispatcherPortlet` already expose all +relevant state. + +If you use a Servlet 2.5 web container, with requests processed outside of Spring's +DispatcherServlet (for example, when using JSF or Struts), you need to register the +`org.springframework.web.context.request.RequestContextListener` `ServletRequestListener`. +For Servlet 3.0+, this can done programmatically via the `WebApplicationInitializer` +interface. Alternatively, or for older containers, add the following declaration to +your web application's `web.xml` file: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + ... + + + org.springframework.web.context.request.RequestContextListener + + + ... + +---- + +Alternatively, if there are issues with your listener setup, consider the provided +`RequestContextFilter`. The filter mapping depends on the surrounding web +application configuration, so you have to change it as appropriate. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + ... + + requestContextFilter + org.springframework.web.filter.RequestContextFilter + + + requestContextFilter + /* + + ... + +---- + +`DispatcherServlet`, `RequestContextListener` and `RequestContextFilter` all do exactly +the same thing, namely bind the HTTP request object to the `Thread` that is servicing +that request. This makes beans that are request- and session-scoped available further +down the call chain. + + +[[beans-factory-scopes-request]] +===== Request scope +Consider the following bean definition: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + +---- + +The Spring container creates a new instance of the `LoginAction` bean by using the +`loginAction` bean definition for each and every HTTP request. That is, the +`loginAction` bean is scoped at the HTTP request level. You can change the internal +state of the instance that is created as much as you want, because other instances +created from the same `loginAction` bean definition will not see these changes in state; +they are particular to an individual request. When the request completes processing, the +bean that is scoped to the request is discarded. + + +[[beans-factory-scopes-session]] +===== Session scope +Consider the following bean definition: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + +---- + +The Spring container creates a new instance of the `UserPreferences` bean by using the +`userPreferences` bean definition for the lifetime of a single HTTP `Session`. In other +words, the `userPreferences` bean is effectively scoped at the HTTP `Session` level. As +with `request-scoped` beans, you can change the internal state of the instance that is +created as much as you want, knowing that other HTTP `Session` instances that are also +using instances created from the same `userPreferences` bean definition do not see these +changes in state, because they are particular to an individual HTTP `Session`. When the +HTTP `Session` is eventually discarded, the bean that is scoped to that particular HTTP +`Session` is also discarded. + + +[[beans-factory-scopes-global-session]] +===== Global session scope +Consider the following bean definition: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + +---- + +The `global session` scope is similar to the standard HTTP `Session` scope +(<>), and applies only in the context of +portlet-based web applications. The portlet specification defines the notion of a global +`Session` that is shared among all portlets that make up a single portlet web +application. Beans defined at the `global session` scope are scoped (or bound) to the +lifetime of the global portlet `Session`. + +If you write a standard Servlet-based web application and you define one or more beans +as having `global session` scope, the standard HTTP `Session` scope is used, and no +error is raised. + + +[[beans-factory-scopes-application]] +===== Application scope +Consider the following bean definition: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + +---- + +The Spring container creates a new instance of the `AppPreferences` bean by using the +`appPreferences` bean definition once for the entire web application. That is, the +`appPreferences` bean is scoped at the `ServletContext` level, stored as a regular +`ServletContext` attribute. This is somewhat similar to a Spring singleton bean but +differs in two important ways: It is a singleton per `ServletContext`, not per Spring +'ApplicationContext' (or which there may be several in any given web application), +and it is actually exposed and therefore visible as a `ServletContext` attribute. + + +[[beans-factory-scopes-other-injection]] +===== Scoped beans as dependencies +The Spring IoC container manages not only the instantiation of your objects (beans), but +also the wiring up of collaborators (or dependencies). If you want to inject (for +example) an HTTP request scoped bean into another bean, you must inject an AOP proxy in +place of the scoped bean. That is, you need to inject a proxy object that exposes the +same public interface as the scoped object but that can also retrieve the real, target +object from the relevant scope (for example, an HTTP request) and delegate method calls +onto the real object. + +[NOTE] +==== +You __do not__ need to use the `` in conjunction with beans that are +scoped as `singletons` or `prototypes`. +==== + +The configuration in the following example is only one line, but it is important to +understand the "why" as well as the "how" behind it. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + + + + + + + + +---- + +To create such a proxy, you insert a child `` element into a scoped +bean definition. See <> and +<>.) Why do definitions of beans scoped at the `request`, `session`, +`globalSession` and custom-scope levels require the `` element ? +Let's examine the following singleton bean definition and contrast it with what you need +to define for the aforementioned scopes. (The following `userPreferences` bean +definition as it stands is __incomplete.)__ + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + +---- + +In the preceding example, the singleton bean `userManager` is injected with a reference +to the HTTP `Session`-scoped bean `userPreferences`. The salient point here is that the +`userManager` bean is a singleton: it will be instantiated __exactly once__ per +container, and its dependencies (in this case only one, the `userPreferences` bean) are +also injected only once. This means that the `userManager` bean will only operate on the +exact same `userPreferences` object, that is, the one that it was originally injected +with. + +This is __not__ the behavior you want when injecting a shorter-lived scoped bean into a +longer-lived scoped bean, for example injecting an HTTP `Session`-scoped collaborating +bean as a dependency into singleton bean. Rather, you need a single `userManager` +object, and for the lifetime of an HTTP `Session`, you need a `userPreferences` object +that is specific to said HTTP `Session`. Thus the container creates an object that +exposes the exact same public interface as the `UserPreferences` class (ideally an +object that __is a__ `UserPreferences` instance) which can fetch the real +`UserPreferences` object from the scoping mechanism (HTTP request, `Session`, etc.). The +container injects this proxy object into the `userManager` bean, which is unaware that +this `UserPreferences` reference is a proxy. In this example, when a `UserManager` +instance invokes a method on the dependency-injected `UserPreferences` object, it +actually is invoking a method on the proxy. The proxy then fetches the real +`UserPreferences` object from (in this case) the HTTP `Session`, and delegates the +method invocation onto the retrieved real `UserPreferences` object. + +Thus you need the following, correct and complete, configuration when injecting +`request-`, `session-`, and `globalSession-scoped` beans into collaborating objects: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + +---- + +[[beans-factory-scopes-other-injection-proxies]] +====== Choosing the type of proxy to create +By default, when the Spring container creates a proxy for a bean that is marked up with +the `` element, __a CGLIB-based class proxy is created__. + +[NOTE] +==== +CGLIB proxies only intercept public method calls! Do not call non-public methods +on such a proxy; they will not be delegated to the actual scoped target object. +==== + +Alternatively, you can configure the Spring container to create standard JDK +interface-based proxies for such scoped beans, by specifying `false` for the value of +the `proxy-target-class` attribute of the `` element. Using JDK +interface-based proxies means that you do not need additional libraries in your +application classpath to effect such proxying. However, it also means that the class of +the scoped bean must implement at least one interface, and __that all__ collaborators +into which the scoped bean is injected must reference the bean through one of its +interfaces. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + +---- + +For more detailed information about choosing class-based or interface-based proxying, +see <>. + + + +[[beans-factory-scopes-custom]] +==== Custom scopes +The bean scoping mechanism is extensible; You can define your own +scopes, or even redefine existing scopes, although the latter is considered bad practice +and you __cannot__ override the built-in `singleton` and `prototype` scopes. + + +[[beans-factory-scopes-custom-creating]] +===== Creating a custom scope +To integrate your custom scope(s) into the Spring container, you need to implement the +`org.springframework.beans.factory.config.Scope` interface, which is described in this +section. For an idea of how to implement your own scopes, see the `Scope` +implementations that are supplied with the Spring Framework itself and the +{javadoc-baseurl}/org/springframework/beans/factory/config/Scope.html[`Scope` javadocs], +which explains the methods you need to implement in more detail. + +The `Scope` interface has four methods to get objects from the scope, remove them from +the scope, and allow them to be destroyed. + +The following method returns the object from the underlying scope. The session scope +implementation, for example, returns the session-scoped bean (and if it does not exist, +the method returns a new instance of the bean, after having bound it to the session for +future reference). + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + Object get(String name, ObjectFactory objectFactory) +---- + +The following method removes the object from the underlying scope. The session scope +implementation for example, removes the session-scoped bean from the underlying session. +The object should be returned, but you can return null if the object with the specified +name is not found. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + Object remove(String name) +---- + +The following method registers the callbacks the scope should execute when it is +destroyed or when the specified object in the scope is destroyed. Refer to the javadocs +or a Spring scope implementation for more information on destruction callbacks. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + void registerDestructionCallback(String name, Runnable destructionCallback) +---- + +The following method obtains the conversation identifier for the underlying scope. This +identifier is different for each scope. For a session scoped implementation, this +identifier can be the session identifier. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + String getConversationId() +---- + + +[[beans-factory-scopes-custom-using]] +===== Using a custom scope +After you write and test one or more custom `Scope` implementations, you need to make +the Spring container aware of your new scope(s). The following method is the central +method to register a new `Scope` with the Spring container: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + void registerScope(String scopeName, Scope scope); +---- + +This method is declared on the `ConfigurableBeanFactory` interface, which is available +on most of the concrete `ApplicationContext` implementations that ship with Spring via +the BeanFactory property. + +The first argument to the `registerScope(..)` method is the unique name associated with +a scope; examples of such names in the Spring container itself are `singleton` and +`prototype`. The second argument to the `registerScope(..)` method is an actual instance +of the custom `Scope` implementation that you wish to register and use. + +Suppose that you write your custom `Scope` implementation, and then register it as below. + +[NOTE] +==== +The example below uses `SimpleThreadScope` which is included with Spring, but not +registered by default. The instructions would be the same for your own custom `Scope` +implementations. +==== + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + Scope threadScope = new SimpleThreadScope(); + beanFactory.registerScope("thread", threadScope); +---- + +You then create bean definitions that adhere to the scoping rules of your custom `Scope`: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + +---- + +With a custom `Scope` implementation, you are not limited to programmatic registration +of the scope. You can also do the `Scope` registration declaratively, using the +`CustomScopeConfigurer` class: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + + + + + + + + + + + + + + + + +---- + +[NOTE] +==== +When you place `` in a `FactoryBean` implementation, it is the factory +bean itself that is scoped, not the object returned from `getObject()`. +==== + + + + +[[beans-factory-nature]] +=== Customizing the nature of a bean + + + +[[beans-factory-lifecycle]] +==== Lifecycle callbacks +To interact with the container's management of the bean lifecycle, you can implement the +Spring `InitializingBean` and `DisposableBean` interfaces. The container calls +`afterPropertiesSet()` for the former and `destroy()` for the latter to allow the bean +to perform certain actions upon initialization and destruction of your beans. + +[TIP] +==== + +The JSR-250 `@PostConstruct` and `@PreDestroy` annotations are generally considered best +practice for receiving lifecycle callbacks in a modern Spring application. Using these +annotations means that your beans are not coupled to Spring specific interfaces. For +details see <>. + +If you don't want to use the JSR-250 annotations but you are still looking to remove +coupling consider the use of init-method and destroy-method object definition metadata. +==== + +Internally, the Spring Framework uses `BeanPostProcessor` implementations to process any +callback interfaces it can find and call the appropriate methods. If you need custom +features or other lifecycle behavior Spring does not offer out-of-the-box, you can +implement a `BeanPostProcessor` yourself. For more information, see +<>. + +In addition to the initialization and destruction callbacks, Spring-managed objects may +also implement the `Lifecycle` interface so that those objects can participate in the +startup and shutdown process as driven by the container's own lifecycle. + +The lifecycle callback interfaces are described in this section. + + +[[beans-factory-lifecycle-initializingbean]] +===== Initialization callbacks +The `org.springframework.beans.factory.InitializingBean` interface allows a bean to +perform initialization work after all necessary properties on the bean have been set by +the container. The `InitializingBean` interface specifies a single method: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + void afterPropertiesSet() throws Exception; +---- + +It is recommended that you do not use the `InitializingBean` interface because it +unnecessarily couples the code to Spring. Alternatively, use +the <> annotation or +specify a POJO initialization method. In the case of XML-based configuration metadata, +you use the `init-method` attribute to specify the name of the method that has a void +no-argument signature. For example, the following definition: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + +---- + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class ExampleBean { + + public void init() { + // do some initialization work + } + + } +---- + +...is exactly the same as... + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + +---- + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class AnotherExampleBean implements InitializingBean { + + public void afterPropertiesSet() { + // do some initialization work + } + + } +---- + +but does not couple the code to Spring. + + +[[beans-factory-lifecycle-disposablebean]] +===== Destruction callbacks +Implementing the `org.springframework.beans.factory.DisposableBean` interface allows a +bean to get a callback when the container containing it is destroyed. The +`DisposableBean` interface specifies a single method: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + void destroy() throws Exception; +---- + +It is recommended that you do not use the `DisposableBean` callback interface because it +unnecessarily couples the code to Spring. Alternatively, use +the <> annotation or +specify a generic method that is supported by bean definitions. With XML-based +configuration metadata, you use the `destroy-method` attribute on the ``. For +example, the following definition: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + +---- + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class ExampleBean { + + public void cleanup() { + // do some destruction work (like releasing pooled connections) + } + + } +---- + +is exactly the same as: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + +---- + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class AnotherExampleBean implements DisposableBean { + + public void destroy() { + // do some destruction work (like releasing pooled connections) + } + + } +---- + +but does not couple the code to Spring. + + +[[beans-factory-lifecycle-default-init-destroy-methods]] +===== Default initialization and destroy methods +When you write initialization and destroy method callbacks that do not use the +Spring-specific `InitializingBean` and `DisposableBean` callback interfaces, you +typically write methods with names such as `init()`, `initialize()`, `dispose()`, and so +on. Ideally, the names of such lifecycle callback methods are standardized across a +project so that all developers use the same method names and ensure consistency. + +You can configure the Spring container to `look` for named initialization and destroy +callback method names on __every__ bean. This means that you, as an application +developer, can write your application classes and use an initialization callback called +`init()`, without having to configure an `init-method="init"` attribute with each bean +definition. The Spring IoC container calls that method when the bean is created (and in +accordance with the standard lifecycle callback contract described previously). This +feature also enforces a consistent naming convention for initialization and destroy +method callbacks. + +Suppose that your initialization callback methods are named `init()` and destroy +callback methods are named `destroy()`. Your class will resemble the class in the +following example. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class DefaultBlogService implements BlogService { + + private BlogDao blogDao; + + public void setBlogDao(BlogDao blogDao) { + this.blogDao = blogDao; + } + + // this is (unsurprisingly) the initialization callback method + public void init() { + if (this.blogDao == null) { + throw new IllegalStateException("The [blogDao] property must be set."); + } + } + + } +---- + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + +---- + +The presence of the `default-init-method` attribute on the top-level `` element +attribute causes the Spring IoC container to recognize a method called `init` on beans +as the initialization method callback. When a bean is created and assembled, if the bean +class has such a method, it is invoked at the appropriate time. + +You configure destroy method callbacks similarly (in XML, that is) by using the +`default-destroy-method` attribute on the top-level `` element. + +Where existing bean classes already have callback methods that are named at variance +with the convention, you can override the default by specifying (in XML, that is) the +method name using the `init-method` and `destroy-method` attributes of the +itself. + +The Spring container guarantees that a configured initialization callback is called +immediately after a bean is supplied with all dependencies. Thus the initialization +callback is called on the raw bean reference, which means that AOP interceptors and so +forth are not yet applied to the bean. A target bean is fully created __first__, +__then__ an AOP proxy (for example) with its interceptor chain is applied. If the target +bean and the proxy are defined separately, your code can even interact with the raw +target bean, bypassing the proxy. Hence, it would be inconsistent to apply the +interceptors to the init method, because doing so would couple the lifecycle of the +target bean with its proxy/interceptors and leave strange semantics when your code +interacts directly to the raw target bean. + + +[[beans-factory-lifecycle-combined-effects]] +===== Combining lifecycle mechanisms +As of Spring 2.5, you have three options for controlling bean lifecycle behavior: the +<> and +<> callback interfaces; custom +`init()` and `destroy()` methods; and the +<>. You can combine these mechanisms to control a given bean. + +[NOTE] +==== +If multiple lifecycle mechanisms are configured for a bean, and each mechanism is +configured with a different method name, then each configured method is executed in the +order listed below. However, if the same method name is configured - for example, +`init()` for an initialization method - for more than one of these lifecycle mechanisms, +that method is executed once, as explained in the preceding section. +==== + +Multiple lifecycle mechanisms configured for the same bean, with different +initialization methods, are called as follows: + +* Methods annotated with `@PostConstruct` +* `afterPropertiesSet()` as defined by the `InitializingBean` callback interface +* A custom configured `init()` method + +Destroy methods are called in the same order: + +* Methods annotated with `@PreDestroy` +* `destroy()` as defined by the `DisposableBean` callback interface +* A custom configured `destroy()` method + + +[[beans-factory-lifecycle-processor]] +===== Startup and shutdown callbacks +The `Lifecycle` interface defines the essential methods for any object that has its own +lifecycle requirements (e.g. starts and stops some background process): + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public interface Lifecycle { + + void start(); + + void stop(); + + boolean isRunning(); + + } +---- + +Any Spring-managed object may implement that interface. Then, when the +`ApplicationContext` itself starts and stops, it will cascade those calls to all `Lifecycle` +implementations defined within that context. It does this by delegating to a +`LifecycleProcessor`: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public interface LifecycleProcessor extends Lifecycle { + + void onRefresh(); + + void onClose(); + + } +---- + +Notice that the `LifecycleProcessor` is itself an extension of the `Lifecycle` +interface. It also adds two other methods for reacting to the context being refreshed +and closed. + +The order of startup and shutdown invocations can be important. If a "depends-on" +relationship exists between any two objects, the dependent side will start __after__ its +dependency, and it will stop __before__ its dependency. However, at times the direct +dependencies are unknown. You may only know that objects of a certain type should start +prior to objects of another type. In those cases, the `SmartLifecycle` interface defines +another option, namely the `getPhase()` method as defined on its super-interface, +`Phased`. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public interface Phased { + + int getPhase(); + + } +---- + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public interface SmartLifecycle extends Lifecycle, Phased { + + boolean isAutoStartup(); + + void stop(Runnable callback); + + } +---- + +When starting, the objects with the lowest phase start first, and when stopping, the +reverse order is followed. Therefore, an object that implements `SmartLifecycle` and +whose `getPhase()` method returns `Integer.MIN_VALUE` would be among the first to start +and the last to stop. At the other end of the spectrum, a phase value of +`Integer.MAX_VALUE` would indicate that the object should be started last and stopped +first (likely because it depends on other processes to be running). When considering the +phase value, it's also important to know that the default phase for any "normal" +`Lifecycle` object that does not implement `SmartLifecycle` would be 0. Therefore, any +negative phase value would indicate that an object should start before those standard +components (and stop after them), and vice versa for any positive phase value. + +As you can see the stop method defined by `SmartLifecycle` accepts a callback. Any +implementation __must__ invoke that callback's `run()` method after that implementation's +shutdown process is complete. That enables asynchronous shutdown where necessary since +the default implementation of the `LifecycleProcessor` interface, +`DefaultLifecycleProcessor`, will wait up to its timeout value for the group of objects +within each phase to invoke that callback. The default per-phase timeout is 30 seconds. +You can override the default lifecycle processor instance by defining a bean named +"lifecycleProcessor" within the context. If you only want to modify the timeout, then +defining the following would be sufficient: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + +---- + +As mentioned, the `LifecycleProcessor` interface defines callback methods for the +refreshing and closing of the context as well. The latter will simply drive the shutdown +process as if `stop()` had been called explicitly, but it will happen when the context is +closing. The 'refresh' callback on the other hand enables another feature of +`SmartLifecycle` beans. When the context is refreshed (after all objects have been +instantiated and initialized), that callback will be invoked, and at that point the +default lifecycle processor will check the boolean value returned by each +`SmartLifecycle` object's `isAutoStartup()` method. If "true", then that object will be +started at that point rather than waiting for an explicit invocation of the context's or +its own `start()` method (unlike the context refresh, the context start does not happen +automatically for a standard context implementation). The "phase" value as well as any +"depends-on" relationships will determine the startup order in the same way as described +above. + + +[[beans-factory-shutdown]] +===== Shutting down the Spring IoC container gracefully in non-web applications +[NOTE] +==== +This section applies only to non-web applications. Spring's web-based +`ApplicationContext` implementations already have code in place to shut down the Spring +IoC container gracefully when the relevant web application is shut down. +==== + +If you are using Spring's IoC container in a non-web application environment; for +example, in a rich client desktop environment; you register a shutdown hook with the +JVM. Doing so ensures a graceful shutdown and calls the relevant destroy methods on your +singleton beans so that all resources are released. Of course, you must still configure +and implement these destroy callbacks correctly. + +To register a shutdown hook, you call the `registerShutdownHook()` method that is +declared on the `AbstractApplicationContext` class: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + import org.springframework.context.support.AbstractApplicationContext; + import org.springframework.context.support.ClassPathXmlApplicationContext; + + public final class Boot { + + public static void main(final String[] args) throws Exception { + + AbstractApplicationContext ctx = new ClassPathXmlApplicationContext( + new String []{"beans.xml"}); + + // add a shutdown hook for the above context... + ctx.registerShutdownHook(); + + // app runs here... + + // main method exits, hook is called prior to the app shutting down... + + } + } +---- + + + +[[beans-factory-aware]] +==== ApplicationContextAware and BeanNameAware + +When an `ApplicationContext` creates an object instance that implements the +`org.springframework.context.ApplicationContextAware` interface, the instance is provided +with a reference to that `ApplicationContext`. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public interface ApplicationContextAware { + + void setApplicationContext(ApplicationContext applicationContext) throws BeansException; + + } +---- + +Thus beans can manipulate programmatically the `ApplicationContext` that created them, +through the `ApplicationContext` interface, or by casting the reference to a known +subclass of this interface, such as `ConfigurableApplicationContext`, which exposes +additional functionality. One use would be the programmatic retrieval of other beans. +Sometimes this capability is useful; however, in general you should avoid it, because it +couples the code to Spring and does not follow the Inversion of Control style, where +collaborators are provided to beans as properties. Other methods of the +`ApplicationContext` provide access to file resources, publishing application events, and +accessing a `MessageSource`. These additional features are described in +<> + +As of Spring 2.5, autowiring is another alternative to obtain reference to the +`ApplicationContext`. The "traditional" `constructor` and `byType` autowiring modes (as +described in <>) can provide a dependency of type +`ApplicationContext` for a constructor argument or setter method parameter, +respectively. For more flexibility, including the ability to autowire fields and +multiple parameter methods, use the new annotation-based autowiring features. If you do, +the `ApplicationContext` is autowired into a field, constructor argument, or method +parameter that is expecting the `ApplicationContext` type if the field, constructor, or +method in question carries the `@Autowired` annotation. For more information, see +<>. + +When an `ApplicationContext` creates a class that implements the +`org.springframework.beans.factory.BeanNameAware` interface, the class is provided with +a reference to the name defined in its associated object definition. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public interface BeanNameAware { + + void setBeanName(string name) throws BeansException; + + } +---- + +The callback is invoked after population of normal bean properties but before an +initialization callback such as `InitializingBean` __afterPropertiesSet__ or a custom +init-method. + + + +[[aware-list]] +==== Other Aware interfaces + +Besides `ApplicationContextAware` and `BeanNameAware` discussed above, Spring offers a +range of `Aware` interfaces that allow beans to indicate to the container that they +require a certain __infrastructure__ dependency. The most important `Aware` interfaces +are summarized below - as a general rule, the name is a good indication of the +dependency type: + +[[beans-factory-nature-aware-list]] +.Aware interfaces +|=== +| Name| Injected Dependency| Explained in... + +| `ApplicationContextAware` +| Declaring `ApplicationContext` +| <> + +| `ApplicationEventPublisherAware` +| Event publisher of the enclosing `ApplicationContext` +| <> + +| `BeanClassLoaderAware` +| Class loader used to load the bean classes. +| <> + +| `BeanFactoryAware` +| Declaring `BeanFactory` +| <> + +| `BeanNameAware` +| Name of the declaring bean +| <> + +| `BootstrapContextAware` +| Resource adapter `BootstrapContext` the container runs in. Typically available only in + JCA aware ++ApplicationContext++s +| <> + +| `LoadTimeWeaverAware` +| Defined __weaver__ for processing class definition at load time +| <> + +| `MessageSourceAware` +| Configured strategy for resolving messages (with support for parametrization and + internationalization) +| <> + +| `NotificationPublisherAware` +| Spring JMX notification publisher +| <> + +| `PortletConfigAware` +| Current `PortletConfig` the container runs in. Valid only in a web-aware Spring + `ApplicationContext` +| <> + +| `PortletContextAware` +| Current `PortletContext` the container runs in. Valid only in a web-aware Spring + `ApplicationContext` +| <> + +| `ResourceLoaderAware` +| Configured loader for low-level access to resources +| <> + +| `ServletConfigAware` +| Current `ServletConfig` the container runs in. Valid only in a web-aware Spring + `ApplicationContext` +| <> + +| `ServletContextAware` +| Current `ServletContext` the container runs in. Valid only in a web-aware Spring + `ApplicationContext` +| <> +|=== + +Note again that usage of these interfaces ties your code to the Spring API and does not +follow the Inversion of Control style. As such, they are recommended for infrastructure +beans that require programmatic access to the container. + + + + +[[beans-child-bean-definitions]] +=== Bean definition inheritance +A bean definition can contain a lot of configuration information, including constructor +arguments, property values, and container-specific information such as initialization +method, static factory method name, and so on. A child bean definition inherits +configuration data from a parent definition. The child definition can override some +values, or add others, as needed. Using parent and child bean definitions can save a lot +of typing. Effectively, this is a form of templating. + +If you work with an `ApplicationContext` interface programmatically, child bean +definitions are represented by the `ChildBeanDefinition` class. Most users do not work +with them on this level, instead configuring bean definitions declaratively in something +like the `ClassPathXmlApplicationContext`. When you use XML-based configuration +metadata, you indicate a child bean definition by using the `parent` attribute, +specifying the parent bean as the value of this attribute. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + + +---- + +A child bean definition uses the bean class from the parent definition if none is +specified, but can also override it. In the latter case, the child bean class must be +compatible with the parent, that is, it must accept the parent's property values. + +A child bean definition inherits constructor argument values, property values, and +method overrides from the parent, with the option to add new values. Any initialization +method, destroy method, and/or `static` factory method settings that you specify will +override the corresponding parent settings. + +The remaining settings are __always__ taken from the child definition: __depends on__, +__autowire mode__, __dependency check__, __singleton__, __scope__, __lazy init__. + +The preceding example explicitly marks the parent bean definition as abstract by using +the `abstract` attribute. If the parent definition does not specify a class, explicitly +marking the parent bean definition as `abstract` is required, as follows: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + + +---- + +The parent bean cannot be instantiated on its own because it is incomplete, and it is +also explicitly marked as `abstract`. When a definition is `abstract` like this, it is +usable only as a pure template bean definition that serves as a parent definition for +child definitions. Trying to use such an `abstract` parent bean on its own, by referring +to it as a ref property of another bean or doing an explicit `getBean()` call with the +parent bean id, returns an error. Similarly, the container's internal +`preInstantiateSingletons()` method ignores bean definitions that are defined as +abstract. + +[NOTE] +==== +`ApplicationContext` pre-instantiates all singletons by default. Therefore, it is +important (at least for singleton beans) that if you have a (parent) bean definition +which you intend to use only as a template, and this definition specifies a class, you +must make sure to set the __abstract__ attribute to __true__, otherwise the application +context will actually (attempt to) pre-instantiate the `abstract` bean. +==== + + + + +[[beans-factory-extension]] +=== Container Extension Points +Typically, an application developer does not need to subclass `ApplicationContext` +implementation classes. Instead, the Spring IoC container can be extended by plugging in +implementations of special integration interfaces. The next few sections describe these +integration interfaces. + + + +[[beans-factory-extension-bpp]] +==== Customizing beans using a BeanPostProcessor + +The `BeanPostProcessor` interface defines __callback methods__ that you can implement to +provide your own (or override the container's default) instantiation logic, +dependency-resolution logic, and so forth. If you want to implement some custom logic +after the Spring container finishes instantiating, configuring, and initializing a bean, +you can plug in one or more `BeanPostProcessor` implementations. + +You can configure multiple `BeanPostProcessor` instances, and you can control the order +in which these ++BeanPostProcessor++s execute by setting the `order` property. You can +set this property only if the `BeanPostProcessor` implements the `Ordered` interface; if +you write your own `BeanPostProcessor` you should consider implementing the `Ordered` +interface too. For further details, consult the javadocs of the `BeanPostProcessor` and +`Ordered` interfaces. See also the note below on +<> + +[NOTE] +==== +++BeanPostProcessor++s operate on bean (or object) __instances__; that is to say, the +Spring IoC container instantiates a bean instance and __then__ ++BeanPostProcessor++s do +their work. + +++BeanPostProcessor++s are scoped __per-container__. This is only relevant if you are +using container hierarchies. If you define a `BeanPostProcessor` in one container, it +will __only__ post-process the beans in that container. In other words, beans that are +defined in one container are not post-processed by a `BeanPostProcessor` defined in +another container, even if both containers are part of the same hierarchy. + +To change the actual bean definition (i.e., the __blueprint__ that defines the bean), +you instead need to use a `BeanFactoryPostProcessor` as described in +<>. +==== + +The `org.springframework.beans.factory.config.BeanPostProcessor` interface consists of +exactly two callback methods. When such a class is registered as a post-processor with +the container, for each bean instance that is created by the container, the +post-processor gets a callback from the container both __before__ container +initialization methods (such as InitializingBean's __afterPropertiesSet()__ and any +declared init method) are called as well as __after__ any bean initialization callbacks. +The post-processor can take any action with the bean instance, including ignoring the +callback completely. A bean post-processor typically checks for callback interfaces or +may wrap a bean with a proxy. Some Spring AOP infrastructure classes are implemented as +bean post-processors in order to provide proxy-wrapping logic. + +An `ApplicationContext` __automatically detects__ any beans that are defined in the +configuration metadata which implement the `BeanPostProcessor` interface. The +`ApplicationContext` registers these beans as post-processors so that they can be called +later upon bean creation. Bean post-processors can be deployed in the container just +like any other beans. + +Note that when declaring a ++BeanPostProcessor++ using an `@Bean` factory method on a +configuration class, the return type of the factory method should be the implementation +class itself or at least the `org.springframework.beans.factory.config.BeanPostProcessor` +interface, clearly indicating the post-processor nature of that bean. Otherwise, the +`ApplicationContext` won't be able to autodetect it by type before fully creating it. +Since a ++BeanPostProcessor++ needs to be instantiated early in order to apply to the +initialization of other beans in the context, this early type detection is critical. + +[NOTE] +==== + +*Programmatically registering BeanPostProcessors* + +While the recommended approach for `BeanPostProcessor` registration is through +`ApplicationContext` auto-detection (as described above), it is also possible to +register them __programmatically__ against a `ConfigurableBeanFactory` using the +`addBeanPostProcessor` method. This can be useful when needing to evaluate conditional +logic before registration, or even for copying bean post processors across contexts in a +hierarchy. Note however that `BeanPostProcessors` added programmatically __do not +respect the `Ordered` interface__. Here it is the __order of registration__ that +dictates the order of execution. Note also that `BeanPostProcessors` registered +programmatically are always processed before those registered through auto-detection, +regardless of any explicit ordering. +==== + +[NOTE] +==== + +*BeanPostProcessors and AOP auto-proxying* + +Classes that implement the `BeanPostProcessor` interface are __special__ and are treated +differently by the container. All `BeanPostProcessors` __and beans that they reference +directly__ are instantiated on startup, as part of the special startup phase of the +`ApplicationContext`. Next, all `BeanPostProcessors` are registered in a sorted fashion +and applied to all further beans in the container. Because AOP auto-proxying is +implemented as a `BeanPostProcessor` itself, neither `BeanPostProcessors` nor the beans +they reference directly are eligible for auto-proxying, and thus do not have aspects +woven into them. + +For any such bean, you should see an informational log message: "__Bean foo is not +eligible for getting processed by all BeanPostProcessor interfaces (for example: not +eligible for auto-proxying)__". + +Note that if you have beans wired into your `BeanPostProcessor` using autowiring or +`@Resource` (which may fall back to autowiring), Spring might access unexpected beans +when searching for type-matching dependency candidates, and therefore make them +ineligible for auto-proxying or other kinds of bean post-processing. For example, if you +have a dependency annotated with `@Resource` where the field/setter name does not +directly correspond to the declared name of a bean and no name attribute is used, then +Spring will access other beans for matching them by type. +==== + +The following examples show how to write, register, and use `BeanPostProcessors` in an +`ApplicationContext`. + + +[[beans-factory-extension-bpp-examples-hw]] +===== Example: Hello World, BeanPostProcessor-style + +This first example illustrates basic usage. The example shows a custom +`BeanPostProcessor` implementation that invokes the `toString()` method of each bean as +it is created by the container and prints the resulting string to the system console. + +Find below the custom `BeanPostProcessor` implementation class definition: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + package scripting; + + import org.springframework.beans.factory.config.BeanPostProcessor; + import org.springframework.beans.BeansException; + + public class InstantiationTracingBeanPostProcessor implements BeanPostProcessor { + + // simply return the instantiated bean as-is + public Object postProcessBeforeInitialization(Object bean, + String beanName) throws BeansException { + return bean; // we could potentially return any object reference here... + } + + public Object postProcessAfterInitialization(Object bean, + String beanName) throws BeansException { + System.out.println("Bean '" + beanName + "' created : " + bean.toString()); + return bean; + } + + } +---- + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + + + + +---- + +Notice how the `InstantiationTracingBeanPostProcessor` is simply defined. It does not +even have a name, and because it is a bean it can be dependency-injected just like any +other bean. (The preceding configuration also defines a bean that is backed by a Groovy +script. The Spring dynamic language support is detailed in the chapter entitled +<>.) + +The following simple Java application executes the preceding code and configuration: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + import org.springframework.context.ApplicationContext; + import org.springframework.context.support.ClassPathXmlApplicationContext; + import org.springframework.scripting.Messenger; + + public final class Boot { + + public static void main(final String[] args) throws Exception { + ApplicationContext ctx = new ClassPathXmlApplicationContext("scripting/beans.xml"); + Messenger messenger = (Messenger) ctx.getBean("messenger"); + System.out.println(messenger); + } + + } +---- + +The output of the preceding application resembles the following: + +[literal] +[subs="verbatim,quotes"] +---- +Bean 'messenger' created : org.springframework.scripting.groovy.GroovyMessenger@272961 +org.springframework.scripting.groovy.GroovyMessenger@272961 +---- + + +[[beans-factory-extension-bpp-examples-rabpp]] +===== Example: The RequiredAnnotationBeanPostProcessor + +Using callback interfaces or annotations in conjunction with a custom +`BeanPostProcessor` implementation is a common means of extending the Spring IoC +container. An example is Spring's `RequiredAnnotationBeanPostProcessor` - a +`BeanPostProcessor` implementation that ships with the Spring distribution which ensures +that JavaBean properties on beans that are marked with an (arbitrary) annotation are +actually (configured to be) dependency-injected with a value. + + + +[[beans-factory-extension-factory-postprocessors]] +==== Customizing configuration metadata with a BeanFactoryPostProcessor + +The next extension point that we will look at is the +`org.springframework.beans.factory.config.BeanFactoryPostProcessor`. The semantics of +this interface are similar to those of the `BeanPostProcessor`, with one major +difference: `BeanFactoryPostProcessor` operates on the __bean configuration metadata__; +that is, the Spring IoC container allows a `BeanFactoryPostProcessor` to read the +configuration metadata and potentially change it __before__ the container instantiates +any beans other than `BeanFactoryPostProcessors`. + +You can configure multiple `BeanFactoryPostProcessors`, and you can control the order in +which these `BeanFactoryPostProcessors` execute by setting the `order` property. +However, you can only set this property if the `BeanFactoryPostProcessor` implements the +`Ordered` interface. If you write your own `BeanFactoryPostProcessor`, you should +consider implementing the `Ordered` interface too. Consult the javadocs of the +`BeanFactoryPostProcessor` and `Ordered` interfaces for more details. + +[NOTE] +==== +If you want to change the actual bean __instances__ (i.e., the objects that are created +from the configuration metadata), then you instead need to use a `BeanPostProcessor` +(described above in <>). While it is technically possible +to work with bean instances within a `BeanFactoryPostProcessor` (e.g., using +`BeanFactory.getBean()`), doing so causes premature bean instantiation, violating the +standard container lifecycle. This may cause negative side effects such as bypassing +bean post processing. + +Also, `BeanFactoryPostProcessors` are scoped __per-container__. This is only relevant if +you are using container hierarchies. If you define a `BeanFactoryPostProcessor` in one +container, it will __only__ be applied to the bean definitions in that container. Bean +definitions in one container will not be post-processed by `BeanFactoryPostProcessors` +in another container, even if both containers are part of the same hierarchy. +==== + +A bean factory post-processor is executed automatically when it is declared inside an +`ApplicationContext`, in order to apply changes to the configuration metadata that +define the container. Spring includes a number of predefined bean factory +post-processors, such as `PropertyOverrideConfigurer` and +`PropertyPlaceholderConfigurer`. A custom `BeanFactoryPostProcessor` can also be used, +for example, to register custom property editors. + +[[null]] + +An `ApplicationContext` automatically detects any beans that are deployed into it that +implement the `BeanFactoryPostProcessor` interface. It uses these beans as bean factory +post-processors, at the appropriate time. You can deploy these post-processor beans as +you would any other bean. + +[NOTE] +==== +As with ++BeanPostProcessor++s , you typically do not want to configure +++BeanFactoryPostProcessor++s for lazy initialization. If no other bean references a +`Bean(Factory)PostProcessor`, that post-processor will not get instantiated at all. +Thus, marking it for lazy initialization will be ignored, and the +`Bean(Factory)PostProcessor` will be instantiated eagerly even if you set the +`default-lazy-init` attribute to `true` on the declaration of your `` element. +==== + + +[[beans-factory-placeholderconfigurer]] +===== Example: the Class name substitution PropertyPlaceholderConfigurer + +You use the `PropertyPlaceholderConfigurer` to externalize property values from a bean +definition in a separate file using the standard Java `Properties` format. Doing so +enables the person deploying an application to customize environment-specific properties +such as database URLs and passwords, without the complexity or risk of modifying the +main XML definition file or files for the container. + +Consider the following XML-based configuration metadata fragment, where a `DataSource` +with placeholder values is defined. The example shows properties configured from an +external `Properties` file. At runtime, a `PropertyPlaceholderConfigurer` is applied to +the metadata that will replace some properties of the DataSource. The values to replace +are specified as __placeholders__ of the form `${property-name}` which follows the Ant / +log4j / JSP EL style. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + + + +---- + +The actual values come from another file in the standard Java `Properties` format: + +[literal] +[subs="verbatim,quotes"] +---- +jdbc.driverClassName=org.hsqldb.jdbcDriver +jdbc.url=jdbc:hsqldb:hsql://production:9002 +jdbc.username=sa +jdbc.password=root +---- + +Therefore, the string `${jdbc.username}` is replaced at runtime with the value 'sa', and +the same applies for other placeholder values that match keys in the properties file. +The `PropertyPlaceholderConfigurer` checks for placeholders in most properties and +attributes of a bean definition. Furthermore, the placeholder prefix and suffix can be +customized. + +With the `context` namespace introduced in Spring 2.5, it is possible to configure +property placeholders with a dedicated configuration element. One or more locations can +be provided as a comma-separated list in the `location` attribute. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + +---- + +The `PropertyPlaceholderConfigurer` not only looks for properties in the `Properties` +file you specify. By default it also checks against the Java `System` properties if it +cannot find a property in the specified properties files. You can customize this +behavior by setting the `systemPropertiesMode` property of the configurer with one of +the following three supported integer values: + +* __never__ (0): Never check system properties +* __fallback__ (1): Check system properties if not resolvable in the specified + properties files. This is the default. +* __override__ (2): Check system properties first, before trying the specified + properties files. This allows system properties to override any other property source. + +Consult the `PropertyPlaceholderConfigurer` javadocs for more information. + +[TIP] +==== + +You can use the `PropertyPlaceholderConfigurer` to substitute class names, which is +sometimes useful when you have to pick a particular implementation class at runtime. For +example: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + classpath:com/foo/strategy.properties + + + custom.strategy.class=com.foo.DefaultStrategy + + + + +---- + +If the class cannot be resolved at runtime to a valid class, resolution of the bean +fails when it is about to be created, which is during the `preInstantiateSingletons()` +phase of an `ApplicationContext` for a non-lazy-init bean. +==== + + +[[beans-factory-overrideconfigurer]] +===== Example: the PropertyOverrideConfigurer + +The `PropertyOverrideConfigurer`, another bean factory post-processor, resembles the +`PropertyPlaceholderConfigurer`, but unlike the latter, the original definitions can +have default values or no values at all for bean properties. If an overriding +`Properties` file does not have an entry for a certain bean property, the default +context definition is used. + +Note that the bean definition is __not__ aware of being overridden, so it is not +immediately obvious from the XML definition file that the override configurer is being +used. In case of multiple `PropertyOverrideConfigurer` instances that define different +values for the same bean property, the last one wins, due to the overriding mechanism. + +Properties file configuration lines take this format: + +[literal] +[subs="verbatim,quotes"] +---- +beanName.property=value +---- + +For example: + +[literal] +[subs="verbatim,quotes"] +---- +dataSource.driverClassName=com.mysql.jdbc.Driver +dataSource.url=jdbc:mysql:mydb +---- + +This example file can be used with a container definition that contains a bean called +__dataSource__, which has __driver__ and __url__ properties. + +Compound property names are also supported, as long as every component of the path +except the final property being overridden is already non-null (presumably initialized +by the constructors). In this example... + +[literal] +[subs="verbatim,quotes"] +---- +foo.fred.bob.sammy=123 +---- + +... the `sammy` property of the `bob` property of the `fred` property of the `foo` bean +is set to the scalar value `123`. + +[NOTE] +==== +Specified override values are always __literal__ values; they are not translated into +bean references. This convention also applies when the original value in the XML bean +definition specifies a bean reference. +==== + +With the `context` namespace introduced in Spring 2.5, it is possible to configure +property overriding with a dedicated configuration element: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + +---- + + + +[[beans-factory-extension-factorybean]] +==== Customizing instantiation logic with a FactoryBean + +Implement the `org.springframework.beans.factory.FactoryBean` interface for objects that +__are themselves factories__. + +The `FactoryBean` interface is a point of pluggability into the Spring IoC container's +instantiation logic. If you have complex initialization code that is better expressed in +Java as opposed to a (potentially) verbose amount of XML, you can create your own +`FactoryBean`, write the complex initialization inside that class, and then plug your +custom `FactoryBean` into the container. + +The `FactoryBean` interface provides three methods: + +* `Object getObject()`: returns an instance of the object this factory creates. The + instance can possibly be shared, depending on whether this factory returns singletons + or prototypes. +* `boolean isSingleton()`: returns `true` if this `FactoryBean` returns singletons, + `false` otherwise. +* `Class getObjectType()`: returns the object type returned by the `getObject()` method + or `null` if the type is not known in advance. + +The `FactoryBean` concept and interface is used in a number of places within the Spring +Framework; more than 50 implementations of the `FactoryBean` interface ship with Spring +itself. + +When you need to ask a container for an actual `FactoryBean` instance itself instead of +the bean it produces, preface the bean's id with the ampersand symbol ( `&`) when +calling the `getBean()` method of the `ApplicationContext`. So for a given `FactoryBean` +with an id of `myBean`, invoking `getBean("myBean")` on the container returns the +product of the `FactoryBean`; whereas, invoking `getBean("&myBean")` returns the +`FactoryBean` instance itself. + + + + +[[beans-annotation-config]] +=== Annotation-based container configuration + +.Are annotations better than XML for configuring Spring? +**** +The introduction of annotation-based configurations raised the question of whether this +approach is 'better' than XML. The short answer is __it depends__. The long answer is +that each approach has its pros and cons, and usually it is up to the developer to +decide which strategy suits them better. Due to the way they are defined, annotations +provide a lot of context in their declaration, leading to shorter and more concise +configuration. However, XML excels at wiring up components without touching their source +code or recompiling them. Some developers prefer having the wiring close to the source +while others argue that annotated classes are no longer POJOs and, furthermore, that the +configuration becomes decentralized and harder to control. + +No matter the choice, Spring can accommodate both styles and even mix them together. +It's worth pointing out that through its <> option, Spring allows +annotations to be used in a non-invasive way, without touching the target components +source code and that in terms of tooling, all configuration styles are supported by the +https://spring.io/tools/sts[Spring Tool Suite]. +**** + +An alternative to XML setups is provided by annotation-based configuration which rely on +the bytecode metadata for wiring up components instead of angle-bracket declarations. +Instead of using XML to describe a bean wiring, the developer moves the configuration +into the component class itself by using annotations on the relevant class, method, or +field declaration. As mentioned in <>, using +a `BeanPostProcessor` in conjunction with annotations is a common means of extending the +Spring IoC container. For example, Spring 2.0 introduced the possibility of enforcing +required properties with the <> annotation. Spring +2.5 made it possible to follow that same general approach to drive Spring's dependency +injection. Essentially, the `@Autowired` annotation provides the same capabilities as +described in <> but with more fine-grained control and wider +applicability. Spring 2.5 also added support for JSR-250 annotations such as +`@PostConstruct`, and `@PreDestroy`. Spring 3.0 added support for JSR-330 (Dependency +Injection for Java) annotations contained in the javax.inject package such as `@Inject` +and `@Named`. Details about those annotations can be found in the +<>. +[NOTE] +==== +Annotation injection is performed __before__ XML injection, thus the latter +configuration will override the former for properties wired through both approaches. +==== +As always, you can register them as individual bean definitions, but they can also be +implicitly registered by including the following tag in an XML-based Spring +configuration (notice the inclusion of the `context` namespace): + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + +---- + +(The implicitly registered post-processors include +{javadoc-baseurl}/org/springframework/beans/factory/annotation/AutowiredAnnotationBeanPostProcessor.html[`AutowiredAnnotationBeanPostProcessor`], + {javadoc-baseurl}/org/springframework/context/annotation/CommonAnnotationBeanPostProcessor.html[`CommonAnnotationBeanPostProcessor`], + {javadoc-baseurl}/org/springframework/orm/jpa/support/PersistenceAnnotationBeanPostProcessor.html[`PersistenceAnnotationBeanPostProcessor`], +as well as the aforementioned +{javadoc-baseurl}/org/springframework/beans/factory/annotation/RequiredAnnotationBeanPostProcessor.html[`RequiredAnnotationBeanPostProcessor`].) + +[NOTE] +==== +`` only looks for annotations on beans in the same +application context in which it is defined. This means that, if you put +`` in a `WebApplicationContext` for a `DispatcherServlet`, +it only checks for `@Autowired` beans in your controllers, and not your services. See +<> for more information. +==== + + + +[[beans-required-annotation]] +==== @Required + +The `@Required` annotation applies to bean property setter methods, as in the following +example: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class SimpleMovieLister { + + private MovieFinder movieFinder; + + @Required + public void setMovieFinder(MovieFinder movieFinder) { + this.movieFinder = movieFinder; + } + + // ... + + } +---- + +This annotation simply indicates that the affected bean property must be populated at +configuration time, through an explicit property value in a bean definition or through +autowiring. The container throws an exception if the affected bean property has not been +populated; this allows for eager and explicit failure, avoiding ++NullPointerException++s +or the like later on. It is still recommended that you put assertions into the bean +class itself, for example, into an init method. Doing so enforces those required +references and values even when you use the class outside of a container. + + + +[[beans-autowired-annotation]] +==== @Autowired + +As expected, you can apply the `@Autowired` annotation to "traditional" setter methods: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class SimpleMovieLister { + + private MovieFinder movieFinder; + + @Autowired + public void setMovieFinder(MovieFinder movieFinder) { + this.movieFinder = movieFinder; + } + + // ... + + } +---- + +[NOTE] +==== +JSR 330's @Inject annotation can be used in place of Spring's `@Autowired` annotation in +the examples below. See <> for more details +==== + +You can also apply the annotation to methods with arbitrary names and/or multiple +arguments: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class MovieRecommender { + + private MovieCatalog movieCatalog; + + private CustomerPreferenceDao customerPreferenceDao; + + @Autowired + public void prepare(MovieCatalog movieCatalog, + CustomerPreferenceDao customerPreferenceDao) { + this.movieCatalog = movieCatalog; + this.customerPreferenceDao = customerPreferenceDao; + } + + // ... + + } +---- + +You can apply `@Autowired` to constructors and fields: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class MovieRecommender { + + @Autowired + private MovieCatalog movieCatalog; + + private CustomerPreferenceDao customerPreferenceDao; + + @Autowired + public MovieRecommender(CustomerPreferenceDao customerPreferenceDao) { + this.customerPreferenceDao = customerPreferenceDao; + } + + // ... + + } +---- + +It is also possible to provide __all__ beans of a particular type from the +`ApplicationContext` by adding the annotation to a field or method that expects an array +of that type: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class MovieRecommender { + + @Autowired + private MovieCatalog[] movieCatalogs; + + // ... + + } +---- + +The same applies for typed collections: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class MovieRecommender { + + private Set movieCatalogs; + + @Autowired + public void setMovieCatalogs(Set movieCatalogs) { + this.movieCatalogs = movieCatalogs; + } + + // ... + + } +---- + +[TIP] +==== +Your beans can implement the `org.springframework.core.Ordered` interface or either use +the `@Order` or standard `@Priority` annotation if you want items in the array or list +to be sorted into a specific order. +==== + + +Even typed Maps can be autowired as long as the expected key type is `String`. The Map +values will contain all beans of the expected type, and the keys will contain the +corresponding bean names: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class MovieRecommender { + + private Map movieCatalogs; + + @Autowired + public void setMovieCatalogs(Map movieCatalogs) { + this.movieCatalogs = movieCatalogs; + } + + // ... + + } +---- + +By default, the autowiring fails whenever __zero__ candidate beans are available; the +default behavior is to treat annotated methods, constructors, and fields as +indicating __required__ dependencies. This behavior can be changed as demonstrated below. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class SimpleMovieLister { + + private MovieFinder movieFinder; + + @Autowired(required=false) + public void setMovieFinder(MovieFinder movieFinder) { + this.movieFinder = movieFinder; + } + + // ... + + } +---- + +[NOTE] +==== +Only __one annotated constructor per-class__ can be marked as __required__, but multiple +non-required constructors can be annotated. In that case, each is considered among the +candidates and Spring uses the __greediest__ constructor whose dependencies can be +satisfied, that is the constructor that has the largest number of arguments. + +`@Autowired`'s __required__ attribute is recommended over the `@Required` annotation. +The __required__ attribute indicates that the property is not required for autowiring +purposes, the property is ignored if it cannot be autowired. `@Required`, on the other +hand, is stronger in that it enforces the property that was set by any means supported +by the container. If no value is injected, a corresponding exception is raised. +==== + +You can also use `@Autowired` for interfaces that are well-known resolvable +dependencies: `BeanFactory`, `ApplicationContext`, `Environment`, `ResourceLoader`, +`ApplicationEventPublisher`, and `MessageSource`. These interfaces and their extended +interfaces, such as `ConfigurableApplicationContext` or `ResourcePatternResolver`, are +automatically resolved, with no special setup necessary. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class MovieRecommender { + + @Autowired + private ApplicationContext context; + + public MovieRecommender() { + } + + // ... + + } +---- + +[NOTE] +==== +`@Autowired`, `@Inject`, `@Resource`, and `@Value` annotations are handled by a Spring +`BeanPostProcessor` implementations which in turn means that you __cannot__ apply these +annotations within your own `BeanPostProcessor` or `BeanFactoryPostProcessor` types (if +any). These types must be 'wired up' explicitly via XML or using a Spring `@Bean` method. +==== + + + +[[beans-autowired-annotation-qualifiers]] +==== Fine-tuning annotation-based autowiring with qualifiers +Because autowiring by type may lead to multiple candidates, it is often necessary to +have more control over the selection process. One way to accomplish this is with +Spring's `@Qualifier` annotation. You can associate qualifier values with specific +arguments, narrowing the set of type matches so that a specific bean is chosen for each +argument. In the simplest case, this can be a plain descriptive value: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class MovieRecommender { + + @Autowired + **@Qualifier("main")** + private MovieCatalog movieCatalog; + + // ... + + } +---- + +The `@Qualifier` annotation can also be specified on individual constructor arguments or +method parameters: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class MovieRecommender { + + private MovieCatalog movieCatalog; + + private CustomerPreferenceDao customerPreferenceDao; + + @Autowired + public void prepare(**@Qualifier("main")**MovieCatalog movieCatalog, + CustomerPreferenceDao customerPreferenceDao) { + this.movieCatalog = movieCatalog; + this.customerPreferenceDao = customerPreferenceDao; + } + + // ... + + } +---- + +The corresponding bean definitions appear as follows. The bean with qualifier value +"main" is wired with the constructor argument that is qualified with the same value. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + **** + + + + + + **** + + + + + + + +---- + +For a fallback match, the bean name is considered a default qualifier value. Thus you +can define the bean with an id "main" instead of the nested qualifier element, leading +to the same matching result. However, although you can use this convention to refer to +specific beans by name, `@Autowired` is fundamentally about type-driven injection with +optional semantic qualifiers. This means that qualifier values, even with the bean name +fallback, always have narrowing semantics within the set of type matches; they do not +semantically express a reference to a unique bean id. Good qualifier values are "main" +or "EMEA" or "persistent", expressing characteristics of a specific component that are +independent from the bean id, which may be auto-generated in case of an anonymous bean +definition like the one in the preceding example. + +Qualifiers also apply to typed collections, as discussed above, for example, to +`Set`. In this case, all matching beans according to the declared +qualifiers are injected as a collection. This implies that qualifiers do not have to be +unique; they rather simply constitute filtering criteria. For example, you can define +multiple `MovieCatalog` beans with the same qualifier value "action"; all of which would +be injected into a `Set` annotated with `@Qualifier("action")`. + +[TIP] +==== + +If you intend to express annotation-driven injection by name, do not primarily use +`@Autowired`, even if is technically capable of referring to a bean name through +`@Qualifier` values. Instead, use the JSR-250 `@Resource` annotation, which is +semantically defined to identify a specific target component by its unique name, with +the declared type being irrelevant for the matching process. + +As a specific consequence of this semantic difference, beans that are themselves defined +as a collection or map type cannot be injected through `@Autowired`, because type +matching is not properly applicable to them. Use `@Resource` for such beans, referring +to the specific collection or map bean by unique name. + +`@Autowired` applies to fields, constructors, and multi-argument methods, allowing for +narrowing through qualifier annotations at the parameter level. By contrast, `@Resource` +is supported only for fields and bean property setter methods with a single argument. As +a consequence, stick with qualifiers if your injection target is a constructor or a +multi-argument method. +==== + +You can create your own custom qualifier annotations. Simply define an annotation and +provide the `@Qualifier` annotation within your definition: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Target({ElementType.FIELD, ElementType.PARAMETER}) + @Retention(RetentionPolicy.RUNTIME) + **@Qualifier** + public @interface Genre { + + String value(); + } +---- + +Then you can provide the custom qualifier on autowired fields and parameters: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class MovieRecommender { + + @Autowired + **@Genre("Action")** + private MovieCatalog actionCatalog; + private MovieCatalog comedyCatalog; + + @Autowired + public void setComedyCatalog(**@Genre("Comedy")** MovieCatalog comedyCatalog) { + this.comedyCatalog = comedyCatalog; + } + + // ... + + } +---- + +Next, provide the information for the candidate bean definitions. You can add +`` tags as sub-elements of the `` tag and then specify the `type` and +`value` to match your custom qualifier annotations. The type is matched against the +fully-qualified class name of the annotation. Or, as a convenience if no risk of +conflicting names exists, you can use the short class name. Both approaches are +demonstrated in the following example. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + **** + + + + + **_** + + + + + + +---- + +In <>, you will see an annotation-based alternative to +providing the qualifier metadata in XML. Specifically, see <>. + +In some cases, it may be sufficient to use an annotation without a value. This may be +useful when the annotation serves a more generic purpose and can be applied across +several different types of dependencies. For example, you may provide an __offline__ +catalog that would be searched when no Internet connection is available. First define +the simple annotation: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Target({ElementType.FIELD, ElementType.PARAMETER}) + @Retention(RetentionPolicy.RUNTIME) + @Qualifier + public @interface Offline { + + } +---- + +Then add the annotation to the field or property to be autowired: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class MovieRecommender { + + @Autowired + **@Offline** + private MovieCatalog offlineCatalog; + + // ... + + } +---- + +Now the bean definition only needs a qualifier `type`: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + **** + + +---- + +You can also define custom qualifier annotations that accept named attributes in +addition to or instead of the simple `value` attribute. If multiple attribute values are +then specified on a field or parameter to be autowired, a bean definition must match +__all__ such attribute values to be considered an autowire candidate. As an example, +consider the following annotation definition: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Target({ElementType.FIELD, ElementType.PARAMETER}) + @Retention(RetentionPolicy.RUNTIME) + @Qualifier + public @interface MovieQualifier { + + String genre(); + + Format format(); + + } +---- + +In this case `Format` is an enum: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public enum Format { + VHS, DVD, BLURAY + } +---- + +The fields to be autowired are annotated with the custom qualifier and include values +for both attributes: `genre` and `format`. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class MovieRecommender { + + @Autowired + @MovieQualifier(format=Format.VHS, genre="Action") + private MovieCatalog actionVhsCatalog; + + @Autowired + @MovieQualifier(format=Format.VHS, genre="Comedy") + private MovieCatalog comedyVhsCatalog; + + @Autowired + @MovieQualifier(format=Format.DVD, genre="Action") + private MovieCatalog actionDvdCatalog; + + @Autowired + @MovieQualifier(format=Format.BLURAY, genre="Comedy") + private MovieCatalog comedyBluRayCatalog; + + // ... + + } +---- + +Finally, the bean definitions should contain matching qualifier values. This example +also demonstrates that bean __meta__ attributes may be used instead of the +`` sub-elements. If available, the `` and its attributes take +precedence, but the autowiring mechanism falls back on the values provided within the +`` tags if no such qualifier is present, as in the last two bean definitions in +the following example. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +---- + + + +[[beans-generics-as-qualifiers]] +==== Using generics as autowiring qualifiers +In addition to the `@Qualifier` annotation, it is also possible to use Java generic types +as an implicit form of qualification. For example, suppose you have the following +configuration: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Configuration + public class MyConfiguration { + + @Bean + public StringStore stringStore() { + return new StringStore(); + } + + @Bean + public IntegerStore integerStore() { + return new IntegerStore(); + } + + } +---- + +Assuming that beans above implement a generic interface, i.e. `Store` and +`Store`, you can `@Autowire` the `Store` interface and the __generic__ will +be used as a qualifier: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Autowired + private Store s1; // qualifier, injects the stringStore bean + + @Autowired + private Store s2; // qualifier, injects the integerStore bean +---- + +Generic qualifiers also apply when autowiring Lists, Maps and Arrays: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + // Inject all Store beans as long as they have an generic + // Store beans will not appear in this list + @Autowired + private List> s; +---- + + + + +[[beans-custom-autowire-configurer]] +==== CustomAutowireConfigurer + +The +{javadoc-baseurl}/org/springframework/beans/factory/annotation/CustomAutowireConfigurer.html[`CustomAutowireConfigurer`] +is a `BeanFactoryPostProcessor` that enables you to register your own custom qualifier +annotation types even if they are not annotated with Spring's `@Qualifier` annotation. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + example.CustomQualifier + + + +---- + +The `AutowireCandidateResolver` determines autowire candidates by: + +* the `autowire-candidate` value of each bean definition +* any `default-autowire-candidates` pattern(s) available on the `` element +* the presence of `@Qualifier` annotations and any custom annotations registered +with the `CustomAutowireConfigurer` + +When multiple beans qualify as autowire candidates, the determination of a "primary" is +the following: if exactly one bean definition among the candidates has a `primary` +attribute set to `true`, it will be selected. + + + +[[beans-resource-annotation]] +==== @Resource + +Spring also supports injection using the JSR-250 `@Resource` annotation on fields or +bean property setter methods. This is a common pattern in Java EE 5 and 6, for example +in JSF 1.2 managed beans or JAX-WS 2.0 endpoints. Spring supports this pattern for +Spring-managed objects as well. + +`@Resource` takes a name attribute, and by default Spring interprets that value as the +bean name to be injected. In other words, it follows __by-name__ semantics, as +demonstrated in this example: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class SimpleMovieLister { + + private MovieFinder movieFinder; + + **@Resource(name="myMovieFinder")** + public void setMovieFinder(MovieFinder movieFinder) { + this.movieFinder = movieFinder; + } + + } +---- + +If no name is specified explicitly, the default name is derived from the field name or +setter method. In case of a field, it takes the field name; in case of a setter method, +it takes the bean property name. So the following example is going to have the bean with +name "movieFinder" injected into its setter method: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class SimpleMovieLister { + + private MovieFinder movieFinder; + + **@Resource** + public void setMovieFinder(MovieFinder movieFinder) { + this.movieFinder = movieFinder; + } + + } +---- + +[NOTE] +==== +The name provided with the annotation is resolved as a bean name by the +`ApplicationContext` of which the `CommonAnnotationBeanPostProcessor` is aware. The +names can be resolved through JNDI if you configure Spring's +{javadoc-baseurl}/org/springframework/jndi/support/SimpleJndiBeanFactory.html[`SimpleJndiBeanFactory`] +explicitly. However, it is recommended that you rely on the default behavior and simply +use Spring's JNDI lookup capabilities to preserve the level of indirection. +==== + +In the exclusive case of `@Resource` usage with no explicit name specified, and similar +to `@Autowired`, `@Resource` finds a primary type match instead of a specific named bean +and resolves well-known resolvable dependencies: the `BeanFactory`, +`ApplicationContext`, `ResourceLoader`, `ApplicationEventPublisher`, and `MessageSource` +interfaces. + +Thus in the following example, the `customerPreferenceDao` field first looks for a bean +named customerPreferenceDao, then falls back to a primary type match for the type +`CustomerPreferenceDao`. The "context" field is injected based on the known resolvable +dependency type `ApplicationContext`. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class MovieRecommender { + + @Resource + private CustomerPreferenceDao customerPreferenceDao; + + @Resource + private ApplicationContext context; + + public MovieRecommender() { + } + + // ... + + } +---- + + + +[[beans-postconstruct-and-predestroy-annotations]] +==== @PostConstruct and @PreDestroy + +The `CommonAnnotationBeanPostProcessor` not only recognizes the `@Resource` annotation +but also the JSR-250 __lifecycle__ annotations. Introduced in Spring 2.5, the support +for these annotations offers yet another alternative to those described in +<> and +<>. Provided that the +`CommonAnnotationBeanPostProcessor` is registered within the Spring +`ApplicationContext`, a method carrying one of these annotations is invoked at the same +point in the lifecycle as the corresponding Spring lifecycle interface method or +explicitly declared callback method. In the example below, the cache will be +pre-populated upon initialization and cleared upon destruction. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class CachingMovieLister { + + @PostConstruct + public void populateMovieCache() { + // populates the movie cache upon initialization... + } + + @PreDestroy + public void clearMovieCache() { + // clears the movie cache upon destruction... + } + + } +---- + +[NOTE] +==== +For details about the effects of combining various lifecycle mechanisms, see +<>. +==== + + + + +[[beans-classpath-scanning]] +=== Classpath scanning and managed components +Most examples in this chapter use XML to specify the configuration metadata that +produces each `BeanDefinition` within the Spring container. The previous section +(<>) demonstrates how to provide a lot of the configuration +metadata through source-level annotations. Even in those examples, however, the "base" +bean definitions are explicitly defined in the XML file, while the annotations only +drive the dependency injection. This section describes an option for implicitly +detecting the __candidate components__ by scanning the classpath. Candidate components +are classes that match against a filter criteria and have a corresponding bean +definition registered with the container. This removes the need to use XML to perform +bean registration, instead you can use annotations (for example @Component), AspectJ +type expressions, or your own custom filter criteria to select which classes will have +bean definitions registered with the container. + +[NOTE] +==== +Starting with Spring 3.0, many features provided by the Spring JavaConfig project are +part of the core Spring Framework. This allows you to define beans using Java rather +than using the traditional XML files. Take a look at the `@Configuration`, `@Bean`, +`@Import`, and `@DependsOn` annotations for examples of how to use these new features. +==== + + + +[[beans-stereotype-annotations]] +==== @Component and further stereotype annotations + +The `@Repository` annotation is a marker for any class that fulfills the role or +__stereotype__ (also known as Data Access Object or DAO) of a repository. Among the uses +of this marker is the automatic translation of exceptions as described in +<>. + +Spring provides further stereotype annotations: `@Component`, `@Service`, and +`@Controller`. `@Component` is a generic stereotype for any Spring-managed component. +`@Repository`, `@Service`, and `@Controller` are specializations of `@Component` for +more specific use cases, for example, in the persistence, service, and presentation +layers, respectively. Therefore, you can annotate your component classes with +`@Component`, but by annotating them with `@Repository`, `@Service`, or `@Controller` +instead, your classes are more properly suited for processing by tools or associating +with aspects. For example, these stereotype annotations make ideal targets for +pointcuts. It is also possible that `@Repository`, `@Service`, and `@Controller` may +carry additional semantics in future releases of the Spring Framework. Thus, if you are +choosing between using `@Component` or `@Service` for your service layer, `@Service` is +clearly the better choice. Similarly, as stated above, `@Repository` is already +supported as a marker for automatic exception translation in your persistence layer. + + + +[[beans-meta-annotations]] +==== Meta-annotations +Many of the annotations provided by Spring can be used as "meta-annotations" in +your own code. A meta-annotation is simply an annotation, that can be applied to another +annotation. For example, The `@Service` annotation mentioned above is meta-annotated with +with `@Component`: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Target({ElementType.TYPE}) + @Retention(RetentionPolicy.RUNTIME) + @Documented + **@Component** // Spring will see this and treat @Service in the same way as @Component + public @interface Service { + + // .... + + } +---- + +Meta-annotations can also be combined together to create __composed annotations__. For +example, the `@RestController` annotation from Spring MVC is __composed__ of +`@Controller` and `@ResponseBody`. + +With the exception of `value()`, meta-annotated types may redeclare attributes from the +source annotation to allow user customization. This can be particularly useful when you +want to only expose a subset of the source annotation attributes. For example, here is a +custom `@Scope` annotation that defines `session` scope, but still allows customization +of the `proxyMode`. + + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Target({ElementType.TYPE}) + @Retention(RetentionPolicy.RUNTIME) + @Documented + **@Scope("session")** + public @interface SessionScope { + + ScopedProxyMode proxyMode() default ScopedProxyMode.DEFAULT + + } +---- + + + + +[[beans-scanning-autodetection]] +==== Automatically detecting classes and registering bean definitions +Spring can automatically detect stereotyped classes and register corresponding +++BeanDefinition++s with the `ApplicationContext`. For example, the following two classes +are eligible for such autodetection: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Service + public class SimpleMovieLister { + + private MovieFinder movieFinder; + + @Autowired + public SimpleMovieLister(MovieFinder movieFinder) { + this.movieFinder = movieFinder; + } + + } +---- + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Repository + public class JpaMovieFinder implements MovieFinder { + // implementation elided for clarity + } +---- + +To autodetect these classes and register the corresponding beans, you need to add +`@ComponentScan` to your `@Configuration` class, where the `basePackages` attribute +is a common parent package for the two classes. (Alternatively, you can specify a +comma-separated list that includes the parent package of each class.) + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Configuration + @ComponentScan(basePackages = "org.example") + public class AppConfig { + ... + } +---- + +[NOTE] +==== +for concision, the above may have used the `value` attribute of the +annotation, i.e. `ComponentScan("org.example")` +==== + +The following is an alternative using XML + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + +---- + +[TIP] +==== + +The use of `` implicitly enables the functionality of +``. There is usually no need to include the +`` element when using ``. +==== + +[NOTE] +==== +The scanning of classpath packages requires the presence of corresponding directory +entries in the classpath. When you build JARs with Ant, make sure that you do __not__ +activate the files-only switch of the JAR task. Also, classpath directories may not +get exposed based on security policies in some environments, e.g. standalone apps on +JDK 1.7.0_45 and higher (which requires 'Trusted-Library' setup in your manifests; see +http://stackoverflow.com/questions/19394570/java-jre-7u45-breaks-classloader-getresources). +==== + +Furthermore, the `AutowiredAnnotationBeanPostProcessor` and +`CommonAnnotationBeanPostProcessor` are both included implicitly when you use the +component-scan element. That means that the two components are autodetected __and__ +wired together - all without any bean configuration metadata provided in XML. + +[NOTE] +==== +You can disable the registration of `AutowiredAnnotationBeanPostProcessor` and +`CommonAnnotationBeanPostProcessor` by including the __annotation-config__ attribute +with a value of false. +==== + + + +[[beans-scanning-filters]] +==== Using filters to customize scanning +By default, classes annotated with `@Component`, `@Repository`, `@Service`, +`@Controller`, or a custom annotation that itself is annotated with `@Component` are the +only detected candidate components. However, you can modify and extend this behavior +simply by applying custom filters. Add them as __includeFilters__ or __excludeFilters__ +parameters of the `@ComponentScan` annotation (or as __include-filter__ or __exclude-filter__ +sub-elements of the `component-scan` element). Each filter element requires the `type` +and `expression` attributes. The following table describes the filtering options. + +[[beans-scanning-filters-tbl]] +.Filter Types +|=== +| Filter Type| Example Expression| Description + +| annotation (default) +| `org.example.SomeAnnotation` +| An annotation to be present at the type level in target components. + +| assignable +| `org.example.SomeClass` +| A class (or interface) that the target components are assignable to (extend/implement). + +| aspectj +| `org.example..*Service+` +| An AspectJ type expression to be matched by the target components. + +| regex +| `org\.example\.Default.*` +| A regex expression to be matched by the target components class names. + +| custom +| `org.example.MyTypeFilter` +| A custom implementation of the `org.springframework.core.type .TypeFilter` interface. +|=== + +The following example shows the configuration ignoring all `@Repository` annotations +and using "stub" repositories instead. + + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Configuration + @ComponentScan(basePackages = "org.example", + includeFilters = @Filter(type = FilterType.REGEX, pattern = ".*Stub.*Repository"), + excludeFilters = @Filter(Repository.class)) + public class AppConfig { + ... + } +---- + +and the equivalent using XML + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + +---- + +[NOTE] +==== +You can also disable the default filters by setting `useDefaultFilters=false` on the annotation or +providing `use-default-filters="false"` as an attribute of the element. This +will in effect disable automatic detection of classes annotated with `@Component`, `@Repository`, +`@Service`, or `@Controller`. +==== + + + +[[beans-factorybeans-annotations]] +==== Defining bean metadata within components +Spring components can also contribute bean definition metadata to the container. You do +this with the same `@Bean` annotation used to define bean metadata within +`@Configuration` annotated classes. Here is a simple example: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Component + public class FactoryMethodComponent { + + @Bean + @Qualifier("public") + public TestBean publicInstance() { + return new TestBean("publicInstance"); + } + + public void doWork() { + // Component method implementation omitted + } + + } +---- + +This class is a Spring component that has application-specific code contained in its +`doWork()` method. However, it also contributes a bean definition that has a factory +method referring to the method `publicInstance()`. The `@Bean` annotation identifies the +factory method and other bean definition properties, such as a qualifier value through +the `@Qualifier` annotation. Other method level annotations that can be specified are +`@Scope`, `@Lazy`, and custom qualifier annotations. + +[TIP] +==== +In addition to its role for component initialization, the `@Lazy` annotation may also be +placed on injection points marked with `@Autowired` or `@Inject`. In this context, it +leads to the injection of a lazy-resolution proxy. +==== + +Autowired fields and methods are supported as previously discussed, with additional +support for autowiring of `@Bean` methods: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Component + public class FactoryMethodComponent { + + private static int i; + + @Bean + @Qualifier("public") + public TestBean publicInstance() { + return new TestBean("publicInstance"); + } + + // use of a custom qualifier and autowiring of method parameters + + @Bean + protected TestBean protectedInstance( + @Qualifier("public") TestBean spouse, + @Value("#{privateInstance.age}") String country) { + TestBean tb = new TestBean("protectedInstance", 1); + tb.setSpouse(tb); + tb.setCountry(country); + return tb; + } + + @Bean + @Scope(BeanDefinition.SCOPE_SINGLETON) + private TestBean privateInstance() { + return new TestBean("privateInstance", i++); + } + + @Bean + @Scope(value = WebApplicationContext.SCOPE_SESSION, proxyMode = ScopedProxyMode.TARGET_CLASS) + public TestBean requestScopedInstance() { + return new TestBean("requestScopedInstance", 3); + } + + } +---- + +The example autowires the `String` method parameter `country` to the value of the `Age` +property on another bean named `privateInstance`. A Spring Expression Language element +defines the value of the property through the notation `#{ }`. For `@Value` +annotations, an expression resolver is preconfigured to look for bean names when +resolving expression text. + +The `@Bean` methods in a Spring component are processed differently than their +counterparts inside a Spring `@Configuration` class. The difference is that `@Component` +classes are not enhanced with CGLIB to intercept the invocation of methods and fields. +CGLIB proxying is the means by which invoking methods or fields within `@Bean` methods +in `@Configuration` classes creates bean metadata references to collaborating objects; +such methods are __not__ invoked with normal Java semantics. In contrast, invoking a +method or field in an `@Bean` method within a `@Component` class __has__ standard Java +semantics. + + + +[[beans-scanning-name-generator]] +==== Naming autodetected components +When a component is autodetected as part of the scanning process, its bean name is +generated by the `BeanNameGenerator` strategy known to that scanner. By default, any +Spring stereotype annotation ( `@Component`, `@Repository`, `@Service`, and +`@Controller`) that contains a `name` value will thereby provide that name to the +corresponding bean definition. + +If such an annotation contains no `name` value or for any other detected component (such +as those discovered by custom filters), the default bean name generator returns the +uncapitalized non-qualified class name. For example, if the following two components +were detected, the names would be myMovieLister and movieFinderImpl: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Service("myMovieLister") + public class SimpleMovieLister { + // ... + } +---- + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Repository + public class MovieFinderImpl implements MovieFinder { + // ... + } +---- + +[NOTE] +==== +If you do not want to rely on the default bean-naming strategy, you can provide a custom +bean-naming strategy. First, implement the +{javadoc-baseurl}/org/springframework/beans/factory/support/BeanNameGenerator.html[`BeanNameGenerator`] +interface, and be sure to include a default no-arg constructor. Then, provide the +fully-qualified class name when configuring the scanner: +==== + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Configuration + @ComponentScan(basePackages = "org.example", nameGenerator = MyNameGenerator.class) + public class AppConfig { + ... + } +---- + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + +---- + +As a general rule, consider specifying the name with the annotation whenever other +components may be making explicit references to it. On the other hand, the +auto-generated names are adequate whenever the container is responsible for wiring. + + + +[[beans-scanning-scope-resolver]] +==== Providing a scope for autodetected components +As with Spring-managed components in general, the default and most common scope for +autodetected components is singleton. However, sometimes you need other scopes, which +Spring 2.5 provides with a new `@Scope` annotation. Simply provide the name of the scope +within the annotation: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Scope("prototype") + @Repository + public class MovieFinderImpl implements MovieFinder { + // ... + } +---- + +[NOTE] +==== +To provide a custom strategy for scope resolution rather than relying on the +annotation-based approach, implement the +{javadoc-baseurl}/org/springframework/context/annotation/ScopeMetadataResolver.html[`ScopeMetadataResolver`] +interface, and be sure to include a default no-arg constructor. Then, provide the +fully-qualified class name when configuring the scanner: +==== + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Configuration + @ComponentScan(basePackages = "org.example", scopeResolver = MyScopeResolver.class) + public class AppConfig { + ... + } +---- + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + +---- + +When using certain non-singleton scopes, it may be necessary to generate proxies for the +scoped objects. The reasoning is described in <>. +For this purpose, a __scoped-proxy__ attribute is available on the component-scan +element. The three possible values are: no, interfaces, and targetClass. For example, +the following configuration will result in standard JDK dynamic proxies: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Configuration + @ComponentScan(basePackages = "org.example", scopedProxy = ScopedProxyMode.INTERFACES) + public class AppConfig { + ... + } +---- + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + +---- + + + +[[beans-scanning-qualifiers]] +==== Providing qualifier metadata with annotations +The `@Qualifier` annotation is discussed in <>. +The examples in that section demonstrate the use of the `@Qualifier` annotation and +custom qualifier annotations to provide fine-grained control when you resolve autowire +candidates. Because those examples were based on XML bean definitions, the qualifier +metadata was provided on the candidate bean definitions using the `qualifier` or `meta` +sub-elements of the `bean` element in the XML. When relying upon classpath scanning for +autodetection of components, you provide the qualifier metadata with type-level +annotations on the candidate class. The following three examples demonstrate this +technique: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Component + **@Qualifier("Action")** + public class ActionMovieCatalog implements MovieCatalog { + // ... + } +---- + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Component + **@Genre("Action")** + public class ActionMovieCatalog implements MovieCatalog { + // ... + } +---- + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Component + **@Offline** + public class CachingMovieCatalog implements MovieCatalog { + // ... + } +---- + +[NOTE] +==== +As with most annotation-based alternatives, keep in mind that the annotation metadata is +bound to the class definition itself, while the use of XML allows for multiple beans +__of the same type__ to provide variations in their qualifier metadata, because that +metadata is provided per-instance rather than per-class. +==== + + + + +[[beans-standard-annotations]] +=== Using JSR 330 Standard Annotations +Starting with Spring 3.0, Spring offers support for JSR-330 standard annotations +(Dependency Injection). Those annotations are scanned in the same way as the Spring +annotations. You just need to have the relevant jars in your classpath. + +[NOTE] +==== +If you are using Maven, the `javax.inject` artifact is available in the standard Maven +repository ( +http://repo1.maven.org/maven2/javax/inject/javax.inject/1/[http://repo1.maven.org/maven2/javax/inject/javax.inject/1/]). +You can add the following dependency to your file pom.xml: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + javax.inject + javax.inject + 1 + +---- +==== + + + +[[beans-inject-named]] +==== Dependency Injection with @Inject and @Named + +Instead of `@Autowired`, `@javax.inject.Inject` may be used as follows: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + import javax.inject.Inject; + + public class SimpleMovieLister { + + private MovieFinder movieFinder; + + @Inject + public void setMovieFinder(MovieFinder movieFinder) { + this.movieFinder = movieFinder; + } + + // ... + + } +---- + +As with `@Autowired`, it is possible to use `@Inject` at the class-level, field-level, +method-level and constructor-argument level. If you would like to use a qualified name +for the dependency that should be injected, you should use the `@Named` annotation as +follows: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + import javax.inject.Inject; + import javax.inject.Named; + + public class SimpleMovieLister { + + private MovieFinder movieFinder; + + @Inject + public void setMovieFinder(@Named("main") MovieFinder movieFinder) { + this.movieFinder = movieFinder; + } + + // ... + + } +---- + + + +[[beans-named]] +==== @Named: a standard equivalent to the @Component annotation + +Instead of `@Component`, `@javax.inject.Named` may be used as follows: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + import javax.inject.Inject; + import javax.inject.Named; + + @Named("movieListener") + public class SimpleMovieLister { + + private MovieFinder movieFinder; + + @Inject + public void setMovieFinder(MovieFinder movieFinder) { + this.movieFinder = movieFinder; + } + + // ... + + } +---- + +It is very common to use `@Component` without +specifying a name for the component. `@Named` +can be used in a similar fashion: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + import javax.inject.Inject; + import javax.inject.Named; + + @Named + public class SimpleMovieLister { + + private MovieFinder movieFinder; + + @Inject + public void setMovieFinder(MovieFinder movieFinder) { + this.movieFinder = movieFinder; + } + + // ... + + } +---- + +When using `@Named`, it is possible to use +component-scanning in the exact same way as when using Spring annotations: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Configuration + @ComponentScan(basePackages = "org.example") + public class AppConfig { + ... + } +---- + + + +[[beans-standard-annotations-limitations]] +==== Limitations of the standard approach +When working with standard annotations, it is important to know that some significant +features are not available as shown in the table below: + +[[annotations-comparison]] +.Spring annotations vs. standard annotations +|=== +| Spring| javax.inject.*| javax.inject restrictions / comments + +| @Autowired +| @Inject +| @Inject has no 'required' attribute + +| @Component +| @Named +| - + +| @Scope("singleton") +| @Singleton +| The JSR-330 default scope is like Spring's `prototype`. However, in order to keep it + consistent with Spring's general defaults, a JSR-330 bean declared in the Spring + container is a `singleton` by default. In order to use a scope other than `singleton`, + you should use Spring's `@Scope` annotation. + +`javax.inject` also provides a +http://download.oracle.com/javaee/6/api/javax/inject/Scope.html[@Scope] annotation. +Nevertheless, this one is only intended to be used for creating your own annotations. + +| @Qualifier +| @Named +| - + +| @Value +| - +| no equivalent + +| @Required +| - +| no equivalent + +| @Lazy +| - +| no equivalent +|=== + + + + +[[beans-java]] +=== Java-based container configuration + + + +[[beans-java-basic-concepts]] +==== Basic concepts: @Bean and @Configuration + +The central artifacts in Spring's new Java-configuration support are +`@Configuration`-annotated classes and `@Bean`-annotated methods. + +The `@Bean` annotation is used to indicate that a method instantiates, configures and +initializes a new object to be managed by the Spring IoC container. For those familiar +with Spring's `` XML configuration the `@Bean` annotation plays the same role as +the `` element. You can use `@Bean` annotated methods with any Spring +`@Component`, however, they are most often used with `@Configuration` beans. + +Annotating a class with `@Configuration` indicates that its primary purpose is as a +source of bean definitions. Furthermore, `@Configuration` classes allow inter-bean +dependencies to be defined by simply calling other `@Bean` methods in the same class. +The simplest possible `@Configuration` class would read as follows: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Configuration + public class AppConfig { + + @Bean + public MyService myService() { + return new MyServiceImpl(); + } + + } +---- + +The `AppConfig` class above would be equivalent to the following Spring `` XML: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + +---- + +The `@Bean` and `@Configuration` annotations will be discussed in depth in the sections +below. First, however, we'll cover the various ways of creating a spring container using +Java-based configuration. + +.Full @Configuration vs 'lite' @Beans mode? +**** +When `@Bean` methods are declared within classes that are __not__ annotated with +`@Configuration` they are referred to as being processed in a 'lite' mode. For example, +bean methods declared in a `@Component` or even in a __plain old class__ will be +considered 'lite'. + +Unlike full `@Configuration`, lite `@Bean` methods cannot easily declare inter-bean +dependencies. Usually one `@Bean` method should not invoke another `@Bean` method when +operating in 'lite' mode. + +Only using `@Bean` methods within `@Configuration` classes is a recommended approach of +ensuring that 'full' mode is always used. This will prevent the same `@Bean` method from +accidentally being invoked multiple times and helps to reduce subtle bugs that can be +hard to track down when operating in 'lite' mode. +**** + + +[[beans-java-instantiating-container]] +==== Instantiating the Spring container using AnnotationConfigApplicationContext +The sections below document Spring's `AnnotationConfigApplicationContext`, new in Spring +3.0. This versatile `ApplicationContext` implementation is capable of accepting not only +`@Configuration` classes as input, but also plain `@Component` classes and classes +annotated with JSR-330 metadata. + +When `@Configuration` classes are provided as input, the `@Configuration` class itself +is registered as a bean definition, and all declared `@Bean` methods within the class +are also registered as bean definitions. + +When `@Component` and JSR-330 classes are provided, they are registered as bean +definitions, and it is assumed that DI metadata such as `@Autowired` or `@Inject` are +used within those classes where necessary. + + +[[beans-java-instantiating-container-contstructor]] +===== Simple construction +In much the same way that Spring XML files are used as input when instantiating a +`ClassPathXmlApplicationContext`, `@Configuration` classes may be used as input when +instantiating an `AnnotationConfigApplicationContext`. This allows for completely +XML-free usage of the Spring container: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public static void main(String[] args) { + ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class); + MyService myService = ctx.getBean(MyService.class); + myService.doStuff(); + } +---- + +As mentioned above, `AnnotationConfigApplicationContext` is not limited to working only +with `@Configuration` classes. Any `@Component` or JSR-330 annotated class may be supplied +as input to the constructor. For example: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public static void main(String[] args) { + ApplicationContext ctx = new AnnotationConfigApplicationContext(MyServiceImpl.class, Dependency1.class, Dependency2.class); + MyService myService = ctx.getBean(MyService.class); + myService.doStuff(); + } +---- + +The above assumes that `MyServiceImpl`, `Dependency1` and `Dependency2` use Spring +dependency injection annotations such as `@Autowired`. + + +[[beans-java-instantiating-container-register]] +===== Building the container programmatically using register(Class...) + +An `AnnotationConfigApplicationContext` may be instantiated using a no-arg constructor +and then configured using the `register()` method. This approach is particularly useful +when programmatically building an `AnnotationConfigApplicationContext`. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public static void main(String[] args) { + AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); + ctx.register(AppConfig.class, OtherConfig.class); + ctx.register(AdditionalConfig.class); + ctx.refresh(); + MyService myService = ctx.getBean(MyService.class); + myService.doStuff(); + } +---- + + +[[beans-java-instantiating-container-scan]] +===== Enabling component scanning with scan(String...) + +To enable component scanning, just annotate your `@Configuration` class as follows: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Configuration + @ComponentScan(basePackages = "com.acme") + public class AppConfig { + ... + } +---- + +[TIP] +==== + +Experienced Spring users will be familiar with the XML declaration equivalent from +Spring's `context:` namespace + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + +---- +==== + + +In the example above, the `com.acme` package will be scanned, looking for any +`@Component`-annotated classes, and those classes will be registered as Spring bean +definitions within the container. `AnnotationConfigApplicationContext` exposes the +`scan(String...)` method to allow for the same component-scanning functionality: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public static void main(String[] args) { + AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); + ctx.scan("com.acme"); + ctx.refresh(); + MyService myService = ctx.getBean(MyService.class); + } +---- + +[NOTE] +==== +Remember that `@Configuration` classes are <> +with `@Component`, so they are candidates for component-scanning! In the example above, +assuming that `AppConfig` is declared within the `com.acme` package (or any package +underneath), it will be picked up during the call to `scan()`, and upon `refresh()` all +its `@Bean` methods will be processed and registered as bean definitions within the +container. +==== + + +[[beans-java-instantiating-container-web]] +===== Support for web applications with AnnotationConfigWebApplicationContext + +A `WebApplicationContext` variant of `AnnotationConfigApplicationContext` is available +with `AnnotationConfigWebApplicationContext`. This implementation may be used when +configuring the Spring `ContextLoaderListener` servlet listener, Spring MVC +`DispatcherServlet`, etc. What follows is a `web.xml` snippet that configures a typical +Spring MVC web application. Note the use of the `contextClass` context-param and +init-param: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + contextClass + + org.springframework.web.context.support.AnnotationConfigWebApplicationContext + + + + + + contextConfigLocation + com.acme.AppConfig + + + + + org.springframework.web.context.ContextLoaderListener + + + + + dispatcher + org.springframework.web.servlet.DispatcherServlet + + + contextClass + + org.springframework.web.context.support.AnnotationConfigWebApplicationContext + + + + + contextConfigLocation + com.acme.web.MvcConfig + + + + + + dispatcher + /app/* + + +---- + + + +[[beans-java-bean-annotation]] +==== Using the @Bean annotation + +`@Bean` is a method-level annotation and a direct analog of the XML `` element. +The annotation supports some of the attributes offered by ``, such as: +<>, +<>, +<> and `name`. + +You can use the `@Bean` annotation in a `@Configuration`-annotated or in a +`@Component`-annotated class. + + +[[beans-java-declaring-a-bean]] +===== Declaring a bean +To declare a bean, simply annotate a method with the `@Bean` annotation. You use this +method to register a bean definition within an `ApplicationContext` of the type +specified as the method's return value. By default, the bean name will be the same as +the method name. The following is a simple example of a `@Bean` method declaration: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Configuration + public class AppConfig { + + @Bean + public TransferService transferService() { + return new TransferServiceImpl(); + } + + } +---- + +The preceding configuration is exactly equivalent to the following Spring XML: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + +---- + +Both declarations make a bean named `transferService` available in the +`ApplicationContext`, bound to an object instance of type `TransferServiceImpl`: + +[literal] +[subs="verbatim,quotes"] +---- +transferService -> com.acme.TransferServiceImpl +---- + + +[[beans-java-lifecycle-callbacks]] +===== Receiving lifecycle callbacks +Any classes defined with the `@Bean` annotation support the regular lifecycle callbacks +and can use the `@PostConstruct` and `@PreDestroy` annotations from JSR-250, see +<> for further +details. + +The regular Spring <> callbacks are fully supported as +well. If a bean implements `InitializingBean`, `DisposableBean`, or `Lifecycle`, their +respective methods are called by the container. + +The standard set of `*Aware` interfaces such as <>, +<>, +<>, +<>, and so on are also fully supported. + +The `@Bean` annotation supports specifying arbitrary initialization and destruction +callback methods, much like Spring XML's `init-method` and `destroy-method` attributes +on the `bean` element: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class Foo { + public void init() { + // initialization logic + } + } + + public class Bar { + public void cleanup() { + // destruction logic + } + } + + @Configuration + public class AppConfig { + + @Bean(initMethod = "init") + public Foo foo() { + return new Foo(); + } + + @Bean(destroyMethod = "cleanup") + public Bar bar() { + return new Bar(); + } + + } +---- + +Of course, in the case of `Foo` above, it would be equally as valid to call the `init()` +method directly during construction: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Configuration + public class AppConfig { + @Bean + public Foo foo() { + Foo foo = new Foo(); + foo.init(); + return foo; + } + + // ... + + } +---- + +[TIP] +==== + +When you work directly in Java, you can do anything you like with your objects and do +not always need to rely on the container lifecycle! +==== + + +[[beans-java-specifying-bean-scope]] +===== Specifying bean scope + +[[beans-java-available-scopes]] +====== Using the @Scope annotation + +You can specify that your beans defined with the `@Bean` annotation should have a +specific scope. You can use any of the standard scopes specified in the +<> section. + +The default scope is `singleton`, but you can override this with the `@Scope` annotation: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Configuration + public class MyConfiguration { + + @Bean + **@Scope("prototype")** + public Encryptor encryptor() { + // ... + } + + } +---- + +[[beans-java-scoped-proxy]] +====== @Scope and scoped-proxy + +Spring offers a convenient way of working with scoped dependencies through +<>. The easiest way to create such +a proxy when using the XML configuration is the `` element. +Configuring your beans in Java with a @Scope annotation offers equivalent support with +the proxyMode attribute. The default is no proxy ( `ScopedProxyMode.NO`), but you can +specify `ScopedProxyMode.TARGET_CLASS` or `ScopedProxyMode.INTERFACES`. + +If you port the scoped proxy example from the XML reference documentation (see preceding +link) to our `@Bean` using Java, it would look like the following: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + // an HTTP Session-scoped bean exposed as a proxy + @Bean + **@Scope(value = "session", proxyMode = ScopedProxyMode.TARGET_CLASS)** + public UserPreferences userPreferences() { + return new UserPreferences(); + } + + @Bean + public Service userService() { + UserService service = new SimpleUserService(); + // a reference to the proxied userPreferences bean + service.setUserPreferences(userPreferences()); + return service; + } +---- + + +[[beans-java-customizing-bean-naming]] +===== Customizing bean naming +By default, configuration classes use a `@Bean` method's name as the name of the +resulting bean. This functionality can be overridden, however, with the `name` attribute. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Configuration + public class AppConfig { + + @Bean(name = "myFoo") + public Foo foo() { + return new Foo(); + } + + } +---- + + +[[beans-java-bean-aliasing]] +===== Bean aliasing +As discussed in <>, it is sometimes desirable to give a single bean +multiple names, otherwise known as__bean aliasing__. The `name` attribute of the `@Bean` +annotation accepts a String array for this purpose. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Configuration + public class AppConfig { + + @Bean(name = { "dataSource", "subsystemA-dataSource", "subsystemB-dataSource" }) + public DataSource dataSource() { + // instantiate, configure and return DataSource bean... + } + + } +---- + + +[[beans-java-bean-description]] +===== Bean description +Sometimes it is helpful to provide a more detailed textual description of a bean. This can +be particularly useful when beans are exposed (perhaps via JMX) for monitoring purposes. + +To add a description to a `@Bean` the +{javadoc-baseurl}/org/springframework/context/annotation/Description.html[`@Description`] +annotation can be used: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Configuration + public class AppConfig { + + @Bean + **@Desciption("Provides a basic example of a bean")** + public Foo foo() { + return new Foo(); + } + + } +---- + + +[[beans-java-configuration-annotation]] +==== Using the @Configuration annotation + +`@Configuration` is a class-level annotation indicating that an object is a source of +bean definitions. `@Configuration` classes declare beans via public `@Bean` annotated +methods. Calls to `@Bean` methods on `@Configuration` classes can also be used to define +inter-bean dependencies. See <> for a general introduction. + + +[[beans-java-injecting-dependencies]] +===== Injecting inter-bean dependencies +When ++@Bean++s have dependencies on one another, expressing that dependency is as simple +as having one bean method call another: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Configuration + public class AppConfig { + + @Bean + public Foo foo() { + return new Foo(bar()); + } + + @Bean + public Bar bar() { + return new Bar(); + } + + } +---- + +In the example above, the `foo` bean receives a reference to `bar` via constructor +injection. + +[NOTE] +==== +This method of declaring inter-bean dependencies only works when the `@Bean` method is +declared within a `@Configuration` class. You cannot declare inter-bean dependencies +using plain `@Component` classes. +==== + + +[[beans-java-method-injection]] +===== Lookup method injection +As noted earlier, <> is an +advanced feature that you should use rarely. It is useful in cases where a +singleton-scoped bean has a dependency on a prototype-scoped bean. Using Java for this +type of configuration provides a natural means for implementing this pattern. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public abstract class CommandManager { + public Object process(Object commandState) { + // grab a new instance of the appropriate Command interface + Command command = createCommand(); + + // set the state on the (hopefully brand new) Command instance + command.setState(commandState); + return command.execute(); + } + + // okay... but where is the implementation of this method? + protected abstract Command createCommand(); + } +---- + +Using Java-configuration support , you can create a subclass of `CommandManager` where +the abstract `createCommand()` method is overridden in such a way that it looks up a new +(prototype) command object: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Bean + @Scope("prototype") + public AsyncCommand asyncCommand() { + AsyncCommand command = new AsyncCommand(); + // inject dependencies here as required + return command; + } + + @Bean + public CommandManager commandManager() { + // return new anonymous implementation of CommandManager with command() overridden + // to return a new prototype Command object + return new CommandManager() { + protected Command createCommand() { + return asyncCommand(); + } + } + } +---- + + +[[beans-java-further-information-java-config]] +===== Further information about how Java-based configuration works internally +The following example shows a `@Bean` annotated method being called twice: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Configuration + public class AppConfig { + + @Bean + public ClientService clientService1() { + ClientServiceImpl clientService = new ClientServiceImpl(); + clientService.setClientDao(clientDao()); + return clientService; + } + + @Bean + public ClientService clientService2() { + ClientServiceImpl clientService = new ClientServiceImpl(); + clientService.setClientDao(clientDao()); + return clientService; + } + + @Bean + public ClientDao clientDao() { + return new ClientDaoImpl(); + } + + } +---- + +`clientDao()` has been called once in `clientService1()` and once in `clientService2()`. +Since this method creates a new instance of `ClientDaoImpl` and returns it, you would +normally expect having 2 instances (one for each service). That definitely would be +problematic: in Spring, instantiated beans have a `singleton` scope by default. This is +where the magic comes in: All `@Configuration` classes are subclassed at startup-time +with `CGLIB`. In the subclass, the child method checks the container first for any +cached (scoped) beans before it calls the parent method and creates a new instance. Note +that as of Spring 3.2, it is no longer necessary to add CGLIB to your classpath because +CGLIB classes have been repackaged under org.springframework and included directly +within the spring-core JAR. + +[NOTE] +==== +The behavior could be different according to the scope of your bean. We are talking +about singletons here. +==== + +[NOTE] +==== +There are a few restrictions due to the fact that CGLIB dynamically adds features at +startup-time: + +* Configuration classes should not be final +* They should have a constructor with no arguments +==== + + + +[[beans-java-composing-configuration-classes]] +==== Composing Java-based configurations + + +[[beans-java-using-import]] +===== Using the @Import annotation + +Much as the `` element is used within Spring XML files to aid in modularizing +configurations, the `@Import` annotation allows for loading `@Bean` definitions from +another configuration class: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Configuration + public class ConfigA { + + @Bean + public A a() { + return new A(); + } + + } + + @Configuration + @Import(ConfigA.class) + public class ConfigB { + + @Bean + public B b() { + return new B(); + } + + } +---- + +Now, rather than needing to specify both `ConfigA.class` and `ConfigB.class` when +instantiating the context, only `ConfigB` needs to be supplied explicitly: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public static void main(String[] args) { + ApplicationContext ctx = new AnnotationConfigApplicationContext(ConfigB.class); + + // now both beans A and B will be available... + A a = ctx.getBean(A.class); + B b = ctx.getBean(B.class); + } +---- + +This approach simplifies container instantiation, as only one class needs to be dealt +with, rather than requiring the developer to remember a potentially large number of +`@Configuration` classes during construction. + +[[beans-java-injecting-imported-beans]] +====== Injecting dependencies on imported @Bean definitions + +The example above works, but is simplistic. In most practical scenarios, beans will have +dependencies on one another across configuration classes. When using XML, this is not an +issue, per se, because there is no compiler involved, and one can simply declare +`ref="someBean"` and trust that Spring will work it out during container initialization. +Of course, when using `@Configuration` classes, the Java compiler places constraints on +the configuration model, in that references to other beans must be valid Java syntax. + +Fortunately, solving this problem is simple. Remember that `@Configuration` classes are +ultimately just another bean in the container - this means that they can take advantage +of `@Autowired` injection metadata just like any other bean! + +Let's consider a more real-world scenario with several `@Configuration` classes, each +depending on beans declared in the others: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Configuration + public class ServiceConfig { + + @Autowired + private AccountRepository accountRepository; + + @Bean + public TransferService transferService() { + return new TransferServiceImpl(accountRepository); + } + + } + + @Configuration + public class RepositoryConfig { + + @Autowired + private DataSource dataSource; + + @Bean + public AccountRepository accountRepository() { + return new JdbcAccountRepository(dataSource); + } + + } + + @Configuration + @Import({ServiceConfig.class, RepositoryConfig.class}) + public class SystemTestConfig { + + @Bean + public DataSource dataSource() { + // return new DataSource + } + + } + + public static void main(String[] args) { + ApplicationContext ctx = new AnnotationConfigApplicationContext(SystemTestConfig.class); + // everything wires up across configuration classes... + TransferService transferService = ctx.getBean(TransferService.class); + transferService.transfer(100.00, "A123", "C456"); + } +---- + +.[[beans-java-injecting-imported-beans-fq]]Fully-qualifying imported beans for ease of navigation +-- +In the scenario above, using `@Autowired` works well and provides the desired +modularity, but determining exactly where the autowired bean definitions are declared is +still somewhat ambiguous. For example, as a developer looking at `ServiceConfig`, how do +you know exactly where the `@Autowired AccountRepository` bean is declared? It's not +explicit in the code, and this may be just fine. Remember that the +https://spring.io/tools/sts[Spring Tool Suite] provides tooling that +can render graphs showing how everything is wired up - that may be all you need. Also, +your Java IDE can easily find all declarations and uses of the `AccountRepository` type, +and will quickly show you the location of `@Bean` methods that return that type. + +In cases where this ambiguity is not acceptable and you wish to have direct navigation +from within your IDE from one `@Configuration` class to another, consider autowiring the +configuration classes themselves: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Configuration + public class ServiceConfig { + + @Autowired + private RepositoryConfig repositoryConfig; + + @Bean + public TransferService transferService() { + // navigate 'through' the config class to the @Bean method! + return new TransferServiceImpl(repositoryConfig.accountRepository()); + } + + } +---- + +In the situation above, it is completely explicit where `AccountRepository` is defined. +However, `ServiceConfig` is now tightly coupled to `RepositoryConfig`; that's the +tradeoff. This tight coupling can be somewhat mitigated by using interface-based or +abstract class-based `@Configuration` classes. Consider the following: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Configuration + public class ServiceConfig { + + @Autowired + private RepositoryConfig repositoryConfig; + + @Bean + public TransferService transferService() { + return new TransferServiceImpl(repositoryConfig.accountRepository()); + } + } + + @Configuration + public interface RepositoryConfig { + + @Bean + AccountRepository accountRepository(); + + } + + @Configuration + public class DefaultRepositoryConfig implements RepositoryConfig { + + @Bean + public AccountRepository accountRepository() { + return new JdbcAccountRepository(...); + } + + } + + @Configuration + @Import({ServiceConfig.class, DefaultRepositoryConfig.class}) // import the concrete config! + public class SystemTestConfig { + + @Bean + public DataSource dataSource() { + // return DataSource + } + + } + + public static void main(String[] args) { + ApplicationContext ctx = new AnnotationConfigApplicationContext(SystemTestConfig.class); + TransferService transferService = ctx.getBean(TransferService.class); + transferService.transfer(100.00, "A123", "C456"); + } +---- + +Now `ServiceConfig` is loosely coupled with respect to the concrete +`DefaultRepositoryConfig`, and built-in IDE tooling is still useful: it will be easy for +the developer to get a type hierarchy of `RepositoryConfig` implementations. In this +way, navigating `@Configuration` classes and their dependencies becomes no different +than the usual process of navigating interface-based code. +-- + + +[[beans-java-conditional]] +===== Conditionally including @Configuration classes or @Beans +It is often useful to conditionally enable to disable a complete `@Configuration` class, +or even individual `@Bean` methods, based on some arbitrary system state. One common +example of this it to use the `@Profile` annotation to active beans only when a specific +profile has been enabled in the Spring `Environment` (see <> +for details). + +The `@Profile` annotation is actually implemented using a much more flexible annotation +called {javadoc-baseurl}/org/springframework/context/annotation/Conditional.html[`@Conditional`]. +The `@Conditional` annotation indicates specific +`org.springframework.context.annotation.Condition` implementations that should be +consulted before a `@Bean` is registered. + +Implementations of the `Condition` interface simply provide a `matches(...)` +method that returns `true` or `false`. For example, here is the actual +`Condition` implementation used for `@Profile`: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Override + public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { + if (context.getEnvironment() != null) { + // Read the @Profile annotation attributes + MultiValueMap attrs = metadata.getAllAnnotationAttributes(Profile.class.getName()); + if (attrs != null) { + for (Object value : attrs.get("value")) { + if (context.getEnvironment().acceptsProfiles(((String[]) value))) { + return true; + } + } + return false; + } + } + return true; + } +---- + +See the {javadoc-baseurl}/org/springframework/context/annotation/Conditional.html[ +`@Conditional` javadocs] for more detail. + +[[beans-java-combining]] +===== Combining Java and XML configuration +Spring's `@Configuration` class support does not aim to be a 100% complete replacement +for Spring XML. Some facilities such as Spring XML namespaces remain an ideal way to +configure the container. In cases where XML is convenient or necessary, you have a +choice: either instantiate the container in an "XML-centric" way using, for example, +`ClassPathXmlApplicationContext`, or in a "Java-centric" fashion using +`AnnotationConfigApplicationContext` and the `@ImportResource` annotation to import XML +as needed. + +[[beans-java-combining-xml-centric]] +====== XML-centric use of @Configuration classes + +It may be preferable to bootstrap the Spring container from XML and include +`@Configuration` classes in an ad-hoc fashion. For example, in a large existing codebase +that uses Spring XML, it will be easier to create `@Configuration` classes on an +as-needed basis and include them from the existing XML files. Below you'll find the +options for using `@Configuration` classes in this kind of "XML-centric" situation. + +.[[beans-java-combining-xml-centric-declare-as-bean]]Declaring @Configuration classes as plain Spring `` elements +-- +Remember that `@Configuration` classes are ultimately just bean definitions in the +container. In this example, we create a `@Configuration` class named `AppConfig` and +include it within `system-test-config.xml` as a `` definition. Because +`` is switched on, the container will recognize the +`@Configuration` annotation, and process the `@Bean` methods declared in `AppConfig` +properly. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Configuration + public class AppConfig { + + @Autowired + private DataSource dataSource; + + @Bean + public AccountRepository accountRepository() { + return new JdbcAccountRepository(dataSource); + } + + @Bean + public TransferService transferService() { + return new TransferService(accountRepository()); + } + + } +---- + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + system-test-config.xml + + + + + + + + + + + + + +---- + +[literal] +[subs="verbatim,quotes"] +---- +jdbc.properties +jdbc.url=jdbc:hsqldb:hsql://localhost/xdb +jdbc.username=sa +jdbc.password= +---- + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public static void main(String[] args) { + ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:/com/acme/system-test-config.xml"); + TransferService transferService = ctx.getBean(TransferService.class); + // ... + } +---- + +[NOTE] +==== +In `system-test-config.xml` above, the `AppConfig` does not declare an `id` +element. While it would be acceptable to do so, it is unnecessary given that no other +bean will ever refer to it, and it is unlikely that it will be explicitly fetched from +the container by name. Likewise with the `DataSource` bean - it is only ever autowired +by type, so an explicit bean id is not strictly required. +==== +-- + +.[[beans-java-combining-xml-centric-component-scan]] Using to pick up `@Configuration` classes +-- +Because `@Configuration` is meta-annotated with `@Component`, `@Configuration`-annotated +classes are automatically candidates for component scanning. Using the same scenario as +above, we can redefine `system-test-config.xml` to take advantage of component-scanning. +Note that in this case, we don't need to explicitly declare +``, because `` enables all the same +functionality. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + system-test-config.xml + + + + + + + + + + + +---- +-- + +[[beans-java-combining-java-centric]] +====== @Configuration class-centric use of XML with @ImportResource + +In applications where `@Configuration` classes are the primary mechanism for configuring +the container, it will still likely be necessary to use at least some XML. In these +scenarios, simply use `@ImportResource` and define only as much XML as is needed. Doing +so achieves a "Java-centric" approach to configuring the container and keeps XML to a +bare minimum. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Configuration + @ImportResource("classpath:/com/acme/properties-config.xml") + public class AppConfig { + + @Value("${jdbc.url}") + private String url; + + @Value("${jdbc.username}") + private String username; + + @Value("${jdbc.password}") + private String password; + + @Bean + public DataSource dataSource() { + return new DriverManagerDataSource(url, username, password); + } + + } +---- + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + properties-config.xml + + + +---- + +[literal] +[subs="verbatim,quotes"] +---- +jdbc.properties +jdbc.url=jdbc:hsqldb:hsql://localhost/xdb +jdbc.username=sa +jdbc.password= +---- + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public static void main(String[] args) { + ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class); + TransferService transferService = ctx.getBean(TransferService.class); + // ... + } +---- + +[[beans-environment]] +=== Environment abstraction + +The {javadoc-baseurl}/org/springframework/core/env/Environment.html[`Environment`] +is an abstraction integrated in the container that models two key +aspects of the application environment: <> +and <>. + +A _profile_ is a named, logical group of bean definitions to be registered with the +container only if the given profile is active. Beans may be assigned to a profile +whether defined in XML or via annotations. The role of the `Environment` object with +relation to profiles is in determining which profiles (if any) are currently active, +and which profiles (if any) should be active by default. + +Properties play an important role in almost all applications, and may originate from +a variety of sources: properties files, JVM system properties, system environment +variables, JNDI, servlet context parameters, ad-hoc Properties objects, Maps, and so +on. The role of the `Environment` object with relation to properties is to provide the +user with a convenient service interface for configuring property sources and resolving +properties from them. + +[[beans-definition-profiles]] +==== Bean definition profiles + +Bean definition profiles is a mechanism in the core container that allows for +registration of different beans in different environments. The word _environment_ +can mean different things to different users and this feature can help with many +use cases, including: + +* working against an in-memory datasource in development vs looking up that same +datasource from JNDI when in QA or production +* registering monitoring infrastructure only when deploying an application into a +performance environment +* registering customized implementations of beans for customer A vs. customer +B deployments + +Let's consider the first use case in a practical application that requires a +`DataSource`. In a test environment, the configuration may look like this: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Bean + public DataSource dataSource() { + return new EmbeddedDatabaseBuilder() + .setType(EmbeddedDatabaseType.HSQL) + .addScript("my-schema.sql") + .addScript("my-test-data.sql") + .build(); + } +---- + +Let's now consider how this application will be deployed into a QA or production +environment, assuming that the datasource for the application will be registered +with the production application server's JNDI directory. Our `dataSource` bean +now looks like this: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Bean + public DataSource dataSource() throws Exception { + Context ctx = new InitialContext(); + return (DataSource) ctx.lookup("java:comp/env/jdbc/datasource"); + } +---- + +The problem is how to switch between using these two variations based on the +current environment. Over time, Spring users have devised a number of ways to +get this done, usually relying on a combination of system environment variables +and XML `` statements containing `${placeholder}` tokens that resolve +to the correct configuration file path depending on the value of an environment +variable. Bean definition profiles is a core container feature that provides a +solution to this problem. + +If we generalize the example use case above of environment-specific bean +definitions, we end up with the need to register certain bean definitions in +certain contexts, while not in others. You could say that you want to register a +certain profile of bean definitions in situation A, and a different profile in +situation B. Let's first see how we can update our configuration to reflect +this need. + +[[beans-definition-profiles-java]] +===== @Profile + +The {javadoc-baseurl}/org/springframework/context/annotation/Profile.html[`@Profile`] +annotation allows to indicate that a component is eligible for registration +when one or more specified profiles are active. Using our example above, we +can rewrite the _dataSource_ configuration as follows: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Configuration + **@Profile("dev")** + public class StandaloneDataConfig { + + @Bean + public DataSource dataSource() { + return new EmbeddedDatabaseBuilder() + .setType(EmbeddedDatabaseType.HSQL) + .addScript("classpath:com/bank/config/sql/schema.sql") + .addScript("classpath:com/bank/config/sql/test-data.sql") + .build(); + } + } +---- + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Configuration + **@Profile("production")** + public class JndiDataConfig { + + @Bean + public DataSource dataSource() throws Exception { + Context ctx = new InitialContext(); + return (DataSource) ctx.lookup("java:comp/env/jdbc/datasource"); + } + } +---- + + +`@Profile` can be used as a meta-annotation, for the purpose of composing +custom stereotype annotations. The following example defines a `@Production` +custom annotation that can be used as a drop-in replacement of +`@Profile("production")`: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Target(ElementType.TYPE) + @Retention(RetentionPolicy.RUNTIME) + **@Profile("production")** + public @interface Production { + } +---- + +`@Profile` can also be specified at method-level to include only one particular +bean of a configuration class: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Configuration + public class AppConfig { + + @Bean + **@Profile("dev")** + public DataSource devDataSource() { + return new EmbeddedDatabaseBuilder() + .setType(EmbeddedDatabaseType.HSQL) + .addScript("classpath:com/bank/config/sql/schema.sql") + .addScript("classpath:com/bank/config/sql/test-data.sql") + .build(); + } + + @Bean + **@Profile("production")** + public DataSource productionDataSource() throws Exception { + Context ctx = new InitialContext(); + return (DataSource) ctx.lookup("java:comp/env/jdbc/datasource"); + } + } +---- + +[TIP] +==== +If a `@Configuration` class is marked with `@Profile`, all of the `@Bean` methods +and `@Import` annotations associated with that class will be bypassed unless one +or more of the specified profiles are active. If a `@Component` or `@Configuration` +class is marked with `@Profile({"p1", "p2"})`, that class will not be registered/ +processed unless profiles 'p1' and/or 'p2' have been activated. If a given profile +is prefixed with the NOT operator (`!`), the annotated element will be registered +if the profile is **not** active. e.g., for `@Profile({"p1", "!p2"})`, registration +will occur if profile 'p1' is active or if profile 'p2' is not active. +==== + +[[beans-definition-profiles-xml]] +==== XML Bean definition profiles + +The XML counterpart is an update of the `beans` element that accepts a +`profile` attribute. Our sample configuration above can be rewritten in two XML +files as follows: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + +---- + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + +---- + +It is also possible to avoid that split and nest `` elements within the same file: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + + + + + + + + +---- + +The `spring-bean.xsd` has been constrained to allow such elements only as the +last ones in the file. This should help provide flexibility without incurring +clutter in the XML files. + +[[beans-definition-profiles-enable]] +===== Enabling a profile + +Now that we have updated our configuration, we still need to instruct which +profile is active. If we started our sample application right now, we would see +a `NoSuchBeanDefinitionException` thrown, because the container could not find +the Spring bean named `dataSource`. + +Activating a profile can be done in several ways, but the most straightforward +is to do it programmatically against the `ApplicationContext` API: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); + ctx.getEnvironment().setActiveProfiles("dev"); + ctx.register(SomeConfig.class, StandaloneDataConfig.class, JndiDataConfig.class); + ctx.refresh(); +---- + +In addition, profiles may also be activated declaratively through the `spring.profiles.active` +property which may be specified through system environment variables, JVM system properties, +servlet context parameters in `web.xml` or even as an entry in JNDI (see +<>). + +Note that profiles are not an "either-or" proposition; it is possible to activate multiple +profiles at once. Programmatically, simply provide multiple profile names to the +`setActiveProfiles()` method, which accepts `String...` varargs: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + ctx.getEnvironment().setActiveProfiles("profile1", "profile2"); +---- + +Declaratively, `spring.profiles.active` may accept a comma-separated list of profile names: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + -Dspring.profiles.active="profile1,profile2" +---- + +[[beans-definition-profiles-default]] +===== Default profile + +The _default_ profile represents the profile that is enabled by default. Consider the +following: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Configuration + **@Profile("default")** + public class DefaultDataConfig { + + @Bean + public DataSource dataSource() { + return new EmbeddedDatabaseBuilder() + .setType(EmbeddedDatabaseType.HSQL) + .addScript("classpath:com/bank/config/sql/schema.sql") + .build(); + } + } +---- + +If no profile is active, the `dataSource` above will be created; this can be +seen as a way to provide a _default_ definition for one or more beans. If any +profile is enabled, the _default_ profile will not apply. + +The name of that default profile can be changed using `setDefaultProfiles` on +the `Environment` or declaratively using the `spring.profiles.default` property. + +[[beans-property-source-abstraction]] +==== PropertySource Abstraction + +Spring's Environment abstraction provides search operations over a configurable +hierarchy of property sources. To explain fully, consider the following: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- +ApplicationContext ctx = new GenericApplicationContext(); +Environment env = ctx.getEnvironment(); +boolean containsFoo = env.containsProperty("foo"); +System.out.println("Does my environment contain the 'foo' property? " + containsFoo); +---- + +In the snippet above, we see a high-level way of asking Spring whether the `foo` property is +defined for the current environment. To answer this question, the `Environment` object performs +a search over a set of {javadoc-baseurl}/org/springframework/core/env/PropertySource.html[`PropertySource`] +objects. A `PropertySource` is a simple abstraction over any source of key-value pairs, and +Spring's {javadoc-baseurl}/org/springframework/core/env/StandardEnvironment.html[`StandardEnvironment`] +is configured with two PropertySource objects -- one representing the set of JVM system properties +(_a la_ `System.getProperties()`) and one representing the set of system environment variables +(_a la_ `System.getenv()`). + +[NOTE] +==== +These default property sources are present for `StandardEnvironment`, for use in standalone +applications. {javadoc-baseurl}/org/springframework/web/context/support/StandardServletEnvironment.html[`StandardServletEnvironment`] +is populated with additional default property sources including servlet config and servlet +context parameters. {javadoc-baseurl}/org/springframework/web/portlet/context/StandardPortletEnvironment.html[`StandardPortletEnvironment`] +similarly has access to portlet config and portlet context parameters as property sources. +Both can optionally enable a {javadoc-baseurl}/org/springframework/jndi/JndiPropertySource.html[`JndiPropertySource`]. +See Javadoc for details. +==== + +Concretely, when using the `StandardEnvironment`, the call to `env.containsProperty("foo")` +will return true if a `foo` system property or `foo` environment variable is present at +runtime. + +[TIP] +==== +The search performed is hierarchical. By default, system properties have precedence over +environment variables, so if the `foo` property happens to be set in both places during +a call to `env.getProperty("foo")`, the system property value will 'win' and be returned +preferentially over the environment variable. +==== + +Most importantly, the entire mechanism is configurable. Perhaps you have a custom source +of properties that you'd like to integrate into this search. No problem -- simply implement +and instantiate your own `PropertySource` and add it to the set of `PropertySources` for the +current `Environment`: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- +ConfigurableApplicationContext ctx = new GenericApplicationContext(); +MutablePropertySources sources = ctx.getEnvironment().getPropertySources(); +sources.addFirst(new MyPropertySource()); +---- + +In the code above, `MyPropertySource` has been added with highest precedence in the +search. If it contains a `foo` property, it will be detected and returned ahead of +any `foo` property in any other `PropertySource`. The +{javadoc-baseurl}/org/springframework/core/env/MutablePropertySources.html[`MutablePropertySources`] +API exposes a number of methods that allow for precise manipulation of the set of +property sources. + +==== @PropertySource + +The {javadoc-baseurl}/org/springframework/context/annotation/PropertySource.html[`@PropertySource`] +annotation provides a convenient and declarative mechanism for adding a `PropertySource` +to Spring's `Environment`. + +Given a file "app.properties" containing the key/value pair `testbean.name=myTestBean`, +the following `@Configuration` class uses `@PropertySource` in such a way that +a call to `testBean.getName()` will return "myTestBean". + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Configuration + **@PropertySource("classpath:/com/myco/app.properties")** + public class AppConfig { + @Autowired + Environment env; + + @Bean + public TestBean testBean() { + TestBean testBean = new TestBean(); + testBean.setName(env.getProperty("testbean.name")); + return testBean; + } + } +---- + +Any `${...}` placeholders present in a `@PropertySource` resource location will +be resolved against the set of property sources already registered against the +environment. For example: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Configuration + @PropertySource("classpath:/com/${my.placeholder:default/path}/app.properties") + public class AppConfig { + @Autowired + Environment env; + + @Bean + public TestBean testBean() { + TestBean testBean = new TestBean(); + testBean.setName(env.getProperty("testbean.name")); + return testBean; + } + } +---- + +Assuming that "my.placeholder" is present in one of the property sources already +registered, e.g. system properties or environment variables, the placeholder will +be resolved to the corresponding value. If not, then "default/path" will be used +as a default. If no default is specified and a property cannot be resolved, an +`IllegalArgumentException` will be thrown. + + +==== Placeholder resolution in statements + +Historically, the value of placeholders in elements could be resolved only against +JVM system properties or environment variables. No longer is this the case. Because +the Environment abstraction is integrated throughout the container, it's easy to +route resolution of placeholders through it. This means that you may configure the +resolution process in any way you like: change the precedence of searching through +system properties and environment variables, or remove them entirely; add your +own property sources to the mix as appropriate. + +Concretely, the following statement works regardless of where the `customer` +property is defined, as long as it is available in the `Environment`: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + +---- + + +[[context-load-time-weaver]] +=== Registering a LoadTimeWeaver + +The `LoadTimeWeaver` is used by Spring to dynamically transform classes as they are +loaded into the Java virtual machine (JVM). + +To enable load-time weaving add the `@EnableLoadTimeWeaving` to one of your +`@Configuration` classes: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Configuration + @EnableLoadTimeWeaving + public class AppConfig { + + } +---- + +Alternatively for XML configuration use the `context:load-time-weaver` element: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + +---- + +Once configured for the `ApplicationContext`. Any bean within that `ApplicationContext` +may implement `LoadTimeWeaverAware`, thereby receiving a reference to the load-time +weaver instance. This is particularly useful in combination with <> where load-time weaving may be necessary for JPA class transformation. Consult +the `LocalContainerEntityManagerFactoryBean` javadocs for more detail. For more on +AspectJ load-time weaving, see <>. + + + + +[[context-introduction]] +=== Additional Capabilities of the ApplicationContext + +As was discussed in the chapter introduction, the `org.springframework.beans.factory` +package provides basic functionality for managing and manipulating beans, including in a +programmatic way. The `org.springframework.context` package adds the +{javadoc-baseurl}/org/springframework/context/ApplicationContext.html[`ApplicationContext`] +interface, which extends the `BeanFactory` interface, in addition to extending other +interfaces to provide additional functionality in a more __application +framework-oriented style__. Many people use the `ApplicationContext` in a completely +declarative fashion, not even creating it programmatically, but instead relying on +support classes such as `ContextLoader` to automatically instantiate an +`ApplicationContext` as part of the normal startup process of a Java EE web application. + +To enhance `BeanFactory` functionality in a more framework-oriented style the context +package also provides the following functionality: + +* __Access to messages in i18n-style__, through the `MessageSource` interface. +* __Access to resources__, such as URLs and files, through the `ResourceLoader` interface. +* __Event publication__ to beans implementing the `ApplicationListener` interface, + through the use of the `ApplicationEventPublisher` interface. +* __Loading of multiple (hierarchical) contexts__, allowing each to be focused on one + particular layer, such as the web layer of an application, through the + `HierarchicalBeanFactory` interface. + + + +[[context-functionality-messagesource]] +==== Internationalization using MessageSource + +The `ApplicationContext` interface extends an interface called `MessageSource`, and +therefore provides internationalization (i18n) functionality. Spring also provides the +interface `HierarchicalMessageSource`, which can resolve messages hierarchically. +Together these interfaces provide the foundation upon which Spring effects message +resolution. The methods defined on these interfaces include: + +* `String getMessage(String code, Object[] args, String default, Locale loc)`: The basic + method used to retrieve a message from the `MessageSource`. When no message is found + for the specified locale, the default message is used. Any arguments passed in become + replacement values, using the `MessageFormat` functionality provided by the standard + library. +* `String getMessage(String code, Object[] args, Locale loc)`: Essentially the same as + the previous method, but with one difference: no default message can be specified; if + the message cannot be found, a `NoSuchMessageException` is thrown. +* `String getMessage(MessageSourceResolvable resolvable, Locale locale)`: All properties + used in the preceding methods are also wrapped in a class named + `MessageSourceResolvable`, which you can use with this method. + +When an `ApplicationContext` is loaded, it automatically searches for a `MessageSource` +bean defined in the context. The bean must have the name `messageSource`. If such a bean +is found, all calls to the preceding methods are delegated to the message source. If no +message source is found, the `ApplicationContext` attempts to find a parent containing a +bean with the same name. If it does, it uses that bean as the `MessageSource`. If the +`ApplicationContext` cannot find any source for messages, an empty +`DelegatingMessageSource` is instantiated in order to be able to accept calls to the +methods defined above. + +Spring provides two `MessageSource` implementations, `ResourceBundleMessageSource` and +`StaticMessageSource`. Both implement `HierarchicalMessageSource` in order to do nested +messaging. The `StaticMessageSource` is rarely used but provides programmatic ways to +add messages to the source. The `ResourceBundleMessageSource` is shown in the following +example: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + format + exceptions + windows + + + + +---- + +In the example it is assumed you have three resource bundles defined in your classpath +called `format`, `exceptions` and `windows`. Any request to resolve a message will be +handled in the JDK standard way of resolving messages through ResourceBundles. For the +purposes of the example, assume the contents of two of the above resource bundle files +are... + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + # in format.properties + message=Alligators rock! +---- + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + # in exceptions.properties + argument.required=The '{0}' argument is required. +---- + +A program to execute the `MessageSource` functionality is shown in the next example. +Remember that all `ApplicationContext` implementations are also `MessageSource` +implementations and so can be cast to the `MessageSource` interface. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public static void main(String[] args) { + MessageSource resources = new ClassPathXmlApplicationContext("beans.xml"); + String message = resources.getMessage("message", null, "Default", null); + System.out.println(message); + } +---- + +The resulting output from the above program will be... + +[literal] +[subs="verbatim,quotes"] +---- +Alligators rock! +---- + +So to summarize, the `MessageSource` is defined in a file called `beans.xml`, which +exists at the root of your classpath. The `messageSource` bean definition refers to a +number of resource bundles through its `basenames` property. The three files that are +passed in the list to the `basenames` property exist as files at the root of your +classpath and are called `format.properties`, `exceptions.properties`, and +`windows.properties` respectively. + +The next example shows arguments passed to the message lookup; these arguments will be +converted into Strings and inserted into placeholders in the lookup message. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + + + + + + +---- + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class Example { + + private MessageSource messages; + + public void setMessages(MessageSource messages) { + this.messages = messages; + } + + public void execute() { + String message = this.messages.getMessage("argument.required", + new Object [] {"userDao"}, "Required", null); + System.out.println(message); + } + + } +---- + +The resulting output from the invocation of the `execute()` method will be... + +[literal] +[subs="verbatim,quotes"] +---- +The userDao argument is required. +---- + +With regard to internationalization (i18n), Spring's various `MessageResource` +implementations follow the same locale resolution and fallback rules as the standard JDK +`ResourceBundle`. In short, and continuing with the example `messageSource` defined +previously, if you want to resolve messages against the British (`en-GB`) locale, you +would create files called `format_en_GB.properties`, `exceptions_en_GB.properties`, and +`windows_en_GB.properties` respectively. + +Typically, locale resolution is managed by the surrounding environment of the +application. In this example, the locale against which (British) messages will be +resolved is specified manually. + +[literal] +[subs="verbatim,quotes"] +---- +# in exceptions_en_GB.properties +argument.required=Ebagum lad, the '{0}' argument is required, I say, required. +---- + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public static void main(final String[] args) { + MessageSource resources = new ClassPathXmlApplicationContext("beans.xml"); + String message = resources.getMessage("argument.required", + new Object [] {"userDao"}, "Required", Locale.UK); + System.out.println(message); + } +---- + +The resulting output from the running of the above program will be... + +[literal] +[subs="verbatim,quotes"] +---- +Ebagum lad, the 'userDao' argument is required, I say, required. +---- + +You can also use the `MessageSourceAware` interface to acquire a reference to any +`MessageSource` that has been defined. Any bean that is defined in an +`ApplicationContext` that implements the `MessageSourceAware` interface is injected with +the application context's `MessageSource` when the bean is created and configured. + +[NOTE] +==== +__As an alternative to `ResourceBundleMessageSource`, Spring provides a +`ReloadableResourceBundleMessageSource` class. This variant supports the same bundle +file format but is more flexible than the standard JDK based +`ResourceBundleMessageSource` implementation.__ In particular, it allows for reading +files from any Spring resource location (not just from the classpath) and supports hot +reloading of bundle property files (while efficiently caching them in between). Check +out the `ReloadableResourceBundleMessageSource` javadocs for details. +==== + + + +[[context-functionality-events]] +==== Standard and Custom Events +Event handling in the `ApplicationContext` is provided through the `ApplicationEvent` +class and `ApplicationListener` interface. If a bean that implements the +`ApplicationListener` interface is deployed into the context, every time an +`ApplicationEvent` gets published to the `ApplicationContext`, that bean is notified. +Essentially, this is the standard __Observer__ design pattern. Spring provides the +following standard events: + +[[beans-ctx-events-tbl]] +.Built-in Events +|=== +| Event| Explanation + +| `ContextRefreshedEvent` +| Published when the `ApplicationContext` is initialized or refreshed, for example, + using the `refresh()` method on the `ConfigurableApplicationContext` interface. + "Initialized" here means that all beans are loaded, post-processor beans are detected + and activated, singletons are pre-instantiated, and the `ApplicationContext` object is + ready for use. As long as the context has not been closed, a refresh can be triggered + multiple times, provided that the chosen `ApplicationContext` actually supports such + "hot" refreshes. For example, `XmlWebApplicationContext` supports hot refreshes, but + `GenericApplicationContext` does not. + +| `ContextStartedEvent` +| Published when the `ApplicationContext` is started, using the `start()` method on the + `ConfigurableApplicationContext` interface. "Started" here means that all `Lifecycle` + beans receive an explicit start signal. Typically this signal is used to restart beans + after an explicit stop, but it may also be used to start components that have not been + configured for autostart , for example, components that have not already started on + initialization. + +| `ContextStoppedEvent` +| Published when the `ApplicationContext` is stopped, using the `stop()` method on the + `ConfigurableApplicationContext` interface. "Stopped" here means that all `Lifecycle` + beans receive an explicit stop signal. A stopped context may be restarted through a + `start()` call. + +| `ContextClosedEvent` +| Published when the `ApplicationContext` is closed, using the `close()` method on the + `ConfigurableApplicationContext` interface. "Closed" here means that all singleton + beans are destroyed. A closed context reaches its end of life; it cannot be refreshed + or restarted. + +| `RequestHandledEvent` +| A web-specific event telling all beans that an HTTP request has been serviced. This + event is published __after__ the request is complete. This event is only applicable to + web applications using Spring's `DispatcherServlet`. +|=== + +You can also create and publish your own custom events. This example demonstrates a +simple class that extends Spring's `ApplicationEvent` base class: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class BlackListEvent extends ApplicationEvent { + + private final String address; + private final String test; + + public BlackListEvent(Object source, String address, String test) { + super(source); + this.address = address; + this.test = test; + } + + // accessor and other methods... + + } +---- + +To publish a custom `ApplicationEvent`, call the `publishEvent()` method on an +`ApplicationEventPublisher`. Typically this is done by creating a class that implements +`ApplicationEventPublisherAware` and registering it as a Spring bean. The following +example demonstrates such a class: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class EmailService implements ApplicationEventPublisherAware { + + private List blackList; + private ApplicationEventPublisher publisher; + + public void setBlackList(List blackList) { + this.blackList = blackList; + } + + public void setApplicationEventPublisher(ApplicationEventPublisher publisher) { + this.publisher = publisher; + } + + public void sendEmail(String address, String text) { + if (blackList.contains(address)) { + BlackListEvent event = new BlackListEvent(this, address, text); + publisher.publishEvent(event); + return; + } + // send email... + } + + } +---- + +At configuration time, the Spring container will detect that `EmailService` implements +`ApplicationEventPublisherAware` and will automatically call +`setApplicationEventPublisher()`. In reality, the parameter passed in will be the Spring +container itself; you're simply interacting with the application context via its +`ApplicationEventPublisher` interface. + +To receive the custom `ApplicationEvent`, create a class that implements +`ApplicationListener` and register it as a Spring bean. The following example +demonstrates such a class: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class BlackListNotifier implements ApplicationListener { + + private String notificationAddress; + + public void setNotificationAddress(String notificationAddress) { + this.notificationAddress = notificationAddress; + } + + public void onApplicationEvent(BlackListEvent event) { + // notify appropriate parties via notificationAddress... + } + + } +---- + +Notice that `ApplicationListener` is generically parameterized with the type of your +custom event, `BlackListEvent`. This means that the `onApplicationEvent()` method can +remain type-safe, avoiding any need for downcasting. You may register as many event +listeners as you wish, but note that by default event listeners receive events +synchronously. This means the `publishEvent()` method blocks until all listeners have +finished processing the event. One advantage of this synchronous and single-threaded +approach is that when a listener receives an event, it operates inside the transaction +context of the publisher if a transaction context is available. If another strategy for +event publication becomes necessary, refer to the JavaDoc for Spring's +`ApplicationEventMulticaster` interface. + +The following example shows the bean definitions used to register and configure each of +the classes above: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + known.spammer@example.org + known.hacker@example.org + john.doe@example.org + + + + + + + +---- + +Putting it all together, when the `sendEmail()` method of the `emailService` bean is +called, if there are any emails that should be blacklisted, a custom event of type +`BlackListEvent` is published. The `blackListNotifier` bean is registered as an +`ApplicationListener` and thus receives the `BlackListEvent`, at which point it can +notify appropriate parties. + +[NOTE] +==== +Spring's eventing mechanism is designed for simple communication between Spring beans +within the same application context. However, for more sophisticated enterprise +integration needs, the separately-maintained +http://projects.spring.io/spring-integration/[Spring Integration] project provides +complete support for building lightweight, +http://www.enterpriseintegrationpatterns.com[pattern-oriented], event-driven +architectures that build upon the well-known Spring programming model. +==== + + + +[[context-functionality-resources]] +==== Convenient access to low-level resources +For optimal usage and understanding of application contexts, users should generally +familiarize themselves with Spring's `Resource` abstraction, as described in the chapter +<>. + +An application context is a `ResourceLoader`, which can be used to load ++Resource++s. A +`Resource` is essentially a more feature rich version of the JDK class `java.net.URL`, +in fact, the implementations of the `Resource` wrap an instance of `java.net.URL` where +appropriate. A `Resource` can obtain low-level resources from almost any location in a +transparent fashion, including from the classpath, a filesystem location, anywhere +describable with a standard URL, and some other variations. If the resource location +string is a simple path without any special prefixes, where those resources come from is +specific and appropriate to the actual application context type. + +You can configure a bean deployed into the application context to implement the special +callback interface, `ResourceLoaderAware`, to be automatically called back at +initialization time with the application context itself passed in as the +`ResourceLoader`. You can also expose properties of type `Resource`, to be used to +access static resources; they will be injected into it like any other properties. You +can specify those `Resource` properties as simple String paths, and rely on a special +JavaBean `PropertyEditor` that is automatically registered by the context, to convert +those text strings to actual `Resource` objects when the bean is deployed. + +The location path or paths supplied to an `ApplicationContext` constructor are actually +resource strings, and in simple form are treated appropriately to the specific context +implementation. `ClassPathXmlApplicationContext` treats a simple location path as a +classpath location. You can also use location paths (resource strings) with special +prefixes to force loading of definitions from the classpath or a URL, regardless of the +actual context type. + + + +[[context-create]] +==== Convenient ApplicationContext instantiation for web applications + +You can create `ApplicationContext` instances declaratively by using, for example, a +`ContextLoader`. Of course you can also create `ApplicationContext` instances +programmatically by using one of the `ApplicationContext` implementations. + +You can register an `ApplicationContext` using the `ContextLoaderListener` as follows: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + contextConfigLocation + /WEB-INF/daoContext.xml /WEB-INF/applicationContext.xml + + + + org.springframework.web.context.ContextLoaderListener + + + +---- + +The listener inspects the `contextConfigLocation` parameter. If the parameter does not +exist, the listener uses `/WEB-INF/applicationContext.xml` as a default. When the +parameter __does__ exist, the listener separates the String by using predefined +delimiters (comma, semicolon and whitespace) and uses the values as locations where +application contexts will be searched. Ant-style path patterns are supported as well. +Examples are `/WEB-INF/*Context.xml` for all files with names ending with "Context.xml", +residing in the "WEB-INF" directory, and `/WEB-INF/**/*Context.xml`, for all such files +in any subdirectory of "WEB-INF". + +You can use `ContextLoaderServlet` instead of `ContextLoaderListener`. The Servlet uses +the `contextConfigLocation` parameter just as the listener does. + + + +[[context-deploy-rar]] +==== Deploying a Spring ApplicationContext as a Java EE RAR file +It is possible to deploy a Spring ApplicationContext as a RAR file, encapsulating the +context and all of its required bean classes and library JARs in a Java EE RAR deployment +unit. This is the equivalent of bootstrapping a standalone ApplicationContext, just hosted +in Java EE environment, being able to access the Java EE servers facilities. RAR deployment +is more natural alternative to scenario of deploying a headless WAR file, in effect, a WAR +file without any HTTP entry points that is used only for bootstrapping a Spring +ApplicationContext in a Java EE environment. + +RAR deployment is ideal for application contexts that do not need HTTP entry points but +rather consist only of message endpoints and scheduled jobs. Beans in such a context can +use application server resources such as the JTA transaction manager and JNDI-bound JDBC +DataSources and JMS ConnectionFactory instances, and may also register with the +platform's JMX server - all through Spring's standard transaction management and JNDI +and JMX support facilities. Application components can also interact with the +application server's JCA WorkManager through Spring's `TaskExecutor` abstraction. + +Check out the JavaDoc of the +{javadoc-baseurl}/org/springframework/jca/context/SpringContextResourceAdapter.html[`SpringContextResourceAdapter`] +class for the configuration details involved in RAR deployment. + +__For a simple deployment of a Spring ApplicationContext as a Java EE RAR file:__ package +all application classes into a RAR file, which is a standard JAR file with a different +file extension. Add all required library JARs into the root of the RAR archive. Add a +"META-INF/ra.xml" deployment descriptor (as shown in ++SpringContextResourceAdapter++'s +JavaDoc) and the corresponding Spring XML bean definition file(s) (typically +"META-INF/applicationContext.xml"), and drop the resulting RAR file into your +application server's deployment directory. + +[NOTE] +==== +Such RAR deployment units are usually self-contained; they do not expose components to +the outside world, not even to other modules of the same application. Interaction with a +RAR-based ApplicationContext usually occurs through JMS destinations that it shares with +other modules. A RAR-based ApplicationContext may also, for example, schedule some jobs, +reacting to new files in the file system (or the like). If it needs to allow synchronous +access from the outside, it could for example export RMI endpoints, which of course may +be used by other application modules on the same machine. +==== + + + + +[[beans-beanfactory]] +=== The BeanFactory +The `BeanFactory` provides the underlying basis for Spring's IoC functionality but it is +only used directly in integration with other third-party frameworks and is now largely +historical in nature for most users of Spring. The `BeanFactory` and related interfaces, +such as `BeanFactoryAware`, `InitializingBean`, `DisposableBean`, are still present in +Spring for the purposes of backward compatibility with the large number of third-party +frameworks that integrate with Spring. Often third-party components that can not use +more modern equivalents such as `@PostConstruct` or `@PreDestroy` in order to remain +compatible with JDK 1.4 or to avoid a dependency on JSR-250. + +This section provides additional background into the differences between the +`BeanFactory` and `ApplicationContext` and how one might access the IoC container +directly through a classic singleton lookup. + + + +[[context-introduction-ctx-vs-beanfactory]] +==== BeanFactory or ApplicationContext? + +Use an `ApplicationContext` unless you have a good reason for not doing so. + +Because the `ApplicationContext` includes all functionality of the `BeanFactory`, it is +generally recommended over the `BeanFactory`, except for a few situations such as in an +`Applet` where memory consumption might be critical and a few extra kilobytes might make +a difference. However, for most typical enterprise applications and systems, the +`ApplicationContext` is what you will want to use. Spring makes __heavy__ +use of the <> (to +effect proxying and so on). If you use only a plain `BeanFactory`, a fair amount of +support such as transactions and AOP will not take effect, at least not without some +extra steps on your part. This situation could be confusing because nothing is actually +wrong with the configuration. + +The following table lists features provided by the `BeanFactory` and +`ApplicationContext` interfaces and implementations. + +[[context-introduction-ctx-vs-beanfactory-feature-matrix]] +.Feature Matrix +|=== +| Feature| `BeanFactory`| `ApplicationContext` + +| Bean instantiation/wiring +| Yes +| Yes + +| Automatic `BeanPostProcessor` registration +| No +| Yes + +| Automatic `BeanFactoryPostProcessor` registration +| No +| Yes + +| Convenient `MessageSource` access (for i18n) +| No +| Yes + +| `ApplicationEvent` publication +| No +| Yes +|=== + +To explicitly register a bean post-processor with a `BeanFactory` implementation, you +must write code like this: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + ConfigurableBeanFactory factory = new XmlBeanFactory(...); + + // now register any needed BeanPostProcessor instances + MyBeanPostProcessor postProcessor = new MyBeanPostProcessor(); + factory.addBeanPostProcessor(postProcessor); + + // now start using the factory +---- + +To explicitly register a `BeanFactoryPostProcessor` when using a `BeanFactory` +implementation, you must write code like this: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + XmlBeanFactory factory = new XmlBeanFactory(new FileSystemResource("beans.xml")); + + // bring in some property values from a Properties file + PropertyPlaceholderConfigurer cfg = new PropertyPlaceholderConfigurer(); + cfg.setLocation(new FileSystemResource("jdbc.properties")); + + // now actually do the replacement + cfg.postProcessBeanFactory(factory); +---- + +In both cases, the explicit registration step is inconvenient, which is one reason why +the various `ApplicationContext` implementations are preferred above plain `BeanFactory` +implementations in the vast majority of Spring-backed applications, especially when +using `BeanFactoryPostProcessors` and `BeanPostProcessors`. These mechanisms implement +important functionality such as property placeholder replacement and AOP. + + + +[[beans-servicelocator]] +==== Glue code and the evil singleton +It is best to write most application code in a dependency-injection (DI) style, where +that code is served out of a Spring IoC container, has its own dependencies supplied by +the container when it is created, and is completely unaware of the container. However, +for the small glue layers of code that are sometimes needed to tie other code together, +you sometimes need a singleton (or quasi-singleton) style access to a Spring IoC +container. For example, third-party code may try to construct new objects directly ( +`Class.forName()` style), without the ability to get these objects out of a Spring IoC +container.If the object constructed by the third-party code is a small stub or proxy, +which then uses a singleton style access to a Spring IoC container to get a real object +to delegate to, then inversion of control has still been achieved for the majority of +the code (the object coming out of the container). Thus most code is still unaware of +the container or how it is accessed, and remains decoupled from other code, with all +ensuing benefits. EJBs may also use this stub/proxy approach to delegate to a plain Java +implementation object, retrieved from a Spring IoC container. While the Spring IoC +container itself ideally does not have to be a singleton, it may be unrealistic in terms +of memory usage or initialization times (when using beans in the Spring IoC container +such as a Hibernate `SessionFactory`) for each bean to use its own, non-singleton Spring +IoC container. + +Looking up the application context in a service locator style is sometimes the only +option for accessing shared Spring-managed components, such as in an EJB 2.1 +environment, or when you want to share a single ApplicationContext as a parent to +WebApplicationContexts across WAR files. In this case you should look into using the +utility class +{javadoc-baseurl}/org/springframework/context/access/ContextSingletonBeanFactoryLocator.html[`ContextSingletonBeanFactoryLocator`] +locator that is described in this +https://spring.io/blog/2007/06/11/using-a-shared-parent-application-context-in-a-multi-war-spring-application/[Spring +team blog entry]. + + + + diff --git a/src/asciidoc/cache.adoc b/src/asciidoc/cache.adoc new file mode 100644 index 000000000000..dce730888a58 --- /dev/null +++ b/src/asciidoc/cache.adoc @@ -0,0 +1,1081 @@ +[[cache]] +== Cache Abstraction + + + + +[[cache-introduction]] +=== Introduction +Since version 3.1, Spring Framework provides support for transparently adding caching +into an existing Spring application. Similar to the <> support, +the caching abstraction allows consistent use of various caching solutions with minimal +impact on the code. + +As from Spring 4.1, the cache abstraction has been significantly improved with the +support of <> and more customization options. + + + +[[cache-strategies]] +=== Understanding the cache abstraction +.Cache vs Buffer +**** + +The terms "buffer" and "cache" tend to be used interchangeably; note however they +represent different things. A buffer is used traditionally as an intermediate temporary +store for data between a fast and a slow entity. As one party would have to __wait__ for +the other affecting performance, the buffer alleviates this by allowing entire blocks of +data to move at once rather then in small chunks. The data is written and read only once +from the buffer. Furthermore, the buffers are __visible__ to at least one party which is +aware of it. + +A cache on the other hand by definition is hidden and neither party is aware that +caching occurs.It as well improves performance but does that by allowing the same data +to be read multiple times in a fast fashion. + +A further explanation of the differences between two can be found +http://en.wikipedia.org/wiki/Cache_(computing)#The_difference_between_buffer_and_cache[here]. +**** + +At its core, the abstraction applies caching to Java methods, reducing thus the number +of executions based on the information available in the cache. That is, each time a +__targeted__ method is invoked, the abstraction will apply a caching behavior checking +whether the method has been already executed for the given arguments. If it has, then +the cached result is returned without having to execute the actual method; if it has +not, then method is executed, the result cached and returned to the user so that, the +next time the method is invoked, the cached result is returned. This way, expensive +methods (whether CPU or IO bound) can be executed only once for a given set of +parameters and the result reused without having to actually execute the method again. +The caching logic is applied transparently without any interference to the invoker. + +[IMPORTANT] +==== + +Obviously this approach works only for methods that are guaranteed to return the same +output (result) for a given input (or arguments) no matter how many times it is being +executed. +==== + +Other cache-related operations are provided by the abstraction such as the ability +to update the content of the cache or remove one of all entries. These are useful if +the cache deals with data that can change during the course of the application. + +Just like other services in the Spring Framework, the caching service is an +abstraction (not a cache implementation) and requires the use of an actual storage to +store the cache data - that is, the abstraction frees the developer from having to write +the caching logic but does not provide the actual stores. This abstraction is +materialized by the `org.springframework.cache.Cache` and +`org.springframework.cache.CacheManager` interfaces. + +There are <> of that abstraction +available out of the box: JDK `java.util.concurrent.ConcurrentMap` based caches, +http://ehcache.org/[EhCache], Gemfire cache, +https://code.google.com/p/guava-libraries/wiki/CachesExplained[Guava caches] and +JSR-107 compliant caches. See <> for more information on plugging in +other cache stores/providers. + +[IMPORTANT] +==== +The caching abstraction has no special handling of multi-threaded and multi-process +environments as such features are handled by the cache implementation. . +==== + +If you have a multi-process environment (i.e. an application deployed on several nodes), +you will need to configure your cache provider accordingly. Depending on your use cases, +a copy of the same data on several nodes may be enough but if you change the data during +the course of the application, you may need to enable other propagation mechanisms. + +Caching a particular item is a direct equivalent of the typical get-if-not-found-then- +proceed-and-put-eventually code blocks found with programmatic cache interaction: no locks +are applied and several threads may try to load the same item concurrently. The same applies +to eviction: if several threads are trying to update or evict data concurrently, you may +use stale data. Certain cache providers offer advanced features in that area, refer to +the documentation of the cache provider that you are using for more details. + +To use the cache abstraction, the developer needs to take care of two aspects: + +* caching declaration - identify the methods that need to be cached and their policy +* cache configuration - the backing cache where the data is stored and read from + + +[[cache-annotations]] +=== Declarative annotation-based caching +For caching declaration, the abstraction provides a set of Java annotations: + +* `@Cacheable` triggers cache population +* `@CacheEvict` triggers cache eviction +* `@CachePut` updates the cache without interfering with the method execution +* `@Caching` regroups multiple cache operations to be applied on a method +* `@CacheConfig` shares some common cache-related settings at class-level + +Let us take a closer look at each annotation: + +[[cache-annotations-cacheable]] +==== @Cacheable annotation + +As the name implies, `@Cacheable` is used to demarcate methods that are cacheable - that +is, methods for whom the result is stored into the cache so on subsequent invocations +(with the same arguments), the value in the cache is returned without having to actually +execute the method. In its simplest form, the annotation declaration requires the name +of the cache associated with the annotated method: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Cacheable("books") + public Book findBook(ISBN isbn) {...} +---- + +In the snippet above, the method `findBook` is associated with the cache named `books`. +Each time the method is called, the cache is checked to see whether the invocation has +been already executed and does not have to be repeated. While in most cases, only one +cache is declared, the annotation allows multiple names to be specified so that more +than one cache are being used. In this case, each of the caches will be checked before +executing the method - if at least one cache is hit, then the associated value will be +returned: + +[NOTE] +==== +All the other caches that do not contain the value will be updated as well even though +the cached method was not actually executed. +==== + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Cacheable({"books", "isbns"}) + public Book findBook(ISBN isbn) {...} +---- + + +[[cache-annotations-cacheable-default-key]] +===== Default Key Generation +Since caches are essentially key-value stores, each invocation of a cached method needs +to be translated into a suitable key for cache access. Out of the box, the caching +abstraction uses a simple `KeyGenerator` based on the following algorithm: + +* If no params are given, return `SimpleKey.EMPTY`. +* If only one param is given, return that instance. +* If more the one param is given, return a `SimpleKey` containing all parameters. + +This approach works well for most use-cases; As long as parameters have __natural keys__ +and implement valid `hashCode()` and `equals()` methods. If that is not the case then the +strategy needs to be changed. + +To provide a different __default__ key generator, one needs to implement the +`org.springframework.cache.interceptor.KeyGenerator` interface. + + +[NOTE] +==== +The default key generation strategy changed with the release of Spring 4.0. Earlier +versions of Spring used a key generation strategy that, for multiple key parameters, +only considered the `hashCode()` of parameters and not `equals()`; this could cause +unexpected key collisions (see https://jira.spring.io/browse/SPR-10237[SPR-10237] +for background). The new 'SimpleKeyGenerator' uses a compound key for such scenarios. + +If you want to keep using the previous key strategy, you can configure the deprecated +`org.springframework.cache.interceptor.DefaultKeyGenerator` class or create a custom +hash-based 'KeyGenerator' implementation. +==== + + +[[cache-annotations-cacheable-key]] +===== Custom Key Generation Declaration +Since caching is generic, it is quite likely the target methods have various signatures +that cannot be simply mapped on top of the cache structure. This tends to become obvious +when the target method has multiple arguments out of which only some are suitable for +caching (while the rest are used only by the method logic). For example: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Cacheable("books") + public Book findBook(ISBN isbn, boolean checkWarehouse, boolean includeUsed) +---- + +At first glance, while the two `boolean` arguments influence the way the book is found, +they are no use for the cache. Further more what if only one of the two is important +while the other is not? + +For such cases, the `@Cacheable` annotation allows the user to specify how the key is +generated through its `key` attribute. The developer can use <> to +pick the arguments of interest (or their nested properties), perform operations or even +invoke arbitrary methods without having to write any code or implement any interface. +This is the recommended approach over the +<> since methods tend to be +quite different in signatures as the code base grows; while the default strategy might +work for some methods, it rarely does for all methods. + +Below are some examples of various SpEL declarations - if you are not familiar with it, +do yourself a favor and read <>: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Cacheable(value="books", **key="#isbn"**) + public Book findBook(ISBN isbn, boolean checkWarehouse, boolean includeUsed) + + @Cacheable(value="books", **key="#isbn.rawNumber"**) + public Book findBook(ISBN isbn, boolean checkWarehouse, boolean includeUsed) + + @Cacheable(value="books", **key="T(someType).hash(#isbn)"**) + public Book findBook(ISBN isbn, boolean checkWarehouse, boolean includeUsed) +---- + +The snippets above show how easy it is to select a certain argument, one of its +properties or even an arbitrary (static) method. + +If the algorithm responsible to generate the key is too specific or if it needs +to be shared, you may define a custom `keyGenerator` on the operation. To do +this, specify the name of the `KeyGenerator` bean implementation to use: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Cacheable(value="books", **keyGenerator="myKeyGenerator"**) + public Book findBook(ISBN isbn, boolean checkWarehouse, boolean includeUsed) +---- + + +[NOTE] +==== +The `key` and `keyGenerator` parameters are mutually exclusive and an operation +specifying both will result in an exception. +==== + +[[cache-annotations-cacheable-default-cache-resolver]] +===== Default Cache Resolution + +Out of the box, the caching abstraction uses a simple `CacheResolver` that +retrieves the cache(s) defined at the operation level using the configured +`CacheManager`. + +To provide a different __default__ cache resolver, one needs to implement the +`org.springframework.cache.interceptor.CacheResolver` interface. + + +[[cache-annotations-cacheable-cache-resolver]] +===== Custom cache resolution + +The default cache resolution fits well for applications working with a +single `CacheManager` and with no complex cache resolution requirements. + +For applications working with several cache managers, it is possible +to set the `cacheManager` to use per operation: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Cacheable(value="books", **cacheManager="anotherCacheManager"**) + public Book findBook(ISBN isbn) {...} +---- + +It is also possible to replace the `CacheResolver` entirely in a similar +fashion as for <>. The +resolution is requested for every cache operation, giving a chance to +the implementation to actually resolve the cache(s) to use based on +runtime arguments: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Cacheable(**cacheResolver="runtimeCacheResolver"**) + public Book findBook(ISBN isbn) {...} +---- + +[NOTE] +==== +Since Spring 4.1, the `value` attribute of the cache annotations are no longer +mandatory since this particular information can be provided by the `CacheResolver` +regardless of the content of the annotation. + +Similarly to `key` and `keyGenerator`, the `cacheManager` and `cacheResolver` +parameters are mutually exclusive and an operation specifying both will +result in an exception as a custom `CacheManager` will be ignored by the +`CacheResolver` implementation. This is probably not what you expect. +==== + +[[cache-annotations-cacheable-condition]] +===== Conditional caching +Sometimes, a method might not be suitable for caching all the time (for example, it +might depend on the given arguments). The cache annotations support such functionality +through the `conditional` parameter which takes a `SpEL` expression that is evaluated to +either `true` or `false`. If `true`, the method is cached - if not, it behaves as if the +method is not cached, that is executed every since time no matter what values are in the +cache or what arguments are used. A quick example - the following method will be cached +only if the argument `name` has a length shorter than 32: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Cacheable(value="book", **condition="#name.length < 32"**) + public Book findBook(String name) +---- + +In addition the `conditional` parameter, the `unless` parameter can be used to veto the +adding of a value to the cache. Unlike `conditional`, `unless` expressions are evaluated +__after__ the method has been called. Expanding on the previous example - perhaps we +only want to cache paperback books: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Cacheable(value="book", condition="#name.length < 32", **unless="#result.hardback"**) + public Book findBook(String name) +---- + + +[[cache-spel-context]] +===== Available caching SpEL evaluation context + +Each `SpEL` expression evaluates again a dedicated +<>. In addition to the build in parameters, the +framework provides dedicated caching related metadata such as the argument names. The +next table lists the items made available to the context so one can use them for key and +conditional computations: + +[[cache-spel-context-tbl]] +.Cache SpEL available metadata +|=== +| Name| Location| Description| Example + +| methodName +| root object +| The name of the method being invoked +| `#root.methodName` + +| method +| root object +| The method being invoked +| `#root.method.name` + +| target +| root object +| The target object being invoked +| `#root.target` + +| targetClass +| root object +| The class of the target being invoked +| `#root.targetClass` + +| args +| root object +| The arguments (as array) used for invoking the target +| `#root.args[0]` + +| caches +| root object +| Collection of caches against which the current method is executed +| `#root.caches[0].name` + +| __argument name__ +| evaluation context +| Name of any of the method argument. If for some reason the names are not available + (ex: no debug information), the argument names are also available under the `a<#arg>` + where __#arg__ stands for the argument index (starting from 0). +| `iban` or `a0` (one can also use `p0` or `p<#arg>` notation as an alias). + +| result +| evaluation context +| The result of the method call (the value to be cached). Only available in `unless`' + expressions, `cache put` expression (to compute the `key`) or `cache evict` + expression (when `beforeInvocation` is `false`). +| `#result` +|=== + + +[[cache-annotations-put]] +==== @CachePut annotation + +For cases where the cache needs to be updated without interfering with the method +execution, one can use the `@CachePut` annotation. That is, the method will always be +executed and its result placed into the cache (according to the `@CachePut` options). It +supports the same options as `@Cacheable` and should be used for cache population rather +than method flow optimization: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @CachePut(value="book", key="#isbn") + public Book updateBook(ISBN isbn, BookDescriptor descriptor) +---- + + +[IMPORTANT] +==== +Note that using `@CachePut` and `@Cacheable` annotations on the same method is generally +strongly discouraged because they have different behaviors. While the latter causes the +method execution to be skipped by using the cache, the former forces the execution in +order to execute a cache update. This leads to unexpected behavior and with the exception of +specific corner-cases (such as annotations having conditions that exclude them from each +other), such declaration should be avoided. Note also that such condition should not rely +on the result object (i.e. the `#result` variable) as these are validated upfront to confirm +the exclusion. +==== + + +[[cache-annotations-evict]] +==== @CacheEvict annotation + +The cache abstraction allows not just population of a cache store but also eviction. +This process is useful for removing stale or unused data from the cache. Opposed to +`@Cacheable`, annotation `@CacheEvict` demarcates methods that perform cache +__eviction__, that is methods that act as triggers for removing data from the cache. +Just like its sibling, `@CacheEvict` requires specifying one (or multiple) caches +that are affected by the action, allows a custom cache and key resolution or a +condition to be specified but in addition, features an extra parameter +`allEntries` which indicates whether a cache-wide eviction needs to be performed +rather then just an entry one (based on the key): + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @CacheEvict(value="books", **allEntries=true**) + public void loadBooks(InputStream batch) +---- + +This option comes in handy when an entire cache region needs to be cleared out - rather +then evicting each entry (which would take a long time since it is inefficient), all the +entries are removed in one operation as shown above. Note that the framework will ignore +any key specified in this scenario as it does not apply (the entire cache is evicted not +just one entry). + +One can also indicate whether the eviction should occur after (the default) or before +the method executes through the `beforeInvocation` attribute. The former provides the +same semantics as the rest of the annotations - once the method completes successfully, +an action (in this case eviction) on the cache is executed. If the method does not +execute (as it might be cached) or an exception is thrown, the eviction does not occur. +The latter ( `beforeInvocation=true`) causes the eviction to occur always, before the +method is invoked - this is useful in cases where the eviction does not need to be tied +to the method outcome. + +It is important to note that void methods can be used with `@CacheEvict` - as the +methods act as triggers, the return values are ignored (as they don't interact with the +cache) - this is not the case with `@Cacheable` which adds/updates data into the cache +and thus requires a result. + + + +[[cache-annotations-caching]] +==== @Caching annotation + +There are cases when multiple annotations of the same type, such as `@CacheEvict` or +`@CachePut` need to be specified, for example because the condition or the key +expression is different between different caches. Unfortunately Java does not support +such declarations however there is a workaround - using an __enclosing__ annotation, in +this case, `@Caching`. `@Caching` allows multiple nested `@Cacheable`, `@CachePut` and +`@CacheEvict` to be used on the same method: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Caching(evict = { @CacheEvict("primary"), @CacheEvict(value="secondary", key="#p0") }) + public Book importBooks(String deposit, Date date) +---- + + +[[cache-annotations-config]] +==== @CacheConfig annotation + +So far we have seen that caching operations offered many customization options and +these can be set on an operation basis. However, some of the customization options +can be tedious to configure if they apply to all operations of the class. For +instance, specifying the name of the cache to use for every cache operation of the +class could be replaced by a single class-level definition. This is where `@CacheConfig` +comes into play. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + **@CacheConfig("books")** + public class BookRepositoryImpl implements BookRepository { + + @Cacheable + public Book findBook(ISBN isbn) {...} + } +---- + +`@CacheConfig` is a class-level annotation that allows to share the cache names, the custom +`KeyGenerator`, the custom `CacheManager` and finally the custom `CacheResolver`. Placing +this annotation on the class does not turn on any caching operation. + +An operation-level customization will always override a customization set on `@CacheConfig`. This +gives therefore three levels of customizations per cache operation: + +* Globally configured, available for `CacheManager`, `KeyGenerator` +* At class level, using `@CacheConfig` +* At the operation level + +[[cache-annotation-enable]] +==== Enable caching annotations +It is important to note that even though declaring the cache annotations does not +automatically trigger their actions - like many things in Spring, the feature has to be +declaratively enabled (which means if you ever suspect caching is to blame, you can +disable it by removing only one configuration line rather than all the annotations in +your code). + +To enable caching annotations add the annotation `@EnableCaching` to one of your +`@Configuration` classes: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Configuration + @EnableCaching + public class AppConfig { + } +---- + +Alternatively for XML configuration use the `cache:annotation-driven` element: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + +---- + +Both the `cache:annotation-driven` element and `@EnableCaching` annotation allow various +options to be specified that influence the way the caching behavior is added to the +application through AOP. The configuration is intentionally similar with that of +<>: + +[[cache-annotation-driven-settings]] +.Cache annotation settings +[cols="1,1,1,3"] +|=== +| XML Attribute| Annotation Attribute| Default| Description + +| `cache-manager` +| N/A (See `CachingConfigurer` javadocs) +| cacheManager +| Name of cache manager to use. A default `CacheResolver` will be initialized behind + the scenes with this cache manager (or `cacheManager`if not set). For more + fine-grained management of the cache resolution, consider setting the 'cache-resolver' + attribute. + +| `cache-resolver` +| N/A (See `CachingConfigurer` javadocs) +| A `SimpleCacheResolver` using the configured `cacheManager`. +| The bean name of the CacheResolver that is to be used to resolve the backing caches. + This attribute is not required, and only needs to be specified as an alternative to + the 'cache-manager' attribute. + +| `key-generator` +| N/A (See `CachingConfigurer` javadocs) +| `SimpleKeyGenerator` +| Name of the custom key generator to use. + +| `error-handler` +| N/A (See `CachingConfigurer` javadocs) +| `SimpleCacheErrorHandler` +| Name of the custom cache error handler to use. By default, any exception throw during + a cache related operations are thrown back at the client. + +| `mode` +| `mode` +| proxy +| The default mode "proxy" processes annotated beans to be proxied using Spring's AOP + framework (following proxy semantics, as discussed above, applying to method calls + coming in through the proxy only). The alternative mode "aspectj" instead weaves the + affected classes with Spring's AspectJ caching aspect, modifying the target class byte + code to apply to any kind of method call. AspectJ weaving requires spring-aspects.jar + in the classpath as well as load-time weaving (or compile-time weaving) enabled. (See + <> for details on how to set up load-time weaving.) + +| `proxy-target-class` +| `proxyTargetClass` +| false +| Applies to proxy mode only. Controls what type of caching proxies are created for + classes annotated with the `@Cacheable` or `@CacheEvict` annotations. If the + `proxy-target-class` attribute is set to `true`, then class-based proxies are created. + If `proxy-target-class` is `false` or if the attribute is omitted, then standard JDK + interface-based proxies are created. (See <> for a detailed examination + of the different proxy types.) + +| `order` +| `order` +| Ordered.LOWEST_PRECEDENCE +| Defines the order of the cache advice that is applied to beans annotated with + `@Cacheable` or `@CacheEvict`. (For more information about the rules related to + ordering of AOP advice, see <>.) No specified ordering + means that the AOP subsystem determines the order of the advice. +|=== + +[NOTE] +==== +`` only looks for `@Cacheable/@CachePut/@CacheEvict/@Caching` +on beans in the same application context it is defined in. This means that, if you put +`` in a `WebApplicationContext` for a `DispatcherServlet`, it +only checks for beans in your controllers, and not your services. See <> +for more information. +==== + +.Method visibility and cache annotations +**** +When using proxies, you should apply the cache annotations only to methods with +__public__ visibility. If you do annotate protected, private or package-visible methods +with these annotations, no error is raised, but the annotated method does not exhibit +the configured caching settings. Consider the use of AspectJ (see below) if you need to +annotate non-public methods as it changes the bytecode itself. +**** + +[TIP] +==== +Spring recommends that you only annotate concrete classes (and methods of concrete +classes) with the `@Cache*` annotation, as opposed to annotating interfaces. You +certainly can place the `@Cache*` annotation on an interface (or an interface method), +but this works only as you would expect it to if you are using interface-based proxies. +The fact that Java annotations are __not inherited from interfaces__ means that if you +are using class-based proxies ( `proxy-target-class="true"`) or the weaving-based aspect +( `mode="aspectj"`), then the caching settings are not recognized by the proxying and +weaving infrastructure, and the object will not be wrapped in a caching proxy, which +would be decidedly __bad__. +==== + +[NOTE] +==== +In proxy mode (which is the default), only external method calls coming in through the +proxy are intercepted. This means that self-invocation, in effect, a method within the +target object calling another method of the target object, will not lead to an actual +caching at runtime even if the invoked method is marked with `@Cacheable` - considering +using the aspectj mode in this case. +==== + + + +[[cache-annotation-stereotype]] +==== Using custom annotations + +.Custom annotation and AspectJ +**** +This feature only works out-of-the-box with the proxy-based approach but can be enabled +with a bit of extra effort using AspectJ. + +The `spring-aspects` module defines an aspect for the standard annotations only. If you +have defined your own annotations, you also need to define an aspect for those. Check +`AnnotationCacheAspect` for an example. +**** + +The caching abstraction allows you to use your own annotations to identify what method +triggers cache population or eviction. This is quite handy as a template mechanism as it +eliminates the need to duplicate cache annotation declarations (especially useful if the +key or condition are specified) or if the foreign imports (`org.springframework`) are +not allowed in your code base. Similar to the rest of the +<> annotations, `@Cacheable`, `@CachePut`, +`@CacheEvict` and `@CacheConfig` can be used as <>, +that is annotations that can annotate other annotations. To wit, let us replace a common +`@Cacheable` declaration with our own, custom annotation: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Retention(RetentionPolicy.RUNTIME) + @Target({ElementType.METHOD}) + @Cacheable(value="books", key="#isbn") + public @interface SlowService { + } +---- + +Above, we have defined our own `SlowService` annotation which itself is annotated with +`@Cacheable` - now we can replace the following code: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Cacheable(value="books", key="#isbn") + public Book findBook(ISBN isbn, boolean checkWarehouse, boolean includeUsed) +---- + +with: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @SlowService + public Book findBook(ISBN isbn, boolean checkWarehouse, boolean includeUsed) +---- + +Even though `@SlowService` is not a Spring annotation, the container automatically picks +up its declaration at runtime and understands its meaning. Note that as mentioned +<>, the annotation-driven behavior needs to be enabled. + + +[[cache-jsr-107]] +=== JCache (JSR-107) annotations + +Since the Spring Framework 4.1, the caching abstraction fully supports the JCache +standard annotations: these are `@CacheResult`, `@CacheEvict`, `@CacheRemove` and +`@CacheRemoveAll` as well as the `@CacheDefaults`, `@CacheKey` and `@CacheValue` +companions. These annotations can be used right the way without migrating your +cache store to JSR-107: the internal implementation uses Spring's caching abstraction +and provides default `CacheResolver` and `KeyGenerator` implementations that are +compliant with the specification. In other words, if you are already using Spring's +caching abstraction, you can switch to these standard annotations without changing +your cache storage (or configuration, for that matter). + +[[cache-jsr-107-summary]] +==== Features summary + +For those who are familiar with Spring's caching annotations, the following table +describes the main differences between the Spring annotations and the JSR-107 +counterpart: + +.Spring vs. JSR-107 caching annotations +[cols="1,1,3"] +|=== +| Spring| JSR-107| Remark + +| `@Cacheable` +| `@CacheResult` +| Fairly similar. `@CacheResult` can cache specific exceptions and force the + execution of the method regardless of the content of the cache. + +| `@CachePut` +| `@CachePut` +| While Spring updates the cache with the result of the method invocation, JCache + requires to pass it as an argument that is annotated with `@CacheValue`. Due + to this difference, JCache allows to update the cache before or after the + actual method invocation. + +| `@CacheEvict` +| `@CacheRemove` +| Fairly similar. `@CacheRemove` supports a conditional evict in case the + method invocation results in an exception. + +| `@CacheEvict(allEntries=true)` +| `@CacheRemoveAll` +| See `@CacheRemove`. + +| `@CacheConfig` +| `@CacheDefaults` +| Allows to configure the same concepts, in a similar fashion. +|=== + +JCache has the notion of `javax.cache.annotation.CacheResolver` that is identical +to the Spring's `CacheResolver` interface, except that JCache only supports a single +cache. By default, a simple implementation retrieves the cache to use based on +the name declared on the annotation. It should be noted that if no cache name +is specified on the annotation, a default is automatically generated, check the +javadoc of `@CacheResult#cacheName()` for more information. + +`CacheResolver` instances are retrieved by a `CacheResolverFactory`. It is +possible to customize the factory per cache operation: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @CacheResult(value="books", *cacheResolverFactory=MyCacheResolverFactory.class*) + public Book findBook(ISBN isbn) +---- + +[NOTE] +==== +For all referenced _classes_, Spring tries to locate a bean with the given type. If +more than one match exists, a new instance is created and can use the regular +bean lifecycle callbacks such as dependency injection. +==== + +Keys are generated by a `javax.cache.annotation.CacheKeyGenerator` that serves the +same purpose as Spring's `KeyGenerator`. By default, all method arguments are taken +into account unless at least one parameter is annotated with `@CacheKey`. This is +similar to Spring's <>. For instance these are identical operations, one using Spring's +abstraction and the other with JCache: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Cacheable(value="books", **key="#isbn"**) + public Book findBook(ISBN isbn, boolean checkWarehouse, boolean includeUsed) + + @CacheResult(cacheName="books") + public Book findBook(**@CacheKey** ISBN isbn, boolean checkWarehouse, boolean includeUsed) +---- + +The `CacheKeyResolver` to use can also be specified on the operation, in a similar +fashion as the `CacheResolverFactory`. + +JCache can manage exceptions thrown by annotated methods: this can prevent an update of +the cache but it can also cache the exception as an indicator of the failure instead of +calling the method again. Let's assume that `InvalidIsbnNotFoundException` is thrown if +the structure of the ISBN is invalid. This is a permanent failure, no book could ever be +retrieved with such parameter. The following caches the exception so that further calls +with the same, invalid ISBN, throws the cached exception directly instead of invoking +the method again. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @CacheResult(cacheName="books", **exceptionCacheName="failures"** + **cachedExceptions = InvalidIsbnNotFoundException.class**) + public Book findBook(ISBN isbn) +---- + + +==== Enabling JSR-107 support + +Nothing specific needs to be done to enable the JSR-107 support alongside Spring's +declarative annotation support. Both `@EnableCaching` and the +`cache:annotation-driven` element will enable automatically the JCache support +if both the JSR-107 API and the `spring-context-support` module are present in +the classpath. + +[NOTE] +==== +Depending of your use case, the choice is basically yours. You can even mix +and match services using the JSR-107 API and others using Spring's own +annotations. Be aware however that if these services are impacting the same +caches, a consistent and identical key generation implementation should be used. +==== + + +[[cache-declarative-xml]] +=== Declarative XML-based caching +If annotations are not an option (no access to the sources or no external code), one can +use XML for declarative caching. So instead of annotating the methods for caching, one +specifies the target method and the caching directives externally (similar to the +declarative transaction management <>). +The previous example can be translated into: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + + + + + + + + + + +---- + +In the configuration above, the `bookService` is made cacheable. The caching semantics +to apply are encapsulated in the `cache:advice` definition which instructs method +`findBooks` to be used for putting data into the cache while method `loadBooks` for +evicting data. Both definitions are working against the `books` cache. + +The `aop:config` definition applies the cache advice to the appropriate points in the +program by using the AspectJ pointcut expression (more information is available in +<>). In the example above, all methods from the `BookService` are considered and +the cache advice applied to them. + +The declarative XML caching supports all of the annotation-based model so moving between +the two should be fairly easy - further more both can be used inside the same +application. The XML based approach does not touch the target code however it is +inherently more verbose; when dealing with classes with overloaded methods that are +targeted for caching, identifying the proper methods does take an extra effort since the +`method` argument is not a good discriminator - in these cases, the AspectJ pointcut can +be used to cherry pick the target methods and apply the appropriate caching +functionality. However through XML, it is easier to apply a package/group/interface-wide +caching (again due to the AspectJ pointcut) and to create template-like definitions (as +we did in the example above by defining the target cache through the `cache:definitions` +`cache` attribute). + + + + +[[cache-store-configuration]] +=== Configuring the cache storage +Out of the box, the cache abstraction provides several storages integration. To use +them, one needs to simply declare an appropriate `CacheManager` - an entity that +controls and manages ++Cache++s and can be used to retrieve these for storage. + + +[[cache-store-configuration-jdk]] +==== JDK ConcurrentMap-based Cache + +The JDK-based `Cache` implementation resides under +`org.springframework.cache.concurrent` package. It allows one to use `ConcurrentHashMap` +as a backing `Cache` store. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + + +---- + +The snippet above uses the `SimpleCacheManager` to create a `CacheManager` for the two +nested `ConcurrentMapCache` instances named __default__ and __books__. Note that the +names are configured directly for each cache. + +As the cache is created by the application, it is bound to its lifecycle, making it +suitable for basic use cases, tests or simple applications. The cache scales well and is +very fast but it does not provide any management or persistence capabilities nor +eviction contracts. + + + +[[cache-store-configuration-ehcache]] +==== EhCache-based Cache + +The EhCache implementation is located under `org.springframework.cache.ehcache` package. +Again, to use it, one simply needs to declare the appropriate `CacheManager`: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + +---- + +This setup bootstraps the ehcache library inside Spring IoC (through the `ehcache` bean) which +is then wired into the dedicated `CacheManager` implementation. Note the entire +ehcache-specific configuration is read from `ehcache.xml`. + +[[cache-store-configuration-guava]] +==== Guava Cache + +The Guava implementation is located under `org.springframework.cache.guava` package and +provides access to several features of Guava. + +Configuring a `CacheManager` that creates the cache on demand is straightforward: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + +---- + +It is also possible to provide the caches to use explicitly. In that case, only those +will be made available by the manager: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + default + books + + + +---- + +The Guava `CacheManager` also supports customs `CacheBuilder` and `CacheLoader`. See +the https://code.google.com/p/guava-libraries/wiki/CachesExplained[Guava documentation] +for more information about those. + +[[cache-store-configuration-gemfire]] +==== GemFire-based Cache + +GemFire is a memory-oriented/disk-backed, elastically scalable, continuously available, +active (with built-in pattern-based subscription notifications), globally replicated +database and provides fully-featured edge caching. For further information on how to use +GemFire as a CacheManager (and more), please refer to the +http://docs.spring.io/spring-gemfire/docs/current/reference/htmlsingle/[Spring Data GemFire +reference documentation]. + +[[cache-store-configuration-jsr107]] +==== JSR-107 Cache + +JSR-107 compliant caches can also be used by Spring's caching abstraction. The JCache +implementation is located under `org.springframework.cache.jcache` package. + +Again, to use it, one simply needs to declare the appropriate `CacheManager`: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + +---- + + +[[cache-store-configuration-noop]] +==== Dealing with caches without a backing store +Sometimes when switching environments or doing testing, one might have cache +declarations without an actual backing cache configured. As this is an invalid +configuration, at runtime an exception will be thrown since the caching infrastructure +is unable to find a suitable store. In situations like this, rather then removing the +cache declarations (which can prove tedious), one can wire in a simple, dummy cache that +performs no caching - that is, forces the cached methods to be executed every time: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + + +---- + +The `CompositeCacheManager` above chains multiple ++CacheManager++s and additionally, +through the `fallbackToNoOpCache` flag, adds a __no op__ cache that for all the +definitions not handled by the configured cache managers. That is, every cache +definition not found in either `jdkCache` or `gemfireCache` (configured above) will be +handled by the no op cache, which will not store any information causing the target +method to be executed every time. + + + + +[[cache-plug]] +=== Plugging-in different back-end caches +Clearly there are plenty of caching products out there that can be used as a backing +store. To plug them in, one needs to provide a `CacheManager` and `Cache` implementation +since unfortunately there is no available standard that we can use instead. This may +sound harder than it is since in practice, the classes tend to be simple +http://en.wikipedia.org/wiki/Adapter_pattern[adapter]s that map the caching abstraction +framework on top of the storage API as the `ehcache` classes can show. Most +`CacheManager` classes can use the classes in `org.springframework.cache.support` +package, such as `AbstractCacheManager` which takes care of the boiler-plate code +leaving only the actual __mapping__ to be completed. We hope that in time, the libraries +that provide integration with Spring can fill in this small configuration gap. + + + + +[[cache-specific-config]] +=== How can I set the TTL/TTI/Eviction policy/XXX feature? +Directly through your cache provider. The cache abstraction is... well, an abstraction +not a cache implementation. The solution you are using might support various data +policies and different topologies which other solutions do not (take for example the JDK +`ConcurrentHashMap`) - exposing that in the cache abstraction would be useless simply +because there would no backing support. Such functionality should be controlled directly +through the backing cache, when configuring it or through its native API. + + diff --git a/src/asciidoc/cci.adoc b/src/asciidoc/cci.adoc new file mode 100644 index 000000000000..e69d8969d186 --- /dev/null +++ b/src/asciidoc/cci.adoc @@ -0,0 +1,1155 @@ +[[cci]] +== JCA CCI + + + + +[[cci-introduction]] +=== Introduction +Java EE provides a specification to standardize access to enterprise information systems +(EIS): the JCA (Java EE Connector Architecture). This specification is divided into +several different parts: + +* SPI (Service provider interfaces) that the connector provider must implement. These + interfaces constitute a resource adapter which can be deployed on a Java EE + application server. In such a scenario, the server manages connection pooling, + transaction and security (managed mode). The application server is also responsible + for managing the configuration, which is held outside the client application. A + connector can be used without an application server as well; in this case, the + application must configure it directly (non-managed mode). +* CCI (Common Client Interface) that an application can use to interact with the + connector and thus communicate with an EIS. An API for local transaction demarcation + is provided as well. + +The aim of the Spring CCI support is to provide classes to access a CCI connector in +typical Spring style, leveraging the Spring Framework's general resource and transaction +management facilities. + +[NOTE] +==== +The client side of connectors doesn't alway use CCI. Some connectors expose their own +APIs, only providing JCA resource adapter to use the system contracts of a Java EE +container (connection pooling, global transactions, security). Spring does not offer +special support for such connector-specific APIs. +==== + + + + +[[cci-config]] +=== Configuring CCI + + + +[[cci-config-connector]] +==== Connector configuration +The base resource to use JCA CCI is the `ConnectionFactory` interface. The connector +used must provide an implementation of this interface. + +To use your connector, you can deploy it on your application server and fetch the +`ConnectionFactory` from the server's JNDI environment (managed mode). The connector +must be packaged as a RAR file (resource adapter archive) and contain a `ra.xml` file to +describe its deployment characteristics. The actual name of the resource is specified +when you deploy it. To access it within Spring, simply use Spring's +`JndiObjectFactoryBean` / `` fetch the factory by its JNDI name. + +Another way to use a connector is to embed it in your application (non-managed mode), +not using an application server to deploy and configure it. Spring offers the +possibility to configure a connector as a bean, through a provided `FactoryBean` ( +`LocalConnectionFactoryBean`). In this manner, you only need the connector library in +the classpath (no RAR file and no `ra.xml` descriptor needed). The library must be +extracted from the connector's RAR file, if necessary. + +Once you have got access to your `ConnectionFactory` instance, you can inject it into +your components. These components can either be coded against the plain CCI API or +leverage Spring's support classes for CCI access (e.g. `CciTemplate`). + +[NOTE] +==== +When you use a connector in non-managed mode, you can't use global transactions because +the resource is never enlisted / delisted in the current global transaction of the +current thread. The resource is simply not aware of any global Java EE transactions that +might be running. +==== + + + +[[cci-config-connectionfactory]] +==== ConnectionFactory configuration in Spring + +In order to make connections to the EIS, you need to obtain a `ConnectionFactory` from +the application server if you are in a managed mode, or directly from Spring if you are +in a non-managed mode. + +In a managed mode, you access a `ConnectionFactory` from JNDI; its properties will be +configured in the application server. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + +---- + +In non-managed mode, you must configure the `ConnectionFactory` you want to use in the +configuration of Spring as a JavaBean. The `LocalConnectionFactoryBean` class offers +this setup style, passing in the `ManagedConnectionFactory` implementation of your +connector, exposing the application-level CCI `ConnectionFactory`. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + + +---- + +[NOTE] +==== +You can't directly instantiate a specific `ConnectionFactory`. You need to go through +the corresponding implementation of the `ManagedConnectionFactory` interface for your +connector. This interface is part of the JCA SPI specification. +==== + + + +[[cci-config-cci-connections]] +==== Configuring CCI connections +JCA CCI allow the developer to configure the connections to the EIS using the +`ConnectionSpec` implementation of your connector. In order to configure its properties, +you need to wrap the target connection factory with a dedicated adapter, +`ConnectionSpecConnectionFactoryAdapter`. So, the dedicated `ConnectionSpec` can be +configured with the property `connectionSpec` (as an inner bean). + +This property is not mandatory because the CCI `ConnectionFactory` interface defines two +different methods to obtain a CCI connection. Some of the `ConnectionSpec` properties +can often be configured in the application server (in managed mode) or on the +corresponding local `ManagedConnectionFactory` implementation. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public interface ConnectionFactory implements Serializable, Referenceable { + ... + Connection getConnection() throws ResourceException; + Connection getConnection(ConnectionSpec connectionSpec) throws ResourceException; + ... + } +---- + +Spring provides a `ConnectionSpecConnectionFactoryAdapter` that allows for specifying a +`ConnectionSpec` instance to use for all operations on a given factory. If the adapter's +`connectionSpec` property is specified, the adapter uses the `getConnection` variant +with the `ConnectionSpec` argument, otherwise the variant without argument. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + + + + + + + + + + + +---- + + + +[[cci-config-single-connection]] +==== Using a single CCI connection +If you want to use a single CCI connection, Spring provides a further +`ConnectionFactory` adapter to manage this. The `SingleConnectionFactory` adapter class +will open a single connection lazily and close it when this bean is destroyed at +application shutdown. This class will expose special `Connection` proxies that behave +accordingly, all sharing the same underlying physical connection. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + + + + + + +---- + +[NOTE] +==== +This `ConnectionFactory` adapter cannot directly be configured with a `ConnectionSpec`. +Use an intermediary `ConnectionSpecConnectionFactoryAdapter` that the +`SingleConnectionFactory` talks to if you require a single connection for a specific +`ConnectionSpec`. +==== + + + + +[[cci-using]] +=== Using Spring's CCI access support + + + +[[cci-record-creator]] +==== Record conversion +One of the aims of the JCA CCI support is to provide convenient facilities for +manipulating CCI records. The developer can specify the strategy to create records and +extract datas from records, for use with Spring's `CciTemplate`. The following +interfaces will configure the strategy to use input and output records if you don't want +to work with records directly in your application. + +In order to create an input `Record`, the developer can use a dedicated implementation +of the `RecordCreator` interface. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public interface RecordCreator { + + Record createRecord(RecordFactory recordFactory) throws ResourceException, DataAccessException; + + } +---- + +As you can see, the `createRecord(..)` method receives a `RecordFactory` instance as +parameter, which corresponds to the `RecordFactory` of the `ConnectionFactory` used. +This reference can be used to create `IndexedRecord` or `MappedRecord` instances. The +following sample shows how to use the `RecordCreator` interface and indexed/mapped +records. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class MyRecordCreator implements RecordCreator { + + public Record createRecord(RecordFactory recordFactory) throws ResourceException { + IndexedRecord input = recordFactory.createIndexedRecord("input"); + input.add(new Integer(id)); + return input; + } + + } +---- + +An output `Record` can be used to receive data back from the EIS. Hence, a specific +implementation of the `RecordExtractor` interface can be passed to Spring's +`CciTemplate` for extracting data from the output `Record`. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public interface RecordExtractor { + + Object extractData(Record record) throws ResourceException, SQLException, DataAccessException; + + } +---- + +The following sample shows how to use the `RecordExtractor` interface. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class MyRecordExtractor implements RecordExtractor { + + public Object extractData(Record record) throws ResourceException { + CommAreaRecord commAreaRecord = (CommAreaRecord) record; + String str = new String(commAreaRecord.toByteArray()); + String field1 = string.substring(0,6); + String field2 = string.substring(6,1); + return new OutputObject(Long.parseLong(field1), field2); + } + + } +---- + + + +[[cci-using-template]] +==== the CciTemplate + +The `CciTemplate` is the central class of the core CCI support package ( +`org.springframework.jca.cci.core`). It simplifies the use of CCI since it handles the +creation and release of resources. This helps to avoid common errors like forgetting to +always close the connection. It cares for the lifecycle of connection and interaction +objects, letting application code focus on generating input records from application +data and extracting application data from output records. + +The JCA CCI specification defines two distinct methods to call operations on an EIS. The +CCI `Interaction` interface provides two execute method signatures: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public interface javax.resource.cci.Interaction { + + ... + + boolean execute(InteractionSpec spec, Record input, Record output) throws ResourceException; + + Record execute(InteractionSpec spec, Record input) throws ResourceException; + + ... + + } +---- + +Depending on the template method called, `CciTemplate` will know which `execute` method +to call on the interaction. In any case, a correctly initialized `InteractionSpec` +instance is mandatory. + +`CciTemplate.execute(..)` can be used in two ways: + +* With direct `Record` arguments. In this case, you simply need to pass the CCI input + record in, and the returned object be the corresponding CCI output record. +* With application objects, using record mapping. In this case, you need to provide + corresponding `RecordCreator` and `RecordExtractor` instances. + +With the first approach, the following methods of the template will be used. These +methods directly correspond to those on the `Interaction` interface. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class CciTemplate implements CciOperations { + + public Record execute(InteractionSpec spec, Record inputRecord) + throws DataAccessException { ... } + + public void execute(InteractionSpec spec, Record inputRecord, Record outputRecord) + throws DataAccessException { ... } + + } +---- + +With the second approach, we need to specify the record creation and record extraction +strategies as arguments. The interfaces used are those describe in the previous section +on record conversion. The corresponding `CciTemplate` methods are the following: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class CciTemplate implements CciOperations { + + public Record execute(InteractionSpec spec, + RecordCreator inputCreator) throws DataAccessException { + // ... + } + + public Object execute(InteractionSpec spec, Record inputRecord, + RecordExtractor outputExtractor) throws DataAccessException { + // ... + } + + public Object execute(InteractionSpec spec, RecordCreator creator, + RecordExtractor extractor) throws DataAccessException { + // ... + } + + } +---- + +Unless the `outputRecordCreator` property is set on the template (see the following +section), every method will call the corresponding `execute` method of the CCI +`Interaction` with two parameters: `InteractionSpec` and input `Record`, receiving an +output `Record` as return value. + +`CciTemplate` also provides methods to create `IndexRecord` and `MappedRecord` outside a +`RecordCreator` implementation, through its `createIndexRecord(..)` and +`createMappedRecord(..)` methods. This can be used within DAO implementations to create +`Record` instances to pass into corresponding `CciTemplate.execute(..)` methods. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class CciTemplate implements CciOperations { + + public IndexedRecord createIndexedRecord(String name) throws DataAccessException { ... } + + public MappedRecord createMappedRecord(String name) throws DataAccessException { ... } + + } +---- + + + +[[cci-using-dao]] +==== DAO support +Spring's CCI support provides a abstract class for DAOs, supporting injection of a +`ConnectionFactory` or a `CciTemplate` instances. The name of the class is +`CciDaoSupport`: It provides simple `setConnectionFactory` and `setCciTemplate` methods. +Internally, this class will create a `CciTemplate` instance for a passed-in +`ConnectionFactory`, exposing it to concrete data access implementations in subclasses. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public abstract class CciDaoSupport { + + public void setConnectionFactory(ConnectionFactory connectionFactory) { + // ... + } + + public ConnectionFactory getConnectionFactory() { + // ... + } + + public void setCciTemplate(CciTemplate cciTemplate) { + // ... + } + + public CciTemplate getCciTemplate() { + // ... + } + + } +---- + + + +[[automatic-output-generation]] +==== Automatic output record generation +If the connector used only supports the `Interaction.execute(..)` method with input and +output records as parameters (that is, it requires the desired output record to be +passed in instead of returning an appropriate output record), you can set the +`outputRecordCreator` property of the `CciTemplate` to automatically generate an output +record to be filled by the JCA connector when the response is received. This record will +be then returned to the caller of the template. + +This property simply holds an implementation of the `RecordCreator` interface, used for +that purpose. The `RecordCreator` interface has already been discussed in +<>. The `outputRecordCreator` property must be directly specified on +the `CciTemplate`. This could be done in the application code like so: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + cciTemplate.setOutputRecordCreator(new EciOutputRecordCreator()); +---- + +Or (recommended) in the Spring configuration, if the `CciTemplate` is configured as a +dedicated bean instance: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + +---- + +[NOTE] +==== +As the `CciTemplate` class is thread-safe, it will usually be configured as a shared +instance. +==== + + + +[[template-summary]] +==== Summary +The following table summarizes the mechanisms of the `CciTemplate` class and the +corresponding methods called on the CCI `Interaction` interface: + +[[cci-interaction-execute-methods]] +.Usage of Interaction execute methods +[cols="3,1,3"] +|=== +| CciTemplate method signature| CciTemplate outputRecordCreator property| execute method called on the CCI Interaction + +| Record execute(InteractionSpec, Record) +| not set +| Record execute(InteractionSpec, Record) + +| Record execute(InteractionSpec, Record) +| set +| boolean execute(InteractionSpec, Record, Record) + +| void execute(InteractionSpec, Record, Record) +| not set +| void execute(InteractionSpec, Record, Record) + +| void execute(InteractionSpec, Record, Record) +| set +| void execute(InteractionSpec, Record, Record) + +| Record execute(InteractionSpec, RecordCreator) +| not set +| Record execute(InteractionSpec, Record) + +| Record execute(InteractionSpec, RecordCreator) +| set +| void execute(InteractionSpec, Record, Record) + +| Record execute(InteractionSpec, Record, RecordExtractor) +| not set +| Record execute(InteractionSpec, Record) + +| Record execute(InteractionSpec, Record, RecordExtractor) +| set +| void execute(InteractionSpec, Record, Record) + +| Record execute(InteractionSpec, RecordCreator, RecordExtractor) +| not set +| Record execute(InteractionSpec, Record) + +| Record execute(InteractionSpec, RecordCreator, RecordExtractor) +| set +| void execute(InteractionSpec, Record, Record) +|=== + + + +[[cci-straight]] +==== Using a CCI Connection and Interaction directly + +`CciTemplate` also offers the possibility to work directly with CCI connections and +interactions, in the same manner as `JdbcTemplate` and `JmsTemplate`. This is useful +when you want to perform multiple operations on a CCI connection or interaction, for +example. + +The interface `ConnectionCallback` provides a CCI `Connection` as argument, in order to +perform custom operations on it, plus the CCI `ConnectionFactory` which the `Connection` +was created with. The latter can be useful for example to get an associated +`RecordFactory` instance and create indexed/mapped records, for example. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public interface ConnectionCallback { + + Object doInConnection(Connection connection, ConnectionFactory connectionFactory) + throws ResourceException, SQLException, DataAccessException; + + } +---- + +The interface `InteractionCallback` provides the CCI `Interaction`, in order to perform +custom operations on it, plus the corresponding CCI `ConnectionFactory`. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public interface InteractionCallback { + + Object doInInteraction(Interaction interaction, ConnectionFactory connectionFactory) + throws ResourceException, SQLException, DataAccessException; + + } +---- + +[NOTE] +==== +`InteractionSpec` objects can either be shared across multiple template calls or newly +created inside every callback method. This is completely up to the DAO implementation. +==== + + + +[[cci-template-example]] +==== Example for CciTemplate usage + +In this section, the usage of the `CciTemplate` will be shown to acces to a CICS with +ECI mode, with the IBM CICS ECI connector. + +Firstly, some initializations on the CCI `InteractionSpec` must be done to specify which +CICS program to access and how to interact with it. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + ECIInteractionSpec interactionSpec = new ECIInteractionSpec(); + interactionSpec.setFunctionName("MYPROG"); + interactionSpec.setInteractionVerb(ECIInteractionSpec.SYNC_SEND_RECEIVE); +---- + +Then the program can use CCI via Spring's template and specify mappings between custom +objects and CCI `Records`. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class MyDaoImpl extends CciDaoSupport implements MyDao { + + public OutputObject getData(InputObject input) { + ECIInteractionSpec interactionSpec = ...; + + OutputObject output = (ObjectOutput) getCciTemplate().execute(interactionSpec, + new RecordCreator() { + public Record createRecord(RecordFactory recordFactory) throws ResourceException { + return new CommAreaRecord(input.toString().getBytes()); + } + }, + new RecordExtractor() { + public Object extractData(Record record) throws ResourceException { + CommAreaRecord commAreaRecord = (CommAreaRecord)record; + String str = new String(commAreaRecord.toByteArray()); + String field1 = string.substring(0,6); + String field2 = string.substring(6,1); + return new OutputObject(Long.parseLong(field1), field2); + } + }); + + return output; + } + } +---- + +As discussed previously, callbacks can be used to work directly on CCI connections or +interactions. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class MyDaoImpl extends CciDaoSupport implements MyDao { + + public OutputObject getData(InputObject input) { + ObjectOutput output = (ObjectOutput) getCciTemplate().execute( + new ConnectionCallback() { + public Object doInConnection(Connection connection, + ConnectionFactory factory) throws ResourceException { + + // do something... + + } + }); + } + return output; + } + + } +---- + +[NOTE] +==== +With a `ConnectionCallback`, the `Connection` used will be managed and closed by the +`CciTemplate`, but any interactions created on the connection must be managed by the +callback implementation. +==== + +For a more specific callback, you can implement an `InteractionCallback`. The passed-in +`Interaction` will be managed and closed by the `CciTemplate` in this case. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class MyDaoImpl extends CciDaoSupport implements MyDao { + + public String getData(String input) { + ECIInteractionSpec interactionSpec = ...; + String output = (String) getCciTemplate().execute(interactionSpec, + new InteractionCallback() { + public Object doInInteraction(Interaction interaction, + ConnectionFactory factory) throws ResourceException { + Record input = new CommAreaRecord(inputString.getBytes()); + Record output = new CommAreaRecord(); + interaction.execute(holder.getInteractionSpec(), input, output); + return new String(output.toByteArray()); + } + }); + return output; + } + + } +---- + +For the examples above, the corresponding configuration of the involved Spring beans +could look like this in non-managed mode: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + + + + + + + +---- + +In managed mode (that is, in a Java EE environment), the configuration could look as +follows: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + +---- + + + + +[[cci-object]] +=== Modeling CCI access as operation objects +The `org.springframework.jca.cci.object` package contains support classes that allow you +to access the EIS in a different style: through reusable operation objects, analogous to +Spring's JDBC operation objects (see JDBC chapter). This will usually encapsulate the +CCI API: an application-level input object will be passed to the operation object, so it +can construct the input record and then convert the received record data to an +application-level output object and return it. + +[NOTE] +==== +This approach is internally based on the `CciTemplate` class and the +`RecordCreator` / `RecordExtractor` interfaces, reusing the machinery of Spring's core +CCI support. +==== + + + +[[cci-object-mapping-record]] +==== MappingRecordOperation + +`MappingRecordOperation` essentially performs the same work as `CciTemplate`, but +represents a specific, pre-configured operation as an object. It provides two template +methods to specify how to convert an input object to a input record, and how to convert +an output record to an output object (record mapping): + +* `createInputRecord(..)` to specify how to convert an input object to an input `Record` +* `extractOutputData(..)` to specify how to extract an output object from an output + `Record` + +Here are the signatures of these methods: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public abstract class MappingRecordOperation extends EisOperation { + + ... + + protected abstract Record createInputRecord(RecordFactory recordFactory, + Object inputObject) throws ResourceException, DataAccessException { + // ... + } + + protected abstract Object extractOutputData(Record outputRecord) + throws ResourceException, SQLException, DataAccessException { + // ... + } + + ... + + } +---- + +Thereafter, in order to execute an EIS operation, you need to use a single execute +method, passing in an application-level input object and receiving an application-level +output object as result: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public abstract class MappingRecordOperation extends EisOperation { + + ... + + public Object execute(Object inputObject) throws DataAccessException { + } + + ... + } +---- + +As you can see, contrary to the `CciTemplate` class, this `execute(..)` method does not +have an `InteractionSpec` as argument. Instead, the `InteractionSpec` is global to the +operation. The following constructor must be used to instantiate an operation object +with a specific `InteractionSpec`: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + InteractionSpec spec = ...; + MyMappingRecordOperation eisOperation = new MyMappingRecordOperation(getConnectionFactory(), spec); + ... +---- + + + +[[cci-object-mapping-comm-area]] +==== MappingCommAreaOperation + +Some connectors use records based on a COMMAREA which represents an array of bytes +containing parameters to send to the EIS and data returned by it. Spring provides a +special operation class for working directly on COMMAREA rather than on records. The +`MappingCommAreaOperation` class extends the `MappingRecordOperation` class to provide +such special COMMAREA support. It implicitly uses the `CommAreaRecord` class as input +and output record type, and provides two new methods to convert an input object into an +input COMMAREA and the output COMMAREA into an output object. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public abstract class MappingCommAreaOperation extends MappingRecordOperation { + + ... + + protected abstract byte[] objectToBytes(Object inObject) + throws IOException, DataAccessException; + + protected abstract Object bytesToObject(byte[] bytes) + throws IOException, DataAccessException; + + ... + + } +---- + + + +[[cci-automatic-record-gen]] +==== Automatic output record generation +As every `MappingRecordOperation` subclass is based on CciTemplate internally, the same +way to automatically generate output records as with `CciTemplate` is available. Every +operation object provides a corresponding `setOutputRecordCreator(..)` method. For +further information, see <>. + + + +[[cci-object-summary]] +==== Summary +The operation object approach uses records in the same manner as the `CciTemplate` class. + +[[cci-interaction-methods]] +.Usage of Interaction execute methods +[cols="3,1,3"] +|=== +| MappingRecordOperation method signature| MappingRecordOperation outputRecordCreator property| execute method called on the CCI Interaction + +| Object execute(Object) +| not set +| Record execute(InteractionSpec, Record) + +| Object execute(Object) +| set +| boolean execute(InteractionSpec, Record, Record) +|=== + + + +[[cci-objects-mappring-record-example]] +==== Example for MappingRecordOperation usage + +In this section, the usage of the `MappingRecordOperation` will be shown to access a +database with the Blackbox CCI connector. + +[NOTE] +==== +The original version of this connector is provided by the Java EE SDK (version 1.3), +available from Oracle. +==== + +Firstly, some initializations on the CCI `InteractionSpec` must be done to specify which +SQL request to execute. In this sample, we directly define the way to convert the +parameters of the request to a CCI record and the way to convert the CCI result record +to an instance of the `Person` class. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class PersonMappingOperation extends MappingRecordOperation { + + public PersonMappingOperation(ConnectionFactory connectionFactory) { + setConnectionFactory(connectionFactory); + CciInteractionSpec interactionSpec = new CciConnectionSpec(); + interactionSpec.setSql("select * from person where person_id=?"); + setInteractionSpec(interactionSpec); + } + + protected Record createInputRecord(RecordFactory recordFactory, + Object inputObject) throws ResourceException { + Integer id = (Integer) inputObject; + IndexedRecord input = recordFactory.createIndexedRecord("input"); + input.add(new Integer(id)); + return input; + } + + protected Object extractOutputData(Record outputRecord) + throws ResourceException, SQLException { + ResultSet rs = (ResultSet) outputRecord; + Person person = null; + if (rs.next()) { + Person person = new Person(); + person.setId(rs.getInt("person_id")); + person.setLastName(rs.getString("person_last_name")); + person.setFirstName(rs.getString("person_first_name")); + } + return person; + } + } +---- + +Then the application can execute the operation object, with the person identifier as +argument. Note that operation object could be set up as shared instance, as it is +thread-safe. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class MyDaoImpl extends CciDaoSupport implements MyDao { + + public Person getPerson(int id) { + PersonMappingOperation query = new PersonMappingOperation(getConnectionFactory()); + Person person = (Person) query.execute(new Integer(id)); + return person; + } + } +---- + +The corresponding configuration of Spring beans could look as follows in non-managed mode: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + + + + + + + + + + + + + + + +---- + +In managed mode (that is, in a Java EE environment), the configuration could look as +follows: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + + + + + + + + +---- + + + +[[cci-objects-mapping-comm-area-example]] +==== Example for MappingCommAreaOperation usage + +In this section, the usage of the `MappingCommAreaOperation` will be shown: accessing a +CICS with ECI mode with the IBM CICS ECI connector. + +Firstly, the CCI `InteractionSpec` needs to be initialized to specify which CICS program +to access and how to interact with it. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public abstract class EciMappingOperation extends MappingCommAreaOperation { + + public EciMappingOperation(ConnectionFactory connectionFactory, String programName) { + setConnectionFactory(connectionFactory); + ECIInteractionSpec interactionSpec = new ECIInteractionSpec(), + interactionSpec.setFunctionName(programName); + interactionSpec.setInteractionVerb(ECIInteractionSpec.SYNC_SEND_RECEIVE); + interactionSpec.setCommareaLength(30); + setInteractionSpec(interactionSpec); + setOutputRecordCreator(new EciOutputRecordCreator()); + } + + private static class EciOutputRecordCreator implements RecordCreator { + public Record createRecord(RecordFactory recordFactory) throws ResourceException { + return new CommAreaRecord(); + } + } + + } +---- + +The abstract `EciMappingOperation` class can then be subclassed to specify mappings +between custom objects and `Records`. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class MyDaoImpl extends CciDaoSupport implements MyDao { + + public OutputObject getData(Integer id) { + EciMappingOperation query = new EciMappingOperation(getConnectionFactory(), "MYPROG") { + + protected abstract byte[] objectToBytes(Object inObject) throws IOException { + Integer id = (Integer) inObject; + return String.valueOf(id); + } + + protected abstract Object bytesToObject(byte[] bytes) throws IOException; + String str = new String(bytes); + String field1 = str.substring(0,6); + String field2 = str.substring(6,1); + String field3 = str.substring(7,1); + return new OutputObject(field1, field2, field3); + } + }); + + return (OutputObject) query.execute(new Integer(id)); + } + + } +---- + +The corresponding configuration of Spring beans could look as follows in non-managed mode: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + + + + + + + +---- + +In managed mode (that is, in a Java EE environment), the configuration could look as +follows: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + +---- + + + + +[[cci-tx]] +=== Transactions +JCA specifies several levels of transaction support for resource adapters. The kind of +transactions that your resource adapter supports is specified in its `ra.xml` file. +There are essentially three options: none (for example with CICS EPI connector), local +transactions (for example with a CICS ECI connector), global transactions (for example +with an IMS connector). + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + XATransaction + + +---- + +For global transactions, you can use Spring's generic transaction infrastructure to +demarcate transactions, with `JtaTransactionManager` as backend (delegating to the Java +EE server's distributed transaction coordinator underneath). + +For local transactions on a single CCI `ConnectionFactory`, Spring provides a specific +transaction management strategy for CCI, analogous to the `DataSourceTransactionManager` +for JDBC. The CCI API defines a local transaction object and corresponding local +transaction demarcation methods. Spring's `CciLocalTransactionManager` executes such +local CCI transactions, fully compliant with Spring's generic +`PlatformTransactionManager` abstraction. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + +---- + +Both transaction strategies can be used with any of Spring's transaction demarcation +facilities, be it declarative or programmatic. This is a consequence of Spring's generic +`PlatformTransactionManager` abstraction, which decouples transaction demarcation from +the actual execution strategy. Simply switch between `JtaTransactionManager` and +`CciLocalTransactionManager` as needed, keeping your transaction demarcation as-is. + +For more information on Spring's transaction facilities, see the chapter entitled +<>. + + + diff --git a/src/asciidoc/classic-aop-spring.adoc b/src/asciidoc/classic-aop-spring.adoc new file mode 100644 index 000000000000..b90634e5fed4 --- /dev/null +++ b/src/asciidoc/classic-aop-spring.adoc @@ -0,0 +1,1768 @@ +[[classic-aop-spring]] +== Classic Spring AOP Usage +In this appendix we discuss the lower-level Spring AOP APIs and the AOP support used in +Spring 1.2 applications. For new applications, we recommend the use of the Spring 2.0 +AOP support described in the <> chapter, but when working with existing +applications, or when reading books and articles, you may come across Spring 1.2 style +examples. Spring 2.0 is fully backwards compatible with Spring 1.2 and everything +described in this appendix is fully supported in Spring 2.0. + + + + +[[classic-aop-api-pointcuts]] +=== Pointcut API in Spring +Let's look at how Spring handles the crucial pointcut concept. + + + +[[classic-aop-api-concepts]] +==== Concepts +Spring's pointcut model enables pointcut reuse independent of advice types. It's +possible to target different advice using the same pointcut. + +The `org.springframework.aop.Pointcut` interface is the central interface, used to +target advices to particular classes and methods. The complete interface is shown below: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public interface Pointcut { + + ClassFilter getClassFilter(); + + MethodMatcher getMethodMatcher(); + + } +---- + +Splitting the `Pointcut` interface into two parts allows reuse of class and method +matching parts, and fine-grained composition operations (such as performing a "union" +with another method matcher). + +The `ClassFilter` interface is used to restrict the pointcut to a given set of target +classes. If the `matches()` method always returns true, all target classes will be +matched: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public interface ClassFilter { + + boolean matches(Class clazz); + + } +---- + +The `MethodMatcher` interface is normally more important. The complete interface is +shown below: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public interface MethodMatcher { + + boolean matches(Method m, Class targetClass); + + boolean isRuntime(); + + boolean matches(Method m, Class targetClass, Object[] args); + + } +---- + +The `matches(Method, Class)` method is used to test whether this pointcut will ever +match a given method on a target class. This evaluation can be performed when an AOP +proxy is created, to avoid the need for a test on every method invocation. If the +2-argument matches method returns true for a given method, and the `isRuntime()` method +for the MethodMatcher returns true, the 3-argument matches method will be invoked on +every method invocation. This enables a pointcut to look at the arguments passed to the +method invocation immediately before the target advice is to execute. + +Most MethodMatchers are static, meaning that their `isRuntime()` method returns false. +In this case, the 3-argument matches method will never be invoked. + +[TIP] +==== + +If possible, try to make pointcuts static, allowing the AOP framework to cache the +results of pointcut evaluation when an AOP proxy is created. +==== + + + +[[classic-aop-api-pointcut-ops]] +==== Operations on pointcuts +Spring supports operations on pointcuts: notably, __union__ and __intersection__. + +* Union means the methods that either pointcut matches. +* Intersection means the methods that both pointcuts match. +* Union is usually more useful. +* Pointcuts can be composed using the static methods in the + __org.springframework.aop.support.Pointcuts__ class, or using the + __ComposablePointcut__ class in the same package. However, using AspectJ pointcut + expressions is usually a simpler approach. + + + +[[classic-aop-api-pointcuts-aspectj]] +==== AspectJ expression pointcuts +Since 2.0, the most important type of pointcut used by Spring is +`org.springframework.aop.aspectj.AspectJExpressionPointcut`. This is a pointcut that +uses an AspectJ supplied library to parse an AspectJ pointcut expression string. + +See the previous chapter for a discussion of supported AspectJ pointcut primitives. + + + +[[classic-aop-api-pointcuts-impls]] +==== Convenience pointcut implementations +Spring provides several convenient pointcut implementations. Some can be used out of the +box; others are intended to be subclassed in application-specific pointcuts. + + +[[classic-aop-api-pointcuts-static]] +===== Static pointcuts +Static pointcuts are based on method and target class, and cannot take into account the +method's arguments. Static pointcuts are sufficient - __and best__ - for most usages. +It's possible for Spring to evaluate a static pointcut only once, when a method is first +invoked: after that, there is no need to evaluate the pointcut again with each method +invocation. + +Let's consider some static pointcut implementations included with Spring. + +[[classic-aop-api-pointcuts-regex]] +====== Regular expression pointcuts +One obvious way to specify static pointcuts is regular expressions. Several AOP +frameworks besides Spring make this possible. +`org.springframework.aop.support.Perl5RegexpMethodPointcut` is a generic regular +expression pointcut, using Perl 5 regular expression syntax. The +`Perl5RegexpMethodPointcut` class depends on Jakarta ORO for regular expression +matching. Spring also provides the `JdkRegexpMethodPointcut` class that uses the regular +expression support in JDK 1.4+. + +Using the `Perl5RegexpMethodPointcut` class, you can provide a list of pattern Strings. +If any of these is a match, the pointcut will evaluate to true. (So the result is +effectively the union of these pointcuts.) + +The usage is shown below: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + .*set.* + .*absquatulate + + + +---- + +Spring provides a convenience class, `RegexpMethodPointcutAdvisor`, that allows us to +also reference an Advice (remember that an Advice can be an interceptor, before advice, +throws advice etc.). Behind the scenes, Spring will use a `JdkRegexpMethodPointcut`. +Using `RegexpMethodPointcutAdvisor` simplifies wiring, as the one bean encapsulates both +pointcut and advice, as shown below: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + .*set.* + .*absquatulate + + + +---- + +__RegexpMethodPointcutAdvisor__ can be used with any Advice type. + +[[classic-aop-api-pointcuts-attribute-driven]] +====== Attribute-driven pointcuts +An important type of static pointcut is a __metadata-driven__ pointcut. This uses the +values of metadata attributes: typically, source-level metadata. + + +[[classic-aop-api-pointcuts-dynamic]] +===== Dynamic pointcuts +Dynamic pointcuts are costlier to evaluate than static pointcuts. They take into account +method__arguments__, as well as static information. This means that they must be +evaluated with every method invocation; the result cannot be cached, as arguments will +vary. + +The main example is the `control flow` pointcut. + +[[classic-aop-api-pointcuts-cflow]] +====== Control flow pointcuts +Spring control flow pointcuts are conceptually similar to AspectJ __cflow__ pointcuts, +although less powerful. (There is currently no way to specify that a pointcut executes +below a join point matched by another pointcut.) A control flow pointcut matches the +current call stack. For example, it might fire if the join point was invoked by a method +in the `com.mycompany.web` package, or by the `SomeCaller` class. Control flow pointcuts +are specified using the `org.springframework.aop.support.ControlFlowPointcut` class. +[NOTE] +==== +Control flow pointcuts are significantly more expensive to evaluate at runtime than even +other dynamic pointcuts. In Java 1.4, the cost is about 5 times that of other dynamic +pointcuts. +==== + + + +[[classic-aop-api-pointcuts-superclasses]] +==== Pointcut superclasses +Spring provides useful pointcut superclasses to help you to implement your own pointcuts. + +Because static pointcuts are most useful, you'll probably subclass +StaticMethodMatcherPointcut, as shown below. This requires implementing just one +abstract method (although it's possible to override other methods to customize behavior): + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + class TestStaticPointcut extends StaticMethodMatcherPointcut { + + public boolean matches(Method m, Class targetClass) { + // return true if custom criteria match + } + + } +---- + +There are also superclasses for dynamic pointcuts. + +You can use custom pointcuts with any advice type in Spring 1.0 RC2 and above. + + + +[[classic-aop-api-pointcuts-custom]] +==== Custom pointcuts +Because pointcuts in Spring AOP are Java classes, rather than language features (as in +AspectJ) it's possible to declare custom pointcuts, whether static or dynamic. Custom +pointcuts in Spring can be arbitrarily complex. However, using the AspectJ pointcut +expression language is recommended if possible. + +[NOTE] +==== +Later versions of Spring may offer support for "semantic pointcuts" as offered by JAC: +for example, "all methods that change instance variables in the target object." +==== + + + + +[[classic-aop-api-advice]] +=== Advice API in Spring +Let's now look at how Spring AOP handles advice. + + + +[[classic-aop-api-advice-lifecycle]] +==== Advice lifecycles +Each advice is a Spring bean. An advice instance can be shared across all advised +objects, or unique to each advised object. This corresponds to __per-class__ or +__per-instance__ advice. + +Per-class advice is used most often. It is appropriate for generic advice such as +transaction advisors. These do not depend on the state of the proxied object or add new +state; they merely act on the method and arguments. + +Per-instance advice is appropriate for introductions, to support mixins. In this case, +the advice adds state to the proxied object. + +It's possible to use a mix of shared and per-instance advice in the same AOP proxy. + + + +[[classic-aop-api-advice-types]] +==== Advice types in Spring +Spring provides several advice types out of the box, and is extensible to support +arbitrary advice types. Let us look at the basic concepts and standard advice types. + + +[[classic-aop-api-advice-around]] +===== Interception around advice +The most fundamental advice type in Spring is __interception around advice__. + +Spring is compliant with the AOP Alliance interface for around advice using method +interception. MethodInterceptors implementing around advice should implement the +following interface: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public interface MethodInterceptor extends Interceptor { + + Object invoke(MethodInvocation invocation) throws Throwable; + + } +---- + +The `MethodInvocation` argument to the `invoke()` method exposes the method being +invoked; the target join point; the AOP proxy; and the arguments to the method. The +`invoke()` method should return the invocation's result: the return value of the join +point. + +A simple `MethodInterceptor` implementation looks as follows: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class DebugInterceptor implements MethodInterceptor { + + public Object invoke(MethodInvocation invocation) throws Throwable { + System.out.println("Before: invocation=[" + invocation + "]"); + Object rval = invocation.proceed(); + System.out.println("Invocation returned"); + return rval; + } + + } +---- + +Note the call to the MethodInvocation's `proceed()` method. This proceeds down the +interceptor chain towards the join point. Most interceptors will invoke this method, and +return its return value. However, a MethodInterceptor, like any around advice, can +return a different value or throw an exception rather than invoke the proceed method. +However, you don't want to do this without good reason! + +[NOTE] +==== +MethodInterceptors offer interoperability with other AOP Alliance-compliant AOP +implementations. The other advice types discussed in the remainder of this section +implement common AOP concepts, but in a Spring-specific way. While there is an advantage +in using the most specific advice type, stick with MethodInterceptor around advice if +you are likely to want to run the aspect in another AOP framework. Note that pointcuts +are not currently interoperable between frameworks, and the AOP Alliance does not +currently define pointcut interfaces. +==== + + +[[classic-aop-api-advice-before]] +===== Before advice +A simpler advice type is a __before advice__. This does not need a `MethodInvocation` +object, since it will only be called before entering the method. + +The main advantage of a before advice is that there is no need to invoke the `proceed()` +method, and therefore no possibility of inadvertently failing to proceed down the +interceptor chain. + +The `MethodBeforeAdvice` interface is shown below. (Spring's API design would allow for +field before advice, although the usual objects apply to field interception and it's +unlikely that Spring will ever implement it). + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public interface MethodBeforeAdvice extends BeforeAdvice { + + void before(Method m, Object[] args, Object target) throws Throwable; + + } +---- + +Note the return type is `void`. Before advice can insert custom behavior before the join +point executes, but cannot change the return value. If a before advice throws an +exception, this will abort further execution of the interceptor chain. The exception +will propagate back up the interceptor chain. If it is unchecked, or on the signature of +the invoked method, it will be passed directly to the client; otherwise it will be +wrapped in an unchecked exception by the AOP proxy. + +An example of a before advice in Spring, which counts all method invocations: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class CountingBeforeAdvice implements MethodBeforeAdvice { + + private int count; + + public void before(Method m, Object[] args, Object target) throws Throwable { + ++count; + } + + public int getCount() { + return count; + } + } +---- + +[TIP] +==== + +Before advice can be used with any pointcut. +==== + + +[[classic-aop-api-advice-throws]] +===== Throws advice +__Throws advice__ is invoked after the return of the join point if the join point threw +an exception. Spring offers typed throws advice. Note that this means that the +`org.springframework.aop.ThrowsAdvice` interface does not contain any methods: It is a +tag interface identifying that the given object implements one or more typed throws +advice methods. These should be in the form of: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + afterThrowing([Method, args, target], subclassOfThrowable) +---- + +Only the last argument is required. The method signatures may have either one or four +arguments, depending on whether the advice method is interested in the method and +arguments. The following classes are examples of throws advice. + +The advice below is invoked if a `RemoteException` is thrown (including subclasses): + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class RemoteThrowsAdvice implements ThrowsAdvice { + + public void afterThrowing(RemoteException ex) throws Throwable { + // Do something with remote exception + } + + } +---- + +The following advice is invoked if a `ServletException` is thrown. Unlike the above +advice, it declares 4 arguments, so that it has access to the invoked method, method +arguments and target object: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class ServletThrowsAdviceWithArguments implements ThrowsAdvice { + + public void afterThrowing(Method m, Object[] args, Object target, ServletException ex) { + // Do something with all arguments + } + + } +---- + +The final example illustrates how these two methods could be used in a single class, +which handles both `RemoteException` and `ServletException`. Any number of throws advice +methods can be combined in a single class. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public static class CombinedThrowsAdvice implements ThrowsAdvice { + + public void afterThrowing(RemoteException ex) throws Throwable { + // Do something with remote exception + } + + public void afterThrowing(Method m, Object[] args, Object target, ServletException ex) { + // Do something with all arguments + } + } +---- + +__Note:__ If a throws-advice method throws an exception itself, it will override the +original exception (i.e. change the exception thrown to the user). The overriding +exception will typically be a RuntimeException; this is compatible with any method +signature. However, if a throws-advice method throws a checked exception, it will have +to match the declared exceptions of the target method and is hence to some degree +coupled to specific target method signatures. __Do not throw an undeclared checked +exception that is incompatible with the target method's signature!__ + +[TIP] +==== + +Throws advice can be used with any pointcut. +==== + + +[[classic-aop-api-advice-after-returning]] +===== After Returning advice +An after returning advice in Spring must implement the +__org.springframework.aop.AfterReturningAdvice__ interface, shown below: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public interface AfterReturningAdvice extends Advice { + + void afterReturning(Object returnValue, Method m, Object[] args, + Object target) throws Throwable; + + } +---- + +An after returning advice has access to the return value (which it cannot modify), +invoked method, methods arguments and target. + +The following after returning advice counts all successful method invocations that have +not thrown exceptions: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class CountingAfterReturningAdvice implements AfterReturningAdvice { + + private int count; + + public void afterReturning(Object returnValue, Method m, Object[] args, + Object target) throws Throwable { + ++count; + } + + public int getCount() { + return count; + } + + } +---- + +This advice doesn't change the execution path. If it throws an exception, this will be +thrown up the interceptor chain instead of the return value. + +[TIP] +==== + +After returning advice can be used with any pointcut. +==== + + +[[classic-aop-api-advice-introduction]] +===== Introduction advice +Spring treats introduction advice as a special kind of interception advice. + +Introduction requires an `IntroductionAdvisor`, and an `IntroductionInterceptor`, +implementing the following interface: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public interface IntroductionInterceptor extends MethodInterceptor { + + boolean implementsInterface(Class intf); + + } +---- + +The `invoke()` method inherited from the AOP Alliance `MethodInterceptor` interface must +implement the introduction: that is, if the invoked method is on an introduced +interface, the introduction interceptor is responsible for handling the method call - it +cannot invoke `proceed()`. + +Introduction advice cannot be used with any pointcut, as it applies only at class, +rather than method, level. You can only use introduction advice with the +`IntroductionAdvisor`, which has the following methods: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public interface IntroductionAdvisor extends Advisor, IntroductionInfo { + + ClassFilter getClassFilter(); + + void validateInterfaces() throws IllegalArgumentException; + + } + + public interface IntroductionInfo { + + Class[] getInterfaces(); + + } +---- + +There is no `MethodMatcher`, and hence no `Pointcut`, associated with introduction +advice. Only class filtering is logical. + +The `getInterfaces()` method returns the interfaces introduced by this advisor. + +The `validateInterfaces()` method is used internally to see whether or not the +introduced interfaces can be implemented by the configured `IntroductionInterceptor`. + +Let's look at a simple example from the Spring test suite. Let's suppose we want to +introduce the following interface to one or more objects: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public interface Lockable { + + void lock(); + + void unlock(); + + boolean locked(); + + } +---- + +This illustrates a __mixin__. We want to be able to cast advised objects to Lockable, +whatever their type, and call lock and unlock methods. If we call the lock() method, we +want all setter methods to throw a `LockedException`. Thus we can add an aspect that +provides the ability to make objects immutable, without them having any knowledge of it: +a good example of AOP. + +Firstly, we'll need an `IntroductionInterceptor` that does the heavy lifting. In this +case, we extend the `org.springframework.aop.support.DelegatingIntroductionInterceptor` +convenience class. We could implement IntroductionInterceptor directly, but using +`DelegatingIntroductionInterceptor` is best for most cases. + +The `DelegatingIntroductionInterceptor` is designed to delegate an introduction to an +actual implementation of the introduced interface(s), concealing the use of interception +to do so. The delegate can be set to any object using a constructor argument; the +default delegate (when the no-arg constructor is used) is this. Thus in the example +below, the delegate is the `LockMixin` subclass of `DelegatingIntroductionInterceptor`. +Given a delegate (by default itself), a `DelegatingIntroductionInterceptor` instance +looks for all interfaces implemented by the delegate (other than +IntroductionInterceptor), and will support introductions against any of them. It's +possible for subclasses such as `LockMixin` to call the `suppressInterface(Class intf)` +method to suppress interfaces that should not be exposed. However, no matter how many +interfaces an `IntroductionInterceptor` is prepared to support, the +`IntroductionAdvisor` used will control which interfaces are actually exposed. An +introduced interface will conceal any implementation of the same interface by the target. + +Thus LockMixin subclasses `DelegatingIntroductionInterceptor` and implements Lockable +itself. The superclass automatically picks up that Lockable can be supported for +introduction, so we don't need to specify that. We could introduce any number of +interfaces in this way. + +Note the use of the `locked` instance variable. This effectively adds additional state +to that held in the target object. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class LockMixin extends DelegatingIntroductionInterceptor implements Lockable { + + private boolean locked; + + public void lock() { + this.locked = true; + } + + public void unlock() { + this.locked = false; + } + + public boolean locked() { + return this.locked; + } + + public Object invoke(MethodInvocation invocation) throws Throwable { + if (locked() && invocation.getMethod().getName().indexOf("set") == 0) { + throw new LockedException(); + } + return super.invoke(invocation); + } + + } +---- + +Often it isn't necessary to override the `invoke()` method: the +`DelegatingIntroductionInterceptor` implementation - which calls the delegate method if +the method is introduced, otherwise proceeds towards the join point - is usually +sufficient. In the present case, we need to add a check: no setter method can be invoked +if in locked mode. + +The introduction advisor required is simple. All it needs to do is hold a distinct +`LockMixin` instance, and specify the introduced interfaces - in this case, just +`Lockable`. A more complex example might take a reference to the introduction +interceptor (which would be defined as a prototype): in this case, there's no +configuration relevant for a `LockMixin`, so we simply create it using `new`. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class LockMixinAdvisor extends DefaultIntroductionAdvisor { + + public LockMixinAdvisor() { + super(new LockMixin(), Lockable.class); + } + + } +---- + +We can apply this advisor very simply: it requires no configuration. (However, it __is__ +necessary: It's impossible to use an `IntroductionInterceptor` without an +__IntroductionAdvisor__.) As usual with introductions, the advisor must be per-instance, +as it is stateful. We need a different instance of `LockMixinAdvisor`, and hence +`LockMixin`, for each advised object. The advisor comprises part of the advised object's +state. + +We can apply this advisor programmatically, using the `Advised.addAdvisor()` method, or +(the recommended way) in XML configuration, like any other advisor. All proxy creation +choices discussed below, including "auto proxy creators," correctly handle introductions +and stateful mixins. + + + + +[[classic-aop-api-advisor]] +=== Advisor API in Spring +In Spring, an Advisor is an aspect that contains just a single advice object associated +with a pointcut expression. + +Apart from the special case of introductions, any advisor can be used with any advice. +`org.springframework.aop.support.DefaultPointcutAdvisor` is the most commonly used +advisor class. For example, it can be used with a `MethodInterceptor`, `BeforeAdvice` or +`ThrowsAdvice`. + +It is possible to mix advisor and advice types in Spring in the same AOP proxy. For +example, you could use a interception around advice, throws advice and before advice in +one proxy configuration: Spring will automatically create the necessary interceptor +chain. + + + + +[[classic-aop-pfb]] +=== Using the ProxyFactoryBean to create AOP proxies +If you're using the Spring IoC container (an ApplicationContext or BeanFactory) for your +business objects - and you should be! - you will want to use one of Spring's AOP +FactoryBeans. (Remember that a factory bean introduces a layer of indirection, enabling +it to create objects of a different type.) + +[NOTE] +==== +The Spring 2.0 AOP support also uses factory beans under the covers. +==== + +The basic way to create an AOP proxy in Spring is to use the +__org.springframework.aop.framework.ProxyFactoryBean__. This gives complete control over +the pointcuts and advice that will apply, and their ordering. However, there are simpler +options that are preferable if you don't need such control. + + + +[[classic-aop-pfb-1]] +==== Basics +The `ProxyFactoryBean`, like other Spring `FactoryBean` implementations, introduces a +level of indirection. If you define a `ProxyFactoryBean` with name `foo`, what objects +referencing `foo` see is not the `ProxyFactoryBean` instance itself, but an object +created by the `ProxyFactoryBean`'s implementation of the `getObject()` method. This +method will create an AOP proxy wrapping a target object. + +One of the most important benefits of using a `ProxyFactoryBean` or another IoC-aware +class to create AOP proxies, is that it means that advices and pointcuts can also be +managed by IoC. This is a powerful feature, enabling certain approaches that are hard to +achieve with other AOP frameworks. For example, an advice may itself reference +application objects (besides the target, which should be available in any AOP +framework), benefiting from all the pluggability provided by Dependency Injection. + + + +[[classic-aop-pfb-2]] +==== JavaBean properties +In common with most `FactoryBean` implementations provided with Spring, the +`ProxyFactoryBean` class is itself a JavaBean. Its properties are used to: + +* Specify the target you want to proxy. +* Specify whether to use CGLIB (see below and also <>). + +Some key properties are inherited from `org.springframework.aop.framework.ProxyConfig` +(the superclass for all AOP proxy factories in Spring). These key properties include: + +* `proxyTargetClass`: `true` if the target class is to be proxied, rather than the + target class' interfaces. If this property value is set to `true`, then CGLIB proxies + will be created (but see also below <>). +* `optimize`: controls whether or not aggressive optimizations are applied to proxies + __created via CGLIB__. One should not blithely use this setting unless one fully + understands how the relevant AOP proxy handles optimization. This is currently used + only for CGLIB proxies; it has no effect with JDK dynamic proxies. +* `frozen`: if a proxy configuration is `frozen`, then changes to the configuration are + no longer allowed. This is useful both as a slight optimization and for those cases + when you don't want callers to be able to manipulate the proxy (via the `Advised` + interface) after the proxy has been created. The default value of this property is + `false`, so changes such as adding additional advice are allowed. +* `exposeProxy`: determines whether or not the current proxy should be exposed in a + `ThreadLocal` so that it can be accessed by the target. If a target needs to obtain + the proxy and the `exposeProxy` property is set to `true`, the target can use the + `AopContext.currentProxy()` method. +* `aopProxyFactory`: the implementation of `AopProxyFactory` to use. Offers a way of + customizing whether to use dynamic proxies, CGLIB or any other proxy strategy. The + default implementation will choose dynamic proxies or CGLIB appropriately. There + should be no need to use this property; it is intended to allow the addition of new + proxy types in Spring 1.1. + +Other properties specific to `ProxyFactoryBean` include: + +* `proxyInterfaces`: array of String interface names. If this isn't supplied, a CGLIB + proxy for the target class will be used (but see also below <>). +* `interceptorNames`: String array of `Advisor`, interceptor or other advice names to + apply. Ordering is significant, on a first come-first served basis. That is to say + that the first interceptor in the list will be the first to be able to intercept the + invocation. + +The names are bean names in the current factory, including bean names from ancestor +factories. You can't mention bean references here since doing so would result in the +`ProxyFactoryBean` ignoring the singleton setting of the advice. + +You can append an interceptor name with an asterisk ( `*`). This will result in the +application of all advisor beans with names starting with the part before the asterisk +to be applied. An example of using this feature can be found in <>. + +* singleton: whether or not the factory should return a single object, no matter how + often the `getObject()` method is called. Several `FactoryBean` implementations offer + such a method. The default value is `true`. If you want to use stateful advice - for + example, for stateful mixins - use prototype advices along with a singleton value of + `false`. + + + +[[classic-aop-pfb-proxy-types]] +==== JDK- and CGLIB-based proxies +This section serves as the definitive documentation on how the `ProxyFactoryBean` +chooses to create one of either a JDK- and CGLIB-based proxy for a particular target +object (that is to be proxied). + +[NOTE] +==== +The behavior of the `ProxyFactoryBean` with regard to creating JDK- or CGLIB-based +proxies changed between versions 1.2.x and 2.0 of Spring. The `ProxyFactoryBean` now +exhibits similar semantics with regard to auto-detecting interfaces as those of the +`TransactionProxyFactoryBean` class. +==== + +If the class of a target object that is to be proxied (hereafter simply referred to as +the target class) doesn't implement any interfaces, then a CGLIB-based proxy will be +created. This is the easiest scenario, because JDK proxies are interface based, and no +interfaces means JDK proxying isn't even possible. One simply plugs in the target bean, +and specifies the list of interceptors via the `interceptorNames` property. Note that a +CGLIB-based proxy will be created even if the `proxyTargetClass` property of the +`ProxyFactoryBean` has been set to `false`. (Obviously this makes no sense, and is best +removed from the bean definition because it is at best redundant, and at worst +confusing.) + +If the target class implements one (or more) interfaces, then the type of proxy that is +created depends on the configuration of the `ProxyFactoryBean`. + +If the `proxyTargetClass` property of the `ProxyFactoryBean` has been set to `true`, +then a CGLIB-based proxy will be created. This makes sense, and is in keeping with the +principle of least surprise. Even if the `proxyInterfaces` property of the +`ProxyFactoryBean` has been set to one or more fully qualified interface names, the fact +that the `proxyTargetClass` property is set to `true` __will__ cause CGLIB-based +proxying to be in effect. + +If the `proxyInterfaces` property of the `ProxyFactoryBean` has been set to one or more +fully qualified interface names, then a JDK-based proxy will be created. The created +proxy will implement all of the interfaces that were specified in the `proxyInterfaces` +property; if the target class happens to implement a whole lot more interfaces than +those specified in the `proxyInterfaces` property, that is all well and good but those +additional interfaces will not be implemented by the returned proxy. + +If the `proxyInterfaces` property of the `ProxyFactoryBean` has __not__ been set, but +the target class __does implement one (or more)__ interfaces, then the +`ProxyFactoryBean` will auto-detect the fact that the target class does actually +implement at least one interface, and a JDK-based proxy will be created. The interfaces +that are actually proxied will be __all__ of the interfaces that the target class +implements; in effect, this is the same as simply supplying a list of each and every +interface that the target class implements to the `proxyInterfaces` property. However, +it is significantly less work, and less prone to typos. + + + +[[classic-aop-api-proxying-intf]] +==== Proxying interfaces +Let's look at a simple example of `ProxyFactoryBean` in action. This example involves: + +* A __target bean__ that will be proxied. This is the "personTarget" bean definition in + the example below. +* An Advisor and an Interceptor used to provide advice. +* An AOP proxy bean definition specifying the target object (the personTarget bean) and + the interfaces to proxy, along with the advices to apply. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + Tony + 51 + + + + Custom string property value + + + + + + + com.mycompany.Person + + + + myAdvisor + debugInterceptor + + + +---- + +Note that the `interceptorNames` property takes a list of String: the bean names of the +interceptor or advisors in the current factory. Advisors, interceptors, before, after +returning and throws advice objects can be used. The ordering of advisors is significant. + +[NOTE] +==== +You might be wondering why the list doesn't hold bean references. The reason for this is +that if the ProxyFactoryBean's singleton property is set to false, it must be able to +return independent proxy instances. If any of the advisors is itself a prototype, an +independent instance would need to be returned, so it's necessary to be able to obtain +an instance of the prototype from the factory; holding a reference isn't sufficient. +==== + +The "person" bean definition above can be used in place of a Person implementation, as +follows: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + Person person = (Person) factory.getBean("person"); +---- + +Other beans in the same IoC context can express a strongly typed dependency on it, as +with an ordinary Java object: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + +---- + +The `PersonUser` class in this example would expose a property of type Person. As far as +it's concerned, the AOP proxy can be used transparently in place of a "real" person +implementation. However, its class would be a dynamic proxy class. It would be possible +to cast it to the `Advised` interface (discussed below). + +It's possible to conceal the distinction between target and proxy using an anonymous +__inner bean__, as follows. Only the `ProxyFactoryBean` definition is different; the +advice is included only for completeness: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + Custom string property value + + + + + + com.mycompany.Person + + + + Tony + 51 + + + + + myAdvisor + debugInterceptor + + + +---- + +This has the advantage that there's only one object of type `Person`: useful if we want +to prevent users of the application context from obtaining a reference to the un-advised +object, or need to avoid any ambiguity with Spring IoC __autowiring__. There's also +arguably an advantage in that the ProxyFactoryBean definition is self-contained. +However, there are times when being able to obtain the un-advised target from the +factory might actually be an __advantage__: for example, in certain test scenarios. + + + +[[classic-aop-api-proxying-class]] +==== Proxying classes +What if you need to proxy a class, rather than one or more interfaces? + +Imagine that in our example above, there was no `Person` interface: we needed to advise +a class called `Person` that didn't implement any business interface. In this case, you +can configure Spring to use CGLIB proxying, rather than dynamic proxies. Simply set the +`proxyTargetClass` property on the ProxyFactoryBean above to true. While it's best to +program to interfaces, rather than classes, the ability to advise classes that don't +implement interfaces can be useful when working with legacy code. (In general, Spring +isn't prescriptive. While it makes it easy to apply good practices, it avoids forcing a +particular approach.) + +If you want to, you can force the use of CGLIB in any case, even if you do have +interfaces. + +CGLIB proxying works by generating a subclass of the target class at runtime. Spring +configures this generated subclass to delegate method calls to the original target: the +subclass is used to implement the __Decorator__ pattern, weaving in the advice. + +CGLIB proxying should generally be transparent to users. However, there are some issues +to consider: + +* `Final` methods can't be advised, as they can't be overridden. +* As of Spring 3.2 it is no longer required to add CGLIB to your project classpath. + CGLIB classes have been repackaged under org.springframework and included directly in + the spring-core JAR. This is both for user convenience as well as to avoid potential + conflicts with other projects that have dependence on a differing version of CGLIB. + +There's little performance difference between CGLIB proxying and dynamic proxies. As of +Spring 1.0, dynamic proxies are slightly faster. However, this may change in the future. +Performance should not be a decisive consideration in this case. + + + +[[classic-aop-global-advisors]] +==== Using 'global' advisors +By appending an asterisk to an interceptor name, all advisors with bean names matching +the part before the asterisk, will be added to the advisor chain. This can come in handy +if you need to add a standard set of 'global' advisors: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + global* + + + + + + +---- + + + + +[[classic-aop-concise-proxy]] +=== Concise proxy definitions +Especially when defining transactional proxies, you may end up with many similar proxy +definitions. The use of parent and child bean definitions, along with inner bean +definitions, can result in much cleaner and more concise proxy definitions. + +First a parent, __template__, bean definition is created for the proxy: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + PROPAGATION_REQUIRED + + + +---- + +This will never be instantiated itself, so may actually be incomplete. Then each proxy +which needs to be created is just a child bean definition, which wraps the target of the +proxy as an inner bean definition, since the target will never be used on its own anyway. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + +---- + +It is of course possible to override properties from the parent template, such as in +this case, the transaction propagation settings: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + PROPAGATION_REQUIRED,readOnly + PROPAGATION_REQUIRED,readOnly + PROPAGATION_REQUIRED,readOnly + PROPAGATION_REQUIRED + + + +---- + +Note that in the example above, we have explicitly marked the parent bean definition as +__abstract__ by using the __abstract__ attribute, as described +<>, so that it may not actually ever be +instantiated. Application contexts (but not simple bean factories) will by default +pre-instantiate all singletons. It is therefore important (at least for singleton beans) +that if you have a (parent) bean definition which you intend to use only as a template, +and this definition specifies a class, you must make sure to set the__abstract__ +attribute to __true__, otherwise the application context will actually try to +pre-instantiate it. + + + + +[[classic-aop-prog]] +=== Creating AOP proxies programmatically with the ProxyFactory +It's easy to create AOP proxies programmatically using Spring. This enables you to use +Spring AOP without dependency on Spring IoC. + +The following listing shows creation of a proxy for a target object, with one +interceptor and one advisor. The interfaces implemented by the target object will +automatically be proxied: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + ProxyFactory factory = new ProxyFactory(myBusinessInterfaceImpl); + factory.addInterceptor(myMethodInterceptor); + factory.addAdvisor(myAdvisor); + MyBusinessInterface tb = (MyBusinessInterface) factory.getProxy(); +---- + +The first step is to construct an object of type +`org.springframework.aop.framework.ProxyFactory`. You can create this with a target +object, as in the above example, or specify the interfaces to be proxied in an alternate +constructor. + +You can add interceptors or advisors, and manipulate them for the life of the +ProxyFactory. If you add an IntroductionInterceptionAroundAdvisor you can cause the +proxy to implement additional interfaces. + +There are also convenience methods on ProxyFactory (inherited from `AdvisedSupport`) +which allow you to add other advice types such as before and throws advice. +AdvisedSupport is the superclass of both ProxyFactory and ProxyFactoryBean. + +[TIP] +==== + +Integrating AOP proxy creation with the IoC framework is best practice in most +applications. We recommend that you externalize configuration from Java code with AOP, +as in general. +==== + + + + +[[classic-aop-api-advised]] +=== Manipulating advised objects +However you create AOP proxies, you can manipulate them using the +`org.springframework.aop.framework.Advised` interface. Any AOP proxy can be cast to this +interface, whichever other interfaces it implements. This interface includes the +following methods: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + Advisor[] getAdvisors(); + + void addAdvice(Advice advice) throws AopConfigException; + + void addAdvice(int pos, Advice advice) throws AopConfigException; + + void addAdvisor(Advisor advisor) throws AopConfigException; + + void addAdvisor(int pos, Advisor advisor) throws AopConfigException; + + int indexOf(Advisor advisor); + + boolean removeAdvisor(Advisor advisor) throws AopConfigException; + + void removeAdvisor(int index) throws AopConfigException; + + boolean replaceAdvisor(Advisor a, Advisor b) throws AopConfigException; + + boolean isFrozen(); +---- + +The `getAdvisors()` method will return an Advisor for every advisor, interceptor or +other advice type that has been added to the factory. If you added an Advisor, the +returned advisor at this index will be the object that you added. If you added an +interceptor or other advice type, Spring will have wrapped this in an advisor with a +pointcut that always returns true. Thus if you added a `MethodInterceptor`, the advisor +returned for this index will be an `DefaultPointcutAdvisor` returning your +`MethodInterceptor` and a pointcut that matches all classes and methods. + +The `addAdvisor()` methods can be used to add any Advisor. Usually the advisor holding +pointcut and advice will be the generic `DefaultPointcutAdvisor`, which can be used with +any advice or pointcut (but not for introductions). + +By default, it's possible to add or remove advisors or interceptors even once a proxy +has been created. The only restriction is that it's impossible to add or remove an +introduction advisor, as existing proxies from the factory will not show the interface +change. (You can obtain a new proxy from the factory to avoid this problem.) + +A simple example of casting an AOP proxy to the `Advised` interface and examining and +manipulating its advice: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + Advised advised = (Advised) myObject; + Advisor[] advisors = advised.getAdvisors(); + int oldAdvisorCount = advisors.length; + System.out.println(oldAdvisorCount + " advisors"); + + // Add an advice like an interceptor without a pointcut + // Will match all proxied methods + // Can use for interceptors, before, after returning or throws advice + advised.addAdvice(new DebugInterceptor()); + + // Add selective advice using a pointcut + advised.addAdvisor(new DefaultPointcutAdvisor(mySpecialPointcut, myAdvice)); + + assertEquals("Added two advisors", oldAdvisorCount + 2, advised.getAdvisors().length); +---- + +[NOTE] +==== +It's questionable whether it's advisable (no pun intended) to modify advice on a +business object in production, although there are no doubt legitimate usage cases. +However, it can be very useful in development: for example, in tests. I have sometimes +found it very useful to be able to add test code in the form of an interceptor or other +advice, getting inside a method invocation I want to test. (For example, the advice can +get inside a transaction created for that method: for example, to run SQL to check that +a database was correctly updated, before marking the transaction for roll back.) +==== + +Depending on how you created the proxy, you can usually set a `frozen` flag, in which +case the `Advised` `isFrozen()` method will return true, and any attempts to modify +advice through addition or removal will result in an `AopConfigException`. The ability +to freeze the state of an advised object is useful in some cases, for example, to +prevent calling code removing a security interceptor. It may also be used in Spring 1.1 +to allow aggressive optimization if runtime advice modification is known not to be +required. + + + + +[[classic-aop-autoproxy]] +=== Using the "autoproxy" facility +So far we've considered explicit creation of AOP proxies using a `ProxyFactoryBean` or +similar factory bean. + +Spring also allows us to use "autoproxy" bean definitions, which can automatically proxy +selected bean definitions. This is built on Spring "bean post processor" infrastructure, +which enables modification of any bean definition as the container loads. + +In this model, you set up some special bean definitions in your XML bean definition file +to configure the auto proxy infrastructure. This allows you just to declare the targets +eligible for autoproxying: you don't need to use `ProxyFactoryBean`. + +There are two ways to do this: + +* Using an autoproxy creator that refers to specific beans in the current context. +* A special case of autoproxy creation that deserves to be considered separately; + autoproxy creation driven by source-level metadata attributes. + + + +[[classic-aop-autoproxy-choices]] +==== Autoproxy bean definitions +The `org.springframework.aop.framework.autoproxy` package provides the following +standard autoproxy creators. + + +[[classic-aop-api-autoproxy]] +===== BeanNameAutoProxyCreator +The `BeanNameAutoProxyCreator` class is a `BeanPostProcessor` that automatically creates +AOP proxies for beans with names matching literal values or wildcards. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + jdk*,onlyJdk + + + myInterceptor + + + +---- + +As with `ProxyFactoryBean`, there is an `interceptorNames` property rather than a list +of interceptors, to allow correct behavior for prototype advisors. Named "interceptors" +can be advisors or any advice type. + +As with auto proxying in general, the main point of using `BeanNameAutoProxyCreator` is +to apply the same configuration consistently to multiple objects, with minimal volume of +configuration. It is a popular choice for applying declarative transactions to multiple +objects. + +Bean definitions whose names match, such as "jdkMyBean" and "onlyJdk" in the above +example, are plain old bean definitions with the target class. An AOP proxy will be +created automatically by the `BeanNameAutoProxyCreator`. The same advice will be applied +to all matching beans. Note that if advisors are used (rather than the interceptor in +the above example), the pointcuts may apply differently to different beans. + + +[[classic-aop-api-autoproxy-default]] +===== DefaultAdvisorAutoProxyCreator +A more general and extremely powerful auto proxy creator is +`DefaultAdvisorAutoProxyCreator`. This will automagically apply eligible advisors in the +current context, without the need to include specific bean names in the autoproxy +advisor's bean definition. It offers the same merit of consistent configuration and +avoidance of duplication as `BeanNameAutoProxyCreator`. + +Using this mechanism involves: + +* Specifying a `DefaultAdvisorAutoProxyCreator` bean definition. +* Specifying any number of Advisors in the same or related contexts. Note that these + __must__ be Advisors, not just interceptors or other advices. This is necessary + because there must be a pointcut to evaluate, to check the eligibility of each advice + to candidate bean definitions. + +The `DefaultAdvisorAutoProxyCreator` will automatically evaluate the pointcut contained +in each advisor, to see what (if any) advice it should apply to each business object +(such as "businessObject1" and "businessObject2" in the example). + +This means that any number of advisors can be applied automatically to each business +object. If no pointcut in any of the advisors matches any method in a business object, +the object will not be proxied. As bean definitions are added for new business objects, +they will automatically be proxied if necessary. + +Autoproxying in general has the advantage of making it impossible for callers or +dependencies to obtain an un-advised object. Calling getBean("businessObject1") on this +ApplicationContext will return an AOP proxy, not the target business object. (The "inner +bean" idiom shown earlier also offers this benefit.) + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + + + + + + +---- + +The `DefaultAdvisorAutoProxyCreator` is very useful if you want to apply the same advice +consistently to many business objects. Once the infrastructure definitions are in place, +you can simply add new business objects without including specific proxy configuration. +You can also drop in additional aspects very easily - for example, tracing or +performance monitoring aspects - with minimal change to configuration. + +The DefaultAdvisorAutoProxyCreator offers support for filtering (using a naming +convention so that only certain advisors are evaluated, allowing use of multiple, +differently configured, AdvisorAutoProxyCreators in the same factory) and ordering. +Advisors can implement the `org.springframework.core.Ordered` interface to ensure +correct ordering if this is an issue. The TransactionAttributeSourceAdvisor used in the +above example has a configurable order value; the default setting is unordered. + + +[[classic-aop-api-autoproxy-abstract]] +===== AbstractAdvisorAutoProxyCreator +This is the superclass of DefaultAdvisorAutoProxyCreator. You can create your own +autoproxy creators by subclassing this class, in the unlikely event that advisor +definitions offer insufficient customization to the behavior of the framework +`DefaultAdvisorAutoProxyCreator`. + + + +[[classic-aop-autoproxy-metadata]] +==== Using metadata-driven auto-proxying +A particularly important type of autoproxying is driven by metadata. This produces a +similar programming model to .NET `ServicedComponents`. Instead of using XML deployment +descriptors as in EJB, configuration for transaction management and other enterprise +services is held in source-level attributes. + +In this case, you use the `DefaultAdvisorAutoProxyCreator`, in combination with Advisors +that understand metadata attributes. The metadata specifics are held in the pointcut +part of the candidate advisors, rather than in the autoproxy creation class itself. + +This is really a special case of the `DefaultAdvisorAutoProxyCreator`, but deserves +consideration on its own. (The metadata-aware code is in the pointcuts contained in the +advisors, not the AOP framework itself.) + +The `/attributes` directory of the JPetStore sample application shows the use of +attribute-driven autoproxying. In this case, there's no need to use the +`TransactionProxyFactoryBean`. Simply defining transactional attributes on business +objects is sufficient, because of the use of metadata-aware pointcuts. The bean +definitions include the following code, in `/WEB-INF/declarativeServices.xml`. Note that +this is generic, and can be used outside the JPetStore: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + + + + + + + + + +---- + +The `DefaultAdvisorAutoProxyCreator` bean definition (the name is not significant, hence +it can even be omitted) will pick up all eligible pointcuts in the current application +context. In this case, the "transactionAdvisor" bean definition, of type +`TransactionAttributeSourceAdvisor`, will apply to classes or methods carrying a +transaction attribute. The TransactionAttributeSourceAdvisor depends on a +TransactionInterceptor, via constructor dependency. The example resolves this via +autowiring. The `AttributesTransactionAttributeSource` depends on an implementation of +the `org.springframework.metadata.Attributes` interface. In this fragment, the +"attributes" bean satisfies this, using the Jakarta Commons Attributes API to obtain +attribute information. (The application code must have been compiled using the Commons +Attributes compilation task.) + +The `/annotation` directory of the JPetStore sample application contains an analogous +example for auto-proxying driven by JDK 1.5+ annotations. The following configuration +enables automatic detection of Spring's `Transactional` annotation, leading to implicit +proxies for beans containing that annotation: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + + + + + +---- + +The `TransactionInterceptor` defined here depends on a `PlatformTransactionManager` +definition, which is not included in this generic file (although it could be) because it +will be specific to the application's transaction requirements (typically JTA, as in +this example, or Hibernate, JDO or JDBC): + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + +---- + +[TIP] +==== + +If you require only declarative transaction management, using these generic XML +definitions will result in Spring automatically proxying all classes or methods with +transaction attributes. You won't need to work directly with AOP, and the programming +model is similar to that of .NET ServicedComponents. +==== + +This mechanism is extensible. It's possible to do autoproxying based on custom +attributes. You need to: + +* Define your custom attribute. +* Specify an Advisor with the necessary advice, including a pointcut that is triggered + by the presence of the custom attribute on a class or method. You may be able to use + an existing advice, merely implementing a static pointcut that picks up the custom + attribute. + +It's possible for such advisors to be unique to each advised class (for example, +mixins): they simply need to be defined as prototype, rather than singleton, bean +definitions. For example, the `LockMixin` introduction interceptor from the Spring test +suite, shown above, could be used in conjunction with an attribute-driven pointcut to +target a mixin, as shown here. We use the generic `DefaultPointcutAdvisor`, configured +using JavaBean properties: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + + + + + + + + + +---- + +The above `swap()` call changes the target of the swappable bean. Clients who hold a +reference to that bean will be unaware of the change, but will immediately start hitting +the new target. + +Although this example doesn't add any advice - and it's not necessary to add advice to +use a `TargetSource` - of course any `TargetSource` can be used in conjunction with +arbitrary advice. + + + +[[classic-aop-ts-pool]] +==== Pooling target sources +Using a pooling target source provides a similar programming model to stateless session +EJBs, in which a pool of identical instances is maintained, with method invocations +going to free objects in the pool. + +A crucial difference between Spring pooling and SLSB pooling is that Spring pooling can +be applied to any POJO. As with Spring in general, this service can be applied in a +non-invasive way. + +Spring provides out-of-the-box support for Jakarta Commons Pool 1.3, which provides a +fairly efficient pooling implementation. You'll need the commons-pool Jar on your +application's classpath to use this feature. It's also possible to subclass +`org.springframework.aop.target.AbstractPoolingTargetSource` to support any other +pooling API. + +Sample configuration is shown below: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + ... properties omitted + + + + + + + + + + + +---- + +Note that the target object - "businessObjectTarget" in the example - __must__ be a +prototype. This allows the `PoolingTargetSource` implementation to create new instances +of the target to grow the pool as necessary. See the Javadoc for +`AbstractPoolingTargetSource` and the concrete subclass you wish to use for information +about its properties: "maxSize" is the most basic, and always guaranteed to be present. + +In this case, "myInterceptor" is the name of an interceptor that would need to be +defined in the same IoC context. However, it isn't necessary to specify interceptors to +use pooling. If you want only pooling, and no other advice, don't set the +interceptorNames property at all. + +It's possible to configure Spring so as to be able to cast any pooled object to the +`org.springframework.aop.target.PoolingConfig` interface, which exposes information +about the configuration and current size of the pool through an introduction. You'll +need to define an advisor like this: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + +---- + +This advisor is obtained by calling a convenience method on the +`AbstractPoolingTargetSource` class, hence the use of MethodInvokingFactoryBean. This +advisor's name ("poolConfigAdvisor" here) must be in the list of interceptors names in +the ProxyFactoryBean exposing the pooled object. + +The cast will look as follows: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + PoolingConfig conf = (PoolingConfig) beanFactory.getBean("businessObject"); + System.out.println("Max pool size is " + conf.getMaxSize()); +---- + +[NOTE] +==== +Pooling stateless service objects is not usually necessary. We don't believe it should +be the default choice, as most stateless objects are naturally thread safe, and instance +pooling is problematic if resources are cached. +==== + +Simpler pooling is available using autoproxying. It's possible to set the TargetSources +used by any autoproxy creator. + + + +[[classic-aop-ts-prototype]] +==== Prototype target sources +Setting up a "prototype" target source is similar to a pooling TargetSource. In this +case, a new instance of the target will be created on every method invocation. Although +the cost of creating a new object isn't high in a modern JVM, the cost of wiring up the +new object (satisfying its IoC dependencies) may be more expensive. Thus you shouldn't +use this approach without very good reason. + +To do this, you could modify the `poolTargetSource` definition shown above as follows. +(I've also changed the name, for clarity.) + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + +---- + +There's only one property: the name of the target bean. Inheritance is used in the +TargetSource implementations to ensure consistent naming. As with the pooling target +source, the target bean must be a prototype bean definition. + + + +[[classic-aop-ts-threadlocal]] +==== ThreadLocal target sources + +`ThreadLocal` target sources are useful if you need an object to be created for each +incoming request (per thread that is). The concept of a `ThreadLocal` provide a JDK-wide +facility to transparently store resource alongside a thread. Setting up a +`ThreadLocalTargetSource` is pretty much the same as was explained for the other types +of target source: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + +---- + +[NOTE] +==== +ThreadLocals come with serious issues (potentially resulting in memory leaks) when +incorrectly using them in a multi-threaded and multi-classloader environments. One +should always consider wrapping a threadlocal in some other class and never directly use +the `ThreadLocal` itself (except of course in the wrapper class). Also, one should +always remember to correctly set and unset (where the latter simply involved a call to +`ThreadLocal.set(null)`) the resource local to the thread. Unsetting should be done in +any case since not unsetting it might result in problematic behavior. Spring's +ThreadLocal support does this for you and should always be considered in favor of using +ThreadLocals without other proper handling code. +==== + + + + +[[classic-aop-extensibility]] +=== Defining new Advice types + +Spring AOP is designed to be extensible. While the interception implementation strategy +is presently used internally, it is possible to support arbitrary advice types in +addition to the out-of-the-box interception around advice, before, throws advice and +after returning advice. + +The `org.springframework.aop.framework.adapter` package is an SPI package allowing +support for new custom advice types to be added without changing the core framework. The +only constraint on a custom `Advice` type is that it must implement the +`org.aopalliance.aop.Advice` tag interface. + +Please refer to the `org.springframework.aop.framework.adapter` package's Javadocs for +further information. + + + + +[[classic-aop-api-resources]] +=== Further resources +Please refer to the Spring sample applications for further examples of Spring AOP: + +* The JPetStore's default configuration illustrates the use of the + `TransactionProxyFactoryBean` for declarative transaction management. +* The `/attributes` directory of the JPetStore illustrates the use of attribute-driven + declarative transaction management. + diff --git a/src/asciidoc/classic-spring.adoc b/src/asciidoc/classic-spring.adoc new file mode 100644 index 000000000000..370fb3aa583a --- /dev/null +++ b/src/asciidoc/classic-spring.adoc @@ -0,0 +1,427 @@ +[[classic-spring]] +== Classic Spring Usage +This appendix discusses some classic Spring usage patterns as a reference for developers +maintaining legacy Spring applications. These usage patterns no longer reflect the +recommended way of using these features and the current recommended usage is covered in +the respective sections of the reference manual. + + + + +[[classic-spring-orm]] +=== Classic ORM usage +This section documents the classic usage patterns that you might encounter in a legacy +Spring application. For the currently recommended usage patterns, please refer to the +<> chapter. + + + +[[classic-spring-hibernate]] +==== Hibernate +For the currently recommended usage patterns for Hibernate see <> + + +[[orm-hibernate-template]] +===== the HibernateTemplate + +The basic programming model for templating looks as follows, for methods that can be +part of any custom data access object or business service. There are no restrictions on +the implementation of the surrounding object at all, it just needs to provide a +Hibernate `SessionFactory`. It can get the latter from anywhere, but preferably as bean +reference from a Spring IoC container - via a simple `setSessionFactory(..)` bean +property setter. The following snippets show a DAO definition in a Spring container, +referencing the above defined `SessionFactory`, and an example for a DAO method +implementation. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + +---- + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class ProductDaoImpl implements ProductDao { + + private HibernateTemplate hibernateTemplate; + + public void setSessionFactory(SessionFactory sessionFactory) { + this.hibernateTemplate = new HibernateTemplate(sessionFactory); + } + + public Collection loadProductsByCategory(String category) throws DataAccessException { + return this.hibernateTemplate.find("from test.Product product where product.category=?", category); + } + } +---- + +The `HibernateTemplate` class provides many methods that mirror the methods exposed on +the Hibernate `Session` interface, in addition to a number of convenience methods such +as the one shown above. If you need access to the `Session` to invoke methods that are +not exposed on the `HibernateTemplate`, you can always drop down to a callback-based +approach like so. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class ProductDaoImpl implements ProductDao { + + private HibernateTemplate hibernateTemplate; + + public void setSessionFactory(SessionFactory sessionFactory) { + this.hibernateTemplate = new HibernateTemplate(sessionFactory); + } + + public Collection loadProductsByCategory(final String category) throws DataAccessException { + return this.hibernateTemplate.execute(new HibernateCallback() { + public Object doInHibernate(Session session) { + Criteria criteria = session.createCriteria(Product.class); + criteria.add(Expression.eq("category", category)); + criteria.setMaxResults(6); + return criteria.list(); + } + }; + } + + } +---- + +A callback implementation effectively can be used for any Hibernate data access. +`HibernateTemplate` will ensure that `Session` instances are properly opened and closed, +and automatically participate in transactions. The template instances are thread-safe +and reusable, they can thus be kept as instance variables of the surrounding class. For +simple single step actions like a single find, load, saveOrUpdate, or delete call, +`HibernateTemplate` offers alternative convenience methods that can replace such one +line callback implementations. Furthermore, Spring provides a convenient +`HibernateDaoSupport` base class that provides a `setSessionFactory(..)` method for +receiving a `SessionFactory`, and `getSessionFactory()` and `getHibernateTemplate()` for +use by subclasses. In combination, this allows for very simple DAO implementations for +typical requirements: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class ProductDaoImpl extends HibernateDaoSupport implements ProductDao { + + public Collection loadProductsByCategory(String category) throws DataAccessException { + return this.getHibernateTemplate().find( + "from test.Product product where product.category=?", category); + } + + } +---- + + +[[orm-hibernate-daos]] +===== Implementing Spring-based DAOs without callbacks +As alternative to using Spring's `HibernateTemplate` to implement DAOs, data access code +can also be written in a more traditional fashion, without wrapping the Hibernate access +code in a callback, while still respecting and participating in Spring's generic +`DataAccessException` hierarchy. The `HibernateDaoSupport` base class offers methods to +access the current transactional `Session` and to convert exceptions in such a scenario; +similar methods are also available as static helpers on the `SessionFactoryUtils` class. +Note that such code will usually pass ' `false`' as the value of the `getSession(..)` +methods ' `allowCreate`' argument, to enforce running within a transaction (which avoids +the need to close the returned `Session`, as its lifecycle is managed by the +transaction). + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class HibernateProductDao extends HibernateDaoSupport implements ProductDao { + + public Collection loadProductsByCategory(String category) throws DataAccessException, MyException { + Session session = getSession(false); + try { + Query query = session.createQuery("from test.Product product where product.category=?"); + query.setString(0, category); + List result = query.list(); + if (result == null) { + throw new MyException("No search results."); + } + return result; + } + catch (HibernateException ex) { + throw convertHibernateAccessException(ex); + } + } + } +---- + +The advantage of such direct Hibernate access code is that it allows __any__ checked +application exception to be thrown within the data access code; contrast this to the +`HibernateTemplate` class which is restricted to throwing only unchecked exceptions +within the callback. Note that you can often defer the corresponding checks and the +throwing of application exceptions to after the callback, which still allows working +with `HibernateTemplate`. In general, the `HibernateTemplate` class' convenience methods +are simpler and more convenient for many scenarios. + + + +[[classic-spring-jdo]] +==== JDO +For the currently recommended usage patterns for JDO see <> + + +[[orm-jdo-template]] +===== JdoTemplate and `JdoDaoSupport` + +Each JDO-based DAO will then receive the `PersistenceManagerFactory` through dependency +injection. Such a DAO could be coded against plain JDO API, working with the given +`PersistenceManagerFactory`, but will usually rather be used with the Spring Framework's +`JdoTemplate`: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + +---- + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class ProductDaoImpl implements ProductDao { + + private JdoTemplate jdoTemplate; + + public void setPersistenceManagerFactory(PersistenceManagerFactory pmf) { + this.jdoTemplate = new JdoTemplate(pmf); + } + + public Collection loadProductsByCategory(final String category) throws DataAccessException { + return (Collection) this.jdoTemplate.execute(new JdoCallback() { + public Object doInJdo(PersistenceManager pm) throws JDOException { + Query query = pm.newQuery(Product.class, "category = pCategory"); + query.declareParameters("String pCategory"); + List result = query.execute(category); + // do some further stuff with the result list + return result; + } + }); + } + + } +---- + +A callback implementation can effectively be used for any JDO data access. `JdoTemplate` +will ensure that `PersistenceManager` s are properly opened and closed, and +automatically participate in transactions. The template instances are thread-safe and +reusable, they can thus be kept as instance variables of the surrounding class. For +simple single-step actions such as a single `find`, `load`, `makePersistent`, or +`delete` call, `JdoTemplate` offers alternative convenience methods that can replace +such one line callback implementations. Furthermore, Spring provides a convenient +`JdoDaoSupport` base class that provides a `setPersistenceManagerFactory(..)` method for +receiving a `PersistenceManagerFactory`, and `getPersistenceManagerFactory()` and +`getJdoTemplate()` for use by subclasses. In combination, this allows for very simple +DAO implementations for typical requirements: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class ProductDaoImpl extends JdoDaoSupport implements ProductDao { + + public Collection loadProductsByCategory(String category) throws DataAccessException { + return getJdoTemplate().find(Product.class, + "category = pCategory", "String category", new Object[] {category}); + } + + } +---- + +As alternative to working with Spring's `JdoTemplate`, you can also code Spring-based +DAOs at the JDO API level, explicitly opening and closing a `PersistenceManager`. As +elaborated in the corresponding Hibernate section, the main advantage of this approach +is that your data access code is able to throw checked exceptions. `JdoDaoSupport` +offers a variety of support methods for this scenario, for fetching and releasing a +transactional `PersistenceManager` as well as for converting exceptions. + + + +[[classic-spring-jpa]] +==== JPA +For the currently recommended usage patterns for JPA see <> + + +[[orm-jpa-template]] +===== JpaTemplate and `JpaDaoSupport` + +Each JPA-based DAO will then receive a `EntityManagerFactory` via dependency injection. +Such a DAO can be coded against plain JPA and work with the given `EntityManagerFactory` +or through Spring's `JpaTemplate`: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + +---- + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class JpaProductDao implements ProductDao { + + private JpaTemplate jpaTemplate; + + public void setEntityManagerFactory(EntityManagerFactory emf) { + this.jpaTemplate = new JpaTemplate(emf); + } + + public Collection loadProductsByCategory(final String category) throws DataAccessException { + return (Collection) this.jpaTemplate.execute(new JpaCallback() { + public Object doInJpa(EntityManager em) throws PersistenceException { + Query query = em.createQuery("from Product as p where p.category = :category"); + query.setParameter("category", category); + List result = query.getResultList(); + // do some further processing with the result list + return result; + } + }); + } + + } +---- + +The `JpaCallback` implementation allows any type of JPA data access. The `JpaTemplate` +will ensure that `EntityManager` s are properly opened and closed and automatically +participate in transactions. Moreover, the `JpaTemplate` properly handles exceptions, +making sure resources are cleaned up and the appropriate transactions rolled back. The +template instances are thread-safe and reusable and they can be kept as instance +variable of the enclosing class. Note that `JpaTemplate` offers single-step actions such +as find, load, merge, etc along with alternative convenience methods that can replace +one line callback implementations. + +Furthermore, Spring provides a convenient `JpaDaoSupport` base class that provides the +`get/setEntityManagerFactory` and `getJpaTemplate()` to be used by subclasses: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class ProductDaoImpl extends JpaDaoSupport implements ProductDao { + + public Collection loadProductsByCategory(String category) throws DataAccessException { + Map params = new HashMap(); + params.put("category", category); + return getJpaTemplate().findByNamedParams("from Product as p where p.category = :category", params); + } + + } +---- + +Besides working with Spring's `JpaTemplate`, one can also code Spring-based DAOs against +the JPA, doing one's own explicit `EntityManager` handling. As also elaborated in the +corresponding Hibernate section, the main advantage of this approach is that your data +access code is able to throw checked exceptions. `JpaDaoSupport` offers a variety of +support methods for this scenario, for retrieving and releasing a transaction +`EntityManager`, as well as for converting exceptions. + +__JpaTemplate mainly exists as a sibling of JdoTemplate and HibernateTemplate, offering +the same style for people used to it.__ + + + + +[[clasic-spring-mvc]] +=== Classic Spring MVC +... + + + + +[[classic-spring-jms]] +=== JMS Usage + +One of the benefits of Spring's JMS support is to shield the user from differences +between the JMS 1.0.2 and 1.1 APIs. (For a description of the differences between the +two APIs see sidebar on Domain Unification). Since it is now common to encounter only +the JMS 1.1 API the use of classes that are based on the JMS 1.0.2 API has been +deprecated in Spring 3.0. This section describes Spring JMS support for the JMS 1.0.2 +deprecated classes. + +.Domain Unification +**** +There are two major releases of the JMS specification, 1.0.2 and 1.1. + +JMS 1.0.2 defined two types of messaging domains, point-to-point (Queues) and +publish/subscribe (Topics). The 1.0.2 API reflected these two messaging domains by +providing a parallel class hierarchy for each domain. As a result, a client application +became domain specific in its use of the JMS API. JMS 1.1 introduced the concept of +domain unification that minimized both the functional differences and client API +differences between the two domains. As an example of a functional difference that was +removed, if you use a JMS 1.1 provider you can transactionally consume a message from +one domain and produce a message on the other using the same `Session`. + +[NOTE] +==== +The JMS 1.1 specification was released in April 2002 and incorporated as part of J2EE +1.4 in November 2003. As a result, common J2EE 1.3 application servers which are still +in widespread use (such as BEA WebLogic 8.1 and IBM WebSphere 5.1) are based on JMS +1.0.2. +==== +**** + + + +[[classic-spring-jms-template]] +==== JmsTemplate +Located in the package `org.springframework.jms.core` the class `JmsTemplate102` +provides all of the features of the `JmsTemplate` described the JMS chapter, but is +based on the JMS 1.0.2 API instead of the JMS 1.1 API. As a consequence, if you are +using JmsTemplate102 you need to set the boolean property `pubSubDomain` to configure +the `JmsTemplate` with knowledge of what JMS domain is being used. By default the value +of this property is false, indicating that the point-to-point domain, Queues, will be +used. + + + +[[classic-spring-aysnc-messages]] +==== Asynchronous Message Reception +<> are used in +conjunction with Spring's <> to support +asynchronous message reception by exposing almost any class as a Message-driven POJO. If +you are using the JMS 1.0.2 API, you will want to use the 1.0.2 specific classes such as +`MessageListenerAdapter102`, `SimpleMessageListenerContainer102`, and +`DefaultMessageListenerContainer102`. These classes provide the same functionality as +the JMS 1.1 based counterparts but rely only on the JMS 1.0.2 API. + + + +[[classic-spring-jms-connections]] +==== Connections +The `ConnectionFactory` interface is part of the JMS specification and serves as the +entry point for working with JMS. Spring provides an implementation of the +`ConnectionFactory` interface, `SingleConnectionFactory102`, based on the JMS 1.0.2 API +that will return the same `Connection` on all `createConnection()` calls and ignore +calls to `close()`. You will need to set the boolean property `pubSubDomain` to indicate +which messaging domain is used as `SingleConnectionFactory102` will always explicitly +differentiate between a `javax.jms.QueueConnection` and a `javax.jmsTopicConnection`. + + + +[[classic-spring-jms-tx-management]] +==== Transaction Management +In a JMS 1.0.2 environment the class `JmsTransactionManager102` provides support for +managing JMS transactions for a single Connection Factory. Please refer to the reference +documentation on <> for more information on this +functionality. + + + diff --git a/src/asciidoc/dao.adoc b/src/asciidoc/dao.adoc new file mode 100644 index 000000000000..bf94672fd554 --- /dev/null +++ b/src/asciidoc/dao.adoc @@ -0,0 +1,138 @@ +[[dao]] +== DAO support + + + + +[[dao-introduction]] +=== Introduction +The Data Access Object (DAO) support in Spring is aimed at making it easy to work with +data access technologies like JDBC, Hibernate, JPA or JDO in a consistent way. This +allows one to switch between the aforementioned persistence technologies fairly easily +and it also allows one to code without worrying about catching exceptions that are +specific to each technology. + + + + +[[dao-exceptions]] +=== Consistent exception hierarchy +Spring provides a convenient translation from technology-specific exceptions like +`SQLException` to its own exception class hierarchy with the `DataAccessException` as +the root exception. These exceptions wrap the original exception so there is never any +risk that one might lose any information as to what might have gone wrong. + +In addition to JDBC exceptions, Spring can also wrap Hibernate-specific exceptions, +converting them from proprietary, checked exceptions (in the case of versions of +Hibernate prior to Hibernate 3.0), to a set of focused runtime exceptions (the same is +true for JDO and JPA exceptions). This allows one to handle most persistence exceptions, +which are non-recoverable, only in the appropriate layers, without having annoying +boilerplate catch-and-throw blocks and exception declarations in one's DAOs. (One can +still trap and handle exceptions anywhere one needs to though.) As mentioned above, JDBC +exceptions (including database-specific dialects) are also converted to the same +hierarchy, meaning that one can perform some operations with JDBC within a consistent +programming model. + +The above holds true for the various template classes in Springs support for various ORM +frameworks. If one uses the interceptor-based classes then the application must care +about handling `HibernateExceptions` and `JDOExceptions` itself, preferably via +delegating to `SessionFactoryUtils`' `convertHibernateAccessException(..)` or +`convertJdoAccessException()` methods respectively. These methods convert the exceptions +to ones that are compatible with the exceptions in the `org.springframework.dao` +exception hierarchy. As `JDOExceptions` are unchecked, they can simply get thrown too, +sacrificing generic DAO abstraction in terms of exceptions though. + +The exception hierarchy that Spring provides can be seen below. (Please note that the +class hierarchy detailed in the image shows only a subset of the entire +`DataAccessException` hierarchy.) + +image::images/DataAccessException.gif[width=400] + + + + +[[dao-annotations]] +=== Annotations used for configuring DAO or Repository classes +The best way to guarantee that your Data Access Objects (DAOs) or repositories provide +exception translation is to use the `@Repository` annotation. This annotation also +allows the component scanning support to find and configure your DAOs and repositories +without having to provide XML configuration entries for them. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + **@Repository** + public class SomeMovieFinder implements MovieFinder { + // ... + } +---- + +Any DAO or repository implementation will need to access to a persistence resource, +depending on the persistence technology used; for example, a JDBC-based repository will +need access to a JDBC `DataSource`; a JPA-based repository will need access to an +`EntityManager`. The easiest way to accomplish this is to have this resource dependency +injected using one of the `@Autowired,`, `@Inject`, `@Resource` or `@PersistenceContext` +annotations. Here is an example for a JPA repository: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Repository + public class JpaMovieFinder implements MovieFinder { + + @PersistenceContext + private EntityManager entityManager; + + // ... + + } +---- + +If you are using the classic Hibernate APIs than you can inject the SessionFactory: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Repository + public class HibernateMovieFinder implements MovieFinder { + + private SessionFactory sessionFactory; + + @Autowired + public void setSessionFactory(SessionFactory sessionFactory) { + this.sessionFactory = sessionFactory; + } + + // ... + + } +---- + +Last example we will show here is for typical JDBC support. You would have the +`DataSource` injected into an initialization method where you would create a +`JdbcTemplate` and other data access support classes like `SimpleJdbcCall` etc using +this `DataSource`. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Repository + public class JdbcMovieFinder implements MovieFinder { + + private JdbcTemplate jdbcTemplate; + + @Autowired + public void init(DataSource dataSource) { + this.jdbcTemplate = new JdbcTemplate(dataSource); + } + + // ... + + } +---- + +[NOTE] +==== +Please see the specific coverage of each persistence technology for details on how to +configure the application context to take advantage of these annotations. +==== diff --git a/src/asciidoc/dynamic-languages.adoc b/src/asciidoc/dynamic-languages.adoc new file mode 100644 index 000000000000..9064728fe6a1 --- /dev/null +++ b/src/asciidoc/dynamic-languages.adoc @@ -0,0 +1,1043 @@ +[[dynamic-language]] +== Dynamic language support + + + + +[[dynamic-language-introduction]] +=== Introduction +Spring 2.0 introduces comprehensive support for using classes and objects that have been +defined using a dynamic language (such as JRuby) with Spring. This support allows you to +write any number of classes in a supported dynamic language, and have the Spring +container transparently instantiate, configure and dependency inject the resulting +objects. + +The dynamic languages currently supported are: + +* JRuby 1.5+ +* Groovy 1.8+ +* BeanShell 2.0 + +.Why only these languages? +**** +The supported languages were chosen because __a)__ the languages have a lot of traction in +the Java enterprise community, __b)__ no requests were made for other languages at the time +that this support was added, and __c)__ the Spring developers were most familiar with +them. +**** + +Fully working examples of where this dynamic language support can be immediately useful +are described in <>. + + + + +[[dynamic-language-a-first-example]] +=== A first example +This bulk of this chapter is concerned with describing the dynamic language support in +detail. Before diving into all of the ins and outs of the dynamic language support, +let's look at a quick example of a bean defined in a dynamic language. The dynamic +language for this first bean is Groovy (the basis of this example was taken from the +Spring test suite, so if you want to see equivalent examples in any of the other +supported languages, take a look at the source code). + +Find below the `Messenger` interface that the Groovy bean is going to be implementing, +and note that this interface is defined in plain Java. Dependent objects that are +injected with a reference to the `Messenger` won't know that the underlying +implementation is a Groovy script. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + package org.springframework.scripting; + + public interface Messenger { + + String getMessage(); + + } +---- + +Here is the definition of a class that has a dependency on the `Messenger` interface. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + package org.springframework.scripting; + + public class DefaultBookingService implements BookingService { + + private Messenger messenger; + + public void setMessenger(Messenger messenger) { + this.messenger = messenger; + } + + public void processBooking() { + // use the injected Messenger object... + } + + } +---- + +Here is an implementation of the `Messenger` interface in Groovy. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + // from the file 'Messenger.groovy' + package org.springframework.scripting.groovy; + + // import the Messenger interface (written in Java) that is to be implemented + import org.springframework.scripting.Messenger + + // define the implementation in Groovy + class GroovyMessenger implements Messenger { + + String message + + } +---- + +Finally, here are the bean definitions that will effect the injection of the +Groovy-defined `Messenger` implementation into an instance of the +`DefaultBookingService` class. + +[NOTE] +==== +To use the custom dynamic language tags to define dynamic-language-backed beans, you +need to have the XML Schema preamble at the top of your Spring XML configuration file. +You also need to be using a Spring `ApplicationContext` implementation as your IoC +container. Using the dynamic-language-backed beans with a plain `BeanFactory` +implementation is supported, but you have to manage the plumbing of the Spring internals +to do so. + +For more information on schema-based configuration, see <>. +==== + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + + + + + + + +---- + +The `bookingService` bean (a `DefaultBookingService`) can now use its private +`messenger` member variable as normal because the `Messenger` instance that was injected +into it __is__ a `Messenger` instance. There is nothing special going on here, just +plain Java and plain Groovy. + +Hopefully the above XML snippet is self-explanatory, but don't worry unduly if it isn't. +Keep reading for the in-depth detail on the whys and wherefores of the above +configuration. + + + + +[[dynamic-language-beans]] +=== Defining beans that are backed by dynamic languages +This section describes exactly how you define Spring managed beans in any of the +supported dynamic languages. + +Please note that this chapter does not attempt to explain the syntax and idioms of the +supported dynamic languages. For example, if you want to use Groovy to write certain of +the classes in your application, then the assumption is that you already know Groovy. If +you need further details about the dynamic languages themselves, please +consult <> at the end of this chapter. + + + +[[dynamic-language-beans-concepts]] +==== Common concepts +The steps involved in using dynamic-language-backed beans are as follows: + +* Write the test for the dynamic language source code (naturally) +* __Then__ write the dynamic language source code itself :) +* Define your dynamic-language-backed beans using the appropriate `` + element in the XML configuration (you can of course define such beans programmatically + using the Spring API - although you will have to consult the source code for + directions on how to do this as this type of advanced configuration is not covered in + this chapter). Note this is an iterative step. You will need at least one bean + definition per dynamic language source file (although the same dynamic language source + file can of course be referenced by multiple bean definitions). + +The first two steps (testing and writing your dynamic language source files) are beyond +the scope of this chapter. Refer to the language specification and / or reference manual +for your chosen dynamic language and crack on with developing your dynamic language +source files. You __will__ first want to read the rest of this chapter though, as +Spring's dynamic language support does make some (small) assumptions about the contents +of your dynamic language source files. + + +[[dynamic-language-beans-concepts-xml-language-element]] +===== The element +The final step involves defining dynamic-language-backed bean definitions, one for each +bean that you want to configure (this is no different from normal JavaBean +configuration). However, instead of specifying the fully qualified classname of the +class that is to be instantiated and configured by the container, you use the +`` element to define the dynamic language-backed bean. + +Each of the supported languages has a corresponding `` element: + +* `` (JRuby) +* `` (Groovy) +* `` (BeanShell) + +The exact attributes and child elements that are available for configuration depends on +exactly which language the bean has been defined in (the language-specific sections +below provide the full lowdown on this). + + +[[dynamic-language-refreshable-beans]] +===== Refreshable beans +One of the (if not __the__) most compelling value adds of the dynamic language support +in Spring is the__'refreshable bean'__ feature. + +A refreshable bean is a dynamic-language-backed bean that with a small amount of +configuration, a dynamic-language-backed bean can monitor changes in its underlying +source file resource, and then reload itself when the dynamic language source file is +changed (for example when a developer edits and saves changes to the file on the +filesystem). + +This allows a developer to deploy any number of dynamic language source files as part of +an application, configure the Spring container to create beans backed by dynamic +language source files (using the mechanisms described in this chapter), and then later, +as requirements change or some other external factor comes into play, simply edit a +dynamic language source file and have any change they make reflected in the bean that is +backed by the changed dynamic language source file. There is no need to shut down a +running application (or redeploy in the case of a web application). The +dynamic-language-backed bean so amended will pick up the new state and logic from the +changed dynamic language source file. + +[NOTE] +==== +Please note that this feature is __off__ by default. +==== + +Let's take a look at an example to see just how easy it is to start using refreshable +beans. To __turn on__ the refreshable beans feature, you simply have to specify exactly +__one__ additional attribute on the `` element of your bean definition. +So if we stick with <> from earlier in this +chapter, here's what we would change in the Spring XML configuration to effect +refreshable beans: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + script-source="classpath:Messenger.groovy"> + + + + + + + + +---- + +That really is all you have to do. The `'refresh-check-delay'` attribute defined on the +`'messenger'` bean definition is the number of milliseconds after which the bean will be +refreshed with any changes made to the underlying dynamic language source file. You can +turn off the refresh behavior by assigning a negative value to the +`'refresh-check-delay'` attribute. Remember that, by default, the refresh behavior is +disabled. If you don't want the refresh behavior, then simply don't define the attribute. + +If we then run the following application we can exercise the refreshable feature; please +do excuse the __'jumping-through-hoops-to-pause-the-execution'__ shenanigans in this +next slice of code. The `System.in.read()` call is only there so that the execution of +the program pauses while I (the author) go off and edit the underlying dynamic language +source file so that the refresh will trigger on the dynamic-language-backed bean when +the program resumes execution. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + import org.springframework.context.ApplicationContext; + import org.springframework.context.support.ClassPathXmlApplicationContext; + import org.springframework.scripting.Messenger; + + public final class Boot { + + public static void main(final String[] args) throws Exception { + ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml"); + Messenger messenger = (Messenger) ctx.getBean("messenger"); + System.out.println(messenger.getMessage()); + // pause execution while I go off and make changes to the source file... + System.in.read(); + System.out.println(messenger.getMessage()); + } + } +---- + +Let's assume then, for the purposes of this example, that all calls to the +`getMessage()` method of `Messenger` implementations have to be changed such that the +message is surrounded by quotes. Below are the changes that I (the author) make to the +`Messenger.groovy` source file when the execution of the program is paused. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + package org.springframework.scripting + + class GroovyMessenger implements Messenger { + + private String message = "Bingo" + + public String getMessage() { + // change the implementation to surround the message in quotes + return "'" + this.message + "'" + } + + public void setMessage(String message) { + this.message = message + } + } +---- + +When the program executes, the output before the input pause will be __I Can Do The +Frug__. After the change to the source file is made and saved, and the program resumes +execution, the result of calling the `getMessage()` method on the +dynamic-language-backed `Messenger` implementation will be __'I Can Do The Frug'__ +(notice the inclusion of the additional quotes). + +It is important to understand that changes to a script will __not__ trigger a refresh if +the changes occur within the window of the `'refresh-check-delay'` value. It is equally +important to understand that changes to the script are __not__ actually 'picked up' until +a method is called on the dynamic-language-backed bean. It is only when a method is +called on a dynamic-language-backed bean that it checks to see if its underlying script +source has changed. Any exceptions relating to refreshing the script (such as +encountering a compilation error, or finding that the script file has been deleted) will +result in a __fatal__ exception being propagated to the calling code. + +The refreshable bean behavior described above does __not__ apply to dynamic language +source files defined using the `` element notation (see +<>). Additionally, it __only__ applies to beans where +changes to the underlying source file can actually be detected; for example, by code +that checks the last modified date of a dynamic language source file that exists on the +filesystem. + + +[[dynamic-language-beans-inline]] +===== Inline dynamic language source files +The dynamic language support can also cater for dynamic language source files that are +embedded directly in Spring bean definitions. More specifically, the +`` element allows you to define dynamic language source immediately +inside a Spring configuration file. An example will perhaps make the inline script +feature crystal clear: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + package org.springframework.scripting.groovy; + + import org.springframework.scripting.Messenger + + class GroovyMessenger implements Messenger { + String message + } + + + + +---- + +If we put to one side the issues surrounding whether it is good practice to define +dynamic language source inside a Spring configuration file, the `` +element can be useful in some scenarios. For instance, we might want to quickly add a +Spring `Validator` implementation to a Spring MVC `Controller`. This is but a moment's +work using inline source. (See <> for such an +example.) + +Find below an example of defining the source for a JRuby-based bean directly in a Spring +XML configuration file using the `inline:` notation. (Notice the use of the < +characters to denote a `'<'` character. In such a case surrounding the inline source in +a `` region might be better.) + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + require 'java' + + include_class 'org.springframework.scripting.Messenger' + + class RubyMessenger < Messenger + + def setMessage(message) + @@message = message + end + + def getMessage + @@message + end + + end + + + + +---- + + +[[dynamic-language-beans-ctor-injection]] +===== Understanding Constructor Injection in the context of dynamic-language-backed beans +There is one __very__ important thing to be aware of with regard to Spring's dynamic +language support. Namely, it is not (currently) possible to supply constructor arguments +to dynamic-language-backed beans (and hence constructor-injection is not available for +dynamic-language-backed beans). In the interests of making this special handling of +constructors and properties 100% clear, the following mixture of code and configuration +will __not__ work. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + // from the file 'Messenger.groovy' + package org.springframework.scripting.groovy; + + import org.springframework.scripting.Messenger + + class GroovyMessenger implements Messenger { + + GroovyMessenger() {} + + // this constructor is not available for Constructor Injection + GroovyMessenger(String message) { + this.message = message; + } + + String message + + String anotherMessage + + } +---- + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + + +---- + +In practice this limitation is not as significant as it first appears since setter +injection is the injection style favored by the overwhelming majority of developers +anyway (let's leave the discussion as to whether that is a good thing to another day). + + + +[[dynamic-language-beans-jruby]] +==== JRuby beans + +.The JRuby library dependencies +**** +The JRuby scripting support in Spring requires the following libraries to be on the +classpath of your application. + +* `jruby.jar` +**** + +From the JRuby homepage... + +"__JRuby is an 100% pure-Java implementation of the Ruby programming language.__" + +In keeping with the Spring philosophy of offering choice, Spring's dynamic language +support also supports beans defined in the JRuby language. The JRuby language is based +on the quite intuitive Ruby language, and has support for inline regular expressions, +blocks (closures), and a whole host of other features that do make solutions for some +domain problems a whole lot easier to develop. + +The implementation of the JRuby dynamic language support in Spring is interesting in +that what happens is this: Spring creates a JDK dynamic proxy implementing all of the +interfaces that are specified in the `'script-interfaces'` attribute value of the +`` element (this is why you __must__ supply at least one interface in the +value of the attribute, and (accordingly) program to interfaces when using JRuby-backed +beans). + +Let us look at a fully working example of using a JRuby-based bean. Here is the JRuby +implementation of the `Messenger` interface that was defined earlier in this chapter +(for your convenience it is repeated below). + +[source,ruby,indent=0] +[subs="verbatim,quotes"] +---- + package org.springframework.scripting; + + public interface Messenger { + + String getMessage(); + + } +---- + +[source,ruby,indent=0] +[subs="verbatim,quotes"] +---- + require 'java' + + class RubyMessenger + include org.springframework.scripting.Messenger + + def setMessage(message) + @@message = message + end + + def getMessage + @@message + end + end + + # this last line is not essential (but see below) + RubyMessenger.new +---- + +And here is the Spring XML that defines an instance of the `RubyMessenger` JRuby bean. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + +---- + +Take note of the last line of that JRuby source ( `'RubyMessenger.new'`). When using +JRuby in the context of Spring's dynamic language support, you are encouraged to +instantiate and return a new instance of the JRuby class that you want to use as a +dynamic-language-backed bean as the result of the execution of your JRuby source. You +can achieve this by simply instantiating a new instance of your JRuby class on the last +line of the source file like so: + +[source,ruby,indent=0] +[subs="verbatim,quotes"] +---- + require 'java' + + include_class 'org.springframework.scripting.Messenger' + + # class definition same as above... + + # instantiate and return a new instance of the RubyMessenger class + RubyMessenger.new +---- + +If you forget to do this, it is not the end of the world; this will however result in +Spring having to trawl (reflectively) through the type representation of your JRuby +class looking for a class to instantiate. In the grand scheme of things this will be so +fast that you'll never notice it, but it is something that can be avoided by simply +having a line such as the one above as the last line of your JRuby script. If you don't +supply such a line, or if Spring cannot find a JRuby class in your script to instantiate +then an opaque `ScriptCompilationException` will be thrown immediately after the source +is executed by the JRuby interpreter. The key text that identifies this as the root +cause of an exception can be found immediately below (so if your Spring container throws +the following exception when creating your dynamic-language-backed bean and the +following text is there in the corresponding stacktrace, this will hopefully allow you +to identify and then easily rectify the issue): + +[literal] +[subs="verbatim,quotes"] +---- +org.springframework.scripting.ScriptCompilationException: Compilation of JRuby script returned '' +---- + +To rectify this, simply instantiate a new instance of whichever class you want to expose +as a JRuby-dynamic-language-backed bean (as shown above). Please also note that you can +actually define as many classes and objects as you want in your JRuby script; what is +important is that the source file as a whole must return an object (for Spring to +configure). + +See <> for some scenarios where you might want to use +JRuby-based beans. + + + +[[dynamic-language-beans-groovy]] +==== Groovy beans + +.The Groovy library dependencies +**** + +The Groovy scripting support in Spring requires the following libraries to be on the +classpath of your application. + +* `groovy-1.8.jar` +* `asm-3.2.jar` +* `antlr-2.7.7.jar` +**** + +From the Groovy homepage... + +"__Groovy is an agile dynamic language for the Java 2 Platform that has many of the +features that people like so much in languages like Python, Ruby and Smalltalk, making +them available to Java developers using a Java-like syntax. __" + +If you have read this chapter straight from the top, you will already have +<> of a Groovy-dynamic-language-backed +bean. Let's look at another example (again using an example from the Spring test suite). + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + package org.springframework.scripting; + + public interface Calculator { + + int add(int x, int y); + + } +---- + +Here is an implementation of the `Calculator` interface in Groovy. + +[source,groovy,indent=0] +[subs="verbatim,quotes"] +---- + // from the file 'calculator.groovy' + package org.springframework.scripting.groovy + + class GroovyCalculator implements Calculator { + + int add(int x, int y) { + x + y + } + + } +---- + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + <-- from the file 'beans.xml' --> + + + +---- + +Lastly, here is a small application to exercise the above configuration. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + package org.springframework.scripting; + + import org.springframework.context.ApplicationContext; + import org.springframework.context.support.ClassPathXmlApplicationContext; + + public class Main { + + public static void Main(String[] args) { + ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml"); + Calculator calc = (Calculator) ctx.getBean("calculator"); + System.out.println(calc.add(2, 8)); + } + } +---- + +The resulting output from running the above program will be (unsurprisingly) __10__. +(Exciting example, huh? Remember that the intent is to illustrate the concept. Please +consult the dynamic language showcase project for a more complex example, or indeed +<> later in this chapter). + +It is important that you __do not__ define more than one class per Groovy source file. +While this is perfectly legal in Groovy, it is (arguably) a bad practice: in the +interests of a consistent approach, you should (in the opinion of this author) respect +the standard Java conventions of one (public) class per source file. + + +[[dynamic-language-beans-groovy-customizer]] +===== Customizing Groovy objects via a callback +The `GroovyObjectCustomizer` interface is a callback that allows you to hook additional +creation logic into the process of creating a Groovy-backed bean. For example, +implementations of this interface could invoke any required initialization method(s), or +set some default property values, or specify a custom `MetaClass`. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public interface GroovyObjectCustomizer { + + void customize(GroovyObject goo); + + } +---- + +The Spring Framework will instantiate an instance of your Groovy-backed bean, and will +then pass the created `GroovyObject` to the specified `GroovyObjectCustomizer` if one +has been defined. You can do whatever you like with the supplied `GroovyObject` +reference: it is expected that the setting of a custom `MetaClass` is what most folks +will want to do with this callback, and you can see an example of doing that below. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public final class SimpleMethodTracingCustomizer implements GroovyObjectCustomizer { + + public void customize(GroovyObject goo) { + DelegatingMetaClass metaClass = new DelegatingMetaClass(goo.getMetaClass()) { + + public Object invokeMethod(Object object, String methodName, Object[] arguments) { + System.out.println("Invoking '" + methodName + "'."); + return super.invokeMethod(object, methodName, arguments); + } + }; + metaClass.initialize(); + goo.setMetaClass(metaClass); + } + + } +---- + +A full discussion of meta-programming in Groovy is beyond the scope of the Spring +reference manual. Consult the relevant section of the Groovy reference manual, or do a +search online: there are plenty of articles concerning this topic. Actually making use +of a `GroovyObjectCustomizer` is easy if you are using the Spring namespace support. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + +---- + +If you are not using the Spring namespace support, you can still use the +`GroovyObjectCustomizer` functionality. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + + +---- + + + +[[dynamic-language-beans-bsh]] +==== BeanShell beans + +.The BeanShell library dependencies +**** + +The BeanShell scripting support in Spring requires the following libraries to be on the +classpath of your application. + +* `bsh-2.0b4.jar` +**** + +From the BeanShell homepage... + +"__BeanShell is a small, free, embeddable Java source interpreter with dynamic language +features, written in Java. BeanShell dynamically executes standard Java syntax and +extends it with common scripting conveniences such as loose types, commands, and method +closures like those in Perl and JavaScript.__" + +In contrast to Groovy, BeanShell-backed bean definitions require some (small) additional +configuration. The implementation of the BeanShell dynamic language support in Spring is +interesting in that what happens is this: Spring creates a JDK dynamic proxy +implementing all of the interfaces that are specified in the `'script-interfaces'` +attribute value of the `` element (this is why you __must__ supply at least +one interface in the value of the attribute, and (accordingly) program to interfaces +when using BeanShell-backed beans). This means that every method call on a +BeanShell-backed object is going through the JDK dynamic proxy invocation mechanism. + +Let's look at a fully working example of using a BeanShell-based bean that implements +the `Messenger` interface that was defined earlier in this chapter (repeated below for +your convenience). + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + package org.springframework.scripting; + + public interface Messenger { + + String getMessage(); + + } +---- + +Here is the BeanShell 'implementation' (the term is used loosely here) of the +`Messenger` interface. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + String message; + + String getMessage() { + return message; + } + + void setMessage(String aMessage) { + message = aMessage; + } +---- + +And here is the Spring XML that defines an 'instance' of the above 'class' (again, the +term is used very loosely here). + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + +---- + +See <> for some scenarios where you might want to use +BeanShell-based beans. + + + + +[[dynamic-language-scenarios]] +=== Scenarios +The possible scenarios where defining Spring managed beans in a scripting language would +be beneficial are, of course, many and varied. This section describes two possible use +cases for the dynamic language support in Spring. + + + +[[dynamic-language-scenarios-controllers]] +==== Scripted Spring MVC Controllers +One group of classes that may benefit from using dynamic-language-backed beans is that +of Spring MVC controllers. In pure Spring MVC applications, the navigational flow +through a web application is to a large extent determined by code encapsulated within +your Spring MVC controllers. As the navigational flow and other presentation layer logic +of a web application needs to be updated to respond to support issues or changing +business requirements, it may well be easier to effect any such required changes by +editing one or more dynamic language source files and seeing those changes being +immediately reflected in the state of a running application. + +Remember that in the lightweight architectural model espoused by projects such as +Spring, you are typically aiming to have a really __thin__ presentation layer, with all +the meaty business logic of an application being contained in the domain and service +layer classes. Developing Spring MVC controllers as dynamic-language-backed beans allows +you to change presentation layer logic by simply editing and saving text files; any +changes to such dynamic language source files will (depending on the configuration) +automatically be reflected in the beans that are backed by dynamic language source files. + +[NOTE] +==== +In order to effect this automatic 'pickup' of any changes to dynamic-language-backed +beans, you will have had to enable the 'refreshable beans' functionality. See +<> for a full treatment of this feature. +==== + +Find below an example of an `org.springframework.web.servlet.mvc.Controller` implemented +using the Groovy dynamic language. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + // from the file '/WEB-INF/groovy/FortuneController.groovy' + package org.springframework.showcase.fortune.web + + import org.springframework.showcase.fortune.service.FortuneService + import org.springframework.showcase.fortune.domain.Fortune + import org.springframework.web.servlet.ModelAndView + import org.springframework.web.servlet.mvc.Controller + + import javax.servlet.http.HttpServletRequest + import javax.servlet.http.HttpServletResponse + + class FortuneController implements Controller { + + @Property FortuneService fortuneService + + ModelAndView handleRequest(HttpServletRequest request, + HttpServletResponse httpServletResponse) { + return new ModelAndView("tell", "fortune", this.fortuneService.tellFortune()) + } + + } +---- + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + +---- + + + +[[dynamic-language-scenarios-validators]] +==== Scripted Validators +Another area of application development with Spring that may benefit from the +flexibility afforded by dynamic-language-backed beans is that of validation. It __may__ +be easier to express complex validation logic using a loosely typed dynamic language +(that may also have support for inline regular expressions) as opposed to regular Java. + +Again, developing validators as dynamic-language-backed beans allows you to change +validation logic by simply editing and saving a simple text file; any such changes will +(depending on the configuration) automatically be reflected in the execution of a +running application and would not require the restart of an application. + +[NOTE] +==== +Please note that in order to effect the automatic 'pickup' of any changes to +dynamic-language-backed beans, you will have had to enable the 'refreshable beans' +feature. See <> for a full and detailed treatment of +this feature. +==== + +Find below an example of a Spring `org.springframework.validation.Validator` implemented +using the Groovy dynamic language. (See <> for a discussion of the +`Validator` interface.) + +[source,groovy,indent=0] +[subs="verbatim,quotes"] +---- + import org.springframework.validation.Validator + import org.springframework.validation.Errors + import org.springframework.beans.TestBean + + class TestBeanValidator implements Validator { + + boolean supports(Class clazz) { + return TestBean.class.isAssignableFrom(clazz) + } + + void validate(Object bean, Errors errors) { + if(bean.name?.trim()?.size() > 0) { + return + } + errors.reject("whitespace", "Cannot be composed wholly of whitespace.") + } + + } +---- + + + + +[[dynamic-language-final-notes]] +=== Bits and bobs +This last section contains some bits and bobs related to the dynamic language support. + + + +[[dynamic-language-final-notes-aop]] +==== AOP - advising scripted beans +It is possible to use the Spring AOP framework to advise scripted beans. The Spring AOP +framework actually is unaware that a bean that is being advised might be a scripted +bean, so all of the AOP use cases and functionality that you may be using or aim to use +will work with scripted beans. There is just one (small) thing that you need to be aware +of when advising scripted beans... you cannot use class-based proxies, you must +use <>. + +You are of course not just limited to advising scripted beans... you can also write +aspects themselves in a supported dynamic language and use such beans to advise other +Spring beans. This really would be an advanced use of the dynamic language support +though. + + + +[[dynamic-language-final-notes-scopes]] +==== Scoping +In case it is not immediately obvious, scripted beans can of course be scoped just like +any other bean. The `scope` attribute on the various `` elements allows +you to control the scope of the underlying scripted bean, just as it does with a regular +bean. (The default scope is <>, just as it is +with 'regular' beans.) + +Find below an example of using the `scope` attribute to define a Groovy bean scoped as +a <>. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + + + + + +---- + +See <> in <> for a fuller discussion of the scoping support +in the Spring Framework. + + + + +[[dynamic-language-resources]] +=== Further Resources +Find below links to further resources about the various dynamic languages described in +this chapter. + +* The http://jruby.codehaus.org/[JRuby] homepage +* The http://groovy.codehaus.org/[Groovy] homepage +* The http://www.beanshell.org/[BeanShell] homepage + +Some of the more active members of the Spring community have also added support for a +number of additional dynamic languages above and beyond the ones covered in this +chapter. While it is possible that such third party contributions may be added to the +list of languages supported by the main Spring distribution, your best bet for seeing if +your favorite scripting language is supported is the +https://springmodules.dev.java.net/[Spring Modules project]. + diff --git a/src/asciidoc/ejb.adoc b/src/asciidoc/ejb.adoc new file mode 100644 index 000000000000..8752f4fab0ed --- /dev/null +++ b/src/asciidoc/ejb.adoc @@ -0,0 +1,261 @@ +[[ejb]] +== Enterprise JavaBeans (EJB) integration + + + + +[[ejb-introduction]] +=== Introduction +As a lightweight container, Spring is often considered an EJB replacement. We do believe +that for many if not most applications and use cases, Spring as a container, combined +with its rich supporting functionality in the area of transactions, ORM and JDBC access, +is a better choice than implementing equivalent functionality via an EJB container and +EJBs. + +However, it is important to note that using Spring does not prevent you from using EJBs. +In fact, Spring makes it much easier to access EJBs and implement EJBs and functionality +within them. Additionally, using Spring to access services provided by EJBs allows the +implementation of those services to later transparently be switched between local EJB, +remote EJB, or POJO (plain old Java object) variants, without the client code having to +be changed. + +In this chapter, we look at how Spring can help you access and implement EJBs. Spring +provides particular value when accessing stateless session beans (SLSBs), so we'll begin +by discussing this. + + + + +[[ejb-access]] +=== Accessing EJBs + + + +[[ejb-access-concepts]] +==== Concepts +To invoke a method on a local or remote stateless session bean, client code must +normally perform a JNDI lookup to obtain the (local or remote) EJB Home object, then use +a 'create' method call on that object to obtain the actual (local or remote) EJB object. +One or more methods are then invoked on the EJB. + +To avoid repeated low-level code, many EJB applications use the Service Locator and +Business Delegate patterns. These are better than spraying JNDI lookups throughout +client code, but their usual implementations have significant disadvantages. For example: + +* Typically code using EJBs depends on Service Locator or Business Delegate singletons, + making it hard to test. +* In the case of the Service Locator pattern used without a Business Delegate, + application code still ends up having to invoke the create() method on an EJB home, + and deal with the resulting exceptions. Thus it remains tied to the EJB API and the + complexity of the EJB programming model. +* Implementing the Business Delegate pattern typically results in significant code + duplication, where we have to write numerous methods that simply call the same method + on the EJB. + +The Spring approach is to allow the creation and use of proxy objects, normally +configured inside a Spring container, which act as codeless business delegates. You do +not need to write another Service Locator, another JNDI lookup, or duplicate methods in +a hand-coded Business Delegate unless you are actually adding real value in such code. + + + +[[ejb-access-local]] +==== Accessing local SLSBs +Assume that we have a web controller that needs to use a local EJB. We'll follow best +practice and use the EJB Business Methods Interface pattern, so that the EJB's local +interface extends a non EJB-specific business methods interface. Let's call this +business methods interface `MyComponent`. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public interface MyComponent { + ... + } +---- + +One of the main reasons to use the Business Methods Interface pattern is to ensure that +synchronization between method signatures in local interface and bean implementation +class is automatic. Another reason is that it later makes it much easier for us to +switch to a POJO (plain old Java object) implementation of the service if it makes sense +to do so. Of course we'll also need to implement the local home interface and provide an +implementation class that implements `SessionBean` and the `MyComponent` business +methods interface. Now the only Java coding we'll need to do to hook up our web tier +controller to the EJB implementation is to expose a setter method of type `MyComponent` +on the controller. This will save the reference as an instance variable in the +controller: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + private MyComponent myComponent; + + public void setMyComponent(MyComponent myComponent) { + this.myComponent = myComponent; + } +---- + +We can subsequently use this instance variable in any business method in the controller. +Now assuming we are obtaining our controller object out of a Spring container, we can +(in the same context) configure a `LocalStatelessSessionProxyFactoryBean` instance, +which will be the EJB proxy object. The configuration of the proxy, and setting of the +`myComponent` property of the controller is done with a configuration entry such as: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + +---- + +There's a lot of work happening behind the scenes, courtesy of the Spring AOP framework, +although you aren't forced to work with AOP concepts to enjoy the results. The +`myComponent` bean definition creates a proxy for the EJB, which implements the business +method interface. The EJB local home is cached on startup, so there's only a single JNDI +lookup. Each time the EJB is invoked, the proxy invokes the `classname` method on the +local EJB and invokes the corresponding business method on the EJB. + +The `myController` bean definition sets the `myComponent` property of the controller +class to the EJB proxy. + +Alternatively (and preferably in case of many such proxy definitions), consider using +the `` configuration element in Spring's "jee" namespace: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + +---- + +This EJB access mechanism delivers huge simplification of application code: the web tier +code (or other EJB client code) has no dependence on the use of EJB. If we want to +replace this EJB reference with a POJO or a mock object or other test stub, we could +simply change the `myComponent` bean definition without changing a line of Java code. +Additionally, we haven't had to write a single line of JNDI lookup or other EJB plumbing +code as part of our application. + +Benchmarks and experience in real applications indicate that the performance overhead of +this approach (which involves reflective invocation of the target EJB) is minimal, and +is typically undetectable in typical use. Remember that we don't want to make +fine-grained calls to EJBs anyway, as there's a cost associated with the EJB +infrastructure in the application server. + +There is one caveat with regards to the JNDI lookup. In a bean container, this class is +normally best used as a singleton (there simply is no reason to make it a prototype). +However, if that bean container pre-instantiates singletons (as do the various XML +`ApplicationContext` variants) you may have a problem if the bean container is loaded +before the EJB container loads the target EJB. That is because the JNDI lookup will be +performed in the `init()` method of this class and then cached, but the EJB will not +have been bound at the target location yet. The solution is to not pre-instantiate this +factory object, but allow it to be created on first use. In the XML containers, this is +controlled via the `lazy-init` attribute. + +Although this will not be of interest to the majority of Spring users, those doing +programmatic AOP work with EJBs may want to look at `LocalSlsbInvokerInterceptor`. + + + +[[ejb-access-remote]] +==== Accessing remote SLSBs +Accessing remote EJBs is essentially identical to accessing local EJBs, except that the +`SimpleRemoteStatelessSessionProxyFactoryBean` or `` configuration +element is used. Of course, with or without Spring, remote invocation semantics apply; a +call to a method on an object in another VM in another computer does sometimes have to +be treated differently in terms of usage scenarios and failure handling. + +Spring's EJB client support adds one more advantage over the non-Spring approach. +Normally it is problematic for EJB client code to be easily switched back and forth +between calling EJBs locally or remotely. This is because the remote interface methods +must declare that they throw `RemoteException`, and client code must deal with this, +while the local interface methods don't. Client code written for local EJBs which needs +to be moved to remote EJBs typically has to be modified to add handling for the remote +exceptions, and client code written for remote EJBs which needs to be moved to local +EJBs, can either stay the same but do a lot of unnecessary handling of remote +exceptions, or needs to be modified to remove that code. With the Spring remote EJB +proxy, you can instead not declare any thrown `RemoteException` in your Business Method +Interface and implementing EJB code, have a remote interface which is identical except +that it does throw `RemoteException`, and rely on the proxy to dynamically treat the two +interfaces as if they were the same. That is, client code does not have to deal with the +checked `RemoteException` class. Any actual `RemoteException` that is thrown during the +EJB invocation will be re-thrown as the non-checked `RemoteAccessException` class, which +is a subclass of `RuntimeException`. The target service can then be switched at will +between a local EJB or remote EJB (or even plain Java object) implementation, without +the client code knowing or caring. Of course, this is optional; there is nothing +stopping you from declaring `RemoteExceptions` in your business interface. + + + +[[ejb-access-ejb2-ejb3]] +==== Accessing EJB 2.x SLSBs versus EJB 3 SLSBs +Accessing EJB 2.x Session Beans and EJB 3 Session Beans via Spring is largely +transparent. Spring's EJB accessors, including the `` and +`` facilities, transparently adapt to the actual component at runtime. +They handle a home interface if found (EJB 2.x style), or perform straight component +invocations if no home interface is available (EJB 3 style). + +Note: For EJB 3 Session Beans, you could effectively use a `JndiObjectFactoryBean` / +`` as well, since fully usable component references are exposed for +plain JNDI lookups there. Defining explicit `` / `` +lookups simply provides consistent and more explicit EJB access configuration. + + + + +[[ejb-implementation]] +=== Using Spring's EJB implementation support classes + + + +[[ejb-implementation-ejb3]] +==== EJB 3 injection interceptor +For EJB 3 Session Beans and Message-Driven Beans, Spring provides a convenient +interceptor that resolves Spring's `@Autowired` annotation in the EJB component +class: `org.springframework.ejb.interceptor.SpringBeanAutowiringInterceptor`. This +interceptor can be applied through an `@Interceptors` annotation in the EJB component +class, or through an `interceptor-binding` XML element in the EJB deployment descriptor. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Stateless + @Interceptors(SpringBeanAutowiringInterceptor.class) + public class MyFacadeEJB implements MyFacadeLocal { + + // automatically injected with a matching Spring bean + @Autowired + private MyComponent myComp; + + // for business method, delegate to POJO service impl. + public String myFacadeMethod(...) { + return myComp.myMethod(...); + } + + ... + + } +---- + +`SpringBeanAutowiringInterceptor` by default obtains target beans from a +`ContextSingletonBeanFactoryLocator`, with the context defined in a bean definition file +named `beanRefContext.xml`. By default, a single context definition is expected, which +is obtained by type rather than by name. However, if you need to choose between multiple +context definitions, a specific locator key is required. The locator key (i.e. the name +of the context definition in `beanRefContext.xml`) can be explicitly specified either +through overriding the `getBeanFactoryLocatorKey` method in a custom +`SpringBeanAutowiringInterceptor` subclass. + +Alternatively, consider overriding `SpringBeanAutowiringInterceptor`'s `getBeanFactory` +method, e.g. obtaining a shared `ApplicationContext` from a custom holder class. + diff --git a/src/asciidoc/expressions.adoc b/src/asciidoc/expressions.adoc new file mode 100644 index 000000000000..574910967372 --- /dev/null +++ b/src/asciidoc/expressions.adoc @@ -0,0 +1,1317 @@ +[[expressions]] +== Spring Expression Language (SpEL) + + + + +[[expressions-intro]] +=== Introduction +The Spring Expression Language (SpEL for short) is a powerful expression language that +supports querying and manipulating an object graph at runtime. The language syntax is +similar to Unified EL but offers additional features, most notably method invocation and +basic string templating functionality. + +While there are several other Java expression languages available, OGNL, MVEL, and JBoss +EL, to name a few, the Spring Expression Language was created to provide the Spring +community with a single well supported expression language that can be used across all +the products in the Spring portfolio. Its language features are driven by the +requirements of the projects in the Spring portfolio, including tooling requirements for +code completion support within the eclipse based Spring Tool Suite. That said, +SpEL is based on a technology agnostic API allowing other expression language +implementations to be integrated should the need arise. + +While SpEL serves as the foundation for expression evaluation within the Spring +portfolio, it is not directly tied to Spring and can be used independently. In order to +be self contained, many of the examples in this chapter use SpEL as if it were an +independent expression language. This requires creating a few bootstrapping +infrastructure classes such as the parser. Most Spring users will not need to deal with +this infrastructure and will instead only author expression strings for evaluation. An +example of this typical use is the integration of SpEL into creating XML or annotated +based bean definitions as shown in the section <> + +This chapter covers the features of the expression language, its API, and its language +syntax. In several places an Inventor and Inventor's Society class are used as the +target objects for expression evaluation. These class declarations and the data used to +populate them are listed at the end of the chapter. + + + + +[[expressions-features]] +=== Feature Overview +The expression language supports the following functionality + +* Literal expressions +* Boolean and relational operators +* Regular expressions +* Class expressions +* Accessing properties, arrays, lists, maps +* Method invocation +* Relational operators +* Assignment +* Calling constructors +* Bean references +* Array construction +* Inline lists +* Inline maps +* Ternary operator +* Variables +* User defined functions +* Collection projection +* Collection selection +* Templated expressions + + + + +[[expressions-evaluation]] +=== Expression Evaluation using Spring's Expression Interface +This section introduces the simple use of SpEL interfaces and its expression language. +The complete language reference can be found in the section +<>. + +The following code introduces the SpEL API to evaluate the literal string expression +'Hello World'. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + ExpressionParser parser = new SpelExpressionParser(); + Expression exp = parser.parseExpression("**\'Hello World'**"); + String message = (String) exp.getValue(); +---- + +The value of the message variable is simply 'Hello World'. + +The SpEL classes and interfaces you are most likely to use are located in the packages +`org.springframework.expression` and its sub packages and `spel.support`. + +The interface `ExpressionParser` is responsible for parsing an expression string. In +this example the expression string is a string literal denoted by the surrounding single +quotes. The interface `Expression` is responsible for evaluating the previously defined +expression string. There are two exceptions that can be thrown, `ParseException` and +`EvaluationException` when calling ' `parser.parseExpression`' and ' `exp.getValue`' +respectively. + +SpEL supports a wide range of features, such as calling methods, accessing properties, +and calling constructors. + +As an example of method invocation, we call the 'concat' method on the string literal. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + ExpressionParser parser = new SpelExpressionParser(); + Expression exp = parser.parseExpression("**\'Hello World'.concat(\'!')**"); + String message = (String) exp.getValue(); +---- + +The value of message is now 'Hello World!'. + +As an example of calling a JavaBean property, the String property 'Bytes' can be called +as shown below. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + ExpressionParser parser = new SpelExpressionParser(); + + // invokes 'getBytes()' + Expression exp = parser.parseExpression("**\'Hello World'.bytes**"); + byte[] bytes = (byte[]) exp.getValue(); +---- + +SpEL also supports nested properties using standard 'dot' notation, i.e. +prop1.prop2.prop3 and the setting of property values + +Public fields may also be accessed. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + ExpressionParser parser = new SpelExpressionParser(); + + // invokes 'getBytes().length' + Expression exp = parser.parseExpression("**\'Hello World'.bytes.length**"); + int length = (Integer) exp.getValue(); +---- + +The String's constructor can be called instead of using a string literal. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + ExpressionParser parser = new SpelExpressionParser(); + Expression exp = parser.parseExpression("**new String(\'hello world').toUpperCase()**"); + String message = exp.getValue(String.class); +---- + +Note the use of the generic method `public T getValue(Class desiredResultType)`. +Using this method removes the need to cast the value of the expression to the desired +result type. An `EvaluationException` will be thrown if the value cannot be cast to the +type `T` or converted using the registered type converter. + +The more common usage of SpEL is to provide an expression string that is evaluated +against a specific object instance (called the root object). There are two options here +and which to choose depends on whether the object against which the expression is being +evaluated will be changing with each call to evaluate the expression. In the following +example we retrieve the `name` property from an instance of the Inventor class. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + // Create and set a calendar + GregorianCalendar c = new GregorianCalendar(); + c.set(1856, 7, 9); + + // The constructor arguments are name, birthday, and nationality. + Inventor tesla = new Inventor("Nikola Tesla", c.getTime(), "Serbian"); + + ExpressionParser parser = new SpelExpressionParser(); + Expression exp = parser.parseExpression("**name**"); + + EvaluationContext context = new StandardEvaluationContext(tesla); + String name = (String) exp.getValue(context); +---- + +In the last line, the value of the string variable 'name' will be set to "Nikola Tesla". +The class StandardEvaluationContext is where you can specify which object the "name" +property will be evaluated against. This is the mechanism to use if the root object is +unlikely to change, it can simply be set once in the evaluation context. If the root +object is likely to change repeatedly, it can be supplied on each call to `getValue`, as +this next example shows: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + / Create and set a calendar + GregorianCalendar c = new GregorianCalendar(); + c.set(1856, 7, 9); + + // The constructor arguments are name, birthday, and nationality. + Inventor tesla = new Inventor("Nikola Tesla", c.getTime(), "Serbian"); + + ExpressionParser parser = new SpelExpressionParser(); + Expression exp = parser.parseExpression("**name**"); + String name = (String) exp.getValue(tesla); +---- + +In this case the inventor `tesla` has been supplied directly to `getValue` and the +expression evaluation infrastructure creates and manages a default evaluation context +internally - it did not require one to be supplied. + +The StandardEvaluationContext is relatively expensive to construct and during repeated +usage it builds up cached state that enables subsequent expression evaluations to be +performed more quickly. For this reason it is better to cache and reuse them where +possible, rather than construct a new one for each expression evaluation. + +In some cases it can be desirable to use a configured evaluation context and yet still +supply a different root object on each call to `getValue`. `getValue` allows both to be +specified on the same call. In these situations the root object passed on the call is +considered to override any (which maybe null) specified on the evaluation context. + +[NOTE] +==== +In standalone usage of SpEL there is a need to create the parser, parse expressions and +perhaps provide evaluation contexts and a root context object. However, more common +usage is to provide only the SpEL expression string as part of a configuration file, for +example for Spring bean or Spring Web Flow definitions. In this case, the parser, +evaluation context, root object and any predefined variables are all set up implicitly, +requiring the user to specify nothing other than the expressions. +==== +As a final introductory example, the use of a boolean operator is shown using the +Inventor object in the previous example. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + Expression exp = parser.parseExpression("name == 'Nikola Tesla'"); + boolean result = exp.getValue(context, Boolean.class); // evaluates to true +---- + + + +[[expressions-evaluation-context]] +==== The EvaluationContext interface +The interface `EvaluationContext` is used when evaluating an expression to resolve +properties, methods, fields, and to help perform type conversion. The out-of-the-box +implementation, `StandardEvaluationContext`, uses reflection to manipulate the object, +caching `java.lang.reflect`'s `Method`, `Field`, and `Constructor` instances for +increased performance. + +The `StandardEvaluationContext` is where you may specify the root object to evaluate +against via the method `setRootObject()` or passing the root object into the +constructor. You can also specify variables and functions that will be used in the +expression using the methods `setVariable()` and `registerFunction()`. The use of +variables and functions are described in the language reference sections +<> and <>. The +`StandardEvaluationContext` is also where you can register custom +++ConstructorResolver++s, ++MethodResolver++s, and ++PropertyAccessor++s to extend how SpEL +evaluates expressions. Please refer to the JavaDoc of these classes for more details. + + +[[expressions-type-conversion]] +===== Type Conversion +By default SpEL uses the conversion service available in Spring core ( +`org.springframework.core.convert.ConversionService`). This conversion service comes +with many converters built in for common conversions but is also fully extensible so +custom conversions between types can be added. Additionally it has the key capability +that it is generics aware. This means that when working with generic types in +expressions, SpEL will attempt conversions to maintain type correctness for any objects +it encounters. + +What does this mean in practice? Suppose assignment, using `setValue()`, is being used +to set a `List` property. The type of the property is actually `List`. SpEL +will recognize that the elements of the list need to be converted to `Boolean` before +being placed in it. A simple example: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + class Simple { + public List booleanList = new ArrayList(); + } + + Simple simple = new Simple(); + + simple.booleanList.add(true); + + StandardEvaluationContext simpleContext = new StandardEvaluationContext(simple); + + // false is passed in here as a string. SpEL and the conversion service will + // correctly recognize that it needs to be a Boolean and convert it + parser.parseExpression("booleanList[0]").setValue(simpleContext, "false"); + + // b will be false + Boolean b = simple.booleanList.get(0); +---- + + + + +[[expressions-beandef]] +=== Expression support for defining bean definitions +SpEL expressions can be used with XML or annotation-based configuration metadata for +defining ++BeanDefinition++s. In both cases the syntax to define the expression is of the +form `#{ }`. + + + +[[expressions-beandef-xml-based]] +==== XML based configuration +A property or constructor-arg value can be set using expressions as shown below. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + +---- + +The variable `systemProperties` is predefined, so you can use it in your expressions as +shown below. Note that you do not have to prefix the predefined variable with the `#` +symbol in this context. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + +---- + +You can also refer to other bean properties by name, for example. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + + + + +---- + + + +[[expressions-beandef-annotation-based]] +==== Annotation-based configuration +The `@Value` annotation can be placed on fields, methods and method/constructor +parameters to specify a default value. + +Here is an example to set the default value of a field variable. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public static class FieldValueTestBean + + @Value("#{ systemProperties['user.region'] }") + private String defaultLocale; + + public void setDefaultLocale(String defaultLocale) { + this.defaultLocale = defaultLocale; + } + + public String getDefaultLocale() { + return this.defaultLocale; + } + + } +---- + +The equivalent but on a property setter method is shown below. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public static class PropertyValueTestBean + + private String defaultLocale; + + @Value("#{ systemProperties['user.region'] }") + public void setDefaultLocale(String defaultLocale) { + this.defaultLocale = defaultLocale; + } + + public String getDefaultLocale() { + return this.defaultLocale; + } + + } +---- + +Autowired methods and constructors can also use the `@Value` annotation. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class SimpleMovieLister { + + private MovieFinder movieFinder; + private String defaultLocale; + + @Autowired + public void configure(MovieFinder movieFinder, + @Value("#{ systemProperties['user.region'] }") String defaultLocale) { + this.movieFinder = movieFinder; + this.defaultLocale = defaultLocale; + } + + // ... + } +---- + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class MovieRecommender { + + private String defaultLocale; + + private CustomerPreferenceDao customerPreferenceDao; + + @Autowired + public MovieRecommender(CustomerPreferenceDao customerPreferenceDao, + @Value("#{systemProperties['user.country']}") String defaultLocale) { + this.customerPreferenceDao = customerPreferenceDao; + this.defaultLocale = defaultLocale; + } + + // ... + } +---- + + + + +[[expressions-language-ref]] +=== Language Reference + + + +[[expressions-ref-literal]] +==== Literal expressions +The types of literal expressions supported are strings, dates, numeric values (int, +real, and hex), boolean and null. Strings are delimited by single quotes. To put a +single quote itself in a string use two single quote characters. The following listing +shows simple usage of literals. Typically they would not be used in isolation like this, +but as part of a more complex expression, for example using a literal on one side of a +logical comparison operator. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + ExpressionParser parser = new SpelExpressionParser(); + + // evals to "Hello World" + String helloWorld = (String) parser.parseExpression("'Hello World'").getValue(); + + double avogadrosNumber = (Double) parser.parseExpression("6.0221415E+23").getValue(); + + // evals to 2147483647 + int maxValue = (Integer) parser.parseExpression("0x7FFFFFFF").getValue(); + + boolean trueValue = (Boolean) parser.parseExpression("true").getValue(); + + Object nullValue = parser.parseExpression("null").getValue(); +---- + +Numbers support the use of the negative sign, exponential notation, and decimal points. +By default real numbers are parsed using Double.parseDouble(). + + + +[[expressions-properties-arrays]] +==== Properties, Arrays, Lists, Maps, Indexers +Navigating with property references is easy: just use a period to indicate a nested +property value. The instances of the `Inventor` class, pupin, and tesla, were populated with +data listed in the section <>. +To navigate "down" and get Tesla's year of birth and Pupin's city of birth the following +expressions are used. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + // evals to 1856 + int year = (Integer) parser.parseExpression("Birthdate.Year + 1900").getValue(context); + + String city = (String) parser.parseExpression("placeOfBirth.City").getValue(context); +---- + +Case insensitivity is allowed for the first letter of property names. The contents of +arrays and lists are obtained using square bracket notation. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + ExpressionParser parser = new SpelExpressionParser(); + + // Inventions Array + StandardEvaluationContext teslaContext = new StandardEvaluationContext(tesla); + + // evaluates to "Induction motor" + String invention = parser.parseExpression("inventions[3]").getValue( + teslaContext, String.class); + + // Members List + StandardEvaluationContext societyContext = new StandardEvaluationContext(ieee); + + // evaluates to "Nikola Tesla" + String name = parser.parseExpression("Members[0].Name").getValue( + societyContext, String.class); + + // List and Array navigation + // evaluates to "Wireless communication" + String invention = parser.parseExpression("Members[0].Inventions[6]").getValue( + societyContext, String.class); +---- + +The contents of maps are obtained by specifying the literal key value within the +brackets. In this case, because keys for the Officers map are strings, we can specify +string literals. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + // Officer's Dictionary + + Inventor pupin = parser.parseExpression("Officers['president']").getValue( + societyContext, Inventor.class); + + // evaluates to "Idvor" + String city = parser.parseExpression("Officers['president'].PlaceOfBirth.City").getValue( + societyContext, String.class); + + // setting values + parser.parseExpression("Officers['advisors'][0].PlaceOfBirth.Country").setValue( + societyContext, "Croatia"); +---- + + + +[[expressions-inline-lists]] +==== Inline lists +Lists can be expressed directly in an expression using `{}` notation. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + // evaluates to a Java list containing the four numbers + List numbers = (List) parser.parseExpression("{1,2,3,4}").getValue(context); + + List listOfLists = (List) parser.parseExpression("{{'a','b'},{'x','y'}}").getValue(context); +---- + +`{}` by itself means an empty list. For performance reasons, if the list is itself +entirely composed of fixed literals then a constant list is created to represent the +expression, rather than building a new list on each evaluation. + +[[expressions-inline-maps]] +==== Inline Maps +Maps can also be expressed directly in an expression using `{key:value}` notation. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + // evaluates to a Java map containing the two entries + Map inventorInfo = (Map) parser.parseExpression("{name:'Nikola',dob:'10-July-1856'}").getValue(context); + + Map mapOfMaps = (Map) parser.parseExpression("{name:{first:'Nikola',last:'Tesla'},dob:{day:10,month:'July',year:1856}}").getValue(context); +---- +`{:}` by itself means an empty map. For performance reasons, if the map is itself composed +of fixed literals or other nested constant structures (lists or maps) then a constant map is created +to represent the expression, rather than building a new map on each evaluation. Quoting of the map keys +is optional, the examples above are not using quoted keys. + +[[expressions-array-construction]] +==== Array construction +Arrays can be built using the familiar Java syntax, optionally supplying an initializer +to have the array populated at construction time. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + int[] numbers1 = (int[]) parser.parseExpression("new int[4]").getValue(context); + + // Array with initializer + int[] numbers2 = (int[]) parser.parseExpression("new int[]{1,2,3}").getValue(context); + + // Multi dimensional array + int[][] numbers3 = (int[][]) parser.parseExpression("new int[4][5]").getValue(context); +---- + +It is not currently allowed to supply an initializer when constructing a +multi-dimensional array. + + + +[[expressions-methods]] +==== Methods +Methods are invoked using typical Java programming syntax. You may also invoke methods +on literals. Varargs are also supported. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + // string literal, evaluates to "bc" + String c = parser.parseExpression("'abc'.substring(2, 3)").getValue(String.class); + + // evaluates to true + boolean isMember = parser.parseExpression("isMember('Mihajlo Pupin')").getValue( + societyContext, Boolean.class); +---- + + + +[[expressions-operators]] +==== Operators + + +[[expressions-operators-relational]] +===== Relational operators +The relational operators; equal, not equal, less than, less than or equal, greater than, +and greater than or equal are supported using standard operator notation. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + // evaluates to true + boolean trueValue = parser.parseExpression("2 == 2").getValue(Boolean.class); + + // evaluates to false + boolean falseValue = parser.parseExpression("2 < -5.0").getValue(Boolean.class); + + // evaluates to true + boolean trueValue = parser.parseExpression("'black' < 'block'").getValue(Boolean.class); +---- + +In addition to standard relational operators SpEL supports the `instanceof` and regular +expression based `matches` operator. + +[source,java,indent=0] +[subs="none"] +---- + // evaluates to false + boolean falseValue = parser.parseExpression( + "'xyz' instanceof T(int)").getValue(Boolean.class); + + // evaluates to true + boolean trueValue = parser.parseExpression( + "'5.00' matches '^-?\\d+(\\.\\d{2})?$'").getValue(Boolean.class); + + //evaluates to false + boolean falseValue = parser.parseExpression( + "'5.0067' matches '^-?\\d+(\\.\\d{2})?$'").getValue(Boolean.class); +---- + +Each symbolic operator can also be specified as a purely alphabetic equivalent. This +avoids problems where the symbols used have special meaning for the document type in +which the expression is embedded (eg. an XML document). The textual equivalents are +shown here: `lt` (`<`), `gt` (`>`), `le` (`<=`), `ge` (`>=`), `eq` (`==`), +`ne` (`!=`), `div` (`/`), `mod` (`%`), `not` (`!`). These are case insensitive. + + +[[expressions-operators-logical]] +===== Logical operators +The logical operators that are supported are and, or, and not. Their use is demonstrated +below. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + // -- AND -- + + // evaluates to false + boolean falseValue = parser.parseExpression("true and false").getValue(Boolean.class); + + // evaluates to true + String expression = "isMember('Nikola Tesla') and isMember('Mihajlo Pupin')"; + boolean trueValue = parser.parseExpression(expression).getValue(societyContext, Boolean.class); + + // -- OR -- + + // evaluates to true + boolean trueValue = parser.parseExpression("true or false").getValue(Boolean.class); + + // evaluates to true + String expression = "isMember('Nikola Tesla') or isMember('Albert Einstein')"; + boolean trueValue = parser.parseExpression(expression).getValue(societyContext, Boolean.class); + + // -- NOT -- + + // evaluates to false + boolean falseValue = parser.parseExpression("!true").getValue(Boolean.class); + + // -- AND and NOT -- + String expression = "isMember('Nikola Tesla') and !isMember('Mihajlo Pupin')"; + boolean falseValue = parser.parseExpression(expression).getValue(societyContext, Boolean.class); +---- + + +[[expressions-operators-mathematical]] +===== Mathematical operators +The addition operator can be used on both numbers and strings. Subtraction, multiplication +and division can be used only on numbers. Other mathematical operators supported are +modulus (%) and exponential power (^). Standard operator precedence is enforced. These +operators are demonstrated below. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + // Addition + int two = parser.parseExpression("1 + 1").getValue(Integer.class); // 2 + + String testString = parser.parseExpression( + "'test' + ' ' + 'string'").getValue(String.class); // 'test string' + + // Subtraction + int four = parser.parseExpression("1 - -3").getValue(Integer.class); // 4 + + double d = parser.parseExpression("1000.00 - 1e4").getValue(Double.class); // -9000 + + // Multiplication + int six = parser.parseExpression("-2 * -3").getValue(Integer.class); // 6 + + double twentyFour = parser.parseExpression("2.0 * 3e0 * 4").getValue(Double.class); // 24.0 + + // Division + int minusTwo = parser.parseExpression("6 / -3").getValue(Integer.class); // -2 + + double one = parser.parseExpression("8.0 / 4e0 / 2").getValue(Double.class); // 1.0 + + // Modulus + int three = parser.parseExpression("7 % 4").getValue(Integer.class); // 3 + + int one = parser.parseExpression("8 / 5 % 2").getValue(Integer.class); // 1 + + // Operator precedence + int minusTwentyOne = parser.parseExpression("1+2-3*8").getValue(Integer.class); // -21 +---- + + + +[[expressions-assignment]] +==== Assignment +Setting of a property is done by using the assignment operator. This would typically be +done within a call to `setValue` but can also be done inside a call to `getValue`. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + Inventor inventor = new Inventor(); + StandardEvaluationContext inventorContext = new StandardEvaluationContext(inventor); + + parser.parseExpression("Name").setValue(inventorContext, "Alexander Seovic2"); + + // alternatively + + String aleks = parser.parseExpression( + "Name = 'Alexandar Seovic'").getValue(inventorContext, String.class); +---- + + + +[[expressions-types]] +==== Types +The special `T` operator can be used to specify an instance of java.lang.Class (the +_type_). Static methods are invoked using this operator as well. The +`StandardEvaluationContext` uses a `TypeLocator` to find types and the +`StandardTypeLocator` (which can be replaced) is built with an understanding of the +java.lang package. This means T() references to types within java.lang do not need to be +fully qualified, but all other type references must be. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + Class dateClass = parser.parseExpression("T(java.util.Date)").getValue(Class.class); + + Class stringClass = parser.parseExpression("T(String)").getValue(Class.class); + + boolean trueValue = parser.parseExpression( + "T(java.math.RoundingMode).CEILING < T(java.math.RoundingMode).FLOOR") + .getValue(Boolean.class); +---- + + + +[[expressions-constructors]] +==== Constructors +Constructors can be invoked using the new operator. The fully qualified class name +should be used for all but the primitive type and String (where int, float, etc, can be +used). + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + Inventor einstein = p.parseExpression( + "new org.spring.samples.spel.inventor.Inventor('Albert Einstein', 'German')") + .getValue(Inventor.class); + + //create new inventor instance within add method of List + p.parseExpression( + "Members.add(new org.spring.samples.spel.inventor.Inventor( + 'Albert Einstein', 'German'))").getValue(societyContext); +---- + + + +[[expressions-ref-variables]] +==== Variables +Variables can be referenced in the expression using the syntax `#variableName`. Variables +are set using the method setVariable on the `StandardEvaluationContext`. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + Inventor tesla = new Inventor("Nikola Tesla", "Serbian"); + StandardEvaluationContext context = new StandardEvaluationContext(tesla); + context.setVariable("newName", "Mike Tesla"); + + parser.parseExpression("Name = #newName").getValue(context); + + System.out.println(tesla.getName()) // "Mike Tesla" +---- + + +[[expressions-this-root]] +===== The #this and #root variables +The variable #this is always defined and refers to the current evaluation object +(against which unqualified references are resolved). The variable #root is always +defined and refers to the root context object. Although #this may vary as components of +an expression are evaluated, #root always refers to the root. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + // create an array of integers + List primes = new ArrayList(); + primes.addAll(Arrays.asList(2,3,5,7,11,13,17)); + + // create parser and set variable 'primes' as the array of integers + ExpressionParser parser = new SpelExpressionParser(); + StandardEvaluationContext context = new StandardEvaluationContext(); + context.setVariable("primes",primes); + + // all prime numbers > 10 from the list (using selection ?{...}) + // evaluates to [11, 13, 17] + List primesGreaterThanTen = (List) parser.parseExpression( + "#primes.?[#this>10]").getValue(context); +---- + + + +[[expressions-ref-functions]] +==== Functions +You can extend SpEL by registering user defined functions that can be called within the +expression string. The function is registered with the `StandardEvaluationContext` using +the method. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public void registerFunction(String name, Method m) +---- + +A reference to a Java Method provides the implementation of the function. For example, a +utility method to reverse a string is shown below. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public abstract class StringUtils { + + public static String reverseString(String input) { + StringBuilder backwards = new StringBuilder(); + for (int i = 0; i < input.length(); i++) + backwards.append(input.charAt(input.length() - 1 - i)); + } + return backwards.toString(); + } + } +---- + +This method is then registered with the evaluation context and can be used within an +expression string. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + ExpressionParser parser = new SpelExpressionParser(); + StandardEvaluationContext context = new StandardEvaluationContext(); + + context.registerFunction("reverseString", + StringUtils.class.getDeclaredMethod("reverseString", new Class[] { String.class })); + + String helloWorldReversed = parser.parseExpression( + "#reverseString('hello')").getValue(context, String.class); +---- + + + +[[expressions-bean-references]] +==== Bean references +If the evaluation context has been configured with a bean resolver it is possible to +lookup beans from an expression using the (@) symbol. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + ExpressionParser parser = new SpelExpressionParser(); + StandardEvaluationContext context = new StandardEvaluationContext(); + context.setBeanResolver(new MyBeanResolver()); + + // This will end up calling resolve(context,"foo") on MyBeanResolver during evaluation + Object bean = parser.parseExpression("@foo").getValue(context); +---- + + + +[[expressions-operator-ternary]] +==== Ternary Operator (If-Then-Else) +You can use the ternary operator for performing if-then-else conditional logic inside +the expression. A minimal example is: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + String falseString = parser.parseExpression( + "false ? 'trueExp' : 'falseExp'").getValue(String.class); +---- + +In this case, the boolean false results in returning the string value 'falseExp'. A more +realistic example is shown below. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + parser.parseExpression("Name").setValue(societyContext, "IEEE"); + societyContext.setVariable("queryName", "Nikola Tesla"); + + expression = "isMember(#queryName)? #queryName + ' is a member of the ' " + + "+ Name + ' Society' : #queryName + ' is not a member of the ' + Name + ' Society'"; + + String queryResultString = parser.parseExpression(expression) + .getValue(societyContext, String.class); + // queryResultString = "Nikola Tesla is a member of the IEEE Society" +---- + +Also see the next section on the Elvis operator for an even shorter syntax for the +ternary operator. + + + +[[expressions-operator-elvis]] +==== The Elvis Operator +The Elvis operator is a shortening of the ternary operator syntax and is used in the +http://groovy.codehaus.org/Operators#Operators-ElvisOperator(%3F%3A)[Groovy] language. +With the ternary operator syntax you usually have to repeat a variable twice, for +example: + +[source,groovy,indent=0] +[subs="verbatim,quotes"] +---- + String name = "Elvis Presley"; + String displayName = name != null ? name : "Unknown"; +---- + +Instead you can use the Elvis operator, named for the resemblance to Elvis' hair style. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + ExpressionParser parser = new SpelExpressionParser(); + + String name = parser.parseExpression("null?:'Unknown'").getValue(String.class); + + System.out.println(name); // 'Unknown' +---- + +Here is a more complex example. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + ExpressionParser parser = new SpelExpressionParser(); + + Inventor tesla = new Inventor("Nikola Tesla", "Serbian"); + StandardEvaluationContext context = new StandardEvaluationContext(tesla); + + String name = parser.parseExpression("Name?:'Elvis Presley'").getValue(context, String.class); + + System.out.println(name); // Nikola Tesla + + tesla.setName(null); + + name = parser.parseExpression("Name?:'Elvis Presley'").getValue(context, String.class); + + System.out.println(name); // Elvis Presley +---- + + + +[[expressions-operator-safe-navigation]] +==== Safe Navigation operator +The Safe Navigation operator is used to avoid a `NullPointerException` and comes from +the http://groovy.codehaus.org/Operators#Operators-SafeNavigationOperator(%3F.)[Groovy] +language. Typically when you have a reference to an object you might need to verify that +it is not null before accessing methods or properties of the object. To avoid this, the +safe navigation operator will simply return null instead of throwing an exception. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + ExpressionParser parser = new SpelExpressionParser(); + + Inventor tesla = new Inventor("Nikola Tesla", "Serbian"); + tesla.setPlaceOfBirth(new PlaceOfBirth("Smiljan")); + + StandardEvaluationContext context = new StandardEvaluationContext(tesla); + + String city = parser.parseExpression("PlaceOfBirth?.City").getValue(context, String.class); + System.out.println(city); // Smiljan + + tesla.setPlaceOfBirth(null); + + city = parser.parseExpression("PlaceOfBirth?.City").getValue(context, String.class); + + System.out.println(city); // null - does not throw NullPointerException!!! +---- + +[NOTE] +==== +The Elvis operator can be used to apply default values in expressions, e.g. in an +`@Value` expression: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Value("#{systemProperties['pop3.port'] ?: 25}") +---- + +This will inject a system property `pop3.port` if it is defined or 25 if not. +==== + + + +[[expressions-collection-selection]] +==== Collection Selection +Selection is a powerful expression language feature that allows you to transform some +source collection into another by selecting from its entries. + +Selection uses the syntax `?[selectionExpression]`. This will filter the collection and +return a new collection containing a subset of the original elements. For example, +selection would allow us to easily get a list of Serbian inventors: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + List list = (List) parser.parseExpression( + "Members.?[Nationality == 'Serbian']").getValue(societyContext); +---- + +Selection is possible upon both lists and maps. In the former case the selection +criteria is evaluated against each individual list element whilst against a map the +selection criteria is evaluated against each map entry (objects of the Java type +`Map.Entry`). Map entries have their key and value accessible as properties for use in +the selection. + +This expression will return a new map consisting of those elements of the original map +where the entry value is less than 27. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + Map newMap = parser.parseExpression("map.?[value<27]").getValue(); +---- + +In addition to returning all the selected elements, it is possible to retrieve just the +first or the last value. To obtain the first entry matching the selection the syntax is +`^[...]` whilst to obtain the last matching selection the syntax is `$[...]`. + + + +[[expressions-collection-projection]] +==== Collection Projection +Projection allows a collection to drive the evaluation of a sub-expression and the +result is a new collection. The syntax for projection is `![projectionExpression]`. Most +easily understood by example, suppose we have a list of inventors but want the list of +cities where they were born. Effectively we want to evaluate 'placeOfBirth.city' for +every entry in the inventor list. Using projection: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + // returns ['Smiljan', 'Idvor' ] + List placesOfBirth = (List)parser.parseExpression("Members.![placeOfBirth.city]"); +---- + +A map can also be used to drive projection and in this case the projection expression is +evaluated against each entry in the map (represented as a Java `Map.Entry`). The result +of a projection across a map is a list consisting of the evaluation of the projection +expression against each map entry. + + + +[[expressions-templating]] +==== Expression templating +Expression templates allow a mixing of literal text with one or more evaluation blocks. +Each evaluation block is delimited with prefix and suffix characters that you can +define, a common choice is to use `#{ }` as the delimiters. For example, + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + String randomPhrase = parser.parseExpression( + "random number is #{T(java.lang.Math).random()}", + new TemplateParserContext()).getValue(String.class); + + // evaluates to "random number is 0.7038186818312008" +---- + +The string is evaluated by concatenating the literal text 'random number is ' with the +result of evaluating the expression inside the #{ } delimiter, in this case the result +of calling that random() method. The second argument to the method `parseExpression()` +is of the type `ParserContext`. The `ParserContext` interface is used to influence how +the expression is parsed in order to support the expression templating functionality. +The definition of `TemplateParserContext` is shown below. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class TemplateParserContext implements ParserContext { + + public String getExpressionPrefix() { + return "#{"; + } + + public String getExpressionSuffix() { + return "}"; + } + + public boolean isTemplate() { + return true; + } + } +---- + + + + +[[expressions-example-classes]] +=== Classes used in the examples +Inventor.java + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + package org.spring.samples.spel.inventor; + + import java.util.Date; + import java.util.GregorianCalendar; + + public class Inventor { + + private String name; + private String nationality; + private String[] inventions; + private Date birthdate; + private PlaceOfBirth placeOfBirth; + + public Inventor(String name, String nationality) { + GregorianCalendar c= new GregorianCalendar(); + this.name = name; + this.nationality = nationality; + this.birthdate = c.getTime(); + } + + public Inventor(String name, Date birthdate, String nationality) { + this.name = name; + this.nationality = nationality; + this.birthdate = birthdate; + } + + public Inventor() { + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getNationality() { + return nationality; + } + + public void setNationality(String nationality) { + this.nationality = nationality; + } + + public Date getBirthdate() { + return birthdate; + } + + public void setBirthdate(Date birthdate) { + this.birthdate = birthdate; + } + + public PlaceOfBirth getPlaceOfBirth() { + return placeOfBirth; + } + + public void setPlaceOfBirth(PlaceOfBirth placeOfBirth) { + this.placeOfBirth = placeOfBirth; + } + + public void setInventions(String[] inventions) { + this.inventions = inventions; + } + + public String[] getInventions() { + return inventions; + } + } +---- + +PlaceOfBirth.java + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + package org.spring.samples.spel.inventor; + + public class PlaceOfBirth { + + private String city; + private String country; + + public PlaceOfBirth(String city) { + this.city=city; + } + + public PlaceOfBirth(String city, String country) { + this(city); + this.country = country; + } + + public String getCity() { + return city; + } + + public void setCity(String s) { + this.city = s; + } + + public String getCountry() { + return country; + } + + public void setCountry(String country) { + this.country = country; + } + + } +---- + +Society.java + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + package org.spring.samples.spel.inventor; + + import java.util.*; + + public class Society { + + private String name; + + public static String Advisors = "advisors"; + public static String President = "president"; + + private List members = new ArrayList(); + private Map officers = new HashMap(); + + public List getMembers() { + return members; + } + + public Map getOfficers() { + return officers; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public boolean isMember(String name) { + for (Inventor inventor : members) { + if (inventor.getName().equals(name)) { + return true; + } + } + return false; + } + + } +---- + diff --git a/src/asciidoc/index.adoc b/src/asciidoc/index.adoc index 5018113a787f..f1e9ef85268c 100644 --- a/src/asciidoc/index.adoc +++ b/src/asciidoc/index.adoc @@ -52,1020 +52,12 @@ __task focused__. They also cover other projects from the Spring portfolio that https://spring.io/guides/gs/rest-service/[Getting Started Building a RESTful Web Service] would be an excellent first choice to get your feet wet. - - - - -[[overview]] -== Introduction to Spring Framework -Spring Framework is a Java platform that provides comprehensive infrastructure support -for developing Java applications. Spring handles the infrastructure so you can focus on -your application. - -Spring enables you to build applications from "plain old Java objects" (POJOs) and to -apply enterprise services non-invasively to POJOs. This capability applies to the Java -SE programming model and to full and partial Java EE. - -Examples of how you, as an application developer, can use the Spring platform advantage: - -* Make a Java method execute in a database transaction without having to deal with - transaction APIs. -* Make a local Java method a remote procedure without having to deal with remote APIs. -* Make a local Java method a management operation without having to deal with JMX APIs. -* Make a local Java method a message handler without having to deal with JMS APIs. - - - - -[[overview-dependency-injection]] -=== Dependency Injection and Inversion of Control - -[[background-ioc]] -.Background -**** -"__The question is, what aspect of control are [they] inverting?__" Martin Fowler posed -this question about Inversion of Control (IoC) on his site in 2004. Fowler suggested -renaming the principle to make it more self-explanatory and came up with __Dependency -Injection__. - -For insight into IoC and DI, refer to Fowler's article at -http://martinfowler.com/articles/injection.html[http://martinfowler.com/articles/injection.html]. -**** - -Java applications -- a loose term that runs the gamut from constrained applets to n-tier -server-side enterprise applications -- typically consist of objects that collaborate to -form the application proper. Thus the objects in an application have __dependencies__ on -each other. - -Although the Java platform provides a wealth of application development functionality, -it lacks the means to organize the basic building blocks into a coherent whole, leaving -that task to architects and developers. True, you can use design patterns such -as __Factory__, __Abstract Factory__, __Builder__, __Decorator__, and __Service Locator__ -to compose the various classes and object instances that make up an application. -However, these patterns are simply that: best practices given a name, with a description -of what the pattern does, where to apply it, the problems it addresses, and so forth. -Patterns are formalized best practices that __you must implement yourself__ in your -application. - -The Spring Framework __Inversion of Control__ (IoC) component addresses this concern by -providing a formalized means of composing disparate components into a fully working -application ready for use. The Spring Framework codifies formalized design patterns as -first-class objects that you can integrate into your own application(s). Numerous -organizations and institutions use the Spring Framework in this manner to engineer -robust, __maintainable__ applications. - - - - -[[overview-modules]] -=== Modules -The Spring Framework consists of features organized into about 20 modules. These modules -are grouped into Core Container, Data Access/Integration, Web, AOP (Aspect Oriented -Programming), Instrumentation, and Test, as shown in the following diagram. - -.Overview of the Spring Framework -image::images/spring-overview.png[width=400] - - - -[[overview-core-container]] -==== Core Container -The <> consists of the Core, Beans, Context, and -Expression Language modules. - -The <> 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 <> module builds on the solid base provided by the -<> 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. - -The <> 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 context 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. - -[[overview-aop-instrumentation]] -==== AOP and Instrumentation -Spring's <> module provides an __AOP Alliance__-compliant -aspect-oriented programming implementation allowing you to define, for example, -method-interceptors and pointcuts to cleanly decouple code that implements functionality -that should be separated. Using source-level metadata functionality, you can also -incorporate behavioral information into your code, in a manner similar to that of .NET -attributes. - -The separate __Aspects__ module provides integration with AspectJ. - -The __Instrumentation__ module provides class instrumentation support and classloader -implementations to be used in certain application servers. - -[[overview-messaging]] -==== Messaging -Spring Framework 4 includes a new `spring-messaging` module with key abstractions from -the _Spring Integration_ project such as `Message`, `MessageChannel`, -`MessageHandler` and others to serve as a foundation for messaging-based applications. The -module also includes a set of annotations for mapping messages to methods, similar to the -Spring MVC annotation based programming model. - -[[overview-data-access]] -==== Data Access/Integration -The __Data Access/Integration__ layer consists of the JDBC, ORM, OXM, JMS and -Transaction modules. - -The <> module provides a JDBC-abstraction layer that removes the -need to do tedious JDBC coding and parsing of database-vendor specific error codes. - -The <> module provides integration layers for popular -object-relational mapping APIs, including <>, <>, and -<>. Using the ORM package you can use all of these O/R-mapping -frameworks in combination with all of the other features Spring offers, such as the simple -declarative transaction management feature mentioned previously. - -The <> module provides an abstraction layer that supports Object/XML mapping -implementations for JAXB, Castor, XMLBeans, JiBX and XStream. - -The Java Messaging Service (<>) module contains features for producing and -consuming messages. Since Spring Framework 4.1, it provides an integration with the -`spring-messaging` module. - -The <> module supports programmatic and declarative transaction -management for classes that implement special interfaces and for __all your POJOs (plain -old Java objects)__. - - - -[[overview-web]] -==== Web -The __Web__ layer consists of the Web, Web-Servlet, WebSocket and Web-Portlet modules. - -Spring's __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. It also contains the -web-related parts of Spring's remoting support. - -The __Web-Servlet__ module contains Spring's model-view-controller -(<>) implementation for web applications. Spring's MVC -framework provides a clean separation between domain model code and web forms, and -integrates with all the other features of the Spring Framework. - -The __Web-Portlet__ module provides the MVC implementation to be used in a portlet -environment and mirrors the functionality of Web-Servlet module. - - - - - - - -[[overview-testing]] -==== Test -The __Test__ module supports the testing of Spring components with JUnit or TestNG. It -provides consistent loading of Spring ApplicationContexts and caching of those contexts. -It also provides mock objects that you can use to test your code in isolation. - - - - -[[overview-usagescenarios]] -=== Usage scenarios -The building blocks described previously make Spring a logical choice in many scenarios, -from applets to full-fledged enterprise applications that use Spring's transaction -management functionality and web framework integration. - -.Typical full-fledged Spring web application -image::images/overview-full.png[width=400] - -Spring's <> make -the web application fully transactional, just as it would be if you used EJB -container-managed transactions. All your custom business logic can be implemented with -simple POJOs and managed by Spring's IoC container. Additional services include support -for sending email and validation that is independent of the web layer, which lets you -choose where to execute validation rules. Spring's ORM support is integrated with JPA, -Hibernate and and JDO; for example, when using Hibernate, you can continue to use -your existing mapping files and standard Hibernate `SessionFactory` configuration. Form -controllers seamlessly integrate the web-layer with the domain model, removing the need -for `ActionForms` or other classes that transform HTTP parameters to values for your -domain model. - -.Spring middle-tier using a third-party web framework -image::images/overview-thirdparty-web.png[width=400] - -Sometimes circumstances do not allow you to completely switch to a different framework. -The Spring Framework does __not__ force you to use everything within it; it is not an -__all-or-nothing__ solution. Existing front-ends built with Struts, Tapestry, JSF -or other UI frameworks can be integrated with a Spring-based middle-tier, which allows -you to use Spring transaction features. You simply need to wire up your business logic -using an `ApplicationContext` and use a `WebApplicationContext` to integrate your web -layer. - -.Remoting usage scenario -image::images/overview-remoting.png[width=400] - -When you need to access existing code through web services, you can use Spring's -`Hessian-`, `Burlap-`, `Rmi-` or `JaxRpcProxyFactory` classes. Enabling remote access to -existing applications is not difficult. - -.EJBs - Wrapping existing POJOs -image::images/overview-ejb.png[width=400] - -The Spring Framework also provides an <> for -Enterprise JavaBeans, enabling you to reuse your existing POJOs and wrap them in -stateless session beans for use in scalable, fail-safe web applications that might need -declarative security. - - - -[[dependency-management]] -==== Dependency Management and Naming Conventions -Dependency management and dependency injection are different things. To get those nice -features of Spring into your application (like dependency injection) you need to -assemble all the libraries needed (jar files) and get them onto your classpath at -runtime, and possibly at compile time. These dependencies are not virtual components -that are injected, but physical resources in a file system (typically). The process of -dependency management involves locating those resources, storing them and adding them to -classpaths. Dependencies can be direct (e.g. my application depends on Spring at -runtime), or indirect (e.g. my application depends on `commons-dbcp` which depends on -`commons-pool`). The indirect dependencies are also known as "transitive" and it is -those dependencies that are hardest to identify and manage. - -If you are going to use Spring you need to get a copy of the jar libraries that comprise -the pieces of Spring that you need. To make this easier Spring is packaged as a set of -modules that separate the dependencies as much as possible, so for example if you don't -want to write a web application you don't need the spring-web modules. To refer to -Spring library modules in this guide we use a shorthand naming convention `spring-*` or -`spring-*.jar,` where `*` represents the short name for the module (e.g. `spring-core`, -`spring-webmvc`, `spring-jms`, etc.). The actual jar file name that you use is normally -the module name concatenated with the version number -(e.g. __spring-core-{spring-version}.jar__). - -Each release of the Spring Framework will publish artifacts to the following places: - -* Maven Central, which is the default repository that Maven queries, and does not - require any special configuration to use. Many of the common libraries that Spring - depends on also are available from Maven Central and a large section of the Spring - community uses Maven for dependency management, so this is convenient for them. The - names of the jars here are in the form `spring-*-.jar` and the Maven groupId - is `org.springframework`. -* In a public Maven repository hosted specifically for Spring. In addition to the final - GA releases, this repository also hosts development snapshots and milestones. The jar - file names are in the same form as Maven Central, so this is a useful place to get - development versions of Spring to use with other libraries deployed in Maven Central. - This repository also contains a bundle distribution zip file that contains all Spring - jars bundled together for easy download. - -So the first thing you need to decide is how to manage your dependencies: we generally -recommend the use of an automated system like Maven, Gradle or Ivy, but you can also do -it manually by downloading all the jars yourself. We provide detailed instructions later -in this chapter. - - -[[overview-spring-dependencies]] -===== Spring Dependencies and Depending on Spring -Although Spring provides integration and support for a huge range of enterprise and -other external tools, it intentionally keeps its mandatory dependencies to an absolute -minimum: you shouldn't have to locate and download (even automatically) a large number -of jar libraries in order to use Spring for simple use cases. For basic dependency -injection there is only one mandatory external dependency, and that is for logging (see -below for a more detailed description of logging options). - -Next we outline the basic steps needed to configure an application that depends on -Spring, first with Maven and then with Gradle and finally using Ivy. In all cases, if -anything is unclear, refer to the documentation of your dependency management system, or -look at some sample code - Spring itself uses Gradle to manage dependencies when it is -building, and our samples mostly use Gradle or Maven. - - -[[overview-maven-dependency-management]] -===== Maven Dependency Management -If you are using http://maven.apache.org/[Maven] for dependency management you don't even -need to supply the logging dependency explicitly. For example, to create an application -context and use dependency injection to configure an application, your Maven dependencies -will look like this: - -[source,xml,indent=0] -[subs="verbatim,quotes,attributes"] ----- - - - org.springframework - spring-context - {spring-version} - runtime - - ----- - -That's it. Note the scope can be declared as runtime if you don't need to compile -against Spring APIs, which is typically the case for basic dependency injection use -cases. - -The example above works with the Maven Central repository. To use the Spring Maven -repository (e.g. for milestones or developer snapshots), you need to specify the -repository location in your Maven configuration. For full releases: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - io.spring.repo.maven.release - http://repo.spring.io/release/ - false - - ----- - -For milestones: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - io.spring.repo.maven.milestone - http://repo.spring.io/milestone/ - false - - ----- - -And for snapshots: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - io.spring.repo.maven.snapshot - http://repo.spring.io/snapshot/ - true - - ----- - - -[[overview-maven-bom]] -===== Maven "Bill Of Materials" Dependency ===== -It is possible to accidentally mix different versions of Spring JARs when using Maven. -For example, you may find that a third-party library, or another Spring project, -pulls in a transitive dependency to an older release. If you forget to explicitly declare -a direct dependency yourself, all sorts of unexpected issues can arise. - -To overcome such problems Maven supports the concept of a "bill of materials" (BOM) -dependency. You can import the `spring-framework-bom` in your `dependencyManagement` -section to ensure that all spring dependencies (both direct and transitive) are at -the same version. - -[source,xml,indent=0] -[subs="verbatim,quotes,attributes"] ----- - - - - org.springframework - spring-framework-bom - {spring-version} - pom - import - - - ----- - -An added benefit of using the BOM is that you no longer need to specify the `` -attribute when depending on Spring Framework artifacts: - -[source,xml,indent=0] -[subs="verbatim,quotes,attributes"] ----- - - - org.springframework - spring-context - - - org.springframework - spring-web - - ----- - - -[[overview-gradle-dependency-management]] -===== Gradle Dependency Management -To use the Spring repository with the http://www.gradle.org/[Gradle] build system, -include the appropriate URL in the `repositories` section: - -[source,groovy,indent=0] -[subs="verbatim,quotes"] ----- - repositories { - mavenCentral() - // and optionally... - maven { url "http://repo.spring.io/release" } - } ----- - -You can change the `repositories` URL from `/release` to `/milestone` or `/snapshot` as -appropriate. Once a repository has been configured, you can declare dependencies in the -usual Gradle way: - -[source,groovy,indent=0] -[subs="verbatim,quotes,attributes"] ----- - dependencies { - compile("org.springframework:spring-context:{spring-version}") - testCompile("org.springframework:spring-test:{spring-version}") - } ----- - - -[[overview-ivy-dependency-management]] -===== Ivy Dependency Management -If you prefer to use http://ant.apache.org/ivy[Ivy] to manage dependencies then there -are similar configuration options. - -To configure Ivy to point to the Spring repository add the following resolver to your -`ivysettings.xml`: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - ----- - -You can change the `root` URL from `/release/` to `/milestone/` or `/snapshot/` as -appropriate. - -Once configured, you can add dependencies in the usual way. For example (in `ivy.xml`): - -[source,xml,indent=0] -[subs="verbatim,quotes,attributes"] ----- - ----- - - -[[overview-distribution-zip]] -===== Distribution Zip Files -Although using a build system that supports dependency management is the recommended -way to obtain the Spring Framework, it is still possible to download a distribution -zip file. - -Distribution zips are published to the Spring Maven Repository (this is just for our -convenience, you don't need Maven or any other build system in order to download them). - -To download a distribution zip open a web browser to -http://repo.spring.io/release/org/springframework/spring and select the appropriate -subfolder for the version that you want. Distribution files end `-dist.zip`, for example -+spring-framework-{spring-version}-RELEASE-dist.zip+. Distributions are also published -for http://repo.spring.io/milestone/org/springframework/spring[milestones] and -http://repo.spring.io/snapshot/org/springframework/spring[snapshots]. - - - -[[overview-logging]] -==== Logging -Logging is a very important dependency for Spring because __a)__ it is the only mandatory -external dependency, __b)__ everyone likes to see some output from the tools they are -using, and __c)__ Spring integrates with lots of other tools all of which have also made -a choice of logging dependency. One of the goals of an application developer is often to -have unified logging configured in a central place for the whole application, including -all external components. This is more difficult than it might have been since there are so -many choices of logging framework. - -The mandatory logging dependency in Spring is the Jakarta Commons Logging API (JCL). We -compile against JCL and we also make JCL `Log` objects visible for classes that extend -the Spring Framework. It's important to users that all versions of Spring use the same -logging library: migration is easy because backwards compatibility is preserved even -with applications that extend Spring. The way we do this is to make one of the modules -in Spring depend explicitly on `commons-logging` (the canonical implementation of JCL), -and then make all the other modules depend on that at compile time. If you are using -Maven for example, and wondering where you picked up the dependency on -`commons-logging`, then it is from Spring and specifically from the central module -called `spring-core`. - -The nice thing about `commons-logging` is that you don't need anything else to make your -application work. It has a runtime discovery algorithm that looks for other logging -frameworks in well known places on the classpath and uses one that it thinks is -appropriate (or you can tell it which one if you need to). If nothing else is available -you get pretty nice looking logs just from the JDK (java.util.logging or JUL for short). -You should find that your Spring application works and logs happily to the console out -of the box in most situations, and that's important. - - -[[overview-not-using-commons-logging]] -===== Not Using Commons Logging -Unfortunately, the runtime discovery algorithm in `commons-logging`, while convenient -for the end-user, is problematic. If we could turn back the clock and start Spring now -as a new project it would use a different logging dependency. The first choice would -probably be the Simple Logging Facade for Java ( http://www.slf4j.org[SLF4J]), which is -also used by a lot of other tools that people use with Spring inside their applications. - -There are basically two ways to switch off `commons-logging`: - -. Exclude the dependency from the `spring-core` module (as it is the only module that - explicitly depends on `commons-logging`) -. Depend on a special `commons-logging` dependency that replaces the library with - an empty jar (more details can be found in the - http://slf4j.org/faq.html#excludingJCL[SLF4J FAQ]) - -To exclude commons-logging, add the following to your `dependencyManagement` section: - -[source,xml,indent=0] -[subs="verbatim,quotes,attributes"] ----- - - - org.springframework - spring-core - {spring-version} - - - commons-logging - commons-logging - - - - ----- - -Now this application is probably broken because there is no implementation of the JCL -API on the classpath, so to fix it a new one has to be provided. In the next section we -show you how to provide an alternative implementation of JCL using SLF4J as an example. - - -[[overview-logging-slf4j]] -===== Using SLF4J -SLF4J is a cleaner dependency and more efficient at runtime than `commons-logging` -because it uses compile-time bindings instead of runtime discovery of the other logging -frameworks it integrates. This also means that you have to be more explicit about what -you want to happen at runtime, and declare it or configure it accordingly. SLF4J -provides bindings to many common logging frameworks, so you can usually choose one that -you already use, and bind to that for configuration and management. - -SLF4J provides bindings to many common logging frameworks, including JCL, and it also -does the reverse: bridges between other logging frameworks and itself. So to use SLF4J -with Spring you need to replace the `commons-logging` dependency with the SLF4J-JCL -bridge. Once you have done that then logging calls from within Spring will be translated -into logging calls to the SLF4J API, so if other libraries in your application use that -API, then you have a single place to configure and manage logging. - -A common choice might be to bridge Spring to SLF4J, and then provide explicit binding -from SLF4J to Log4J. You need to supply 4 dependencies (and exclude the existing -`commons-logging`): the bridge, the SLF4J API, the binding to Log4J, and the Log4J -implementation itself. In Maven you would do that like this - -[source,xml,indent=0] -[subs="verbatim,quotes,attributes"] ----- - - - org.springframework - spring-core - {spring-version} - - - commons-logging - commons-logging - - - - - org.slf4j - jcl-over-slf4j - 1.5.8 - - - org.slf4j - slf4j-api - 1.5.8 - - - org.slf4j - slf4j-log4j12 - 1.5.8 - - - log4j - log4j - 1.2.14 - - ----- - -That might seem like a lot of dependencies just to get some logging. Well it is, but it -__is__ optional, and it should behave better than the vanilla `commons-logging` with -respect to classloader issues, notably if you are in a strict container like an OSGi -platform. Allegedly there is also a performance benefit because the bindings are at -compile-time not runtime. - -A more common choice amongst SLF4J users, which uses fewer steps and generates fewer -dependencies, is to bind directly to http://logback.qos.ch[Logback]. This removes the -extra binding step because Logback implements SLF4J directly, so you only need to depend -on two libraries not four ( `jcl-over-slf4j` and `logback`). If you do that you might -also need to exclude the slf4j-api dependency from other external dependencies (not -Spring), because you only want one version of that API on the classpath. - - -[[overview-logging-log4j]] -===== Using Log4J -Many people use http://logging.apache.org/log4j[Log4j] as a logging framework for -configuration and management purposes. It's efficient and well-established, and in fact -it's what we use at runtime when we build and test Spring. Spring also provides some -utilities for configuring and initializing Log4j, so it has an optional compile-time -dependency on Log4j in some modules. - -To make Log4j work with the default JCL dependency ( `commons-logging`) all you need to -do is put Log4j on the classpath, and provide it with a configuration file ( -`log4j.properties` or `log4j.xml` in the root of the classpath). So for Maven users this -is your dependency declaration: - -[source,xml,indent=0] -[subs="verbatim,quotes,attributes"] ----- - - - org.springframework - spring-core - {spring-version} - - - log4j - log4j - 1.2.14 - - ----- - -And here's a sample log4j.properties for logging to the console: - -[literal] -[subs="verbatim,quotes"] ----- -log4j.rootCategory=INFO, stdout - -log4j.appender.stdout=org.apache.log4j.ConsoleAppender -log4j.appender.stdout.layout=org.apache.log4j.PatternLayout -log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %t %c{2}:%L - %m%n - -log4j.category.org.springframework.beans.factory=DEBUG ----- - -[[overview-native-jcl]] -====== Runtime Containers with Native JCL -Many people run their Spring applications in a container that itself provides an -implementation of JCL. IBM Websphere Application Server (WAS) is the archetype. This -often causes problems, and unfortunately there is no silver bullet solution; simply -excluding `commons-logging` from your application is not enough in most situations. - -To be clear about this: the problems reported are usually not with JCL per se, or even -with `commons-logging`: rather they are to do with binding `commons-logging` to another -framework (often Log4J). This can fail because `commons-logging` changed the way they do -the runtime discovery in between the older versions (1.0) found in some containers and -the modern versions that most people use now (1.1). Spring does not use any unusual -parts of the JCL API, so nothing breaks there, but as soon as Spring or your application -tries to do any logging you can find that the bindings to Log4J are not working. - -In such cases with WAS the easiest thing to do is to invert the class loader hierarchy -(IBM calls it "parent last") so that the application controls the JCL dependency, not -the container. That option isn't always open, but there are plenty of other suggestions -in the public domain for alternative approaches, and your mileage may vary depending on -the exact version and feature set of the container. - - - - +include::overview.adoc[] [[spring-whats-new]] = What's New in Spring Framework 4.x - - - -[[new-in-4.0]] -== New Features and Enhancements in Spring Framework 4.0 -The Spring Framework was first released in 2004; since then there have been significant -major revisions: Spring 2.0 provided XML namespaces and AspectJ support; Spring 2.5 -embraced annotation-driven configuration; Spring 3.0 introduced a strong Java 5+ foundation -across the framework codebase, and features such as the Java-based `@Configuration` model. - -Version 4.0 is the latest major release of the Spring Framework and the first to fully -support Java 8 features. You can still use Spring with older versions of Java, however, -the minimum requirement has now been raised to Java SE 6. We have also taken the -opportunity of a major release to remove many deprecated classes and methods. - -A https://github.com/spring-projects/spring-framework/wiki/Migrating-from-earlier-versions-of-the-spring-framework[migration guide for upgrading to Spring 4.0] -is available on the https://github.com/spring-projects/spring-framework/wiki[Spring Framework GitHub Wiki]. - - - - -=== Improved Getting Started Experience -The new https://spring.io[spring.io] website provides a whole series of -https://spring.io/guides["Getting Started"] guides to help you learn Spring. You -can read more about the guides in the <> section -in this document. The new website also provides a comprehensive overview of the many -additional projects that are released under the Spring umbrella. - -If you are a Maven user you may also be interested in the helpful -<> POM file that is now published with each Spring -Framework release. - - - - -=== Removed Deprecated Packages and Methods -All deprecated packages, and many deprecated classes and methods have been removed with -version 4.0. If you are upgrading from a previous release of Spring, you should ensure -that you have fixed any deprecated calls that you were making to outdated APIs. - -For a complete set of changes, check out the -http://docs.spring.io/spring-framework/docs/3.2.4.RELEASE_to_4.0.0.RELEASE/[API -Differences Report]. - -Note that optional third-party dependencies have been raised to a 2010/2011 minimum -(i.e. Spring 4 generally only supports versions released in late 2010 or later now): -notably, Hibernate 3.6+, EhCache 2.1+, Quartz 1.8+, Groovy 1.8+, and Joda-Time 2.0+. -As an exception to the rule, Spring 4 requires the recent Hibernate Validator 4.3+, -and support for Jackson has been focused on 2.0+ now (with Jackson 1.8/1.9 support -retained for the time being where Spring 3.2 had it; now just in deprecated form). - - - - -=== Java 8 (as well as 6 and 7) -Spring Framework 4.0 provides support for several Java 8 features. You can make use of -__lambda expressions__ and __method references__ with Spring's callback interfaces. There -is first-class support for `java.time` (http://jcp.org/en/jsr/detail?id=310[JSR-310]), -and several existing annotations have been retrofitted as `@Repeatable`. You can also -use Java 8's parameter name discovery (based on the `-parameters` compiler flag) as an -alternative to compiling your code with debug information enabled. - -Spring remains compatible with older versions of Java and the JDK: concretely, Java SE 6 -(specifically, a minimum level equivalent to JDK 6 update 18, as released in January 2010) -and above are still fully supported. However, for newly started development projects -based on Spring 4, we recommend the use of Java 7 or 8. - - - - -=== Java EE 6 and 7 -Java EE version 6 or above is now considered the baseline for Spring Framework 4, with -the JPA 2.0 and Servlet 3.0 specifications being of particular relevance. In order to -remain compatible with Google App Engine and older application servers, it is possible -to deploy a Spring 4 application into a Servlet 2.5 environment. However, Servlet 3.0+ -is strongly recommended and a prerequisite in Spring's test and mock packages for test -setups in development environments. - -[NOTE] -==== -If you are a WebSphere 7 user, be sure to install the JPA 2.0 feature pack. On -WebLogic 10.3.4 or higher, install the JPA 2.0 patch that comes with it. This turns -both of those server generations into Spring 4 compatible deployment environments. -==== - -On a more forward-looking note, Spring Framework 4.0 supports the Java EE 7 level of -applicable specifications now: in particular, JMS 2.0, JTA 1.2, JPA 2.1, Bean Validation -1.1, and JSR-236 Concurrency Utilities. As usual, this support focuses on individual -use of those specifications, e.g. on Tomcat or in standalone environments. However, -it works equally well when a Spring application is deployed to a Java EE 7 server. - -Note that Hibernate 4.3 is a JPA 2.1 provider and therefore only supported as of -Spring Framework 4.0. The same applies to Hibernate Validator 5.0 as a Bean Validation -1.1 provider. Neither of the two are officially supported with Spring Framework 3.2. - - - -[[groovy-bean-definition-dsl]] -=== Groovy Bean Definition DSL -With Spring Framework 4.0 it is now possible to define external bean configuration using -a Groovy DSL. This is similar in concept to using XML bean definitions, but allows for -a more concise syntax. Using Groovy also allows you to easily embed bean definitions -directly in your bootstrap code. For example: - -[source,groovy,indent=0] -[subs="verbatim,quotes"] ----- - def reader = new GroovyBeanDefinitionReader(myApplicationContext) - reader.beans { - dataSource(BasicDataSource) { - driverClassName = "org.hsqldb.jdbcDriver" - url = "jdbc:hsqldb:mem:grailsDB" - username = "sa" - password = "" - settings = [mynew:"setting"] - } - sessionFactory(SessionFactory) { - dataSource = dataSource - } - myService(MyService) { - nestedBean = { AnotherBean bean -> - dataSource = dataSource - } - } - } ----- - -For more information consult the `GroovyBeanDefinitionReader` -{javadoc-baseurl}/org/springframework/beans/factory/groovy/GroovyBeanDefinitionReader.html[javadocs]. - - - - -=== Core Container Improvements -There have been several general improvements to the core container: - -* Spring now treats <> when injecting Beans. For example, if you are using a Spring Data - `Repository` you can now easily inject a specific implementation: - `@Autowired Repository customerRepository`. -* If you use Spring's meta-annotation support, you can now develop custom annotations that - <>. -* Beans can now be __ordered__ when they are <>. Both the `@Order` annotation and `Ordered` interface are - supported. -* The `@Lazy` annotation can now be used on injection points, as well as on `@Bean` - definitions. -* The <> for - developers using Java-based configuration. -* A generalized model for <> has - been added via the `@Conditional` annotation. This is similar to `@Profile` support but - allows for user-defined strategies to be developed programmatically. -* <> no longer require a default - constructor. Support is provided via the http://code.google.com/p/objenesis/[objenesis] - library which is repackaged __inline__ and distributed as part of the Spring Framework. - With this strategy, no constructor at all is being invoked for proxy instances anymore. -* There is managed time zone support across the framework now, e.g. on `LocaleContext`. - - - - -=== General Web Improvements -Deployment to Servlet 2.5 servers remains an option, but Spring Framework 4.0 is now -focused primarily on Servlet 3.0+ environments. If you are using the -<> you -will need to ensure that a Servlet 3.0 compatible JAR is in your __test classpath__. - -In addition to the WebSocket support mentioned later, the following general improvements -have been made to Spring's Web modules: - -* You can use the <> with Spring - MVC applications, removing the need to add `@ResponseBody` to each of your - `@RequestMapping` methods. -* The `AsyncRestTemplate` class has been added, <> when developing REST clients. -* Spring now offers <> when developing - Spring MVC applications. - - - - -=== WebSocket, SockJS, and STOMP Messaging -A new `spring-websocket` module provides comprehensive support for WebSocket-based, -two-way communication between client and server in web applications. It is compatible with -http://jcp.org/en/jsr/detail?id=356[JSR-356], the Java WebSocket API, and in addition -provides SockJS-based fallback options (i.e. WebSocket emulation) for use in browsers -that don't yet support the WebSocket protocol (e.g. Internet Explorer < 10). - -A new `spring-messaging` module adds support for STOMP as the WebSocket sub-protocol -to use in applications along with an annotation programming model for routing and -processing STOMP messages from WebSocket clients. As a result an `@Controller` -can now contain both `@RequestMapping` and `@MessageMapping` methods for handling -HTTP requests and messages from WebSocket-connected clients. The new `spring-messaging` -module also contains key abstractions formerly from the -http://projects.spring.io/spring-integration/[Spring Integration] project such as -`Message`, `MessageChannel`, `MessageHandler`, and others to serve as a foundation -for messaging-based applications. - -For further details, including a more thorough introduction, see the <> section. - - - - -=== Testing Improvements -In addition to pruning of deprecated code within the `spring-test` module, Spring -Framework 4.0 introduces several new features for use in unit and integration testing. - -* Almost all annotations in the `spring-test` module (e.g., `@ContextConfiguration`, - `@WebAppConfiguration`, `@ContextHierarchy`, `@ActiveProfiles`, etc.) can now be used - as <> to create custom - _composed annotations_ and reduce configuration duplication across a test suite. -* Active bean definition profiles can now be resolved programmatically, simply by - implementing a custom <> - and registering it via the `resolver` attribute of `@ActiveProfiles`. -* A new `SocketUtils` class has been introduced in the `spring-core` module - which enables you to scan for free TCP and UDP server ports on localhost. This - functionality is not specific to testing but can prove very useful when writing - integration tests that require the use of sockets, for example tests that start - an in-memory SMTP server, FTP server, Servlet container, etc. -* As of Spring 4.0, the set of mocks in the `org.springframework.mock.web` package is - now based on the Servlet 3.0 API. Furthermore, several of the Servlet API mocks - (e.g., `MockHttpServletRequest`, `MockServletContext`, etc.) have been updated with - minor enhancements and improved configurability. - - - - -[[new-in-4.1]] -== New Features and Enhancements in Spring Framework 4.1 - -=== JMS Improvements -Spring 4.1 introduces a much simpler infrastructure <> by annotating bean methods with -{javadoc-baseurl}/org/springframework/jms/annotation/JmsListener.html[`@JmsListener`]. -The XML namespace has been enhanced to support this new style (`jms:annotation-driven`) -and it is also possible to fully configure the infrastructure using Java config ( -{javadoc-baseurl}/org/springframework/jms/annotation/EnableJms.html[`@EnableJms`], -`JmsListenerContainerFactory`). It is also possible to register listener endpoints -programmatically using -{javadoc-baseurl}/org/springframework/jms/annotation/JmsListenerConfigurer.html[`JmsListenerConfigurer`]. - -Spring 4.1 also aligns its JMS support to allow you to benefit from the `spring-messaging` -abstraction introduced in 4.0, that is: - -* Message listener endpoints can have a more flexible signature and benefit from - standard messaging annotations such as `@Payload`, `@Header`, `@Headers` and `@SendTo`. It - is also possible to use a standard `Message` in lieu of `javax.jms.Message` as method - argument -* A new {javadoc-baseurl}/org/springframework/jms/core/JmsMessageOperations.html[`JmsMessageOperations`] - interface is available and permits `JmsTemplate` like operations using the `Message` - abstraction - -Finally, Spring 4.1 provides additional miscellaneous improvements: - -* Synchronous request-reply operations support in `JmsTemplate` -* Listener priority can be specified per `` element -* Recovery options for the message listener container is configurable using a - {javadoc-baseurl}/org/springframework/util/backoff/BackOff.html[`BackOff`] implementation -* JMS 2.0 shared consumers are supported - -=== Caching Improvements - -Spring 4.1 supports <> using Spring's -existing cache configuration and infrastructure abstraction; no changes are required -to use the standard annotations. - -Spring 4.1 also improves its own abstraction significantly: - -* Caches can be resolved at runtime using a - <>. As a result the - `value` argument defining the cache name(s) to use is no longer mandatory -* More operation-level customizations: cache resolver, cache manager, key - generator -* A new <> allows - to share common settings at class level **without** enabling any cache operation -* Better exception handling of cached methods using `CacheErrorHandler` - -Spring 4.1 also has a breaking change in the `CacheInterface` as a new -`putIfAbsent` method has been added. - -=== Testing Improvements - -* Groovy scripts can now be used to configure the `ApplicationContext` loaded for - integration tests in the TestContext framework. -** See <> for details. -* Test-managed transactions can now be programmatically started and ended within - transactional test methods via the new `TestTransaction` API. -** See <> for details. -* SQL script execution can now be configured declaratively via the new `@Sql` and - `@SqlConfig` annotations on a per-class or per-method basis. -** See <> for details. -* Test property sources which automatically override system and application property - sources can be configured via the new `@TestPropertySource` annotation. -** See <> for details. -* Default ++TestExecutionListener++s can now be automatically discovered. -** See <> for details. -* Custom ++TestExecutionListener++s can now be automatically merged with the default - listeners. -** See <> for details. -* The documentation for transactional testing support in the TestContext framework has - been improved with more thorough explanations and additional examples. -** See <> for details. -* Various improvements to `MockServletContext`, `MockHttpServletRequest`, and other - Servlet API mocks. -* `AssertThrows` has been refactored to support `Throwable` instead of `Exception`. - - - - +include::new-in-4.adoc[] [[spring-core]] = Core Technologies @@ -1103,48610 +95,139 @@ testing will hopefully convince you of this as well. * <> -- +include::beans.adoc[] +include::resources.adoc[] +include::validation.adoc[] -[[beans]] -== The IoC container - - - +include::expressions.adoc[] -[[beans-introduction]] -=== Introduction to the Spring IoC container and beans -This chapter covers the Spring Framework implementation of the Inversion of Control -(IoC) footnote:[See pass:specialcharacters,macros[<>] ] principle. IoC -is also known as __dependency injection__ (DI). It is a process whereby objects define -their dependencies, that is, the other objects they work with, only through constructor -arguments, arguments to a factory method, or properties that are set on the object -instance after it is constructed or returned from a factory method. The container then -__injects__ those dependencies when it creates the bean. This process is fundamentally -the inverse, hence the name __Inversion of Control__ (IoC), of the bean itself -controlling the instantiation or location of its dependencies by using direct -construction of classes, or a mechanism such as the __Service Locator__ pattern. +include::aop.adoc[] -The `org.springframework.beans` and `org.springframework.context` packages are the basis -for Spring Framework's IoC container. The -{javadoc-baseurl}/org/springframework/beans/factory/BeanFactory.html[`BeanFactory`] -interface provides an advanced configuration mechanism capable of managing any type of -object. -{javadoc-baseurl}/org/springframework/context/ApplicationContext.html[`ApplicationContext`] -is a sub-interface of `BeanFactory`. It adds easier integration with Spring's AOP -features; message resource handling (for use in internationalization), event -publication; and application-layer specific contexts such as the `WebApplicationContext` -for use in web applications. +include::aop-api.adoc[] -In short, the `BeanFactory` provides the configuration framework and basic -functionality, and the `ApplicationContext` adds more enterprise-specific functionality. -The `ApplicationContext` is a complete superset of the `BeanFactory`, and is used -exclusively in this chapter in descriptions of Spring's IoC container. For more -information on using the `BeanFactory` instead of the `ApplicationContext,` refer to -<>. +include::testing.adoc[] -In Spring, the objects that form the backbone of your application and that are managed -by the Spring IoC __container__ are called __beans__. A bean is an object that is -instantiated, assembled, and otherwise managed by a Spring IoC container. Otherwise, a -bean is simply one of many objects in your application. Beans, and the __dependencies__ -among them, are reflected in the __configuration metadata__ used by a container. +[[spring-data-tier]] += Data Access +[partintro] +-- +This part of the reference documentation is concerned with data access and the +interaction between the data access layer and the business or service layer. +Spring's comprehensive transaction management support is covered in some detail, +followed by thorough coverage of the various data access frameworks and technologies +that the Spring Framework integrates with. +* <> +* <> +* <> +* <> +* <> +-- -[[beans-basics]] -=== Container overview -The interface `org.springframework.context.ApplicationContext` represents the Spring IoC -container and is responsible for instantiating, configuring, and assembling the -aforementioned beans. The container gets its instructions on what objects to -instantiate, configure, and assemble by reading configuration metadata. The -configuration metadata is represented in XML, Java annotations, or Java code. It allows -you to express the objects that compose your application and the rich interdependencies -between such objects. +include::transaction.adoc[] -Several implementations of the `ApplicationContext` interface are supplied -out-of-the-box with Spring. In standalone applications it is common to create an -instance of -{javadoc-baseurl}/org/springframework/context/support/ClassPathXmlApplicationContext.html[`ClassPathXmlApplicationContext`] -or {javadoc-baseurl}/org/springframework/context/support/FileSystemXmlApplicationContext.html[`FileSystemXmlApplicationContext`]. - While XML has been the traditional format for defining configuration metadata you can -instruct the container to use Java annotations or code as the metadata format by -providing a small amount of XML configuration to declaratively enable support for these -additional metadata formats. +include::dao.adoc[] -In most application scenarios, explicit user code is not required to instantiate one or -more instances of a Spring IoC container. For example, in a web application scenario, a -simple eight (or so) lines of boilerplate web descriptor XML in the `web.xml` file -of the application will typically suffice (see <>). If you are using the -https://spring.io/tools/sts[Spring Tool Suite] Eclipse-powered development -environment this boilerplate configuration can be easily created with few mouse clicks or -keystrokes. +include::jdbc.adoc[] -The following diagram is a high-level view of how Spring works. Your application classes -are combined with configuration metadata so that after the `ApplicationContext` is -created and initialized, you have a fully configured and executable system or -application. +include::orm.adoc[] -.The Spring IoC container -image::images/container-magic.png[width=250] +include::oxm.adoc[] +[[spring-web]] += The Web +[partintro] +-- +This part of the reference documentation covers Spring Framework's support for the +presentation tier (and specifically web-based presentation tiers) including support +for WebSocket-style messaging in web applications. +Spring Framework's own web framework, <>, is covered in the +first couple of chapters. Subsequent chapters are concerned with Spring Framework's +integration with other web technologies, such as <> and. -[[beans-factory-metadata]] -==== Configuration metadata -As the preceding diagram shows, the Spring IoC container consumes a form of -__configuration metadata__; this configuration metadata represents how you as an -application developer tell the Spring container to instantiate, configure, and assemble -the objects in your application. +Following that is coverage of Spring Framework's MVC <>. -Configuration metadata is traditionally supplied in a simple and intuitive XML format, -which is what most of this chapter uses to convey key concepts and features of the -Spring IoC container. +The section then concludes with comprehensive coverage of the Spring Framework +<> (including <>). -[NOTE] -==== -XML-based metadata is __not__ the only allowed form of configuration metadata. The -Spring IoC container itself is __totally__ decoupled from the format in which this -configuration metadata is actually written. These days many developers choose -<> for their Spring applications. -==== +* <> +* <> +* <> +* <> +* <> +-- -For information about using other forms of metadata with the Spring container, see: +include::mvc.adoc[] -* <>: Spring 2.5 introduced - support for annotation-based configuration metadata. -* <>: Starting with Spring 3.0, many features - provided by the Spring JavaConfig project became part of the core Spring Framework. - Thus you can define beans external to your application classes by using Java rather - than XML files. To use these new features, see the `@Configuration`, `@Bean`, `@Import` - and `@DependsOn` annotations. +include::view.adoc[] -Spring configuration consists of at least one and typically more than one bean -definition that the container must manage. XML-based configuration metadata shows these -beans configured as `` elements inside a top-level `` element. Java -configuration typically uses `@Bean` annotated methods within a `@Configuration` class. +include::web-integration.adoc[] -These bean definitions correspond to the actual objects that make up your application. -Typically you define service layer objects, data access objects (DAOs), presentation -objects such as Struts `Action` instances, infrastructure objects such as Hibernate -`SessionFactories`, JMS `Queues`, and so forth. Typically one does not configure -fine-grained domain objects in the container, because it is usually the responsibility -of DAOs and business logic to create and load domain objects. However, you can use -Spring's integration with AspectJ to configure objects that have been created outside -the control of an IoC container. See <>. +include::portlet.adoc[] -The following example shows the basic structure of XML-based configuration metadata: +include::websocket.adoc[] -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - +[[spring-integration]] += Integration +[partintro] +-- +This part of the reference documentation covers the Spring Framework's integration with +a number of Java EE (and related) technologies. - - - - - - - ----- - -The `id` attribute is a string that you use to identify the individual bean definition. -The `class` attribute defines the type of the bean and uses the fully qualified -classname. The value of the id attribute refers to collaborating objects. The XML for -referring to collaborating objects is not shown in this example; see -<> for more information. - - - -[[beans-factory-instantiation]] -==== Instantiating a container -Instantiating a Spring IoC container is straightforward. The location path or paths -supplied to an `ApplicationContext` constructor are actually resource strings that allow -the container to load configuration metadata from a variety of external resources such -as the local file system, from the Java `CLASSPATH`, and so on. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - ApplicationContext context = - new ClassPathXmlApplicationContext(new String[] {"services.xml", "daos.xml"}); ----- - -[NOTE] -==== -After you learn about Spring's IoC container, you may want to know more about Spring's -`Resource` abstraction, as described in <>, which provides a convenient -mechanism for reading an InputStream from locations defined in a URI syntax. In -particular, `Resource` paths are used to construct applications contexts as described in -<>. -==== - -The following example shows the service layer objects `(services.xml)` configuration file: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - - - - - - - ----- - -The following example shows the data access objects `daos.xml` file: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - - - - - - - ----- - -In the preceding example, the service layer consists of the class `PetStoreServiceImpl`, -and two data access objects of the type `JpaAccountDao` and `JpaItemDao` (based -on the JPA Object/Relational mapping standard). The `property name` element refers to the -name of the JavaBean property, and the `ref` element refers to the name of another bean -definition. This linkage between `id` and `ref` elements expresses the dependency between -collaborating objects. For details of configuring an object's dependencies, see -<>. - - -[[beans-factory-xml-import]] -===== Composing XML-based configuration metadata -It can be useful to have bean definitions span multiple XML files. Often each individual -XML configuration file represents a logical layer or module in your architecture. - -You can use the application context constructor to load bean definitions from all these -XML fragments. This constructor takes multiple `Resource` locations, as was shown in the -previous section. Alternatively, use one or more occurrences of the `` element -to load bean definitions from another file or files. For example: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - ----- - -In the preceding example, external bean definitions are loaded from three files: -`services.xml`, `messageSource.xml`, and `themeSource.xml`. All location paths are -relative to the definition file doing the importing, so `services.xml` must be in the -same directory or classpath location as the file doing the importing, while -`messageSource.xml` and `themeSource.xml` must be in a `resources` location below the -location of the importing file. As you can see, a leading slash is ignored, but given -that these paths are relative, it is better form not to use the slash at all. The -contents of the files being imported, including the top level `` element, must -be valid XML bean definitions according to the Spring Schema. - -[NOTE] -==== -It is possible, but not recommended, to reference files in parent directories using a -relative "../" path. Doing so creates a dependency on a file that is outside the current -application. In particular, this reference is not recommended for "classpath:" URLs (for -example, "classpath:../services.xml"), where the runtime resolution process chooses the -"nearest" classpath root and then looks into its parent directory. Classpath -configuration changes may lead to the choice of a different, incorrect directory. - -You can always use fully qualified resource locations instead of relative paths: for -example, "file:C:/config/services.xml" or "classpath:/config/services.xml". However, be -aware that you are coupling your application's configuration to specific absolute -locations. It is generally preferable to keep an indirection for such absolute -locations, for example, through "${...}" placeholders that are resolved against JVM -system properties at runtime. -==== - - - -[[beans-factory-client]] -==== Using the container -The `ApplicationContext` is the interface for an advanced factory capable of maintaining -a registry of different beans and their dependencies. Using the method `T getBean(String -name, Class requiredType)` you can retrieve instances of your beans. - -The `ApplicationContext` enables you to read bean definitions and access them as follows: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - // create and configure beans - ApplicationContext context = - new ClassPathXmlApplicationContext(new String[] {"services.xml", "daos.xml"}); - - // retrieve configured instance - PetStoreService service = context.getBean("petStore", PetStoreService.class); - - // use configured instance - List userList = service.getUsernameList(); ----- - -You use `getBean()` to retrieve instances of your beans. The `ApplicationContext` -interface has a few other methods for retrieving beans, but ideally your application -code should never use them. Indeed, your application code should have no calls to the -`getBean()` method at all, and thus no dependency on Spring APIs at all. For example, -Spring's integration with web frameworks provides for dependency injection for various -web framework classes such as controllers and JSF-managed beans. - - - - -[[beans-definition]] -=== Bean overview -A Spring IoC container manages one or more __beans__. These beans are created with the -configuration metadata that you supply to the container, for example, in the form of XML -`` definitions. - -Within the container itself, these bean definitions are represented as `BeanDefinition` -objects, which contain (among other information) the following metadata: - -* __A package-qualified class name:__ typically the actual implementation class of the - bean being defined. -* Bean behavioral configuration elements, which state how the bean should behave in the - container (scope, lifecycle callbacks, and so forth). -* References to other beans that are needed for the bean to do its work; these - references are also called __collaborators__ or __dependencies__. -* Other configuration settings to set in the newly created object, for example, the - number of connections to use in a bean that manages a connection pool, or the size - limit of the pool. - -This metadata translates to a set of properties that make up each bean definition. - -[[beans-factory-bean-definition-tbl]] -.The bean definition -|=== -| Property| Explained in... - -| class -| <> - -| name -| <> - -| scope -| <> - -| constructor arguments -| <> - -| properties -| <> - -| autowiring mode -| <> - -| lazy-initialization mode -| <> - -| initialization method -| <> - -| destruction method -| <> -|=== - -In addition to bean definitions that contain information on how to create a specific -bean, the `ApplicationContext` implementations also permit the registration of existing -objects that are created outside the container, by users. This is done by accessing the -ApplicationContext's BeanFactory via the method `getBeanFactory()` which returns the -BeanFactory implementation `DefaultListableBeanFactory`. `DefaultListableBeanFactory` -supports this registration through the methods `registerSingleton(..)` and -`registerBeanDefinition(..)`. However, typical applications work solely with beans -defined through metadata bean definitions. - - - -[[beans-beanname]] -==== Naming beans -Every bean has one or more identifiers. These identifiers must be unique within the -container that hosts the bean. A bean usually has only one identifier, but if it -requires more than one, the extra ones can be considered aliases. - -In XML-based configuration metadata, you use the `id` and/or `name` attributes -to specify the bean identifier(s). The `id` attribute allows you to specify -exactly one id. Conventionally these names are alphanumeric ('myBean', -'fooService', etc.), but may contain special characters as well. If you want to -introduce other aliases to the bean, you can also specify them in the `name` -attribute, separated by a comma (`,`), semicolon (`;`), or white space. As a -historical note, in versions prior to Spring 3.1, the `id` attribute was -defined as an `xsd:ID` type, which constrained possible characters. As of 3.1, -it is defined as an `xsd:string` type. Note that bean `id` uniqueness is still -enforced by the container, though no longer by XML parsers. - -You are not required to supply a name or id for a bean. If no name or id is supplied -explicitly, the container generates a unique name for that bean. However, if you want to -refer to that bean by name, through the use of the `ref` element or -<> style lookup, you must provide a name. -Motivations for not supplying a name are related to using <> and <>. - -.Bean Naming Conventions -**** -The convention is to use the standard Java convention for instance field names when -naming beans. That is, bean names start with a lowercase letter, and are camel-cased -from then on. Examples of such names would be (without quotes) `'accountManager'`, -`'accountService'`, `'userDao'`, `'loginController'`, and so forth. - -Naming beans consistently makes your configuration easier to read and understand, and if -you are using Spring AOP it helps a lot when applying advice to a set of beans related -by name. -**** - - -[[beans-beanname-alias]] -===== Aliasing a bean outside the bean definition -In a bean definition itself, you can supply more than one name for the bean, by using a -combination of up to one name specified by the `id` attribute, and any number of other -names in the `name` attribute. These names can be equivalent aliases to the same bean, -and are useful for some situations, such as allowing each component in an application to -refer to a common dependency by using a bean name that is specific to that component -itself. - -Specifying all aliases where the bean is actually defined is not always adequate, -however. It is sometimes desirable to introduce an alias for a bean that is defined -elsewhere. This is commonly the case in large systems where configuration is split -amongst each subsystem, each subsystem having its own set of object definitions. In -XML-based configuration metadata, you can use the `` element to accomplish this. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - ----- - -In this case, a bean in the same container which is named `fromName`, may also, -after the use of this alias definition, be referred to as `toName`. - -For example, the configuration metadata for subsystem A may refer to a DataSource via -the name `subsystemA-dataSource`. The configuration metadata for subsystem B may refer to -a DataSource via the name `subsystemB-dataSource`. When composing the main application -that uses both these subsystems the main application refers to the DataSource via the -name `myApp-dataSource`. To have all three names refer to the same object you add to the -MyApp configuration metadata the following aliases definitions: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - ----- - -Now each component and the main application can refer to the dataSource through a name -that is unique and guaranteed not to clash with any other definition (effectively -creating a namespace), yet they refer to the same bean. - -.Java-configuration -**** -If you are using Java-configuration, the `@Bean` annotation can be used to provide aliases -see <> for details. -**** - -[[beans-factory-class]] -==== Instantiating beans -A bean definition essentially is a recipe for creating one or more objects. The -container looks at the recipe for a named bean when asked, and uses the configuration -metadata encapsulated by that bean definition to create (or acquire) an actual object. - -If you use XML-based configuration metadata, you specify the type (or class) of object -that is to be instantiated in the `class` attribute of the `` element. This -`class` attribute, which internally is a `Class` property on a `BeanDefinition` -instance, is usually mandatory. (For exceptions, see -<> and <>.) -You use the `Class` property in one of two ways: - -* Typically, to specify the bean class to be constructed in the case where the container - itself directly creates the bean by calling its constructor reflectively, somewhat - equivalent to Java code using the `new` operator. -* To specify the actual class containing the `static` factory method that will be - invoked to create the object, in the less common case where the container invokes a - `static` __factory__ method on a class to create the bean. The object type returned - from the invocation of the `static` factory method may be the same class or another - class entirely. - -**** -.Inner class names -If you want to configure a bean definition for a `static` nested class, you have to use -the __binary__ name of the inner class. - -For example, if you have a class called `Foo` in the `com.example` package, and this -`Foo` class has a `static` inner class called `Bar`, the value of the `'class'` -attribute on a bean definition would be... - -`com.example.Foo$Bar` - -Notice the use of the `$` character in the name to separate the inner class name from -the outer class name. -**** - - -[[beans-factory-class-ctor]] -===== Instantiation with a constructor -When you create a bean by the constructor approach, all normal classes are usable by and -compatible with Spring. That is, the class being developed does not need to implement -any specific interfaces or to be coded in a specific fashion. Simply specifying the bean -class should suffice. However, depending on what type of IoC you use for that specific -bean, you may need a default (empty) constructor. - -The Spring IoC container can manage virtually __any__ class you want it to manage; it is -not limited to managing true JavaBeans. Most Spring users prefer actual JavaBeans with -only a default (no-argument) constructor and appropriate setters and getters modeled -after the properties in the container. You can also have more exotic non-bean-style -classes in your container. If, for example, you need to use a legacy connection pool -that absolutely does not adhere to the JavaBean specification, Spring can manage it as -well. - -With XML-based configuration metadata you can specify your bean class as follows: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - ----- - -For details about the mechanism for supplying arguments to the constructor (if required) -and setting object instance properties after the object is constructed, see -<>. - - -[[beans-factory-class-static-factory-method]] -===== Instantiation with a static factory method -When defining a bean that you create with a static factory method, you use the `class` -attribute to specify the class containing the `static` factory method and an attribute -named `factory-method` to specify the name of the factory method itself. You should be -able to call this method (with optional arguments as described later) and return a live -object, which subsequently is treated as if it had been created through a constructor. -One use for such a bean definition is to call `static` factories in legacy code. - -The following bean definition specifies that the bean will be created by calling a -factory-method. The definition does not specify the type (class) of the returned object, -only the class containing the factory method. In this example, the `createInstance()` -method must be a __static__ method. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - ----- - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class ClientService { - private static ClientService clientService = new ClientService(); - private ClientService() {} - - public static ClientService createInstance() { - return clientService; - } - } ----- - -For details about the mechanism for supplying (optional) arguments to the factory method -and setting object instance properties after the object is returned from the factory, -see <>. - - -[[beans-factory-class-instance-factory-method]] -===== Instantiation using an instance factory method -Similar to instantiation through a <>, instantiation with an instance factory method invokes a non-static -method of an existing bean from the container to create a new bean. To use this -mechanism, leave the `class` attribute empty, and in the `factory-bean` attribute, -specify the name of a bean in the current (or parent/ancestor) container that contains -the instance method that is to be invoked to create the object. Set the name of the -factory method itself with the `factory-method` attribute. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - ----- - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class DefaultServiceLocator { - - private static ClientService clientService = new ClientServiceImpl(); - private DefaultServiceLocator() {} - - public ClientService createClientServiceInstance() { - return clientService; - } - } ----- - -One factory class can also hold more than one factory method as shown here: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - ----- - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class DefaultServiceLocator { - - private static ClientService clientService = new ClientServiceImpl(); - private static AccountService accountService = new AccountServiceImpl(); - - private DefaultServiceLocator() {} - - public ClientService createClientServiceInstance() { - return clientService; - } - - public AccountService createAccountServiceInstance() { - return accountService; - } - - } ----- - -This approach shows that the factory bean itself can be managed and configured through -dependency injection (DI). See <>. - -[NOTE] -==== -In Spring documentation,__ factory bean__ refers to a bean that is configured in the -Spring container that will create objects through an -<> or -<> factory method. By contrast, -`FactoryBean` (notice the capitalization) refers to a Spring-specific -<>. -==== - - - - -[[beans-dependencies]] -=== Dependencies -A typical enterprise application does not consist of a single object (or bean in the -Spring parlance). Even the simplest application has a few objects that work together to -present what the end-user sees as a coherent application. This next section explains how -you go from defining a number of bean definitions that stand alone to a fully realized -application where objects collaborate to achieve a goal. - - - -[[beans-factory-collaborators]] -==== Dependency injection -__Dependency injection__ (DI) is a process whereby objects define their dependencies, -that is, the other objects they work with, only through constructor arguments, arguments -to a factory method, or properties that are set on the object instance after it is -constructed or returned from a factory method. The container then __injects__ those -dependencies when it creates the bean. This process is fundamentally the inverse, hence -the name __Inversion of Control__ (IoC), of the bean itself controlling the instantiation -or location of its dependencies on its own by using direct construction of classes, or -the __Service Locator__ pattern. - -Code is cleaner with the DI principle and decoupling is more effective when objects are -provided with their dependencies. The object does not look up its dependencies, and does -not know the location or class of the dependencies. As such, your classes become easier -to test, in particular when the dependencies are on interfaces or abstract base classes, -which allow for stub or mock implementations to be used in unit tests. - -DI exists in two major variants, <> and <>. - - -[[beans-constructor-injection]] -===== Constructor-based dependency injection -__Constructor-based__ DI is accomplished by the container invoking a constructor with a -number of arguments, each representing a dependency. Calling a `static` factory method -with specific arguments to construct the bean is nearly equivalent, and this discussion -treats arguments to a constructor and to a `static` factory method similarly. The -following example shows a class that can only be dependency-injected with constructor -injection. Notice that there is nothing __special__ about this class, it is a POJO that -has no dependencies on container specific interfaces, base classes or annotations. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class SimpleMovieLister { - - // the SimpleMovieLister has a dependency on a MovieFinder - private MovieFinder movieFinder; - - // a constructor so that the Spring container can inject a MovieFinder - public SimpleMovieLister(MovieFinder movieFinder) { - this.movieFinder = movieFinder; - } - - // business logic that actually uses the injected MovieFinder is omitted... - - } ----- - -[[beans-factory-ctor-arguments-resolution]] -====== Constructor argument resolution -Constructor argument resolution matching occurs using the argument's type. If no -potential ambiguity exists in the constructor arguments of a bean definition, then the -order in which the constructor arguments are defined in a bean definition is the order -in which those arguments are supplied to the appropriate constructor when the bean is -being instantiated. Consider the following class: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - package x.y; - - public class Foo { - - public Foo(Bar bar, Baz baz) { - // ... - } - - } ----- - -No potential ambiguity exists, assuming that `Bar` and `Baz` classes are not related by -inheritance. Thus the following configuration works fine, and you do not need to specify -the constructor argument indexes and/or types explicitly in the `` -element. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - - - ----- - -When another bean is referenced, the type is known, and matching can occur (as was the -case with the preceding example). When a simple type is used, such as -`true`, Spring cannot determine the type of the value, and so cannot match -by type without help. Consider the following class: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - package examples; - - public class ExampleBean { - - // Number of years to calculate the Ultimate Answer - private int years; - - // The Answer to Life, the Universe, and Everything - private String ultimateAnswer; - - public ExampleBean(int years, String ultimateAnswer) { - this.years = years; - this.ultimateAnswer = ultimateAnswer; - } - - } ----- - -.[[beans-factory-ctor-arguments-type]]Constructor argument type matching --- -In the preceding scenario, the container __can__ use type matching with simple types if -you explicitly specify the type of the constructor argument using the `type` attribute. -For example: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - ----- --- - -.[[beans-factory-ctor-arguments-index]]Constructor argument index --- -Use the `index` attribute to specify explicitly the index of constructor arguments. For -example: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - ----- - -In addition to resolving the ambiguity of multiple simple values, specifying an index -resolves ambiguity where a constructor has two arguments of the same type. Note that the -__index is 0 based__. --- - -.[[beans-factory-ctor-arguments-name]]Constructor argument name --- -You can also use the constructor parameter name for value disambiguation: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - ----- - -Keep in mind that to make this work out of the box your code must be compiled with the -debug flag enabled so that Spring can look up the parameter name from the constructor. -If you can't compile your code with debug flag (or don't want to) you can use -http://download.oracle.com/javase/6/docs/api/java/beans/ConstructorProperties.html[@ConstructorProperties] -JDK annotation to explicitly name your constructor arguments. The sample class would -then have to look as follows: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - package examples; - - public class ExampleBean { - - // Fields omitted - - @ConstructorProperties({"years", "ultimateAnswer"}) - public ExampleBean(int years, String ultimateAnswer) { - this.years = years; - this.ultimateAnswer = ultimateAnswer; - } - - } ----- +* <> +* <> +* <> +* <> +* <> +* <> +* <> +* <> +* <> -- -[[beans-setter-injection]] -===== Setter-based dependency injection -__Setter-based__ DI is accomplished by the container calling setter methods on your -beans after invoking a no-argument constructor or no-argument `static` factory method to -instantiate your bean. - -The following example shows a class that can only be dependency-injected using pure -setter injection. This class is conventional Java. It is a POJO that has no dependencies -on container specific interfaces, base classes or annotations. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class SimpleMovieLister { - - // the SimpleMovieLister has a dependency on the MovieFinder - private MovieFinder movieFinder; - - // a setter method so that the Spring container can inject a MovieFinder - public void setMovieFinder(MovieFinder movieFinder) { - this.movieFinder = movieFinder; - } - - // business logic that actually uses the injected MovieFinder is omitted... - - } ----- - -The `ApplicationContext` supports constructor-based and setter-based DI for the beans it -manages. It also supports setter-based DI after some dependencies have already been -injected through the constructor approach. You configure the dependencies in the form of -a `BeanDefinition`, which you use in conjunction with `PropertyEditor` instances to -convert properties from one format to another. However, most Spring users do not work -with these classes directly (i.e., programmatically) but rather with XML `bean` -definitions, annotated components (i.e., classes annotated with `@Component`, -`@Controller`, etc.), or `@Bean` methods in Java-based `@Configuration` classes. These -sources are then converted internally into instances of `BeanDefinition` and used to -load an entire Spring IoC container instance. - -.Constructor-based or setter-based DI? -**** -Since you can mix constructor-based and setter-based DI, it is a good rule of thumb to -use constructors for _mandatory dependencies_ and setter methods or configuration methods -for _optional dependencies_. Note that use of the <> -annotation on a setter method can be used to make the property a required dependency. - -The Spring team generally advocates constructor injection as it enables one to implement -application components as _immutable objects_ and to ensure that required dependencies -are not `null`. Furthermore constructor-injected components are always returned to client -(calling) code in a fully initialized state. As a side note, a large number of constructor -arguments is a _bad code smell_, implying that the class likely has too many -responsibilities and should be refactored to better address proper separation of concerns. - -Setter injection should primarily only be used for optional dependencies that can be -assigned reasonable default values within the class. Otherwise, not-null checks must be -performed everywhere the code uses the dependency. One benefit of setter injection is that -setter methods make objects of that class amenable to reconfiguration or re-injection -later. Management through <> is therefore a compelling use case for setter -injection. - -Use the DI style that makes the most sense for a particular class. Sometimes, when dealing -with third-party classes for which you do not have the source, the choice is made for you. -For example, if a third-party class does not expose any setter methods, then constructor -injection may be the only available form of DI. -**** - - -[[beans-dependency-resolution]] -===== Dependency resolution process -The container performs bean dependency resolution as follows: - -* The `ApplicationContext` is created and initialized with configuration metadata that - describes all the beans. Configuration metadata can be specified via XML, Java code, or - annotations. -* For each bean, its dependencies are expressed in the form of properties, constructor - arguments, or arguments to the static-factory method if you are using that instead of - a normal constructor. These dependencies are provided to the bean, __when the bean is - actually created__. -* Each property or constructor argument is an actual definition of the value to set, or - a reference to another bean in the container. -* Each property or constructor argument which is a value is converted from its specified - format to the actual type of that property or constructor argument. By default Spring - can convert a value supplied in string format to all built-in types, such as `int`, - `long`, `String`, `boolean`, etc. - -The Spring container validates the configuration of each bean as the container is created. -However, the bean properties themselves are not set until the bean __is actually created__. -Beans that are singleton-scoped and set to be pre-instantiated (the default) are created -when the container is created. Scopes are defined in <>. Otherwise, -the bean is created only when it is requested. Creation of a bean potentially causes a -graph of beans to be created, as the bean's dependencies and its dependencies' -dependencies (and so on) are created and assigned. Note that resolution mismatches among -those dependencies may show up late, i.e. on first creation of the affected bean. - -.Circular dependencies -**** -If you use predominantly constructor injection, it is possible to create an unresolvable -circular dependency scenario. - -For example: Class A requires an instance of class B through constructor injection, and -class B requires an instance of class A through constructor injection. If you configure -beans for classes A and B to be injected into each other, the Spring IoC container -detects this circular reference at runtime, and throws a -`BeanCurrentlyInCreationException`. - -One possible solution is to edit the source code of some classes to be configured by -setters rather than constructors. Alternatively, avoid constructor injection and use -setter injection only. In other words, although it is not recommended, you can configure -circular dependencies with setter injection. - -Unlike the __typical__ case (with no circular dependencies), a circular dependency -between bean A and bean B forces one of the beans to be injected into the other prior to -being fully initialized itself (a classic chicken/egg scenario). -**** - -You can generally trust Spring to do the right thing. It detects configuration problems, -such as references to non-existent beans and circular dependencies, at container -load-time. Spring sets properties and resolves dependencies as late as possible, when -the bean is actually created. This means that a Spring container which has loaded -correctly can later generate an exception when you request an object if there is a -problem creating that object or one of its dependencies. For example, the bean throws an -exception as a result of a missing or invalid property. This potentially delayed -visibility of some configuration issues is why `ApplicationContext` implementations by -default pre-instantiate singleton beans. At the cost of some upfront time and memory to -create these beans before they are actually needed, you discover configuration issues -when the `ApplicationContext` is created, not later. You can still override this default -behavior so that singleton beans will lazy-initialize, rather than be pre-instantiated. - -If no circular dependencies exist, when one or more collaborating beans are being -injected into a dependent bean, each collaborating bean is __totally__ configured prior -to being injected into the dependent bean. This means that if bean A has a dependency on -bean B, the Spring IoC container completely configures bean B prior to invoking the -setter method on bean A. In other words, the bean is instantiated (if not a -pre-instantiated singleton), its dependencies are set, and the relevant lifecycle -methods (such as a <> -or the <>) -are invoked. - - -[[beans-some-examples]] -===== Examples of dependency injection -The following example uses XML-based configuration metadata for setter-based DI. A small -part of a Spring XML configuration file specifies some bean definitions: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - - - - - - ----- - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class ExampleBean { - - private AnotherBean beanOne; - private YetAnotherBean beanTwo; - private int i; - - public void setBeanOne(AnotherBean beanOne) { - this.beanOne = beanOne; - } - - public void setBeanTwo(YetAnotherBean beanTwo) { - this.beanTwo = beanTwo; - } - - public void setIntegerProperty(int i) { - this.i = i; - } - - } ----- - -In the preceding example, setters are declared to match against the properties specified -in the XML file. The following example uses constructor-based DI: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - - - - - - - ----- - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class ExampleBean { - - private AnotherBean beanOne; - private YetAnotherBean beanTwo; - private int i; - - public ExampleBean( - AnotherBean anotherBean, YetAnotherBean yetAnotherBean, int i) { - this.beanOne = anotherBean; - this.beanTwo = yetAnotherBean; - this.i = i; - } - - } ----- - -The constructor arguments specified in the bean definition will be used as arguments to -the constructor of the `ExampleBean`. - -Now consider a variant of this example, where instead of using a constructor, Spring is -told to call a `static` factory method to return an instance of the object: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - ----- - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class ExampleBean { - - // a private constructor - private ExampleBean(...) { - ... - } - - // a static factory method; the arguments to this method can be - // considered the dependencies of the bean that is returned, - // regardless of how those arguments are actually used. - public static ExampleBean createInstance ( - AnotherBean anotherBean, YetAnotherBean yetAnotherBean, int i) { - - ExampleBean eb = new ExampleBean (...); - // some other operations... - return eb; - } - - } ----- - -Arguments to the `static` factory method are supplied via `` elements, -exactly the same as if a constructor had actually been used. The type of the class being -returned by the factory method does not have to be of the same type as the class that -contains the `static` factory method, although in this example it is. An instance -(non-static) factory method would be used in an essentially identical fashion (aside -from the use of the `factory-bean` attribute instead of the `class` attribute), so -details will not be discussed here. - - - -[[beans-factory-properties-detailed]] -==== Dependencies and configuration in detail -As mentioned in the previous section, you can define bean properties and constructor -arguments as references to other managed beans (collaborators), or as values defined -inline. Spring's XML-based configuration metadata supports sub-element types within its -`` and `` elements for this purpose. - - -[[beans-value-element]] -===== Straight values (primitives, Strings, and so on) - -The `value` attribute of the `` element specifies a property or constructor -argument as a human-readable string representation. Spring's -<> is used to convert these -values from a `String` to the actual type of the property or argument. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - ----- - -The following example uses the <> for even more succinct -XML configuration. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - ----- - -The preceding XML is more succinct; however, typos are discovered at runtime rather than -design time, unless you use an IDE such as http://www.jetbrains.com/idea/[IntelliJ -IDEA] or the https://spring.io/tools/sts[Spring Tool Suite] (STS) -that support automatic property completion when you create bean definitions. Such IDE -assistance is highly recommended. - -You can also configure a `java.util.Properties` instance as: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - jdbc.driver.className=com.mysql.jdbc.Driver - jdbc.url=jdbc:mysql://localhost:3306/mydb - - - ----- - -The Spring container converts the text inside the `` element into a -`java.util.Properties` instance by using the JavaBeans `PropertyEditor` mechanism. This -is a nice shortcut, and is one of a few places where the Spring team do favor the use of -the nested `` element over the `value` attribute style. - -[[beans-idref-element]] -====== The idref element - -The `idref` element is simply an error-proof way to pass the __id__ (string value - not -a reference) of another bean in the container to a `` or `` -element. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - ----- - -The above bean definition snippet is __exactly__ equivalent (at runtime) to the -following snippet: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - ----- - -The first form is preferable to the second, because using the `idref` tag allows the -container to validate __at deployment time__ that the referenced, named bean actually -exists. In the second variation, no validation is performed on the value that is passed -to the `targetName` property of the `client` bean. Typos are only discovered (with most -likely fatal results) when the `client` bean is actually instantiated. If the `client` -bean is a <> bean, this typo and the resulting exception -may only be discovered long after the container is deployed. - -[NOTE] -==== -The `local` attribute on the `idref` element is no longer supported in the 4.0 beans xsd -since it does not provide value over a regular `bean` reference anymore. Simply change -your existing `idref local` references to `idref bean` when upgrading to the 4.0 schema. -==== - -A common place (at least in versions earlier than Spring 2.0) where the `` element -brings value is in the configuration of <> in a -`ProxyFactoryBean` bean definition. Using `` elements when you specify the -interceptor names prevents you from misspelling an interceptor id. - - -[[beans-ref-element]] -===== References to other beans (collaborators) -The `ref` element is the final element inside a `` or `` -definition element. Here you set the value of the specified property of a bean to be a -reference to another bean (a collaborator) managed by the container. The referenced bean -is a dependency of the bean whose property will be set, and it is initialized on demand -as needed before the property is set. (If the collaborator is a singleton bean, it may -be initialized already by the container.) All references are ultimately a reference to -another object. Scoping and validation depend on whether you specify the id/name of the -other object through the `bean`, `local,` or `parent` attributes. - -Specifying the target bean through the `bean` attribute of the `` tag is the most -general form, and allows creation of a reference to any bean in the same container or -parent container, regardless of whether it is in the same XML file. The value of the -`bean` attribute may be the same as the `id` attribute of the target bean, or as one of -the values in the `name` attribute of the target bean. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - ----- - -Specifying the target bean through the `parent` attribute creates a reference to a bean -that is in a parent container of the current container. The value of the `parent` -attribute may be the same as either the `id` attribute of the target bean, or one of the -values in the `name` attribute of the target bean, and the target bean must be in a -parent container of the current one. You use this bean reference variant mainly when you -have a hierarchy of containers and you want to wrap an existing bean in a parent -container with a proxy that will have the same name as the parent bean. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - ----- - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - class="org.springframework.aop.framework.ProxyFactoryBean"> - - - - - ----- - -[NOTE] -==== -The `local` attribute on the `ref` element is no longer supported in the 4.0 beans xsd -since it does not provide value over a regular `bean` reference anymore. Simply change -your existing `ref local` references to `ref bean` when upgrading to the 4.0 schema. -==== - - -[[beans-inner-beans]] -===== Inner beans -A `` element inside the `` or `` elements defines a -so-called __inner bean__. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - - ----- - -An inner bean definition does not require a defined id or name; the container ignores -these values. It also ignores the `scope` flag. Inner beans are __always__ anonymous and -they are __always__ created with the outer bean. It is __not__ possible to inject inner -beans into collaborating beans other than into the enclosing bean. - - -[[beans-collection-elements]] -===== Collections -In the ``, ``, ``, and `` elements, you set the properties -and arguments of the Java `Collection` types `List`, `Set`, `Map`, and `Properties`, -respectively. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - administrator@example.org - support@example.org - development@example.org - - - - - - a list element followed by a reference - - - - - - - - - - - - - - just some string - - - - ----- - -__The value of a map key or value, or a set value, can also again be any of the -following elements:__ - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - bean | ref | idref | list | set | map | props | value | null ----- - -[[beans-collection-elements-merging]] -====== Collection merging -The Spring container also supports the __merging__ of collections. An application -developer can define a parent-style ``, ``, `` or `` element, -and have child-style ``, ``, `` or `` elements inherit and -override values from the parent collection. That is, the child collection's values are -the result of merging the elements of the parent and child collections, with the child's -collection elements overriding values specified in the parent collection. - -__This section on merging discusses the parent-child bean mechanism. Readers unfamiliar -with parent and child bean definitions may wish to read the -<> before continuing.__ - -The following example demonstrates collection merging: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - administrator@example.com - support@example.com - - - - - - - - sales@example.com - support@example.co.uk - - - - ----- - -Notice the use of the `merge=true` attribute on the `` element of the -`adminEmails` property of the `child` bean definition. When the `child` bean is resolved -and instantiated by the container, the resulting instance has an `adminEmails` -`Properties` collection that contains the result of the merging of the child's -`adminEmails` collection with the parent's `adminEmails` collection. - -[literal] -[subs="verbatim,quotes"] ----- -administrator=administrator@example.com -sales=sales@example.com -support=support@example.co.uk ----- - -The child `Properties` collection's value set inherits all property elements from the -parent ``, and the child's value for the `support` value overrides the value in -the parent collection. - -This merging behavior applies similarly to the ``, ``, and `` -collection types. In the specific case of the `` element, the semantics -associated with the `List` collection type, that is, the notion of an `ordered` -collection of values, is maintained; the parent's values precede all of the child list's -values. In the case of the `Map`, `Set`, and `Properties` collection types, no ordering -exists. Hence no ordering semantics are in effect for the collection types that underlie -the associated `Map`, `Set`, and `Properties` implementation types that the container -uses internally. - -[[beans-collection-merge-limitations]] -====== Limitations of collection merging -You cannot merge different collection types (such as a `Map` and a `List`), and if you -do attempt to do so an appropriate `Exception` is thrown. The `merge` attribute must be -specified on the lower, inherited, child definition; specifying the `merge` attribute on -a parent collection definition is redundant and will not result in the desired merging. - -[[beans-collection-elements-strongly-typed]] -====== Strongly-typed collection -With the introduction of generic types in Java 5, you can use strongly typed collections. -That is, it is possible to declare a `Collection` type such that it can only contain -`String` elements (for example). If you are using Spring to dependency-inject a -strongly-typed `Collection` into a bean, you can take advantage of Spring's -type-conversion support such that the elements of your strongly-typed `Collection` -instances are converted to the appropriate type prior to being added to the `Collection`. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class Foo { - - private Map accounts; - - public void setAccounts(Map accounts) { - this.accounts = accounts; - } - } ----- - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - - - - ----- - -When the `accounts` property of the `foo` bean is prepared for injection, the generics -information about the element type of the strongly-typed `Map` is -available by reflection. Thus Spring's type conversion infrastructure recognizes the -various value elements as being of type `Float`, and the string values `9.99, 2.75`, and -`3.99` are converted into an actual `Float` type. - - -[[beans-null-element]] -===== Null and empty string values -Spring treats empty arguments for properties and the like as empty `Strings`. The -following XML-based configuration metadata snippet sets the email property to the empty -`String` value (""). - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - ----- - -The preceding example is equivalent to the following Java code: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - exampleBean.setEmail("") ----- - -The `` element handles `null` values. For example: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - ----- - -The above configuration is equivalent to the following Java code: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - exampleBean.setEmail(null) ----- - - -[[beans-p-namespace]] -===== XML shortcut with the p-namespace -The p-namespace enables you to use the `bean` element's attributes, instead of nested -`` elements, to describe your property values and/or collaborating beans. - -Spring supports extensible configuration formats <>, which are -based on an XML Schema definition. The `beans` configuration format discussed in this -chapter is defined in an XML Schema document. However, the p-namespace is not defined in -an XSD file and exists only in the core of Spring. - -The following example shows two XML snippets that resolve to the same result: The first -uses standard XML format and the second uses the p-namespace. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - ----- - -The example shows an attribute in the p-namespace called email in the bean definition. -This tells Spring to include a property declaration. As previously mentioned, the -p-namespace does not have a schema definition, so you can set the name of the attribute -to the property name. - -This next example includes two more bean definitions that both have a reference to -another bean: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - - - - - - ----- - -As you can see, this example includes not only a property value using the p-namespace, -but also uses a special format to declare property references. Whereas the first bean -definition uses `` to create a reference from bean -`john` to bean `jane`, the second bean definition uses `p:spouse-ref="jane"` as an -attribute to do the exact same thing. In this case `spouse` is the property name, -whereas the `-ref` part indicates that this is not a straight value but rather a -reference to another bean. - -[NOTE] -==== -The p-namespace is not as flexible as the standard XML format. For example, the format -for declaring property references clashes with properties that end in `Ref`, whereas the -standard XML format does not. We recommend that you choose your approach carefully and -communicate this to your team members, to avoid producing XML documents that use all -three approaches at the same time. -==== - - -[[beans-c-namespace]] -===== XML shortcut with the c-namespace -Similar to the <>, the __c-namespace__, newly introduced in Spring -3.1, allows usage of inlined attributes for configuring the constructor arguments rather -then nested `constructor-arg` elements. - -Let's review the examples from <> with the `c:` namespace: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - - - - - - - - - ----- - -The `c:` namespace uses the same conventions as the `p:` one (trailing `-ref` for bean -references) for setting the constructor arguments by their names. And just as well, it -needs to be declared even though it is not defined in an XSD schema (but it exists -inside the Spring core). - -For the rare cases where the constructor argument names are not available (usually if -the bytecode was compiled without debugging information), one can use fallback to the -argument indexes: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - - ----- - -[NOTE] -==== -Due to the XML grammar, the index notation requires the presence of the leading `_` as -XML attribute names cannot start with a number (even though some IDE allow it). -==== - -In practice, the constructor resolution -<> is quite efficient in matching -arguments so unless one really needs to, we recommend using the name notation -through-out your configuration. - - -[[beans-compound-property-names]] -===== Compound property names -You can use compound or nested property names when you set bean properties, as long as -all components of the path except the final property name are not `null`. Consider the -following bean definition. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - ----- - -The `foo` bean has a `fred` property, which has a `bob` property, which has a `sammy` -property, and that final `sammy` property is being set to the value `123`. In order for -this to work, the `fred` property of `foo`, and the `bob` property of `fred` must not be -`null` after the bean is constructed, or a `NullPointerException` is thrown. - - - -[[beans-factory-dependson]] -==== Using depends-on - -If a bean is a dependency of another that usually means that one bean is set as a -property of another. Typically you accomplish this with the <` -element>> in XML-based configuration metadata. However, sometimes dependencies between -beans are less direct; for example, a static initializer in a class needs to be -triggered, such as database driver registration. The `depends-on` attribute can -explicitly force one or more beans to be initialized before the bean using this element -is initialized. The following example uses the `depends-on` attribute to express a -dependency on a single bean: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - ----- - -To express a dependency on multiple beans, supply a list of bean names as the value of -the `depends-on` attribute, with commas, whitespace and semicolons, used as valid -delimiters: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - ----- - -[NOTE] -==== -The `depends-on` attribute in the bean definition can specify both an initialization -time dependency and, in the case of <> beans -only, a corresponding destroy time dependency. Dependent beans that define a -`depends-on` relationship with a given bean are destroyed first, prior to the given bean -itself being destroyed. Thus `depends-on` can also control shutdown order. -==== - - - -[[beans-factory-lazy-init]] -==== Lazy-initialized beans -By default, `ApplicationContext` implementations eagerly create and configure all -<> beans as part of the initialization -process. Generally, this pre-instantiation is desirable, because errors in the -configuration or surrounding environment are discovered immediately, as opposed to hours -or even days later. When this behavior is __not__ desirable, you can prevent -pre-instantiation of a singleton bean by marking the bean definition as -lazy-initialized. A lazy-initialized bean tells the IoC container to create a bean -instance when it is first requested, rather than at startup. - -In XML, this behavior is controlled by the `lazy-init` attribute on the `` -element; for example: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - ----- - -When the preceding configuration is consumed by an `ApplicationContext`, the bean named -`lazy` is not eagerly pre-instantiated when the `ApplicationContext` is starting up, -whereas the `not.lazy` bean is eagerly pre-instantiated. - -However, when a lazy-initialized bean is a dependency of a singleton bean that is -__not__ lazy-initialized, the `ApplicationContext` creates the lazy-initialized bean at -startup, because it must satisfy the singleton's dependencies. The lazy-initialized bean -is injected into a singleton bean elsewhere that is not lazy-initialized. - -You can also control lazy-initialization at the container level by using the -`default-lazy-init` attribute on the `` element; for example: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - ----- - - - -[[beans-factory-autowire]] -==== Autowiring collaborators -The Spring container can __autowire__ relationships between collaborating beans. You can -allow Spring to resolve collaborators (other beans) automatically for your bean by -inspecting the contents of the `ApplicationContext`. Autowiring has the following -advantages: - -* Autowiring can significantly reduce the need to specify properties or constructor - arguments. (Other mechanisms such as a bean template - <> are also valuable - in this regard.) -* Autowiring can update a configuration as your objects evolve. For example, if you need - to add a dependency to a class, that dependency can be satisfied automatically without - you needing to modify the configuration. Thus autowiring can be especially useful - during development, without negating the option of switching to explicit wiring when - the code base becomes more stable. - -When using XML-based configuration metadata footnote:[See -pass:specialcharacters,macros[<>]], you specify autowire -mode for a bean definition with the `autowire` attribute of the `` element. The -autowiring functionality has five modes. You specify autowiring __per__ bean and thus -can choose which ones to autowire. - -[[beans-factory-autowiring-modes-tbl]] -.Autowiring modes -|=== -| Mode| Explanation - -| no -| (Default) No autowiring. Bean references must be defined via a `ref` element. Changing - the default setting is not recommended for larger deployments, because specifying - collaborators explicitly gives greater control and clarity. To some extent, it - documents the structure of a system. - -| byName -| Autowiring by property name. Spring looks for a bean with the same name as the - property that needs to be autowired. For example, if a bean definition is set to - autowire by name, and it contains a __master__ property (that is, it has a - __setMaster(..)__ method), Spring looks for a bean definition named `master`, and uses - it to set the property. - -| byType -| Allows a property to be autowired if exactly one bean of the property type exists in - the container. If more than one exists, a fatal exception is thrown, which indicates - that you may not use __byType__ autowiring for that bean. If there are no matching - beans, nothing happens; the property is not set. - -| constructor -| Analogous to __byType__, but applies to constructor arguments. If there is not exactly - one bean of the constructor argument type in the container, a fatal error is raised. -|=== - -With __byType__ or __constructor__ autowiring mode, you can wire arrays and -typed-collections. In such cases __all__ autowire candidates within the container that -match the expected type are provided to satisfy the dependency. You can autowire -strongly-typed Maps if the expected key type is `String`. An autowired Maps values will -consist of all bean instances that match the expected type, and the Maps keys will -contain the corresponding bean names. - -You can combine autowire behavior with dependency checking, which is performed after -autowiring completes. - - -[[beans-autowired-exceptions]] -===== Limitations and disadvantages of autowiring -Autowiring works best when it is used consistently across a project. If autowiring is -not used in general, it might be confusing to developers to use it to wire only one or -two bean definitions. - -Consider the limitations and disadvantages of autowiring: - -* Explicit dependencies in `property` and `constructor-arg` settings always override - autowiring. You cannot autowire so-called __simple__ properties such as primitives, - `Strings`, and `Classes` (and arrays of such simple properties). This limitation is - by-design. -* Autowiring is less exact than explicit wiring. Although, as noted in the above table, - Spring is careful to avoid guessing in case of ambiguity that might have unexpected - results, the relationships between your Spring-managed objects are no longer - documented explicitly. -* Wiring information may not be available to tools that may generate documentation from - a Spring container. -* Multiple bean definitions within the container may match the type specified by the - setter method or constructor argument to be autowired. For arrays, collections, or - Maps, this is not necessarily a problem. However for dependencies that expect a single - value, this ambiguity is not arbitrarily resolved. If no unique bean definition is - available, an exception is thrown. - -In the latter scenario, you have several options: - -* Abandon autowiring in favor of explicit wiring. -* Avoid autowiring for a bean definition by setting its `autowire-candidate` attributes - to `false` as described in the next section. -* Designate a single bean definition as the __primary__ candidate by setting the - `primary` attribute of its `` element to `true`. -* Implement the more fine-grained control available - with annotation-based configuration, as described in <>. - - -[[beans-factory-autowire-candidate]] -===== Excluding a bean from autowiring -On a per-bean basis, you can exclude a bean from autowiring. In Spring's XML format, set -the `autowire-candidate` attribute of the `` element to `false`; the container -makes that specific bean definition unavailable to the autowiring infrastructure -(including annotation style configurations such as <>). - -You can also limit autowire candidates based on pattern-matching against bean names. The -top-level `` element accepts one or more patterns within its -`default-autowire-candidates` attribute. For example, to limit autowire candidate status -to any bean whose name ends with __Repository,__ provide a value of *Repository. To -provide multiple patterns, define them in a comma-separated list. An explicit value of -`true` or `false` for a bean definitions `autowire-candidate` attribute always takes -precedence, and for such beans, the pattern matching rules do not apply. - -These techniques are useful for beans that you never want to be injected into other -beans by autowiring. It does not mean that an excluded bean cannot itself be configured -using autowiring. Rather, the bean itself is not a candidate for autowiring other beans. - - - -[[beans-factory-method-injection]] -==== Method injection -In most application scenarios, most beans in the container are -<>. When a singleton bean needs to -collaborate with another singleton bean, or a non-singleton bean needs to collaborate -with another non-singleton bean, you typically handle the dependency by defining one -bean as a property of the other. A problem arises when the bean lifecycles are -different. Suppose singleton bean A needs to use non-singleton (prototype) bean B, -perhaps on each method invocation on A. The container only creates the singleton bean A -once, and thus only gets one opportunity to set the properties. The container cannot -provide bean A with a new instance of bean B every time one is needed. - -A solution is to forego some inversion of control. You can <> by implementing the `ApplicationContextAware` interface, -and by <> ask for (a -typically new) bean B instance every time bean A needs it. The following is an example -of this approach: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - // a class that uses a stateful Command-style class to perform some processing - package fiona.apple; - - // Spring-API imports - import org.springframework.beans.BeansException; - import org.springframework.context.ApplicationContext; - import org.springframework.context.ApplicationContextAware; - - public class CommandManager implements ApplicationContextAware { - - private ApplicationContext applicationContext; - - public Object process(Map commandState) { - // grab a new instance of the appropriate Command - Command command = createCommand(); - // set the state on the (hopefully brand new) Command instance - command.setState(commandState); - return command.execute(); - } - - protected Command createCommand() { - // notice the Spring API dependency! - return this.applicationContext.getBean("command", Command.class); - } - - public void setApplicationContext( - ApplicationContext applicationContext) throws BeansException { - this.applicationContext = applicationContext; - } - } ----- - -The preceding is not desirable, because the business code is aware of and coupled to the -Spring Framework. Method Injection, a somewhat advanced feature of the Spring IoC -container, allows this use case to be handled in a clean fashion. - -**** -You can read more about the motivation for Method Injection in -https://spring.io/blog/2004/08/06/method-injection/[this blog entry]. -**** - - -[[beans-factory-lookup-method-injection]] -===== Lookup method injection -Lookup method injection is the ability of the container to override methods on -__container managed beans__, to return the lookup result for another named bean in the -container. The lookup typically involves a prototype bean as in the scenario described -in the preceding section. The Spring Framework implements this method injection by using -bytecode generation from the CGLIB library to generate dynamically a subclass that -overrides the method. - -[NOTE] -==== -For this dynamic subclassing to work, the class that the Spring container will subclass -cannot be `final`, and the method to be overridden cannot be `final` either. Also, -testing a class that has an `abstract` method requires you to subclass the class -yourself and to supply a stub implementation of the `abstract` method. Finally, objects -that have been the target of method injection cannot be serialized. As of Spring 3.2 it -is no longer necessary to add CGLIB to your classpath, because CGLIB classes are -repackaged under org.springframework and distributed within the spring-core JAR. This is -done both for convenience as well as to avoid potential conflicts with other projects -that use differing versions of CGLIB. -==== - -Looking at the `CommandManager` class in the previous code snippet, you see that the -Spring container will dynamically override the implementation of the `createCommand()` -method. Your `CommandManager` class will not have any Spring dependencies, as can be -seen in the reworked example: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - package fiona.apple; - - // no more Spring imports! - - public abstract class CommandManager { - - public Object process(Object commandState) { - // grab a new instance of the appropriate Command interface - Command command = createCommand(); - // set the state on the (hopefully brand new) Command instance - command.setState(commandState); - return command.execute(); - } - - // okay... but where is the implementation of this method? - protected abstract Command createCommand(); - } ----- - -In the client class containing the method to be injected (the `CommandManager` in this -case), the method to be injected requires a signature of the following form: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - [abstract] theMethodName(no-arguments); ----- - -If the method is `abstract`, the dynamically-generated subclass implements the method. -Otherwise, the dynamically-generated subclass overrides the concrete method defined in -the original class. For example: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - - ----- - -The bean identified as __commandManager__ calls its own method `createCommand()` -whenever it needs a new instance of the __command__ bean. You must be careful to deploy -the `command` bean as a prototype, if that is actually what is needed. If it is deployed -as a <>, the same instance of the `command` -bean is returned each time. - -[TIP] -==== -The interested reader may also find the `ServiceLocatorFactoryBean` (in the -`org.springframework.beans.factory.config` package) to be of use. The approach used in -ServiceLocatorFactoryBean is similar to that of another utility class, -`ObjectFactoryCreatingFactoryBean`, but it allows you to specify your own lookup -interface as opposed to a Spring-specific lookup interface. Consult the javadocs of -these classes for additional information. -==== - - -[[beans-factory-arbitrary-method-replacement]] -===== Arbitrary method replacement -A less useful form of method injection than lookup method Injection is the ability to -replace arbitrary methods in a managed bean with another method implementation. Users -may safely skip the rest of this section until the functionality is actually needed. - -With XML-based configuration metadata, you can use the `replaced-method` element to -replace an existing method implementation with another, for a deployed bean. Consider -the following class, with a method computeValue, which we want to override: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class MyValueCalculator { - - public String computeValue(String input) { - // some real code... - } - - // some other methods... - - } ----- - -A class implementing the `org.springframework.beans.factory.support.MethodReplacer` -interface provides the new method definition. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - /** - * meant to be used to override the existing computeValue(String) - * implementation in MyValueCalculator - */ - public class ReplacementComputeValue implements MethodReplacer { - - public Object reimplement(Object o, Method m, Object[] args) throws Throwable { - // get the input value, work with it, and return a computed result - String input = (String) args[0]; - ... - return ...; - } - } ----- - -The bean definition to deploy the original class and specify the method override would -look like this: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - String - - - - ----- - -You can use one or more contained `` elements within the `` -element to indicate the method signature of the method being overridden. The signature -for the arguments is necessary only if the method is overloaded and multiple variants -exist within the class. For convenience, the type string for an argument may be a -substring of the fully qualified type name. For example, the following all match -`java.lang.String`: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - java.lang.String - String - Str ----- - -Because the number of arguments is often enough to distinguish between each possible -choice, this shortcut can save a lot of typing, by allowing you to type only the -shortest string that will match an argument type. - - - - -[[beans-factory-scopes]] -=== Bean scopes -When you create a bean definition, you create a __recipe__ for creating actual instances -of the class defined by that bean definition. The idea that a bean definition is a -recipe is important, because it means that, as with a class, you can create many object -instances from a single recipe. - -You can control not only the various dependencies and configuration values that are to -be plugged into an object that is created from a particular bean definition, but also -the __scope__ of the objects created from a particular bean definition. This approach is -powerful and flexible in that you can __choose__ the scope of the objects you create -through configuration instead of having to bake in the scope of an object at the Java -class level. Beans can be defined to be deployed in one of a number of scopes: out of -the box, the Spring Framework supports five scopes, three of which are available only if -you use a web-aware `ApplicationContext`. - -The following scopes are supported out of the box. You can also create -<> - -[[beans-factory-scopes-tbl]] -.Bean scopes -|=== -| Scope| Description - -| <> -| (Default) Scopes a single bean definition to a single object instance per Spring IoC - container. - -| <> -| Scopes a single bean definition to any number of object instances. - -| <> -| Scopes a single bean definition to the lifecycle of a single HTTP request; that is, - each HTTP request has its own instance of a bean created off the back of a single bean - definition. Only valid in the context of a web-aware Spring `ApplicationContext`. - -| <> -| Scopes a single bean definition to the lifecycle of an HTTP `Session`. Only valid in - the context of a web-aware Spring `ApplicationContext`. - -| <> -| Scopes a single bean definition to the lifecycle of a global HTTP `Session`. Typically - only valid when used in a portlet context. Only valid in the context of a web-aware - Spring `ApplicationContext`. - -| <> -| Scopes a single bean definition to the lifecycle of a `ServletContext`. Only valid in - the context of a web-aware Spring `ApplicationContext`. -|=== - -[NOTE] -==== -As of Spring 3.0, a __thread scope__ is available, but is not registered by default. For -more information, see the documentation for -{javadoc-baseurl}/org/springframework/context/support/SimpleThreadScope.html[`SimpleThreadScope`]. -For instructions on how to register this or any other custom scope, see -<>. -==== - - - -[[beans-factory-scopes-singleton]] -==== The singleton scope -Only one __shared__ instance of a singleton bean is managed, and all requests for beans -with an id or ids matching that bean definition result in that one specific bean -instance being returned by the Spring container. - -To put it another way, when you define a bean definition and it is scoped as a -singleton, the Spring IoC container creates __exactly one__ instance of the object -defined by that bean definition. This single instance is stored in a cache of such -singleton beans, and __all subsequent requests and references__ for that named bean -return the cached object. - -image::images/singleton.png[width=400] - -Spring's concept of a singleton bean differs from the Singleton pattern as defined in -the Gang of Four (GoF) patterns book. The GoF Singleton hard-codes the scope of an -object such that one __and only one__ instance of a particular class is created __per -ClassLoader__. The scope of the Spring singleton is best described as __per container -and per bean__. This means that if you define one bean for a particular class in a -single Spring container, then the Spring container creates one __and only one__ instance -of the class defined by that bean definition. __The singleton scope is the default scope -in Spring__. To define a bean as a singleton in XML, you would write, for example: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - ----- - - - -[[beans-factory-scopes-prototype]] -==== The prototype scope -The non-singleton, prototype scope of bean deployment results in the __creation of a new -bean instance__ every time a request for that specific bean is made. That is, the bean -is injected into another bean or you request it through a `getBean()` method call on the -container. As a rule, use the prototype scope for all stateful beans and the singleton -scope for stateless beans. - -The following diagram illustrates the Spring prototype scope. __A data access object -(DAO) is not typically configured as a prototype, because a typical DAO does not hold -any conversational state; it was just easier for this author to reuse the core of the -singleton diagram.__ - -image::images/prototype.png[width=400] - -The following example defines a bean as a prototype in XML: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - ----- - -In contrast to the other scopes, Spring does not manage the complete lifecycle of a -prototype bean: the container instantiates, configures, and otherwise assembles a -prototype object, and hands it to the client, with no further record of that prototype -instance. Thus, although__ initialization__ lifecycle callback methods are called on all -objects regardless of scope, in the case of prototypes, configured __destruction__ -lifecycle callbacks are __not__ called. The client code must clean up prototype-scoped -objects and release expensive resources that the prototype bean(s) are holding. To get -the Spring container to release resources held by prototype-scoped beans, try using a -custom <>, which holds a reference to -beans that need to be cleaned up. - -In some respects, the Spring container's role in regard to a prototype-scoped bean is a -replacement for the Java `new` operator. All lifecycle management past that point must -be handled by the client. (For details on the lifecycle of a bean in the Spring -container, see <>.) - - - -[[beans-factory-scopes-sing-prot-interaction]] -==== Singleton beans with prototype-bean dependencies -When you use singleton-scoped beans with dependencies on prototype beans, be aware that -__dependencies are resolved at instantiation time__. Thus if you dependency-inject a -prototype-scoped bean into a singleton-scoped bean, a new prototype bean is instantiated -and then dependency-injected into the singleton bean. The prototype instance is the sole -instance that is ever supplied to the singleton-scoped bean. - -However, suppose you want the singleton-scoped bean to acquire a new instance of the -prototype-scoped bean repeatedly at runtime. You cannot dependency-inject a -prototype-scoped bean into your singleton bean, because that injection occurs only -__once__, when the Spring container is instantiating the singleton bean and resolving -and injecting its dependencies. If you need a new instance of a prototype bean at -runtime more than once, see <> - - - -[[beans-factory-scopes-other]] -==== Request, session, and global session scopes -The `request`, `session`, and `global session` scopes are __only__ available if you use -a web-aware Spring `ApplicationContext` implementation (such as -`XmlWebApplicationContext`). If you use these scopes with regular Spring IoC containers -such as the `ClassPathXmlApplicationContext`, you get an `IllegalStateException` -complaining about an unknown bean scope. - - -[[beans-factory-scopes-other-web-configuration]] -===== Initial web configuration -To support the scoping of beans at the `request`, `session`, and `global session` levels -(web-scoped beans), some minor initial configuration is required before you define your -beans. (This initial setup is __not__ required for the standard scopes, singleton and -prototype.) - -How you accomplish this initial setup depends on your particular Servlet environment.. - -If you access scoped beans within Spring Web MVC, in effect, within a request that is -processed by the Spring `DispatcherServlet`, or `DispatcherPortlet`, then no special -setup is necessary: `DispatcherServlet` and `DispatcherPortlet` already expose all -relevant state. - -If you use a Servlet 2.5 web container, with requests processed outside of Spring's -DispatcherServlet (for example, when using JSF or Struts), you need to register the -`org.springframework.web.context.request.RequestContextListener` `ServletRequestListener`. -For Servlet 3.0+, this can done programmatically via the `WebApplicationInitializer` -interface. Alternatively, or for older containers, add the following declaration to -your web application's `web.xml` file: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - ... - - - org.springframework.web.context.request.RequestContextListener - - - ... - ----- - -Alternatively, if there are issues with your listener setup, consider the provided -`RequestContextFilter`. The filter mapping depends on the surrounding web -application configuration, so you have to change it as appropriate. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - ... - - requestContextFilter - org.springframework.web.filter.RequestContextFilter - - - requestContextFilter - /* - - ... - ----- - -`DispatcherServlet`, `RequestContextListener` and `RequestContextFilter` all do exactly -the same thing, namely bind the HTTP request object to the `Thread` that is servicing -that request. This makes beans that are request- and session-scoped available further -down the call chain. - - -[[beans-factory-scopes-request]] -===== Request scope -Consider the following bean definition: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - ----- - -The Spring container creates a new instance of the `LoginAction` bean by using the -`loginAction` bean definition for each and every HTTP request. That is, the -`loginAction` bean is scoped at the HTTP request level. You can change the internal -state of the instance that is created as much as you want, because other instances -created from the same `loginAction` bean definition will not see these changes in state; -they are particular to an individual request. When the request completes processing, the -bean that is scoped to the request is discarded. - - -[[beans-factory-scopes-session]] -===== Session scope -Consider the following bean definition: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - ----- - -The Spring container creates a new instance of the `UserPreferences` bean by using the -`userPreferences` bean definition for the lifetime of a single HTTP `Session`. In other -words, the `userPreferences` bean is effectively scoped at the HTTP `Session` level. As -with `request-scoped` beans, you can change the internal state of the instance that is -created as much as you want, knowing that other HTTP `Session` instances that are also -using instances created from the same `userPreferences` bean definition do not see these -changes in state, because they are particular to an individual HTTP `Session`. When the -HTTP `Session` is eventually discarded, the bean that is scoped to that particular HTTP -`Session` is also discarded. - - -[[beans-factory-scopes-global-session]] -===== Global session scope -Consider the following bean definition: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - ----- - -The `global session` scope is similar to the standard HTTP `Session` scope -(<>), and applies only in the context of -portlet-based web applications. The portlet specification defines the notion of a global -`Session` that is shared among all portlets that make up a single portlet web -application. Beans defined at the `global session` scope are scoped (or bound) to the -lifetime of the global portlet `Session`. - -If you write a standard Servlet-based web application and you define one or more beans -as having `global session` scope, the standard HTTP `Session` scope is used, and no -error is raised. - - -[[beans-factory-scopes-application]] -===== Application scope -Consider the following bean definition: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - ----- - -The Spring container creates a new instance of the `AppPreferences` bean by using the -`appPreferences` bean definition once for the entire web application. That is, the -`appPreferences` bean is scoped at the `ServletContext` level, stored as a regular -`ServletContext` attribute. This is somewhat similar to a Spring singleton bean but -differs in two important ways: It is a singleton per `ServletContext`, not per Spring -'ApplicationContext' (or which there may be several in any given web application), -and it is actually exposed and therefore visible as a `ServletContext` attribute. - - -[[beans-factory-scopes-other-injection]] -===== Scoped beans as dependencies -The Spring IoC container manages not only the instantiation of your objects (beans), but -also the wiring up of collaborators (or dependencies). If you want to inject (for -example) an HTTP request scoped bean into another bean, you must inject an AOP proxy in -place of the scoped bean. That is, you need to inject a proxy object that exposes the -same public interface as the scoped object but that can also retrieve the real, target -object from the relevant scope (for example, an HTTP request) and delegate method calls -onto the real object. - -[NOTE] -==== -You __do not__ need to use the `` in conjunction with beans that are -scoped as `singletons` or `prototypes`. -==== - -The configuration in the following example is only one line, but it is important to -understand the "why" as well as the "how" behind it. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - - - - - - - - ----- - -To create such a proxy, you insert a child `` element into a scoped -bean definition. See <> and -<>.) Why do definitions of beans scoped at the `request`, `session`, -`globalSession` and custom-scope levels require the `` element ? -Let's examine the following singleton bean definition and contrast it with what you need -to define for the aforementioned scopes. (The following `userPreferences` bean -definition as it stands is __incomplete.)__ - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - ----- - -In the preceding example, the singleton bean `userManager` is injected with a reference -to the HTTP `Session`-scoped bean `userPreferences`. The salient point here is that the -`userManager` bean is a singleton: it will be instantiated __exactly once__ per -container, and its dependencies (in this case only one, the `userPreferences` bean) are -also injected only once. This means that the `userManager` bean will only operate on the -exact same `userPreferences` object, that is, the one that it was originally injected -with. - -This is __not__ the behavior you want when injecting a shorter-lived scoped bean into a -longer-lived scoped bean, for example injecting an HTTP `Session`-scoped collaborating -bean as a dependency into singleton bean. Rather, you need a single `userManager` -object, and for the lifetime of an HTTP `Session`, you need a `userPreferences` object -that is specific to said HTTP `Session`. Thus the container creates an object that -exposes the exact same public interface as the `UserPreferences` class (ideally an -object that __is a__ `UserPreferences` instance) which can fetch the real -`UserPreferences` object from the scoping mechanism (HTTP request, `Session`, etc.). The -container injects this proxy object into the `userManager` bean, which is unaware that -this `UserPreferences` reference is a proxy. In this example, when a `UserManager` -instance invokes a method on the dependency-injected `UserPreferences` object, it -actually is invoking a method on the proxy. The proxy then fetches the real -`UserPreferences` object from (in this case) the HTTP `Session`, and delegates the -method invocation onto the retrieved real `UserPreferences` object. - -Thus you need the following, correct and complete, configuration when injecting -`request-`, `session-`, and `globalSession-scoped` beans into collaborating objects: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - ----- - -[[beans-factory-scopes-other-injection-proxies]] -====== Choosing the type of proxy to create -By default, when the Spring container creates a proxy for a bean that is marked up with -the `` element, __a CGLIB-based class proxy is created__. - -[NOTE] -==== -CGLIB proxies only intercept public method calls! Do not call non-public methods -on such a proxy; they will not be delegated to the actual scoped target object. -==== - -Alternatively, you can configure the Spring container to create standard JDK -interface-based proxies for such scoped beans, by specifying `false` for the value of -the `proxy-target-class` attribute of the `` element. Using JDK -interface-based proxies means that you do not need additional libraries in your -application classpath to effect such proxying. However, it also means that the class of -the scoped bean must implement at least one interface, and __that all__ collaborators -into which the scoped bean is injected must reference the bean through one of its -interfaces. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - ----- - -For more detailed information about choosing class-based or interface-based proxying, -see <>. - - - -[[beans-factory-scopes-custom]] -==== Custom scopes -The bean scoping mechanism is extensible; You can define your own -scopes, or even redefine existing scopes, although the latter is considered bad practice -and you __cannot__ override the built-in `singleton` and `prototype` scopes. - - -[[beans-factory-scopes-custom-creating]] -===== Creating a custom scope -To integrate your custom scope(s) into the Spring container, you need to implement the -`org.springframework.beans.factory.config.Scope` interface, which is described in this -section. For an idea of how to implement your own scopes, see the `Scope` -implementations that are supplied with the Spring Framework itself and the -{javadoc-baseurl}/org/springframework/beans/factory/config/Scope.html[`Scope` javadocs], -which explains the methods you need to implement in more detail. - -The `Scope` interface has four methods to get objects from the scope, remove them from -the scope, and allow them to be destroyed. - -The following method returns the object from the underlying scope. The session scope -implementation, for example, returns the session-scoped bean (and if it does not exist, -the method returns a new instance of the bean, after having bound it to the session for -future reference). - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - Object get(String name, ObjectFactory objectFactory) ----- - -The following method removes the object from the underlying scope. The session scope -implementation for example, removes the session-scoped bean from the underlying session. -The object should be returned, but you can return null if the object with the specified -name is not found. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - Object remove(String name) ----- - -The following method registers the callbacks the scope should execute when it is -destroyed or when the specified object in the scope is destroyed. Refer to the javadocs -or a Spring scope implementation for more information on destruction callbacks. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - void registerDestructionCallback(String name, Runnable destructionCallback) ----- - -The following method obtains the conversation identifier for the underlying scope. This -identifier is different for each scope. For a session scoped implementation, this -identifier can be the session identifier. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - String getConversationId() ----- - - -[[beans-factory-scopes-custom-using]] -===== Using a custom scope -After you write and test one or more custom `Scope` implementations, you need to make -the Spring container aware of your new scope(s). The following method is the central -method to register a new `Scope` with the Spring container: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - void registerScope(String scopeName, Scope scope); ----- - -This method is declared on the `ConfigurableBeanFactory` interface, which is available -on most of the concrete `ApplicationContext` implementations that ship with Spring via -the BeanFactory property. - -The first argument to the `registerScope(..)` method is the unique name associated with -a scope; examples of such names in the Spring container itself are `singleton` and -`prototype`. The second argument to the `registerScope(..)` method is an actual instance -of the custom `Scope` implementation that you wish to register and use. - -Suppose that you write your custom `Scope` implementation, and then register it as below. - -[NOTE] -==== -The example below uses `SimpleThreadScope` which is included with Spring, but not -registered by default. The instructions would be the same for your own custom `Scope` -implementations. -==== - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - Scope threadScope = new SimpleThreadScope(); - beanFactory.registerScope("thread", threadScope); ----- - -You then create bean definitions that adhere to the scoping rules of your custom `Scope`: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - ----- - -With a custom `Scope` implementation, you are not limited to programmatic registration -of the scope. You can also do the `Scope` registration declaratively, using the -`CustomScopeConfigurer` class: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - - - - - - - - - - - - - - - - ----- - -[NOTE] -==== -When you place `` in a `FactoryBean` implementation, it is the factory -bean itself that is scoped, not the object returned from `getObject()`. -==== - - - - -[[beans-factory-nature]] -=== Customizing the nature of a bean - - - -[[beans-factory-lifecycle]] -==== Lifecycle callbacks -To interact with the container's management of the bean lifecycle, you can implement the -Spring `InitializingBean` and `DisposableBean` interfaces. The container calls -`afterPropertiesSet()` for the former and `destroy()` for the latter to allow the bean -to perform certain actions upon initialization and destruction of your beans. - -[TIP] -==== - -The JSR-250 `@PostConstruct` and `@PreDestroy` annotations are generally considered best -practice for receiving lifecycle callbacks in a modern Spring application. Using these -annotations means that your beans are not coupled to Spring specific interfaces. For -details see <>. - -If you don't want to use the JSR-250 annotations but you are still looking to remove -coupling consider the use of init-method and destroy-method object definition metadata. -==== - -Internally, the Spring Framework uses `BeanPostProcessor` implementations to process any -callback interfaces it can find and call the appropriate methods. If you need custom -features or other lifecycle behavior Spring does not offer out-of-the-box, you can -implement a `BeanPostProcessor` yourself. For more information, see -<>. - -In addition to the initialization and destruction callbacks, Spring-managed objects may -also implement the `Lifecycle` interface so that those objects can participate in the -startup and shutdown process as driven by the container's own lifecycle. - -The lifecycle callback interfaces are described in this section. - - -[[beans-factory-lifecycle-initializingbean]] -===== Initialization callbacks -The `org.springframework.beans.factory.InitializingBean` interface allows a bean to -perform initialization work after all necessary properties on the bean have been set by -the container. The `InitializingBean` interface specifies a single method: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - void afterPropertiesSet() throws Exception; ----- - -It is recommended that you do not use the `InitializingBean` interface because it -unnecessarily couples the code to Spring. Alternatively, use -the <> annotation or -specify a POJO initialization method. In the case of XML-based configuration metadata, -you use the `init-method` attribute to specify the name of the method that has a void -no-argument signature. For example, the following definition: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - ----- - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class ExampleBean { - - public void init() { - // do some initialization work - } - - } ----- - -...is exactly the same as... - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - ----- - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class AnotherExampleBean implements InitializingBean { - - public void afterPropertiesSet() { - // do some initialization work - } - - } ----- - -but does not couple the code to Spring. - - -[[beans-factory-lifecycle-disposablebean]] -===== Destruction callbacks -Implementing the `org.springframework.beans.factory.DisposableBean` interface allows a -bean to get a callback when the container containing it is destroyed. The -`DisposableBean` interface specifies a single method: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - void destroy() throws Exception; ----- - -It is recommended that you do not use the `DisposableBean` callback interface because it -unnecessarily couples the code to Spring. Alternatively, use -the <> annotation or -specify a generic method that is supported by bean definitions. With XML-based -configuration metadata, you use the `destroy-method` attribute on the ``. For -example, the following definition: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - ----- - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class ExampleBean { - - public void cleanup() { - // do some destruction work (like releasing pooled connections) - } - - } ----- - -is exactly the same as: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - ----- - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class AnotherExampleBean implements DisposableBean { - - public void destroy() { - // do some destruction work (like releasing pooled connections) - } - - } ----- - -but does not couple the code to Spring. - - -[[beans-factory-lifecycle-default-init-destroy-methods]] -===== Default initialization and destroy methods -When you write initialization and destroy method callbacks that do not use the -Spring-specific `InitializingBean` and `DisposableBean` callback interfaces, you -typically write methods with names such as `init()`, `initialize()`, `dispose()`, and so -on. Ideally, the names of such lifecycle callback methods are standardized across a -project so that all developers use the same method names and ensure consistency. - -You can configure the Spring container to `look` for named initialization and destroy -callback method names on __every__ bean. This means that you, as an application -developer, can write your application classes and use an initialization callback called -`init()`, without having to configure an `init-method="init"` attribute with each bean -definition. The Spring IoC container calls that method when the bean is created (and in -accordance with the standard lifecycle callback contract described previously). This -feature also enforces a consistent naming convention for initialization and destroy -method callbacks. - -Suppose that your initialization callback methods are named `init()` and destroy -callback methods are named `destroy()`. Your class will resemble the class in the -following example. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class DefaultBlogService implements BlogService { - - private BlogDao blogDao; - - public void setBlogDao(BlogDao blogDao) { - this.blogDao = blogDao; - } - - // this is (unsurprisingly) the initialization callback method - public void init() { - if (this.blogDao == null) { - throw new IllegalStateException("The [blogDao] property must be set."); - } - } - - } ----- - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - ----- - -The presence of the `default-init-method` attribute on the top-level `` element -attribute causes the Spring IoC container to recognize a method called `init` on beans -as the initialization method callback. When a bean is created and assembled, if the bean -class has such a method, it is invoked at the appropriate time. - -You configure destroy method callbacks similarly (in XML, that is) by using the -`default-destroy-method` attribute on the top-level `` element. - -Where existing bean classes already have callback methods that are named at variance -with the convention, you can override the default by specifying (in XML, that is) the -method name using the `init-method` and `destroy-method` attributes of the -itself. - -The Spring container guarantees that a configured initialization callback is called -immediately after a bean is supplied with all dependencies. Thus the initialization -callback is called on the raw bean reference, which means that AOP interceptors and so -forth are not yet applied to the bean. A target bean is fully created __first__, -__then__ an AOP proxy (for example) with its interceptor chain is applied. If the target -bean and the proxy are defined separately, your code can even interact with the raw -target bean, bypassing the proxy. Hence, it would be inconsistent to apply the -interceptors to the init method, because doing so would couple the lifecycle of the -target bean with its proxy/interceptors and leave strange semantics when your code -interacts directly to the raw target bean. - - -[[beans-factory-lifecycle-combined-effects]] -===== Combining lifecycle mechanisms -As of Spring 2.5, you have three options for controlling bean lifecycle behavior: the -<> and -<> callback interfaces; custom -`init()` and `destroy()` methods; and the -<>. You can combine these mechanisms to control a given bean. - -[NOTE] -==== -If multiple lifecycle mechanisms are configured for a bean, and each mechanism is -configured with a different method name, then each configured method is executed in the -order listed below. However, if the same method name is configured - for example, -`init()` for an initialization method - for more than one of these lifecycle mechanisms, -that method is executed once, as explained in the preceding section. -==== - -Multiple lifecycle mechanisms configured for the same bean, with different -initialization methods, are called as follows: - -* Methods annotated with `@PostConstruct` -* `afterPropertiesSet()` as defined by the `InitializingBean` callback interface -* A custom configured `init()` method - -Destroy methods are called in the same order: - -* Methods annotated with `@PreDestroy` -* `destroy()` as defined by the `DisposableBean` callback interface -* A custom configured `destroy()` method - - -[[beans-factory-lifecycle-processor]] -===== Startup and shutdown callbacks -The `Lifecycle` interface defines the essential methods for any object that has its own -lifecycle requirements (e.g. starts and stops some background process): - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public interface Lifecycle { - - void start(); - - void stop(); - - boolean isRunning(); - - } ----- - -Any Spring-managed object may implement that interface. Then, when the -`ApplicationContext` itself starts and stops, it will cascade those calls to all `Lifecycle` -implementations defined within that context. It does this by delegating to a -`LifecycleProcessor`: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public interface LifecycleProcessor extends Lifecycle { - - void onRefresh(); - - void onClose(); - - } ----- - -Notice that the `LifecycleProcessor` is itself an extension of the `Lifecycle` -interface. It also adds two other methods for reacting to the context being refreshed -and closed. - -The order of startup and shutdown invocations can be important. If a "depends-on" -relationship exists between any two objects, the dependent side will start __after__ its -dependency, and it will stop __before__ its dependency. However, at times the direct -dependencies are unknown. You may only know that objects of a certain type should start -prior to objects of another type. In those cases, the `SmartLifecycle` interface defines -another option, namely the `getPhase()` method as defined on its super-interface, -`Phased`. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public interface Phased { - - int getPhase(); - - } ----- - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public interface SmartLifecycle extends Lifecycle, Phased { - - boolean isAutoStartup(); - - void stop(Runnable callback); - - } ----- - -When starting, the objects with the lowest phase start first, and when stopping, the -reverse order is followed. Therefore, an object that implements `SmartLifecycle` and -whose `getPhase()` method returns `Integer.MIN_VALUE` would be among the first to start -and the last to stop. At the other end of the spectrum, a phase value of -`Integer.MAX_VALUE` would indicate that the object should be started last and stopped -first (likely because it depends on other processes to be running). When considering the -phase value, it's also important to know that the default phase for any "normal" -`Lifecycle` object that does not implement `SmartLifecycle` would be 0. Therefore, any -negative phase value would indicate that an object should start before those standard -components (and stop after them), and vice versa for any positive phase value. - -As you can see the stop method defined by `SmartLifecycle` accepts a callback. Any -implementation __must__ invoke that callback's `run()` method after that implementation's -shutdown process is complete. That enables asynchronous shutdown where necessary since -the default implementation of the `LifecycleProcessor` interface, -`DefaultLifecycleProcessor`, will wait up to its timeout value for the group of objects -within each phase to invoke that callback. The default per-phase timeout is 30 seconds. -You can override the default lifecycle processor instance by defining a bean named -"lifecycleProcessor" within the context. If you only want to modify the timeout, then -defining the following would be sufficient: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - ----- - -As mentioned, the `LifecycleProcessor` interface defines callback methods for the -refreshing and closing of the context as well. The latter will simply drive the shutdown -process as if `stop()` had been called explicitly, but it will happen when the context is -closing. The 'refresh' callback on the other hand enables another feature of -`SmartLifecycle` beans. When the context is refreshed (after all objects have been -instantiated and initialized), that callback will be invoked, and at that point the -default lifecycle processor will check the boolean value returned by each -`SmartLifecycle` object's `isAutoStartup()` method. If "true", then that object will be -started at that point rather than waiting for an explicit invocation of the context's or -its own `start()` method (unlike the context refresh, the context start does not happen -automatically for a standard context implementation). The "phase" value as well as any -"depends-on" relationships will determine the startup order in the same way as described -above. - - -[[beans-factory-shutdown]] -===== Shutting down the Spring IoC container gracefully in non-web applications -[NOTE] -==== -This section applies only to non-web applications. Spring's web-based -`ApplicationContext` implementations already have code in place to shut down the Spring -IoC container gracefully when the relevant web application is shut down. -==== - -If you are using Spring's IoC container in a non-web application environment; for -example, in a rich client desktop environment; you register a shutdown hook with the -JVM. Doing so ensures a graceful shutdown and calls the relevant destroy methods on your -singleton beans so that all resources are released. Of course, you must still configure -and implement these destroy callbacks correctly. - -To register a shutdown hook, you call the `registerShutdownHook()` method that is -declared on the `AbstractApplicationContext` class: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - import org.springframework.context.support.AbstractApplicationContext; - import org.springframework.context.support.ClassPathXmlApplicationContext; - - public final class Boot { - - public static void main(final String[] args) throws Exception { - - AbstractApplicationContext ctx = new ClassPathXmlApplicationContext( - new String []{"beans.xml"}); - - // add a shutdown hook for the above context... - ctx.registerShutdownHook(); - - // app runs here... - - // main method exits, hook is called prior to the app shutting down... - - } - } ----- - - - -[[beans-factory-aware]] -==== ApplicationContextAware and BeanNameAware - -When an `ApplicationContext` creates an object instance that implements the -`org.springframework.context.ApplicationContextAware` interface, the instance is provided -with a reference to that `ApplicationContext`. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public interface ApplicationContextAware { - - void setApplicationContext(ApplicationContext applicationContext) throws BeansException; - - } ----- - -Thus beans can manipulate programmatically the `ApplicationContext` that created them, -through the `ApplicationContext` interface, or by casting the reference to a known -subclass of this interface, such as `ConfigurableApplicationContext`, which exposes -additional functionality. One use would be the programmatic retrieval of other beans. -Sometimes this capability is useful; however, in general you should avoid it, because it -couples the code to Spring and does not follow the Inversion of Control style, where -collaborators are provided to beans as properties. Other methods of the -`ApplicationContext` provide access to file resources, publishing application events, and -accessing a `MessageSource`. These additional features are described in -<> - -As of Spring 2.5, autowiring is another alternative to obtain reference to the -`ApplicationContext`. The "traditional" `constructor` and `byType` autowiring modes (as -described in <>) can provide a dependency of type -`ApplicationContext` for a constructor argument or setter method parameter, -respectively. For more flexibility, including the ability to autowire fields and -multiple parameter methods, use the new annotation-based autowiring features. If you do, -the `ApplicationContext` is autowired into a field, constructor argument, or method -parameter that is expecting the `ApplicationContext` type if the field, constructor, or -method in question carries the `@Autowired` annotation. For more information, see -<>. - -When an `ApplicationContext` creates a class that implements the -`org.springframework.beans.factory.BeanNameAware` interface, the class is provided with -a reference to the name defined in its associated object definition. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public interface BeanNameAware { - - void setBeanName(string name) throws BeansException; - - } ----- - -The callback is invoked after population of normal bean properties but before an -initialization callback such as `InitializingBean` __afterPropertiesSet__ or a custom -init-method. - - - -[[aware-list]] -==== Other Aware interfaces - -Besides `ApplicationContextAware` and `BeanNameAware` discussed above, Spring offers a -range of `Aware` interfaces that allow beans to indicate to the container that they -require a certain __infrastructure__ dependency. The most important `Aware` interfaces -are summarized below - as a general rule, the name is a good indication of the -dependency type: - -[[beans-factory-nature-aware-list]] -.Aware interfaces -|=== -| Name| Injected Dependency| Explained in... - -| `ApplicationContextAware` -| Declaring `ApplicationContext` -| <> - -| `ApplicationEventPublisherAware` -| Event publisher of the enclosing `ApplicationContext` -| <> - -| `BeanClassLoaderAware` -| Class loader used to load the bean classes. -| <> - -| `BeanFactoryAware` -| Declaring `BeanFactory` -| <> - -| `BeanNameAware` -| Name of the declaring bean -| <> - -| `BootstrapContextAware` -| Resource adapter `BootstrapContext` the container runs in. Typically available only in - JCA aware ++ApplicationContext++s -| <> - -| `LoadTimeWeaverAware` -| Defined __weaver__ for processing class definition at load time -| <> - -| `MessageSourceAware` -| Configured strategy for resolving messages (with support for parametrization and - internationalization) -| <> - -| `NotificationPublisherAware` -| Spring JMX notification publisher -| <> - -| `PortletConfigAware` -| Current `PortletConfig` the container runs in. Valid only in a web-aware Spring - `ApplicationContext` -| <> - -| `PortletContextAware` -| Current `PortletContext` the container runs in. Valid only in a web-aware Spring - `ApplicationContext` -| <> - -| `ResourceLoaderAware` -| Configured loader for low-level access to resources -| <> - -| `ServletConfigAware` -| Current `ServletConfig` the container runs in. Valid only in a web-aware Spring - `ApplicationContext` -| <> - -| `ServletContextAware` -| Current `ServletContext` the container runs in. Valid only in a web-aware Spring - `ApplicationContext` -| <> -|=== - -Note again that usage of these interfaces ties your code to the Spring API and does not -follow the Inversion of Control style. As such, they are recommended for infrastructure -beans that require programmatic access to the container. - - - - -[[beans-child-bean-definitions]] -=== Bean definition inheritance -A bean definition can contain a lot of configuration information, including constructor -arguments, property values, and container-specific information such as initialization -method, static factory method name, and so on. A child bean definition inherits -configuration data from a parent definition. The child definition can override some -values, or add others, as needed. Using parent and child bean definitions can save a lot -of typing. Effectively, this is a form of templating. - -If you work with an `ApplicationContext` interface programmatically, child bean -definitions are represented by the `ChildBeanDefinition` class. Most users do not work -with them on this level, instead configuring bean definitions declaratively in something -like the `ClassPathXmlApplicationContext`. When you use XML-based configuration -metadata, you indicate a child bean definition by using the `parent` attribute, -specifying the parent bean as the value of this attribute. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - - ----- - -A child bean definition uses the bean class from the parent definition if none is -specified, but can also override it. In the latter case, the child bean class must be -compatible with the parent, that is, it must accept the parent's property values. - -A child bean definition inherits constructor argument values, property values, and -method overrides from the parent, with the option to add new values. Any initialization -method, destroy method, and/or `static` factory method settings that you specify will -override the corresponding parent settings. - -The remaining settings are __always__ taken from the child definition: __depends on__, -__autowire mode__, __dependency check__, __singleton__, __scope__, __lazy init__. - -The preceding example explicitly marks the parent bean definition as abstract by using -the `abstract` attribute. If the parent definition does not specify a class, explicitly -marking the parent bean definition as `abstract` is required, as follows: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - - ----- - -The parent bean cannot be instantiated on its own because it is incomplete, and it is -also explicitly marked as `abstract`. When a definition is `abstract` like this, it is -usable only as a pure template bean definition that serves as a parent definition for -child definitions. Trying to use such an `abstract` parent bean on its own, by referring -to it as a ref property of another bean or doing an explicit `getBean()` call with the -parent bean id, returns an error. Similarly, the container's internal -`preInstantiateSingletons()` method ignores bean definitions that are defined as -abstract. - -[NOTE] -==== -`ApplicationContext` pre-instantiates all singletons by default. Therefore, it is -important (at least for singleton beans) that if you have a (parent) bean definition -which you intend to use only as a template, and this definition specifies a class, you -must make sure to set the __abstract__ attribute to __true__, otherwise the application -context will actually (attempt to) pre-instantiate the `abstract` bean. -==== - - - - -[[beans-factory-extension]] -=== Container Extension Points -Typically, an application developer does not need to subclass `ApplicationContext` -implementation classes. Instead, the Spring IoC container can be extended by plugging in -implementations of special integration interfaces. The next few sections describe these -integration interfaces. - - - -[[beans-factory-extension-bpp]] -==== Customizing beans using a BeanPostProcessor - -The `BeanPostProcessor` interface defines __callback methods__ that you can implement to -provide your own (or override the container's default) instantiation logic, -dependency-resolution logic, and so forth. If you want to implement some custom logic -after the Spring container finishes instantiating, configuring, and initializing a bean, -you can plug in one or more `BeanPostProcessor` implementations. - -You can configure multiple `BeanPostProcessor` instances, and you can control the order -in which these ++BeanPostProcessor++s execute by setting the `order` property. You can -set this property only if the `BeanPostProcessor` implements the `Ordered` interface; if -you write your own `BeanPostProcessor` you should consider implementing the `Ordered` -interface too. For further details, consult the javadocs of the `BeanPostProcessor` and -`Ordered` interfaces. See also the note below on -<> - -[NOTE] -==== -++BeanPostProcessor++s operate on bean (or object) __instances__; that is to say, the -Spring IoC container instantiates a bean instance and __then__ ++BeanPostProcessor++s do -their work. - -++BeanPostProcessor++s are scoped __per-container__. This is only relevant if you are -using container hierarchies. If you define a `BeanPostProcessor` in one container, it -will __only__ post-process the beans in that container. In other words, beans that are -defined in one container are not post-processed by a `BeanPostProcessor` defined in -another container, even if both containers are part of the same hierarchy. - -To change the actual bean definition (i.e., the __blueprint__ that defines the bean), -you instead need to use a `BeanFactoryPostProcessor` as described in -<>. -==== - -The `org.springframework.beans.factory.config.BeanPostProcessor` interface consists of -exactly two callback methods. When such a class is registered as a post-processor with -the container, for each bean instance that is created by the container, the -post-processor gets a callback from the container both __before__ container -initialization methods (such as InitializingBean's __afterPropertiesSet()__ and any -declared init method) are called as well as __after__ any bean initialization callbacks. -The post-processor can take any action with the bean instance, including ignoring the -callback completely. A bean post-processor typically checks for callback interfaces or -may wrap a bean with a proxy. Some Spring AOP infrastructure classes are implemented as -bean post-processors in order to provide proxy-wrapping logic. - -An `ApplicationContext` __automatically detects__ any beans that are defined in the -configuration metadata which implement the `BeanPostProcessor` interface. The -`ApplicationContext` registers these beans as post-processors so that they can be called -later upon bean creation. Bean post-processors can be deployed in the container just -like any other beans. - -Note that when declaring a ++BeanPostProcessor++ using an `@Bean` factory method on a -configuration class, the return type of the factory method should be the implementation -class itself or at least the `org.springframework.beans.factory.config.BeanPostProcessor` -interface, clearly indicating the post-processor nature of that bean. Otherwise, the -`ApplicationContext` won't be able to autodetect it by type before fully creating it. -Since a ++BeanPostProcessor++ needs to be instantiated early in order to apply to the -initialization of other beans in the context, this early type detection is critical. - -[NOTE] -==== - -*Programmatically registering BeanPostProcessors* - -While the recommended approach for `BeanPostProcessor` registration is through -`ApplicationContext` auto-detection (as described above), it is also possible to -register them __programmatically__ against a `ConfigurableBeanFactory` using the -`addBeanPostProcessor` method. This can be useful when needing to evaluate conditional -logic before registration, or even for copying bean post processors across contexts in a -hierarchy. Note however that `BeanPostProcessors` added programmatically __do not -respect the `Ordered` interface__. Here it is the __order of registration__ that -dictates the order of execution. Note also that `BeanPostProcessors` registered -programmatically are always processed before those registered through auto-detection, -regardless of any explicit ordering. -==== - -[NOTE] -==== - -*BeanPostProcessors and AOP auto-proxying* - -Classes that implement the `BeanPostProcessor` interface are __special__ and are treated -differently by the container. All `BeanPostProcessors` __and beans that they reference -directly__ are instantiated on startup, as part of the special startup phase of the -`ApplicationContext`. Next, all `BeanPostProcessors` are registered in a sorted fashion -and applied to all further beans in the container. Because AOP auto-proxying is -implemented as a `BeanPostProcessor` itself, neither `BeanPostProcessors` nor the beans -they reference directly are eligible for auto-proxying, and thus do not have aspects -woven into them. - -For any such bean, you should see an informational log message: "__Bean foo is not -eligible for getting processed by all BeanPostProcessor interfaces (for example: not -eligible for auto-proxying)__". - -Note that if you have beans wired into your `BeanPostProcessor` using autowiring or -`@Resource` (which may fall back to autowiring), Spring might access unexpected beans -when searching for type-matching dependency candidates, and therefore make them -ineligible for auto-proxying or other kinds of bean post-processing. For example, if you -have a dependency annotated with `@Resource` where the field/setter name does not -directly correspond to the declared name of a bean and no name attribute is used, then -Spring will access other beans for matching them by type. -==== - -The following examples show how to write, register, and use `BeanPostProcessors` in an -`ApplicationContext`. - - -[[beans-factory-extension-bpp-examples-hw]] -===== Example: Hello World, BeanPostProcessor-style - -This first example illustrates basic usage. The example shows a custom -`BeanPostProcessor` implementation that invokes the `toString()` method of each bean as -it is created by the container and prints the resulting string to the system console. - -Find below the custom `BeanPostProcessor` implementation class definition: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - package scripting; - - import org.springframework.beans.factory.config.BeanPostProcessor; - import org.springframework.beans.BeansException; - - public class InstantiationTracingBeanPostProcessor implements BeanPostProcessor { - - // simply return the instantiated bean as-is - public Object postProcessBeforeInitialization(Object bean, - String beanName) throws BeansException { - return bean; // we could potentially return any object reference here... - } - - public Object postProcessAfterInitialization(Object bean, - String beanName) throws BeansException { - System.out.println("Bean '" + beanName + "' created : " + bean.toString()); - return bean; - } - - } ----- - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - - - - ----- - -Notice how the `InstantiationTracingBeanPostProcessor` is simply defined. It does not -even have a name, and because it is a bean it can be dependency-injected just like any -other bean. (The preceding configuration also defines a bean that is backed by a Groovy -script. The Spring dynamic language support is detailed in the chapter entitled -<>.) - -The following simple Java application executes the preceding code and configuration: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - import org.springframework.context.ApplicationContext; - import org.springframework.context.support.ClassPathXmlApplicationContext; - import org.springframework.scripting.Messenger; - - public final class Boot { - - public static void main(final String[] args) throws Exception { - ApplicationContext ctx = new ClassPathXmlApplicationContext("scripting/beans.xml"); - Messenger messenger = (Messenger) ctx.getBean("messenger"); - System.out.println(messenger); - } - - } ----- - -The output of the preceding application resembles the following: - -[literal] -[subs="verbatim,quotes"] ----- -Bean 'messenger' created : org.springframework.scripting.groovy.GroovyMessenger@272961 -org.springframework.scripting.groovy.GroovyMessenger@272961 ----- - - -[[beans-factory-extension-bpp-examples-rabpp]] -===== Example: The RequiredAnnotationBeanPostProcessor - -Using callback interfaces or annotations in conjunction with a custom -`BeanPostProcessor` implementation is a common means of extending the Spring IoC -container. An example is Spring's `RequiredAnnotationBeanPostProcessor` - a -`BeanPostProcessor` implementation that ships with the Spring distribution which ensures -that JavaBean properties on beans that are marked with an (arbitrary) annotation are -actually (configured to be) dependency-injected with a value. - - - -[[beans-factory-extension-factory-postprocessors]] -==== Customizing configuration metadata with a BeanFactoryPostProcessor - -The next extension point that we will look at is the -`org.springframework.beans.factory.config.BeanFactoryPostProcessor`. The semantics of -this interface are similar to those of the `BeanPostProcessor`, with one major -difference: `BeanFactoryPostProcessor` operates on the __bean configuration metadata__; -that is, the Spring IoC container allows a `BeanFactoryPostProcessor` to read the -configuration metadata and potentially change it __before__ the container instantiates -any beans other than `BeanFactoryPostProcessors`. - -You can configure multiple `BeanFactoryPostProcessors`, and you can control the order in -which these `BeanFactoryPostProcessors` execute by setting the `order` property. -However, you can only set this property if the `BeanFactoryPostProcessor` implements the -`Ordered` interface. If you write your own `BeanFactoryPostProcessor`, you should -consider implementing the `Ordered` interface too. Consult the javadocs of the -`BeanFactoryPostProcessor` and `Ordered` interfaces for more details. - -[NOTE] -==== -If you want to change the actual bean __instances__ (i.e., the objects that are created -from the configuration metadata), then you instead need to use a `BeanPostProcessor` -(described above in <>). While it is technically possible -to work with bean instances within a `BeanFactoryPostProcessor` (e.g., using -`BeanFactory.getBean()`), doing so causes premature bean instantiation, violating the -standard container lifecycle. This may cause negative side effects such as bypassing -bean post processing. - -Also, `BeanFactoryPostProcessors` are scoped __per-container__. This is only relevant if -you are using container hierarchies. If you define a `BeanFactoryPostProcessor` in one -container, it will __only__ be applied to the bean definitions in that container. Bean -definitions in one container will not be post-processed by `BeanFactoryPostProcessors` -in another container, even if both containers are part of the same hierarchy. -==== - -A bean factory post-processor is executed automatically when it is declared inside an -`ApplicationContext`, in order to apply changes to the configuration metadata that -define the container. Spring includes a number of predefined bean factory -post-processors, such as `PropertyOverrideConfigurer` and -`PropertyPlaceholderConfigurer`. A custom `BeanFactoryPostProcessor` can also be used, -for example, to register custom property editors. - -[[null]] - -An `ApplicationContext` automatically detects any beans that are deployed into it that -implement the `BeanFactoryPostProcessor` interface. It uses these beans as bean factory -post-processors, at the appropriate time. You can deploy these post-processor beans as -you would any other bean. - -[NOTE] -==== -As with ++BeanPostProcessor++s , you typically do not want to configure -++BeanFactoryPostProcessor++s for lazy initialization. If no other bean references a -`Bean(Factory)PostProcessor`, that post-processor will not get instantiated at all. -Thus, marking it for lazy initialization will be ignored, and the -`Bean(Factory)PostProcessor` will be instantiated eagerly even if you set the -`default-lazy-init` attribute to `true` on the declaration of your `` element. -==== - - -[[beans-factory-placeholderconfigurer]] -===== Example: the Class name substitution PropertyPlaceholderConfigurer - -You use the `PropertyPlaceholderConfigurer` to externalize property values from a bean -definition in a separate file using the standard Java `Properties` format. Doing so -enables the person deploying an application to customize environment-specific properties -such as database URLs and passwords, without the complexity or risk of modifying the -main XML definition file or files for the container. - -Consider the following XML-based configuration metadata fragment, where a `DataSource` -with placeholder values is defined. The example shows properties configured from an -external `Properties` file. At runtime, a `PropertyPlaceholderConfigurer` is applied to -the metadata that will replace some properties of the DataSource. The values to replace -are specified as __placeholders__ of the form `${property-name}` which follows the Ant / -log4j / JSP EL style. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - - - ----- - -The actual values come from another file in the standard Java `Properties` format: - -[literal] -[subs="verbatim,quotes"] ----- -jdbc.driverClassName=org.hsqldb.jdbcDriver -jdbc.url=jdbc:hsqldb:hsql://production:9002 -jdbc.username=sa -jdbc.password=root ----- - -Therefore, the string `${jdbc.username}` is replaced at runtime with the value 'sa', and -the same applies for other placeholder values that match keys in the properties file. -The `PropertyPlaceholderConfigurer` checks for placeholders in most properties and -attributes of a bean definition. Furthermore, the placeholder prefix and suffix can be -customized. - -With the `context` namespace introduced in Spring 2.5, it is possible to configure -property placeholders with a dedicated configuration element. One or more locations can -be provided as a comma-separated list in the `location` attribute. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - ----- - -The `PropertyPlaceholderConfigurer` not only looks for properties in the `Properties` -file you specify. By default it also checks against the Java `System` properties if it -cannot find a property in the specified properties files. You can customize this -behavior by setting the `systemPropertiesMode` property of the configurer with one of -the following three supported integer values: - -* __never__ (0): Never check system properties -* __fallback__ (1): Check system properties if not resolvable in the specified - properties files. This is the default. -* __override__ (2): Check system properties first, before trying the specified - properties files. This allows system properties to override any other property source. - -Consult the `PropertyPlaceholderConfigurer` javadocs for more information. - -[TIP] -==== - -You can use the `PropertyPlaceholderConfigurer` to substitute class names, which is -sometimes useful when you have to pick a particular implementation class at runtime. For -example: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - classpath:com/foo/strategy.properties - - - custom.strategy.class=com.foo.DefaultStrategy - - - - ----- - -If the class cannot be resolved at runtime to a valid class, resolution of the bean -fails when it is about to be created, which is during the `preInstantiateSingletons()` -phase of an `ApplicationContext` for a non-lazy-init bean. -==== - - -[[beans-factory-overrideconfigurer]] -===== Example: the PropertyOverrideConfigurer - -The `PropertyOverrideConfigurer`, another bean factory post-processor, resembles the -`PropertyPlaceholderConfigurer`, but unlike the latter, the original definitions can -have default values or no values at all for bean properties. If an overriding -`Properties` file does not have an entry for a certain bean property, the default -context definition is used. - -Note that the bean definition is __not__ aware of being overridden, so it is not -immediately obvious from the XML definition file that the override configurer is being -used. In case of multiple `PropertyOverrideConfigurer` instances that define different -values for the same bean property, the last one wins, due to the overriding mechanism. - -Properties file configuration lines take this format: - -[literal] -[subs="verbatim,quotes"] ----- -beanName.property=value ----- - -For example: - -[literal] -[subs="verbatim,quotes"] ----- -dataSource.driverClassName=com.mysql.jdbc.Driver -dataSource.url=jdbc:mysql:mydb ----- - -This example file can be used with a container definition that contains a bean called -__dataSource__, which has __driver__ and __url__ properties. - -Compound property names are also supported, as long as every component of the path -except the final property being overridden is already non-null (presumably initialized -by the constructors). In this example... - -[literal] -[subs="verbatim,quotes"] ----- -foo.fred.bob.sammy=123 ----- - -... the `sammy` property of the `bob` property of the `fred` property of the `foo` bean -is set to the scalar value `123`. - -[NOTE] -==== -Specified override values are always __literal__ values; they are not translated into -bean references. This convention also applies when the original value in the XML bean -definition specifies a bean reference. -==== - -With the `context` namespace introduced in Spring 2.5, it is possible to configure -property overriding with a dedicated configuration element: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - ----- - - - -[[beans-factory-extension-factorybean]] -==== Customizing instantiation logic with a FactoryBean - -Implement the `org.springframework.beans.factory.FactoryBean` interface for objects that -__are themselves factories__. - -The `FactoryBean` interface is a point of pluggability into the Spring IoC container's -instantiation logic. If you have complex initialization code that is better expressed in -Java as opposed to a (potentially) verbose amount of XML, you can create your own -`FactoryBean`, write the complex initialization inside that class, and then plug your -custom `FactoryBean` into the container. - -The `FactoryBean` interface provides three methods: - -* `Object getObject()`: returns an instance of the object this factory creates. The - instance can possibly be shared, depending on whether this factory returns singletons - or prototypes. -* `boolean isSingleton()`: returns `true` if this `FactoryBean` returns singletons, - `false` otherwise. -* `Class getObjectType()`: returns the object type returned by the `getObject()` method - or `null` if the type is not known in advance. - -The `FactoryBean` concept and interface is used in a number of places within the Spring -Framework; more than 50 implementations of the `FactoryBean` interface ship with Spring -itself. - -When you need to ask a container for an actual `FactoryBean` instance itself instead of -the bean it produces, preface the bean's id with the ampersand symbol ( `&`) when -calling the `getBean()` method of the `ApplicationContext`. So for a given `FactoryBean` -with an id of `myBean`, invoking `getBean("myBean")` on the container returns the -product of the `FactoryBean`; whereas, invoking `getBean("&myBean")` returns the -`FactoryBean` instance itself. - - - - -[[beans-annotation-config]] -=== Annotation-based container configuration - -.Are annotations better than XML for configuring Spring? -**** -The introduction of annotation-based configurations raised the question of whether this -approach is 'better' than XML. The short answer is __it depends__. The long answer is -that each approach has its pros and cons, and usually it is up to the developer to -decide which strategy suits them better. Due to the way they are defined, annotations -provide a lot of context in their declaration, leading to shorter and more concise -configuration. However, XML excels at wiring up components without touching their source -code or recompiling them. Some developers prefer having the wiring close to the source -while others argue that annotated classes are no longer POJOs and, furthermore, that the -configuration becomes decentralized and harder to control. - -No matter the choice, Spring can accommodate both styles and even mix them together. -It's worth pointing out that through its <> option, Spring allows -annotations to be used in a non-invasive way, without touching the target components -source code and that in terms of tooling, all configuration styles are supported by the -https://spring.io/tools/sts[Spring Tool Suite]. -**** - -An alternative to XML setups is provided by annotation-based configuration which rely on -the bytecode metadata for wiring up components instead of angle-bracket declarations. -Instead of using XML to describe a bean wiring, the developer moves the configuration -into the component class itself by using annotations on the relevant class, method, or -field declaration. As mentioned in <>, using -a `BeanPostProcessor` in conjunction with annotations is a common means of extending the -Spring IoC container. For example, Spring 2.0 introduced the possibility of enforcing -required properties with the <> annotation. Spring -2.5 made it possible to follow that same general approach to drive Spring's dependency -injection. Essentially, the `@Autowired` annotation provides the same capabilities as -described in <> but with more fine-grained control and wider -applicability. Spring 2.5 also added support for JSR-250 annotations such as -`@PostConstruct`, and `@PreDestroy`. Spring 3.0 added support for JSR-330 (Dependency -Injection for Java) annotations contained in the javax.inject package such as `@Inject` -and `@Named`. Details about those annotations can be found in the -<>. -[NOTE] -==== -Annotation injection is performed __before__ XML injection, thus the latter -configuration will override the former for properties wired through both approaches. -==== -As always, you can register them as individual bean definitions, but they can also be -implicitly registered by including the following tag in an XML-based Spring -configuration (notice the inclusion of the `context` namespace): - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - ----- - -(The implicitly registered post-processors include -{javadoc-baseurl}/org/springframework/beans/factory/annotation/AutowiredAnnotationBeanPostProcessor.html[`AutowiredAnnotationBeanPostProcessor`], - {javadoc-baseurl}/org/springframework/context/annotation/CommonAnnotationBeanPostProcessor.html[`CommonAnnotationBeanPostProcessor`], - {javadoc-baseurl}/org/springframework/orm/jpa/support/PersistenceAnnotationBeanPostProcessor.html[`PersistenceAnnotationBeanPostProcessor`], -as well as the aforementioned -{javadoc-baseurl}/org/springframework/beans/factory/annotation/RequiredAnnotationBeanPostProcessor.html[`RequiredAnnotationBeanPostProcessor`].) - -[NOTE] -==== -`` only looks for annotations on beans in the same -application context in which it is defined. This means that, if you put -`` in a `WebApplicationContext` for a `DispatcherServlet`, -it only checks for `@Autowired` beans in your controllers, and not your services. See -<> for more information. -==== - - - -[[beans-required-annotation]] -==== @Required - -The `@Required` annotation applies to bean property setter methods, as in the following -example: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class SimpleMovieLister { - - private MovieFinder movieFinder; - - @Required - public void setMovieFinder(MovieFinder movieFinder) { - this.movieFinder = movieFinder; - } - - // ... - - } ----- - -This annotation simply indicates that the affected bean property must be populated at -configuration time, through an explicit property value in a bean definition or through -autowiring. The container throws an exception if the affected bean property has not been -populated; this allows for eager and explicit failure, avoiding ++NullPointerException++s -or the like later on. It is still recommended that you put assertions into the bean -class itself, for example, into an init method. Doing so enforces those required -references and values even when you use the class outside of a container. - - - -[[beans-autowired-annotation]] -==== @Autowired - -As expected, you can apply the `@Autowired` annotation to "traditional" setter methods: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class SimpleMovieLister { - - private MovieFinder movieFinder; - - @Autowired - public void setMovieFinder(MovieFinder movieFinder) { - this.movieFinder = movieFinder; - } - - // ... - - } ----- - -[NOTE] -==== -JSR 330's @Inject annotation can be used in place of Spring's `@Autowired` annotation in -the examples below. See <> for more details -==== - -You can also apply the annotation to methods with arbitrary names and/or multiple -arguments: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class MovieRecommender { - - private MovieCatalog movieCatalog; - - private CustomerPreferenceDao customerPreferenceDao; - - @Autowired - public void prepare(MovieCatalog movieCatalog, - CustomerPreferenceDao customerPreferenceDao) { - this.movieCatalog = movieCatalog; - this.customerPreferenceDao = customerPreferenceDao; - } - - // ... - - } ----- - -You can apply `@Autowired` to constructors and fields: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class MovieRecommender { - - @Autowired - private MovieCatalog movieCatalog; - - private CustomerPreferenceDao customerPreferenceDao; - - @Autowired - public MovieRecommender(CustomerPreferenceDao customerPreferenceDao) { - this.customerPreferenceDao = customerPreferenceDao; - } - - // ... - - } ----- - -It is also possible to provide __all__ beans of a particular type from the -`ApplicationContext` by adding the annotation to a field or method that expects an array -of that type: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class MovieRecommender { - - @Autowired - private MovieCatalog[] movieCatalogs; - - // ... - - } ----- - -The same applies for typed collections: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class MovieRecommender { - - private Set movieCatalogs; - - @Autowired - public void setMovieCatalogs(Set movieCatalogs) { - this.movieCatalogs = movieCatalogs; - } - - // ... - - } ----- - -[TIP] -==== -Your beans can implement the `org.springframework.core.Ordered` interface or either use -the `@Order` or standard `@Priority` annotation if you want items in the array or list -to be sorted into a specific order. -==== - - -Even typed Maps can be autowired as long as the expected key type is `String`. The Map -values will contain all beans of the expected type, and the keys will contain the -corresponding bean names: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class MovieRecommender { - - private Map movieCatalogs; - - @Autowired - public void setMovieCatalogs(Map movieCatalogs) { - this.movieCatalogs = movieCatalogs; - } - - // ... - - } ----- - -By default, the autowiring fails whenever __zero__ candidate beans are available; the -default behavior is to treat annotated methods, constructors, and fields as -indicating __required__ dependencies. This behavior can be changed as demonstrated below. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class SimpleMovieLister { - - private MovieFinder movieFinder; - - @Autowired(required=false) - public void setMovieFinder(MovieFinder movieFinder) { - this.movieFinder = movieFinder; - } - - // ... - - } ----- - -[NOTE] -==== -Only __one annotated constructor per-class__ can be marked as __required__, but multiple -non-required constructors can be annotated. In that case, each is considered among the -candidates and Spring uses the __greediest__ constructor whose dependencies can be -satisfied, that is the constructor that has the largest number of arguments. - -`@Autowired`'s __required__ attribute is recommended over the `@Required` annotation. -The __required__ attribute indicates that the property is not required for autowiring -purposes, the property is ignored if it cannot be autowired. `@Required`, on the other -hand, is stronger in that it enforces the property that was set by any means supported -by the container. If no value is injected, a corresponding exception is raised. -==== - -You can also use `@Autowired` for interfaces that are well-known resolvable -dependencies: `BeanFactory`, `ApplicationContext`, `Environment`, `ResourceLoader`, -`ApplicationEventPublisher`, and `MessageSource`. These interfaces and their extended -interfaces, such as `ConfigurableApplicationContext` or `ResourcePatternResolver`, are -automatically resolved, with no special setup necessary. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class MovieRecommender { - - @Autowired - private ApplicationContext context; - - public MovieRecommender() { - } - - // ... - - } ----- - -[NOTE] -==== -`@Autowired`, `@Inject`, `@Resource`, and `@Value` annotations are handled by a Spring -`BeanPostProcessor` implementations which in turn means that you __cannot__ apply these -annotations within your own `BeanPostProcessor` or `BeanFactoryPostProcessor` types (if -any). These types must be 'wired up' explicitly via XML or using a Spring `@Bean` method. -==== - - - -[[beans-autowired-annotation-qualifiers]] -==== Fine-tuning annotation-based autowiring with qualifiers -Because autowiring by type may lead to multiple candidates, it is often necessary to -have more control over the selection process. One way to accomplish this is with -Spring's `@Qualifier` annotation. You can associate qualifier values with specific -arguments, narrowing the set of type matches so that a specific bean is chosen for each -argument. In the simplest case, this can be a plain descriptive value: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class MovieRecommender { - - @Autowired - **@Qualifier("main")** - private MovieCatalog movieCatalog; - - // ... - - } ----- - -The `@Qualifier` annotation can also be specified on individual constructor arguments or -method parameters: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class MovieRecommender { - - private MovieCatalog movieCatalog; - - private CustomerPreferenceDao customerPreferenceDao; - - @Autowired - public void prepare(**@Qualifier("main")**MovieCatalog movieCatalog, - CustomerPreferenceDao customerPreferenceDao) { - this.movieCatalog = movieCatalog; - this.customerPreferenceDao = customerPreferenceDao; - } - - // ... - - } ----- - -The corresponding bean definitions appear as follows. The bean with qualifier value -"main" is wired with the constructor argument that is qualified with the same value. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - **** - - - - - - **** - - - - - - - ----- - -For a fallback match, the bean name is considered a default qualifier value. Thus you -can define the bean with an id "main" instead of the nested qualifier element, leading -to the same matching result. However, although you can use this convention to refer to -specific beans by name, `@Autowired` is fundamentally about type-driven injection with -optional semantic qualifiers. This means that qualifier values, even with the bean name -fallback, always have narrowing semantics within the set of type matches; they do not -semantically express a reference to a unique bean id. Good qualifier values are "main" -or "EMEA" or "persistent", expressing characteristics of a specific component that are -independent from the bean id, which may be auto-generated in case of an anonymous bean -definition like the one in the preceding example. - -Qualifiers also apply to typed collections, as discussed above, for example, to -`Set`. In this case, all matching beans according to the declared -qualifiers are injected as a collection. This implies that qualifiers do not have to be -unique; they rather simply constitute filtering criteria. For example, you can define -multiple `MovieCatalog` beans with the same qualifier value "action"; all of which would -be injected into a `Set` annotated with `@Qualifier("action")`. - -[TIP] -==== - -If you intend to express annotation-driven injection by name, do not primarily use -`@Autowired`, even if is technically capable of referring to a bean name through -`@Qualifier` values. Instead, use the JSR-250 `@Resource` annotation, which is -semantically defined to identify a specific target component by its unique name, with -the declared type being irrelevant for the matching process. - -As a specific consequence of this semantic difference, beans that are themselves defined -as a collection or map type cannot be injected through `@Autowired`, because type -matching is not properly applicable to them. Use `@Resource` for such beans, referring -to the specific collection or map bean by unique name. - -`@Autowired` applies to fields, constructors, and multi-argument methods, allowing for -narrowing through qualifier annotations at the parameter level. By contrast, `@Resource` -is supported only for fields and bean property setter methods with a single argument. As -a consequence, stick with qualifiers if your injection target is a constructor or a -multi-argument method. -==== - -You can create your own custom qualifier annotations. Simply define an annotation and -provide the `@Qualifier` annotation within your definition: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Target({ElementType.FIELD, ElementType.PARAMETER}) - @Retention(RetentionPolicy.RUNTIME) - **@Qualifier** - public @interface Genre { - - String value(); - } ----- - -Then you can provide the custom qualifier on autowired fields and parameters: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class MovieRecommender { - - @Autowired - **@Genre("Action")** - private MovieCatalog actionCatalog; - private MovieCatalog comedyCatalog; - - @Autowired - public void setComedyCatalog(**@Genre("Comedy")** MovieCatalog comedyCatalog) { - this.comedyCatalog = comedyCatalog; - } - - // ... - - } ----- - -Next, provide the information for the candidate bean definitions. You can add -`` tags as sub-elements of the `` tag and then specify the `type` and -`value` to match your custom qualifier annotations. The type is matched against the -fully-qualified class name of the annotation. Or, as a convenience if no risk of -conflicting names exists, you can use the short class name. Both approaches are -demonstrated in the following example. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - **** - - - - - **_** - - - - - - ----- - -In <>, you will see an annotation-based alternative to -providing the qualifier metadata in XML. Specifically, see <>. - -In some cases, it may be sufficient to use an annotation without a value. This may be -useful when the annotation serves a more generic purpose and can be applied across -several different types of dependencies. For example, you may provide an __offline__ -catalog that would be searched when no Internet connection is available. First define -the simple annotation: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Target({ElementType.FIELD, ElementType.PARAMETER}) - @Retention(RetentionPolicy.RUNTIME) - @Qualifier - public @interface Offline { - - } ----- - -Then add the annotation to the field or property to be autowired: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class MovieRecommender { - - @Autowired - **@Offline** - private MovieCatalog offlineCatalog; - - // ... - - } ----- - -Now the bean definition only needs a qualifier `type`: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - **** - - ----- - -You can also define custom qualifier annotations that accept named attributes in -addition to or instead of the simple `value` attribute. If multiple attribute values are -then specified on a field or parameter to be autowired, a bean definition must match -__all__ such attribute values to be considered an autowire candidate. As an example, -consider the following annotation definition: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Target({ElementType.FIELD, ElementType.PARAMETER}) - @Retention(RetentionPolicy.RUNTIME) - @Qualifier - public @interface MovieQualifier { - - String genre(); - - Format format(); - - } ----- - -In this case `Format` is an enum: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public enum Format { - VHS, DVD, BLURAY - } ----- - -The fields to be autowired are annotated with the custom qualifier and include values -for both attributes: `genre` and `format`. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class MovieRecommender { - - @Autowired - @MovieQualifier(format=Format.VHS, genre="Action") - private MovieCatalog actionVhsCatalog; - - @Autowired - @MovieQualifier(format=Format.VHS, genre="Comedy") - private MovieCatalog comedyVhsCatalog; - - @Autowired - @MovieQualifier(format=Format.DVD, genre="Action") - private MovieCatalog actionDvdCatalog; - - @Autowired - @MovieQualifier(format=Format.BLURAY, genre="Comedy") - private MovieCatalog comedyBluRayCatalog; - - // ... - - } ----- - -Finally, the bean definitions should contain matching qualifier values. This example -also demonstrates that bean __meta__ attributes may be used instead of the -`` sub-elements. If available, the `` and its attributes take -precedence, but the autowiring mechanism falls back on the values provided within the -`` tags if no such qualifier is present, as in the last two bean definitions in -the following example. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ----- - - - -[[beans-generics-as-qualifiers]] -==== Using generics as autowiring qualifiers -In addition to the `@Qualifier` annotation, it is also possible to use Java generic types -as an implicit form of qualification. For example, suppose you have the following -configuration: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Configuration - public class MyConfiguration { - - @Bean - public StringStore stringStore() { - return new StringStore(); - } - - @Bean - public IntegerStore integerStore() { - return new IntegerStore(); - } - - } ----- - -Assuming that beans above implement a generic interface, i.e. `Store` and -`Store`, you can `@Autowire` the `Store` interface and the __generic__ will -be used as a qualifier: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Autowired - private Store s1; // qualifier, injects the stringStore bean - - @Autowired - private Store s2; // qualifier, injects the integerStore bean ----- - -Generic qualifiers also apply when autowiring Lists, Maps and Arrays: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - // Inject all Store beans as long as they have an generic - // Store beans will not appear in this list - @Autowired - private List> s; ----- - - - - -[[beans-custom-autowire-configurer]] -==== CustomAutowireConfigurer - -The -{javadoc-baseurl}/org/springframework/beans/factory/annotation/CustomAutowireConfigurer.html[`CustomAutowireConfigurer`] -is a `BeanFactoryPostProcessor` that enables you to register your own custom qualifier -annotation types even if they are not annotated with Spring's `@Qualifier` annotation. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - example.CustomQualifier - - - ----- - -The `AutowireCandidateResolver` determines autowire candidates by: - -* the `autowire-candidate` value of each bean definition -* any `default-autowire-candidates` pattern(s) available on the `` element -* the presence of `@Qualifier` annotations and any custom annotations registered -with the `CustomAutowireConfigurer` - -When multiple beans qualify as autowire candidates, the determination of a "primary" is -the following: if exactly one bean definition among the candidates has a `primary` -attribute set to `true`, it will be selected. - - - -[[beans-resource-annotation]] -==== @Resource - -Spring also supports injection using the JSR-250 `@Resource` annotation on fields or -bean property setter methods. This is a common pattern in Java EE 5 and 6, for example -in JSF 1.2 managed beans or JAX-WS 2.0 endpoints. Spring supports this pattern for -Spring-managed objects as well. - -`@Resource` takes a name attribute, and by default Spring interprets that value as the -bean name to be injected. In other words, it follows __by-name__ semantics, as -demonstrated in this example: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class SimpleMovieLister { - - private MovieFinder movieFinder; - - **@Resource(name="myMovieFinder")** - public void setMovieFinder(MovieFinder movieFinder) { - this.movieFinder = movieFinder; - } - - } ----- - -If no name is specified explicitly, the default name is derived from the field name or -setter method. In case of a field, it takes the field name; in case of a setter method, -it takes the bean property name. So the following example is going to have the bean with -name "movieFinder" injected into its setter method: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class SimpleMovieLister { - - private MovieFinder movieFinder; - - **@Resource** - public void setMovieFinder(MovieFinder movieFinder) { - this.movieFinder = movieFinder; - } - - } ----- - -[NOTE] -==== -The name provided with the annotation is resolved as a bean name by the -`ApplicationContext` of which the `CommonAnnotationBeanPostProcessor` is aware. The -names can be resolved through JNDI if you configure Spring's -{javadoc-baseurl}/org/springframework/jndi/support/SimpleJndiBeanFactory.html[`SimpleJndiBeanFactory`] -explicitly. However, it is recommended that you rely on the default behavior and simply -use Spring's JNDI lookup capabilities to preserve the level of indirection. -==== - -In the exclusive case of `@Resource` usage with no explicit name specified, and similar -to `@Autowired`, `@Resource` finds a primary type match instead of a specific named bean -and resolves well-known resolvable dependencies: the `BeanFactory`, -`ApplicationContext`, `ResourceLoader`, `ApplicationEventPublisher`, and `MessageSource` -interfaces. - -Thus in the following example, the `customerPreferenceDao` field first looks for a bean -named customerPreferenceDao, then falls back to a primary type match for the type -`CustomerPreferenceDao`. The "context" field is injected based on the known resolvable -dependency type `ApplicationContext`. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class MovieRecommender { - - @Resource - private CustomerPreferenceDao customerPreferenceDao; - - @Resource - private ApplicationContext context; - - public MovieRecommender() { - } - - // ... - - } ----- - - - -[[beans-postconstruct-and-predestroy-annotations]] -==== @PostConstruct and @PreDestroy - -The `CommonAnnotationBeanPostProcessor` not only recognizes the `@Resource` annotation -but also the JSR-250 __lifecycle__ annotations. Introduced in Spring 2.5, the support -for these annotations offers yet another alternative to those described in -<> and -<>. Provided that the -`CommonAnnotationBeanPostProcessor` is registered within the Spring -`ApplicationContext`, a method carrying one of these annotations is invoked at the same -point in the lifecycle as the corresponding Spring lifecycle interface method or -explicitly declared callback method. In the example below, the cache will be -pre-populated upon initialization and cleared upon destruction. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class CachingMovieLister { - - @PostConstruct - public void populateMovieCache() { - // populates the movie cache upon initialization... - } - - @PreDestroy - public void clearMovieCache() { - // clears the movie cache upon destruction... - } - - } ----- - -[NOTE] -==== -For details about the effects of combining various lifecycle mechanisms, see -<>. -==== - - - - -[[beans-classpath-scanning]] -=== Classpath scanning and managed components -Most examples in this chapter use XML to specify the configuration metadata that -produces each `BeanDefinition` within the Spring container. The previous section -(<>) demonstrates how to provide a lot of the configuration -metadata through source-level annotations. Even in those examples, however, the "base" -bean definitions are explicitly defined in the XML file, while the annotations only -drive the dependency injection. This section describes an option for implicitly -detecting the __candidate components__ by scanning the classpath. Candidate components -are classes that match against a filter criteria and have a corresponding bean -definition registered with the container. This removes the need to use XML to perform -bean registration, instead you can use annotations (for example @Component), AspectJ -type expressions, or your own custom filter criteria to select which classes will have -bean definitions registered with the container. - -[NOTE] -==== -Starting with Spring 3.0, many features provided by the Spring JavaConfig project are -part of the core Spring Framework. This allows you to define beans using Java rather -than using the traditional XML files. Take a look at the `@Configuration`, `@Bean`, -`@Import`, and `@DependsOn` annotations for examples of how to use these new features. -==== - - - -[[beans-stereotype-annotations]] -==== @Component and further stereotype annotations - -The `@Repository` annotation is a marker for any class that fulfills the role or -__stereotype__ (also known as Data Access Object or DAO) of a repository. Among the uses -of this marker is the automatic translation of exceptions as described in -<>. - -Spring provides further stereotype annotations: `@Component`, `@Service`, and -`@Controller`. `@Component` is a generic stereotype for any Spring-managed component. -`@Repository`, `@Service`, and `@Controller` are specializations of `@Component` for -more specific use cases, for example, in the persistence, service, and presentation -layers, respectively. Therefore, you can annotate your component classes with -`@Component`, but by annotating them with `@Repository`, `@Service`, or `@Controller` -instead, your classes are more properly suited for processing by tools or associating -with aspects. For example, these stereotype annotations make ideal targets for -pointcuts. It is also possible that `@Repository`, `@Service`, and `@Controller` may -carry additional semantics in future releases of the Spring Framework. Thus, if you are -choosing between using `@Component` or `@Service` for your service layer, `@Service` is -clearly the better choice. Similarly, as stated above, `@Repository` is already -supported as a marker for automatic exception translation in your persistence layer. - - - -[[beans-meta-annotations]] -==== Meta-annotations -Many of the annotations provided by Spring can be used as "meta-annotations" in -your own code. A meta-annotation is simply an annotation, that can be applied to another -annotation. For example, The `@Service` annotation mentioned above is meta-annotated with -with `@Component`: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Target({ElementType.TYPE}) - @Retention(RetentionPolicy.RUNTIME) - @Documented - **@Component** // Spring will see this and treat @Service in the same way as @Component - public @interface Service { - - // .... - - } ----- - -Meta-annotations can also be combined together to create __composed annotations__. For -example, the `@RestController` annotation from Spring MVC is __composed__ of -`@Controller` and `@ResponseBody`. - -With the exception of `value()`, meta-annotated types may redeclare attributes from the -source annotation to allow user customization. This can be particularly useful when you -want to only expose a subset of the source annotation attributes. For example, here is a -custom `@Scope` annotation that defines `session` scope, but still allows customization -of the `proxyMode`. - - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Target({ElementType.TYPE}) - @Retention(RetentionPolicy.RUNTIME) - @Documented - **@Scope("session")** - public @interface SessionScope { - - ScopedProxyMode proxyMode() default ScopedProxyMode.DEFAULT - - } ----- - - - - -[[beans-scanning-autodetection]] -==== Automatically detecting classes and registering bean definitions -Spring can automatically detect stereotyped classes and register corresponding -++BeanDefinition++s with the `ApplicationContext`. For example, the following two classes -are eligible for such autodetection: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Service - public class SimpleMovieLister { - - private MovieFinder movieFinder; - - @Autowired - public SimpleMovieLister(MovieFinder movieFinder) { - this.movieFinder = movieFinder; - } - - } ----- - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Repository - public class JpaMovieFinder implements MovieFinder { - // implementation elided for clarity - } ----- - -To autodetect these classes and register the corresponding beans, you need to add -`@ComponentScan` to your `@Configuration` class, where the `basePackages` attribute -is a common parent package for the two classes. (Alternatively, you can specify a -comma-separated list that includes the parent package of each class.) - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Configuration - @ComponentScan(basePackages = "org.example") - public class AppConfig { - ... - } ----- - -[NOTE] -==== -for concision, the above may have used the `value` attribute of the -annotation, i.e. `ComponentScan("org.example")` -==== - -The following is an alternative using XML - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - ----- - -[TIP] -==== - -The use of `` implicitly enables the functionality of -``. There is usually no need to include the -`` element when using ``. -==== - -[NOTE] -==== -The scanning of classpath packages requires the presence of corresponding directory -entries in the classpath. When you build JARs with Ant, make sure that you do __not__ -activate the files-only switch of the JAR task. Also, classpath directories may not -get exposed based on security policies in some environments, e.g. standalone apps on -JDK 1.7.0_45 and higher (which requires 'Trusted-Library' setup in your manifests; see -http://stackoverflow.com/questions/19394570/java-jre-7u45-breaks-classloader-getresources). -==== - -Furthermore, the `AutowiredAnnotationBeanPostProcessor` and -`CommonAnnotationBeanPostProcessor` are both included implicitly when you use the -component-scan element. That means that the two components are autodetected __and__ -wired together - all without any bean configuration metadata provided in XML. - -[NOTE] -==== -You can disable the registration of `AutowiredAnnotationBeanPostProcessor` and -`CommonAnnotationBeanPostProcessor` by including the __annotation-config__ attribute -with a value of false. -==== - - - -[[beans-scanning-filters]] -==== Using filters to customize scanning -By default, classes annotated with `@Component`, `@Repository`, `@Service`, -`@Controller`, or a custom annotation that itself is annotated with `@Component` are the -only detected candidate components. However, you can modify and extend this behavior -simply by applying custom filters. Add them as __includeFilters__ or __excludeFilters__ -parameters of the `@ComponentScan` annotation (or as __include-filter__ or __exclude-filter__ -sub-elements of the `component-scan` element). Each filter element requires the `type` -and `expression` attributes. The following table describes the filtering options. - -[[beans-scanning-filters-tbl]] -.Filter Types -|=== -| Filter Type| Example Expression| Description - -| annotation (default) -| `org.example.SomeAnnotation` -| An annotation to be present at the type level in target components. - -| assignable -| `org.example.SomeClass` -| A class (or interface) that the target components are assignable to (extend/implement). - -| aspectj -| `org.example..*Service+` -| An AspectJ type expression to be matched by the target components. - -| regex -| `org\.example\.Default.*` -| A regex expression to be matched by the target components class names. - -| custom -| `org.example.MyTypeFilter` -| A custom implementation of the `org.springframework.core.type .TypeFilter` interface. -|=== - -The following example shows the configuration ignoring all `@Repository` annotations -and using "stub" repositories instead. - - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Configuration - @ComponentScan(basePackages = "org.example", - includeFilters = @Filter(type = FilterType.REGEX, pattern = ".*Stub.*Repository"), - excludeFilters = @Filter(Repository.class)) - public class AppConfig { - ... - } ----- - -and the equivalent using XML - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - ----- - -[NOTE] -==== -You can also disable the default filters by setting `useDefaultFilters=false` on the annotation or -providing `use-default-filters="false"` as an attribute of the element. This -will in effect disable automatic detection of classes annotated with `@Component`, `@Repository`, -`@Service`, or `@Controller`. -==== - - - -[[beans-factorybeans-annotations]] -==== Defining bean metadata within components -Spring components can also contribute bean definition metadata to the container. You do -this with the same `@Bean` annotation used to define bean metadata within -`@Configuration` annotated classes. Here is a simple example: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Component - public class FactoryMethodComponent { - - @Bean - @Qualifier("public") - public TestBean publicInstance() { - return new TestBean("publicInstance"); - } - - public void doWork() { - // Component method implementation omitted - } - - } ----- - -This class is a Spring component that has application-specific code contained in its -`doWork()` method. However, it also contributes a bean definition that has a factory -method referring to the method `publicInstance()`. The `@Bean` annotation identifies the -factory method and other bean definition properties, such as a qualifier value through -the `@Qualifier` annotation. Other method level annotations that can be specified are -`@Scope`, `@Lazy`, and custom qualifier annotations. - -[TIP] -==== -In addition to its role for component initialization, the `@Lazy` annotation may also be -placed on injection points marked with `@Autowired` or `@Inject`. In this context, it -leads to the injection of a lazy-resolution proxy. -==== - -Autowired fields and methods are supported as previously discussed, with additional -support for autowiring of `@Bean` methods: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Component - public class FactoryMethodComponent { - - private static int i; - - @Bean - @Qualifier("public") - public TestBean publicInstance() { - return new TestBean("publicInstance"); - } - - // use of a custom qualifier and autowiring of method parameters - - @Bean - protected TestBean protectedInstance( - @Qualifier("public") TestBean spouse, - @Value("#{privateInstance.age}") String country) { - TestBean tb = new TestBean("protectedInstance", 1); - tb.setSpouse(tb); - tb.setCountry(country); - return tb; - } - - @Bean - @Scope(BeanDefinition.SCOPE_SINGLETON) - private TestBean privateInstance() { - return new TestBean("privateInstance", i++); - } - - @Bean - @Scope(value = WebApplicationContext.SCOPE_SESSION, proxyMode = ScopedProxyMode.TARGET_CLASS) - public TestBean requestScopedInstance() { - return new TestBean("requestScopedInstance", 3); - } - - } ----- - -The example autowires the `String` method parameter `country` to the value of the `Age` -property on another bean named `privateInstance`. A Spring Expression Language element -defines the value of the property through the notation `#{ }`. For `@Value` -annotations, an expression resolver is preconfigured to look for bean names when -resolving expression text. - -The `@Bean` methods in a Spring component are processed differently than their -counterparts inside a Spring `@Configuration` class. The difference is that `@Component` -classes are not enhanced with CGLIB to intercept the invocation of methods and fields. -CGLIB proxying is the means by which invoking methods or fields within `@Bean` methods -in `@Configuration` classes creates bean metadata references to collaborating objects; -such methods are __not__ invoked with normal Java semantics. In contrast, invoking a -method or field in an `@Bean` method within a `@Component` class __has__ standard Java -semantics. - - - -[[beans-scanning-name-generator]] -==== Naming autodetected components -When a component is autodetected as part of the scanning process, its bean name is -generated by the `BeanNameGenerator` strategy known to that scanner. By default, any -Spring stereotype annotation ( `@Component`, `@Repository`, `@Service`, and -`@Controller`) that contains a `name` value will thereby provide that name to the -corresponding bean definition. - -If such an annotation contains no `name` value or for any other detected component (such -as those discovered by custom filters), the default bean name generator returns the -uncapitalized non-qualified class name. For example, if the following two components -were detected, the names would be myMovieLister and movieFinderImpl: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Service("myMovieLister") - public class SimpleMovieLister { - // ... - } ----- - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Repository - public class MovieFinderImpl implements MovieFinder { - // ... - } ----- - -[NOTE] -==== -If you do not want to rely on the default bean-naming strategy, you can provide a custom -bean-naming strategy. First, implement the -{javadoc-baseurl}/org/springframework/beans/factory/support/BeanNameGenerator.html[`BeanNameGenerator`] -interface, and be sure to include a default no-arg constructor. Then, provide the -fully-qualified class name when configuring the scanner: -==== - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Configuration - @ComponentScan(basePackages = "org.example", nameGenerator = MyNameGenerator.class) - public class AppConfig { - ... - } ----- - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - ----- - -As a general rule, consider specifying the name with the annotation whenever other -components may be making explicit references to it. On the other hand, the -auto-generated names are adequate whenever the container is responsible for wiring. - - - -[[beans-scanning-scope-resolver]] -==== Providing a scope for autodetected components -As with Spring-managed components in general, the default and most common scope for -autodetected components is singleton. However, sometimes you need other scopes, which -Spring 2.5 provides with a new `@Scope` annotation. Simply provide the name of the scope -within the annotation: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Scope("prototype") - @Repository - public class MovieFinderImpl implements MovieFinder { - // ... - } ----- - -[NOTE] -==== -To provide a custom strategy for scope resolution rather than relying on the -annotation-based approach, implement the -{javadoc-baseurl}/org/springframework/context/annotation/ScopeMetadataResolver.html[`ScopeMetadataResolver`] -interface, and be sure to include a default no-arg constructor. Then, provide the -fully-qualified class name when configuring the scanner: -==== - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Configuration - @ComponentScan(basePackages = "org.example", scopeResolver = MyScopeResolver.class) - public class AppConfig { - ... - } ----- - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - ----- - -When using certain non-singleton scopes, it may be necessary to generate proxies for the -scoped objects. The reasoning is described in <>. -For this purpose, a __scoped-proxy__ attribute is available on the component-scan -element. The three possible values are: no, interfaces, and targetClass. For example, -the following configuration will result in standard JDK dynamic proxies: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Configuration - @ComponentScan(basePackages = "org.example", scopedProxy = ScopedProxyMode.INTERFACES) - public class AppConfig { - ... - } ----- - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - ----- - - - -[[beans-scanning-qualifiers]] -==== Providing qualifier metadata with annotations -The `@Qualifier` annotation is discussed in <>. -The examples in that section demonstrate the use of the `@Qualifier` annotation and -custom qualifier annotations to provide fine-grained control when you resolve autowire -candidates. Because those examples were based on XML bean definitions, the qualifier -metadata was provided on the candidate bean definitions using the `qualifier` or `meta` -sub-elements of the `bean` element in the XML. When relying upon classpath scanning for -autodetection of components, you provide the qualifier metadata with type-level -annotations on the candidate class. The following three examples demonstrate this -technique: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Component - **@Qualifier("Action")** - public class ActionMovieCatalog implements MovieCatalog { - // ... - } ----- - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Component - **@Genre("Action")** - public class ActionMovieCatalog implements MovieCatalog { - // ... - } ----- - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Component - **@Offline** - public class CachingMovieCatalog implements MovieCatalog { - // ... - } ----- - -[NOTE] -==== -As with most annotation-based alternatives, keep in mind that the annotation metadata is -bound to the class definition itself, while the use of XML allows for multiple beans -__of the same type__ to provide variations in their qualifier metadata, because that -metadata is provided per-instance rather than per-class. -==== - - - - -[[beans-standard-annotations]] -=== Using JSR 330 Standard Annotations -Starting with Spring 3.0, Spring offers support for JSR-330 standard annotations -(Dependency Injection). Those annotations are scanned in the same way as the Spring -annotations. You just need to have the relevant jars in your classpath. - -[NOTE] -==== -If you are using Maven, the `javax.inject` artifact is available in the standard Maven -repository ( -http://repo1.maven.org/maven2/javax/inject/javax.inject/1/[http://repo1.maven.org/maven2/javax/inject/javax.inject/1/]). -You can add the following dependency to your file pom.xml: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - javax.inject - javax.inject - 1 - ----- -==== - - - -[[beans-inject-named]] -==== Dependency Injection with @Inject and @Named - -Instead of `@Autowired`, `@javax.inject.Inject` may be used as follows: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - import javax.inject.Inject; - - public class SimpleMovieLister { - - private MovieFinder movieFinder; - - @Inject - public void setMovieFinder(MovieFinder movieFinder) { - this.movieFinder = movieFinder; - } - - // ... - - } ----- - -As with `@Autowired`, it is possible to use `@Inject` at the class-level, field-level, -method-level and constructor-argument level. If you would like to use a qualified name -for the dependency that should be injected, you should use the `@Named` annotation as -follows: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - import javax.inject.Inject; - import javax.inject.Named; - - public class SimpleMovieLister { - - private MovieFinder movieFinder; - - @Inject - public void setMovieFinder(@Named("main") MovieFinder movieFinder) { - this.movieFinder = movieFinder; - } - - // ... - - } ----- - - - -[[beans-named]] -==== @Named: a standard equivalent to the @Component annotation - -Instead of `@Component`, `@javax.inject.Named` may be used as follows: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - import javax.inject.Inject; - import javax.inject.Named; - - @Named("movieListener") - public class SimpleMovieLister { - - private MovieFinder movieFinder; - - @Inject - public void setMovieFinder(MovieFinder movieFinder) { - this.movieFinder = movieFinder; - } - - // ... - - } ----- - -It is very common to use `@Component` without -specifying a name for the component. `@Named` -can be used in a similar fashion: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - import javax.inject.Inject; - import javax.inject.Named; - - @Named - public class SimpleMovieLister { - - private MovieFinder movieFinder; - - @Inject - public void setMovieFinder(MovieFinder movieFinder) { - this.movieFinder = movieFinder; - } - - // ... - - } ----- - -When using `@Named`, it is possible to use -component-scanning in the exact same way as when using Spring annotations: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Configuration - @ComponentScan(basePackages = "org.example") - public class AppConfig { - ... - } ----- - - - -[[beans-standard-annotations-limitations]] -==== Limitations of the standard approach -When working with standard annotations, it is important to know that some significant -features are not available as shown in the table below: - -[[annotations-comparison]] -.Spring annotations vs. standard annotations -|=== -| Spring| javax.inject.*| javax.inject restrictions / comments - -| @Autowired -| @Inject -| @Inject has no 'required' attribute - -| @Component -| @Named -| - - -| @Scope("singleton") -| @Singleton -| The JSR-330 default scope is like Spring's `prototype`. However, in order to keep it - consistent with Spring's general defaults, a JSR-330 bean declared in the Spring - container is a `singleton` by default. In order to use a scope other than `singleton`, - you should use Spring's `@Scope` annotation. - -`javax.inject` also provides a -http://download.oracle.com/javaee/6/api/javax/inject/Scope.html[@Scope] annotation. -Nevertheless, this one is only intended to be used for creating your own annotations. - -| @Qualifier -| @Named -| - - -| @Value -| - -| no equivalent - -| @Required -| - -| no equivalent - -| @Lazy -| - -| no equivalent -|=== - - - - -[[beans-java]] -=== Java-based container configuration - - - -[[beans-java-basic-concepts]] -==== Basic concepts: @Bean and @Configuration - -The central artifacts in Spring's new Java-configuration support are -`@Configuration`-annotated classes and `@Bean`-annotated methods. - -The `@Bean` annotation is used to indicate that a method instantiates, configures and -initializes a new object to be managed by the Spring IoC container. For those familiar -with Spring's `` XML configuration the `@Bean` annotation plays the same role as -the `` element. You can use `@Bean` annotated methods with any Spring -`@Component`, however, they are most often used with `@Configuration` beans. - -Annotating a class with `@Configuration` indicates that its primary purpose is as a -source of bean definitions. Furthermore, `@Configuration` classes allow inter-bean -dependencies to be defined by simply calling other `@Bean` methods in the same class. -The simplest possible `@Configuration` class would read as follows: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Configuration - public class AppConfig { - - @Bean - public MyService myService() { - return new MyServiceImpl(); - } - - } ----- - -The `AppConfig` class above would be equivalent to the following Spring `` XML: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - ----- - -The `@Bean` and `@Configuration` annotations will be discussed in depth in the sections -below. First, however, we'll cover the various ways of creating a spring container using -Java-based configuration. - -.Full @Configuration vs 'lite' @Beans mode? -**** -When `@Bean` methods are declared within classes that are __not__ annotated with -`@Configuration` they are referred to as being processed in a 'lite' mode. For example, -bean methods declared in a `@Component` or even in a __plain old class__ will be -considered 'lite'. - -Unlike full `@Configuration`, lite `@Bean` methods cannot easily declare inter-bean -dependencies. Usually one `@Bean` method should not invoke another `@Bean` method when -operating in 'lite' mode. - -Only using `@Bean` methods within `@Configuration` classes is a recommended approach of -ensuring that 'full' mode is always used. This will prevent the same `@Bean` method from -accidentally being invoked multiple times and helps to reduce subtle bugs that can be -hard to track down when operating in 'lite' mode. -**** - - -[[beans-java-instantiating-container]] -==== Instantiating the Spring container using AnnotationConfigApplicationContext -The sections below document Spring's `AnnotationConfigApplicationContext`, new in Spring -3.0. This versatile `ApplicationContext` implementation is capable of accepting not only -`@Configuration` classes as input, but also plain `@Component` classes and classes -annotated with JSR-330 metadata. - -When `@Configuration` classes are provided as input, the `@Configuration` class itself -is registered as a bean definition, and all declared `@Bean` methods within the class -are also registered as bean definitions. - -When `@Component` and JSR-330 classes are provided, they are registered as bean -definitions, and it is assumed that DI metadata such as `@Autowired` or `@Inject` are -used within those classes where necessary. - - -[[beans-java-instantiating-container-contstructor]] -===== Simple construction -In much the same way that Spring XML files are used as input when instantiating a -`ClassPathXmlApplicationContext`, `@Configuration` classes may be used as input when -instantiating an `AnnotationConfigApplicationContext`. This allows for completely -XML-free usage of the Spring container: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public static void main(String[] args) { - ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class); - MyService myService = ctx.getBean(MyService.class); - myService.doStuff(); - } ----- - -As mentioned above, `AnnotationConfigApplicationContext` is not limited to working only -with `@Configuration` classes. Any `@Component` or JSR-330 annotated class may be supplied -as input to the constructor. For example: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public static void main(String[] args) { - ApplicationContext ctx = new AnnotationConfigApplicationContext(MyServiceImpl.class, Dependency1.class, Dependency2.class); - MyService myService = ctx.getBean(MyService.class); - myService.doStuff(); - } ----- - -The above assumes that `MyServiceImpl`, `Dependency1` and `Dependency2` use Spring -dependency injection annotations such as `@Autowired`. - - -[[beans-java-instantiating-container-register]] -===== Building the container programmatically using register(Class...) - -An `AnnotationConfigApplicationContext` may be instantiated using a no-arg constructor -and then configured using the `register()` method. This approach is particularly useful -when programmatically building an `AnnotationConfigApplicationContext`. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public static void main(String[] args) { - AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); - ctx.register(AppConfig.class, OtherConfig.class); - ctx.register(AdditionalConfig.class); - ctx.refresh(); - MyService myService = ctx.getBean(MyService.class); - myService.doStuff(); - } ----- - - -[[beans-java-instantiating-container-scan]] -===== Enabling component scanning with scan(String...) - -To enable component scanning, just annotate your `@Configuration` class as follows: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Configuration - @ComponentScan(basePackages = "com.acme") - public class AppConfig { - ... - } ----- - -[TIP] -==== - -Experienced Spring users will be familiar with the XML declaration equivalent from -Spring's `context:` namespace - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - ----- -==== - - -In the example above, the `com.acme` package will be scanned, looking for any -`@Component`-annotated classes, and those classes will be registered as Spring bean -definitions within the container. `AnnotationConfigApplicationContext` exposes the -`scan(String...)` method to allow for the same component-scanning functionality: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public static void main(String[] args) { - AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); - ctx.scan("com.acme"); - ctx.refresh(); - MyService myService = ctx.getBean(MyService.class); - } ----- - -[NOTE] -==== -Remember that `@Configuration` classes are <> -with `@Component`, so they are candidates for component-scanning! In the example above, -assuming that `AppConfig` is declared within the `com.acme` package (or any package -underneath), it will be picked up during the call to `scan()`, and upon `refresh()` all -its `@Bean` methods will be processed and registered as bean definitions within the -container. -==== - - -[[beans-java-instantiating-container-web]] -===== Support for web applications with AnnotationConfigWebApplicationContext - -A `WebApplicationContext` variant of `AnnotationConfigApplicationContext` is available -with `AnnotationConfigWebApplicationContext`. This implementation may be used when -configuring the Spring `ContextLoaderListener` servlet listener, Spring MVC -`DispatcherServlet`, etc. What follows is a `web.xml` snippet that configures a typical -Spring MVC web application. Note the use of the `contextClass` context-param and -init-param: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - contextClass - - org.springframework.web.context.support.AnnotationConfigWebApplicationContext - - - - - - contextConfigLocation - com.acme.AppConfig - - - - - org.springframework.web.context.ContextLoaderListener - - - - - dispatcher - org.springframework.web.servlet.DispatcherServlet - - - contextClass - - org.springframework.web.context.support.AnnotationConfigWebApplicationContext - - - - - contextConfigLocation - com.acme.web.MvcConfig - - - - - - dispatcher - /app/* - - ----- - - - -[[beans-java-bean-annotation]] -==== Using the @Bean annotation - -`@Bean` is a method-level annotation and a direct analog of the XML `` element. -The annotation supports some of the attributes offered by ``, such as: -<>, -<>, -<> and `name`. - -You can use the `@Bean` annotation in a `@Configuration`-annotated or in a -`@Component`-annotated class. - - -[[beans-java-declaring-a-bean]] -===== Declaring a bean -To declare a bean, simply annotate a method with the `@Bean` annotation. You use this -method to register a bean definition within an `ApplicationContext` of the type -specified as the method's return value. By default, the bean name will be the same as -the method name. The following is a simple example of a `@Bean` method declaration: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Configuration - public class AppConfig { - - @Bean - public TransferService transferService() { - return new TransferServiceImpl(); - } - - } ----- - -The preceding configuration is exactly equivalent to the following Spring XML: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - ----- - -Both declarations make a bean named `transferService` available in the -`ApplicationContext`, bound to an object instance of type `TransferServiceImpl`: - -[literal] -[subs="verbatim,quotes"] ----- -transferService -> com.acme.TransferServiceImpl ----- - - -[[beans-java-lifecycle-callbacks]] -===== Receiving lifecycle callbacks -Any classes defined with the `@Bean` annotation support the regular lifecycle callbacks -and can use the `@PostConstruct` and `@PreDestroy` annotations from JSR-250, see -<> for further -details. - -The regular Spring <> callbacks are fully supported as -well. If a bean implements `InitializingBean`, `DisposableBean`, or `Lifecycle`, their -respective methods are called by the container. - -The standard set of `*Aware` interfaces such as <>, -<>, -<>, -<>, and so on are also fully supported. - -The `@Bean` annotation supports specifying arbitrary initialization and destruction -callback methods, much like Spring XML's `init-method` and `destroy-method` attributes -on the `bean` element: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class Foo { - public void init() { - // initialization logic - } - } - - public class Bar { - public void cleanup() { - // destruction logic - } - } - - @Configuration - public class AppConfig { - - @Bean(initMethod = "init") - public Foo foo() { - return new Foo(); - } - - @Bean(destroyMethod = "cleanup") - public Bar bar() { - return new Bar(); - } - - } ----- - -Of course, in the case of `Foo` above, it would be equally as valid to call the `init()` -method directly during construction: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Configuration - public class AppConfig { - @Bean - public Foo foo() { - Foo foo = new Foo(); - foo.init(); - return foo; - } - - // ... - - } ----- - -[TIP] -==== - -When you work directly in Java, you can do anything you like with your objects and do -not always need to rely on the container lifecycle! -==== - - -[[beans-java-specifying-bean-scope]] -===== Specifying bean scope - -[[beans-java-available-scopes]] -====== Using the @Scope annotation - -You can specify that your beans defined with the `@Bean` annotation should have a -specific scope. You can use any of the standard scopes specified in the -<> section. - -The default scope is `singleton`, but you can override this with the `@Scope` annotation: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Configuration - public class MyConfiguration { - - @Bean - **@Scope("prototype")** - public Encryptor encryptor() { - // ... - } - - } ----- - -[[beans-java-scoped-proxy]] -====== @Scope and scoped-proxy - -Spring offers a convenient way of working with scoped dependencies through -<>. The easiest way to create such -a proxy when using the XML configuration is the `` element. -Configuring your beans in Java with a @Scope annotation offers equivalent support with -the proxyMode attribute. The default is no proxy ( `ScopedProxyMode.NO`), but you can -specify `ScopedProxyMode.TARGET_CLASS` or `ScopedProxyMode.INTERFACES`. - -If you port the scoped proxy example from the XML reference documentation (see preceding -link) to our `@Bean` using Java, it would look like the following: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - // an HTTP Session-scoped bean exposed as a proxy - @Bean - **@Scope(value = "session", proxyMode = ScopedProxyMode.TARGET_CLASS)** - public UserPreferences userPreferences() { - return new UserPreferences(); - } - - @Bean - public Service userService() { - UserService service = new SimpleUserService(); - // a reference to the proxied userPreferences bean - service.setUserPreferences(userPreferences()); - return service; - } ----- - - -[[beans-java-customizing-bean-naming]] -===== Customizing bean naming -By default, configuration classes use a `@Bean` method's name as the name of the -resulting bean. This functionality can be overridden, however, with the `name` attribute. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Configuration - public class AppConfig { - - @Bean(name = "myFoo") - public Foo foo() { - return new Foo(); - } - - } ----- - - -[[beans-java-bean-aliasing]] -===== Bean aliasing -As discussed in <>, it is sometimes desirable to give a single bean -multiple names, otherwise known as__bean aliasing__. The `name` attribute of the `@Bean` -annotation accepts a String array for this purpose. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Configuration - public class AppConfig { - - @Bean(name = { "dataSource", "subsystemA-dataSource", "subsystemB-dataSource" }) - public DataSource dataSource() { - // instantiate, configure and return DataSource bean... - } - - } ----- - - -[[beans-java-bean-description]] -===== Bean description -Sometimes it is helpful to provide a more detailed textual description of a bean. This can -be particularly useful when beans are exposed (perhaps via JMX) for monitoring purposes. - -To add a description to a `@Bean` the -{javadoc-baseurl}/org/springframework/context/annotation/Description.html[`@Description`] -annotation can be used: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Configuration - public class AppConfig { - - @Bean - **@Desciption("Provides a basic example of a bean")** - public Foo foo() { - return new Foo(); - } - - } ----- - - -[[beans-java-configuration-annotation]] -==== Using the @Configuration annotation - -`@Configuration` is a class-level annotation indicating that an object is a source of -bean definitions. `@Configuration` classes declare beans via public `@Bean` annotated -methods. Calls to `@Bean` methods on `@Configuration` classes can also be used to define -inter-bean dependencies. See <> for a general introduction. - - -[[beans-java-injecting-dependencies]] -===== Injecting inter-bean dependencies -When ++@Bean++s have dependencies on one another, expressing that dependency is as simple -as having one bean method call another: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Configuration - public class AppConfig { - - @Bean - public Foo foo() { - return new Foo(bar()); - } - - @Bean - public Bar bar() { - return new Bar(); - } - - } ----- - -In the example above, the `foo` bean receives a reference to `bar` via constructor -injection. - -[NOTE] -==== -This method of declaring inter-bean dependencies only works when the `@Bean` method is -declared within a `@Configuration` class. You cannot declare inter-bean dependencies -using plain `@Component` classes. -==== - - -[[beans-java-method-injection]] -===== Lookup method injection -As noted earlier, <> is an -advanced feature that you should use rarely. It is useful in cases where a -singleton-scoped bean has a dependency on a prototype-scoped bean. Using Java for this -type of configuration provides a natural means for implementing this pattern. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public abstract class CommandManager { - public Object process(Object commandState) { - // grab a new instance of the appropriate Command interface - Command command = createCommand(); - - // set the state on the (hopefully brand new) Command instance - command.setState(commandState); - return command.execute(); - } - - // okay... but where is the implementation of this method? - protected abstract Command createCommand(); - } ----- - -Using Java-configuration support , you can create a subclass of `CommandManager` where -the abstract `createCommand()` method is overridden in such a way that it looks up a new -(prototype) command object: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Bean - @Scope("prototype") - public AsyncCommand asyncCommand() { - AsyncCommand command = new AsyncCommand(); - // inject dependencies here as required - return command; - } - - @Bean - public CommandManager commandManager() { - // return new anonymous implementation of CommandManager with command() overridden - // to return a new prototype Command object - return new CommandManager() { - protected Command createCommand() { - return asyncCommand(); - } - } - } ----- - - -[[beans-java-further-information-java-config]] -===== Further information about how Java-based configuration works internally -The following example shows a `@Bean` annotated method being called twice: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Configuration - public class AppConfig { - - @Bean - public ClientService clientService1() { - ClientServiceImpl clientService = new ClientServiceImpl(); - clientService.setClientDao(clientDao()); - return clientService; - } - - @Bean - public ClientService clientService2() { - ClientServiceImpl clientService = new ClientServiceImpl(); - clientService.setClientDao(clientDao()); - return clientService; - } - - @Bean - public ClientDao clientDao() { - return new ClientDaoImpl(); - } - - } ----- - -`clientDao()` has been called once in `clientService1()` and once in `clientService2()`. -Since this method creates a new instance of `ClientDaoImpl` and returns it, you would -normally expect having 2 instances (one for each service). That definitely would be -problematic: in Spring, instantiated beans have a `singleton` scope by default. This is -where the magic comes in: All `@Configuration` classes are subclassed at startup-time -with `CGLIB`. In the subclass, the child method checks the container first for any -cached (scoped) beans before it calls the parent method and creates a new instance. Note -that as of Spring 3.2, it is no longer necessary to add CGLIB to your classpath because -CGLIB classes have been repackaged under org.springframework and included directly -within the spring-core JAR. - -[NOTE] -==== -The behavior could be different according to the scope of your bean. We are talking -about singletons here. -==== - -[NOTE] -==== -There are a few restrictions due to the fact that CGLIB dynamically adds features at -startup-time: - -* Configuration classes should not be final -* They should have a constructor with no arguments -==== - - - -[[beans-java-composing-configuration-classes]] -==== Composing Java-based configurations - - -[[beans-java-using-import]] -===== Using the @Import annotation - -Much as the `` element is used within Spring XML files to aid in modularizing -configurations, the `@Import` annotation allows for loading `@Bean` definitions from -another configuration class: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Configuration - public class ConfigA { - - @Bean - public A a() { - return new A(); - } - - } - - @Configuration - @Import(ConfigA.class) - public class ConfigB { - - @Bean - public B b() { - return new B(); - } - - } ----- - -Now, rather than needing to specify both `ConfigA.class` and `ConfigB.class` when -instantiating the context, only `ConfigB` needs to be supplied explicitly: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public static void main(String[] args) { - ApplicationContext ctx = new AnnotationConfigApplicationContext(ConfigB.class); - - // now both beans A and B will be available... - A a = ctx.getBean(A.class); - B b = ctx.getBean(B.class); - } ----- - -This approach simplifies container instantiation, as only one class needs to be dealt -with, rather than requiring the developer to remember a potentially large number of -`@Configuration` classes during construction. - -[[beans-java-injecting-imported-beans]] -====== Injecting dependencies on imported @Bean definitions - -The example above works, but is simplistic. In most practical scenarios, beans will have -dependencies on one another across configuration classes. When using XML, this is not an -issue, per se, because there is no compiler involved, and one can simply declare -`ref="someBean"` and trust that Spring will work it out during container initialization. -Of course, when using `@Configuration` classes, the Java compiler places constraints on -the configuration model, in that references to other beans must be valid Java syntax. - -Fortunately, solving this problem is simple. Remember that `@Configuration` classes are -ultimately just another bean in the container - this means that they can take advantage -of `@Autowired` injection metadata just like any other bean! - -Let's consider a more real-world scenario with several `@Configuration` classes, each -depending on beans declared in the others: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Configuration - public class ServiceConfig { - - @Autowired - private AccountRepository accountRepository; - - @Bean - public TransferService transferService() { - return new TransferServiceImpl(accountRepository); - } - - } - - @Configuration - public class RepositoryConfig { - - @Autowired - private DataSource dataSource; - - @Bean - public AccountRepository accountRepository() { - return new JdbcAccountRepository(dataSource); - } - - } - - @Configuration - @Import({ServiceConfig.class, RepositoryConfig.class}) - public class SystemTestConfig { - - @Bean - public DataSource dataSource() { - // return new DataSource - } - - } - - public static void main(String[] args) { - ApplicationContext ctx = new AnnotationConfigApplicationContext(SystemTestConfig.class); - // everything wires up across configuration classes... - TransferService transferService = ctx.getBean(TransferService.class); - transferService.transfer(100.00, "A123", "C456"); - } ----- - -.[[beans-java-injecting-imported-beans-fq]]Fully-qualifying imported beans for ease of navigation --- -In the scenario above, using `@Autowired` works well and provides the desired -modularity, but determining exactly where the autowired bean definitions are declared is -still somewhat ambiguous. For example, as a developer looking at `ServiceConfig`, how do -you know exactly where the `@Autowired AccountRepository` bean is declared? It's not -explicit in the code, and this may be just fine. Remember that the -https://spring.io/tools/sts[Spring Tool Suite] provides tooling that -can render graphs showing how everything is wired up - that may be all you need. Also, -your Java IDE can easily find all declarations and uses of the `AccountRepository` type, -and will quickly show you the location of `@Bean` methods that return that type. - -In cases where this ambiguity is not acceptable and you wish to have direct navigation -from within your IDE from one `@Configuration` class to another, consider autowiring the -configuration classes themselves: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Configuration - public class ServiceConfig { - - @Autowired - private RepositoryConfig repositoryConfig; - - @Bean - public TransferService transferService() { - // navigate 'through' the config class to the @Bean method! - return new TransferServiceImpl(repositoryConfig.accountRepository()); - } - - } ----- - -In the situation above, it is completely explicit where `AccountRepository` is defined. -However, `ServiceConfig` is now tightly coupled to `RepositoryConfig`; that's the -tradeoff. This tight coupling can be somewhat mitigated by using interface-based or -abstract class-based `@Configuration` classes. Consider the following: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Configuration - public class ServiceConfig { - - @Autowired - private RepositoryConfig repositoryConfig; - - @Bean - public TransferService transferService() { - return new TransferServiceImpl(repositoryConfig.accountRepository()); - } - } - - @Configuration - public interface RepositoryConfig { - - @Bean - AccountRepository accountRepository(); - - } - - @Configuration - public class DefaultRepositoryConfig implements RepositoryConfig { - - @Bean - public AccountRepository accountRepository() { - return new JdbcAccountRepository(...); - } - - } - - @Configuration - @Import({ServiceConfig.class, DefaultRepositoryConfig.class}) // import the concrete config! - public class SystemTestConfig { - - @Bean - public DataSource dataSource() { - // return DataSource - } - - } - - public static void main(String[] args) { - ApplicationContext ctx = new AnnotationConfigApplicationContext(SystemTestConfig.class); - TransferService transferService = ctx.getBean(TransferService.class); - transferService.transfer(100.00, "A123", "C456"); - } ----- - -Now `ServiceConfig` is loosely coupled with respect to the concrete -`DefaultRepositoryConfig`, and built-in IDE tooling is still useful: it will be easy for -the developer to get a type hierarchy of `RepositoryConfig` implementations. In this -way, navigating `@Configuration` classes and their dependencies becomes no different -than the usual process of navigating interface-based code. --- - - -[[beans-java-conditional]] -===== Conditionally including @Configuration classes or @Beans -It is often useful to conditionally enable to disable a complete `@Configuration` class, -or even individual `@Bean` methods, based on some arbitrary system state. One common -example of this it to use the `@Profile` annotation to active beans only when a specific -profile has been enabled in the Spring `Environment` (see <> -for details). - -The `@Profile` annotation is actually implemented using a much more flexible annotation -called {javadoc-baseurl}/org/springframework/context/annotation/Conditional.html[`@Conditional`]. -The `@Conditional` annotation indicates specific -`org.springframework.context.annotation.Condition` implementations that should be -consulted before a `@Bean` is registered. - -Implementations of the `Condition` interface simply provide a `matches(...)` -method that returns `true` or `false`. For example, here is the actual -`Condition` implementation used for `@Profile`: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Override - public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { - if (context.getEnvironment() != null) { - // Read the @Profile annotation attributes - MultiValueMap attrs = metadata.getAllAnnotationAttributes(Profile.class.getName()); - if (attrs != null) { - for (Object value : attrs.get("value")) { - if (context.getEnvironment().acceptsProfiles(((String[]) value))) { - return true; - } - } - return false; - } - } - return true; - } ----- - -See the {javadoc-baseurl}/org/springframework/context/annotation/Conditional.html[ -`@Conditional` javadocs] for more detail. - -[[beans-java-combining]] -===== Combining Java and XML configuration -Spring's `@Configuration` class support does not aim to be a 100% complete replacement -for Spring XML. Some facilities such as Spring XML namespaces remain an ideal way to -configure the container. In cases where XML is convenient or necessary, you have a -choice: either instantiate the container in an "XML-centric" way using, for example, -`ClassPathXmlApplicationContext`, or in a "Java-centric" fashion using -`AnnotationConfigApplicationContext` and the `@ImportResource` annotation to import XML -as needed. - -[[beans-java-combining-xml-centric]] -====== XML-centric use of @Configuration classes - -It may be preferable to bootstrap the Spring container from XML and include -`@Configuration` classes in an ad-hoc fashion. For example, in a large existing codebase -that uses Spring XML, it will be easier to create `@Configuration` classes on an -as-needed basis and include them from the existing XML files. Below you'll find the -options for using `@Configuration` classes in this kind of "XML-centric" situation. - -.[[beans-java-combining-xml-centric-declare-as-bean]]Declaring @Configuration classes as plain Spring `` elements --- -Remember that `@Configuration` classes are ultimately just bean definitions in the -container. In this example, we create a `@Configuration` class named `AppConfig` and -include it within `system-test-config.xml` as a `` definition. Because -`` is switched on, the container will recognize the -`@Configuration` annotation, and process the `@Bean` methods declared in `AppConfig` -properly. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Configuration - public class AppConfig { - - @Autowired - private DataSource dataSource; - - @Bean - public AccountRepository accountRepository() { - return new JdbcAccountRepository(dataSource); - } - - @Bean - public TransferService transferService() { - return new TransferService(accountRepository()); - } - - } ----- - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - system-test-config.xml - - - - - - - - - - - - - ----- - -[literal] -[subs="verbatim,quotes"] ----- -jdbc.properties -jdbc.url=jdbc:hsqldb:hsql://localhost/xdb -jdbc.username=sa -jdbc.password= ----- - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public static void main(String[] args) { - ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:/com/acme/system-test-config.xml"); - TransferService transferService = ctx.getBean(TransferService.class); - // ... - } ----- - -[NOTE] -==== -In `system-test-config.xml` above, the `AppConfig` does not declare an `id` -element. While it would be acceptable to do so, it is unnecessary given that no other -bean will ever refer to it, and it is unlikely that it will be explicitly fetched from -the container by name. Likewise with the `DataSource` bean - it is only ever autowired -by type, so an explicit bean id is not strictly required. -==== --- - -.[[beans-java-combining-xml-centric-component-scan]] Using to pick up `@Configuration` classes --- -Because `@Configuration` is meta-annotated with `@Component`, `@Configuration`-annotated -classes are automatically candidates for component scanning. Using the same scenario as -above, we can redefine `system-test-config.xml` to take advantage of component-scanning. -Note that in this case, we don't need to explicitly declare -``, because `` enables all the same -functionality. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - system-test-config.xml - - - - - - - - - - - ----- --- - -[[beans-java-combining-java-centric]] -====== @Configuration class-centric use of XML with @ImportResource - -In applications where `@Configuration` classes are the primary mechanism for configuring -the container, it will still likely be necessary to use at least some XML. In these -scenarios, simply use `@ImportResource` and define only as much XML as is needed. Doing -so achieves a "Java-centric" approach to configuring the container and keeps XML to a -bare minimum. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Configuration - @ImportResource("classpath:/com/acme/properties-config.xml") - public class AppConfig { - - @Value("${jdbc.url}") - private String url; - - @Value("${jdbc.username}") - private String username; - - @Value("${jdbc.password}") - private String password; - - @Bean - public DataSource dataSource() { - return new DriverManagerDataSource(url, username, password); - } - - } ----- - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - properties-config.xml - - - ----- - -[literal] -[subs="verbatim,quotes"] ----- -jdbc.properties -jdbc.url=jdbc:hsqldb:hsql://localhost/xdb -jdbc.username=sa -jdbc.password= ----- - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public static void main(String[] args) { - ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class); - TransferService transferService = ctx.getBean(TransferService.class); - // ... - } ----- - -[[beans-environment]] -=== Environment abstraction - -The {javadoc-baseurl}/org/springframework/core/env/Environment.html[`Environment`] -is an abstraction integrated in the container that models two key -aspects of the application environment: <> -and <>. - -A _profile_ is a named, logical group of bean definitions to be registered with the -container only if the given profile is active. Beans may be assigned to a profile -whether defined in XML or via annotations. The role of the `Environment` object with -relation to profiles is in determining which profiles (if any) are currently active, -and which profiles (if any) should be active by default. - -Properties play an important role in almost all applications, and may originate from -a variety of sources: properties files, JVM system properties, system environment -variables, JNDI, servlet context parameters, ad-hoc Properties objects, Maps, and so -on. The role of the `Environment` object with relation to properties is to provide the -user with a convenient service interface for configuring property sources and resolving -properties from them. - -[[beans-definition-profiles]] -==== Bean definition profiles - -Bean definition profiles is a mechanism in the core container that allows for -registration of different beans in different environments. The word _environment_ -can mean different things to different users and this feature can help with many -use cases, including: - -* working against an in-memory datasource in development vs looking up that same -datasource from JNDI when in QA or production -* registering monitoring infrastructure only when deploying an application into a -performance environment -* registering customized implementations of beans for customer A vs. customer -B deployments - -Let's consider the first use case in a practical application that requires a -`DataSource`. In a test environment, the configuration may look like this: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Bean - public DataSource dataSource() { - return new EmbeddedDatabaseBuilder() - .setType(EmbeddedDatabaseType.HSQL) - .addScript("my-schema.sql") - .addScript("my-test-data.sql") - .build(); - } ----- - -Let's now consider how this application will be deployed into a QA or production -environment, assuming that the datasource for the application will be registered -with the production application server's JNDI directory. Our `dataSource` bean -now looks like this: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Bean - public DataSource dataSource() throws Exception { - Context ctx = new InitialContext(); - return (DataSource) ctx.lookup("java:comp/env/jdbc/datasource"); - } ----- - -The problem is how to switch between using these two variations based on the -current environment. Over time, Spring users have devised a number of ways to -get this done, usually relying on a combination of system environment variables -and XML `` statements containing `${placeholder}` tokens that resolve -to the correct configuration file path depending on the value of an environment -variable. Bean definition profiles is a core container feature that provides a -solution to this problem. - -If we generalize the example use case above of environment-specific bean -definitions, we end up with the need to register certain bean definitions in -certain contexts, while not in others. You could say that you want to register a -certain profile of bean definitions in situation A, and a different profile in -situation B. Let's first see how we can update our configuration to reflect -this need. - -[[beans-definition-profiles-java]] -===== @Profile - -The {javadoc-baseurl}/org/springframework/context/annotation/Profile.html[`@Profile`] -annotation allows to indicate that a component is eligible for registration -when one or more specified profiles are active. Using our example above, we -can rewrite the _dataSource_ configuration as follows: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Configuration - **@Profile("dev")** - public class StandaloneDataConfig { - - @Bean - public DataSource dataSource() { - return new EmbeddedDatabaseBuilder() - .setType(EmbeddedDatabaseType.HSQL) - .addScript("classpath:com/bank/config/sql/schema.sql") - .addScript("classpath:com/bank/config/sql/test-data.sql") - .build(); - } - } ----- - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Configuration - **@Profile("production")** - public class JndiDataConfig { - - @Bean - public DataSource dataSource() throws Exception { - Context ctx = new InitialContext(); - return (DataSource) ctx.lookup("java:comp/env/jdbc/datasource"); - } - } ----- - - -`@Profile` can be used as a meta-annotation, for the purpose of composing -custom stereotype annotations. The following example defines a `@Production` -custom annotation that can be used as a drop-in replacement of -`@Profile("production")`: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Target(ElementType.TYPE) - @Retention(RetentionPolicy.RUNTIME) - **@Profile("production")** - public @interface Production { - } ----- - -`@Profile` can also be specified at method-level to include only one particular -bean of a configuration class: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Configuration - public class AppConfig { - - @Bean - **@Profile("dev")** - public DataSource devDataSource() { - return new EmbeddedDatabaseBuilder() - .setType(EmbeddedDatabaseType.HSQL) - .addScript("classpath:com/bank/config/sql/schema.sql") - .addScript("classpath:com/bank/config/sql/test-data.sql") - .build(); - } - - @Bean - **@Profile("production")** - public DataSource productionDataSource() throws Exception { - Context ctx = new InitialContext(); - return (DataSource) ctx.lookup("java:comp/env/jdbc/datasource"); - } - } ----- - -[TIP] -==== -If a `@Configuration` class is marked with `@Profile`, all of the `@Bean` methods -and `@Import` annotations associated with that class will be bypassed unless one -or more of the specified profiles are active. If a `@Component` or `@Configuration` -class is marked with `@Profile({"p1", "p2"})`, that class will not be registered/ -processed unless profiles 'p1' and/or 'p2' have been activated. If a given profile -is prefixed with the NOT operator (`!`), the annotated element will be registered -if the profile is **not** active. e.g., for `@Profile({"p1", "!p2"})`, registration -will occur if profile 'p1' is active or if profile 'p2' is not active. -==== - -[[beans-definition-profiles-xml]] -==== XML Bean definition profiles - -The XML counterpart is an update of the `beans` element that accepts a -`profile` attribute. Our sample configuration above can be rewritten in two XML -files as follows: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - ----- - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - ----- - -It is also possible to avoid that split and nest `` elements within the same file: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - - - - - - - - ----- - -The `spring-bean.xsd` has been constrained to allow such elements only as the -last ones in the file. This should help provide flexibility without incurring -clutter in the XML files. - -[[beans-definition-profiles-enable]] -===== Enabling a profile - -Now that we have updated our configuration, we still need to instruct which -profile is active. If we started our sample application right now, we would see -a `NoSuchBeanDefinitionException` thrown, because the container could not find -the Spring bean named `dataSource`. - -Activating a profile can be done in several ways, but the most straightforward -is to do it programmatically against the `ApplicationContext` API: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); - ctx.getEnvironment().setActiveProfiles("dev"); - ctx.register(SomeConfig.class, StandaloneDataConfig.class, JndiDataConfig.class); - ctx.refresh(); ----- - -In addition, profiles may also be activated declaratively through the `spring.profiles.active` -property which may be specified through system environment variables, JVM system properties, -servlet context parameters in `web.xml` or even as an entry in JNDI (see -<>). - -Note that profiles are not an "either-or" proposition; it is possible to activate multiple -profiles at once. Programmatically, simply provide multiple profile names to the -`setActiveProfiles()` method, which accepts `String...` varargs: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - ctx.getEnvironment().setActiveProfiles("profile1", "profile2"); ----- - -Declaratively, `spring.profiles.active` may accept a comma-separated list of profile names: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - -Dspring.profiles.active="profile1,profile2" ----- - -[[beans-definition-profiles-default]] -===== Default profile - -The _default_ profile represents the profile that is enabled by default. Consider the -following: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Configuration - **@Profile("default")** - public class DefaultDataConfig { - - @Bean - public DataSource dataSource() { - return new EmbeddedDatabaseBuilder() - .setType(EmbeddedDatabaseType.HSQL) - .addScript("classpath:com/bank/config/sql/schema.sql") - .build(); - } - } ----- - -If no profile is active, the `dataSource` above will be created; this can be -seen as a way to provide a _default_ definition for one or more beans. If any -profile is enabled, the _default_ profile will not apply. - -The name of that default profile can be changed using `setDefaultProfiles` on -the `Environment` or declaratively using the `spring.profiles.default` property. - -[[beans-property-source-abstraction]] -==== PropertySource Abstraction - -Spring's Environment abstraction provides search operations over a configurable -hierarchy of property sources. To explain fully, consider the following: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- -ApplicationContext ctx = new GenericApplicationContext(); -Environment env = ctx.getEnvironment(); -boolean containsFoo = env.containsProperty("foo"); -System.out.println("Does my environment contain the 'foo' property? " + containsFoo); ----- - -In the snippet above, we see a high-level way of asking Spring whether the `foo` property is -defined for the current environment. To answer this question, the `Environment` object performs -a search over a set of {javadoc-baseurl}/org/springframework/core/env/PropertySource.html[`PropertySource`] -objects. A `PropertySource` is a simple abstraction over any source of key-value pairs, and -Spring's {javadoc-baseurl}/org/springframework/core/env/StandardEnvironment.html[`StandardEnvironment`] -is configured with two PropertySource objects -- one representing the set of JVM system properties -(_a la_ `System.getProperties()`) and one representing the set of system environment variables -(_a la_ `System.getenv()`). - -[NOTE] -==== -These default property sources are present for `StandardEnvironment`, for use in standalone -applications. {javadoc-baseurl}/org/springframework/web/context/support/StandardServletEnvironment.html[`StandardServletEnvironment`] -is populated with additional default property sources including servlet config and servlet -context parameters. {javadoc-baseurl}/org/springframework/web/portlet/context/StandardPortletEnvironment.html[`StandardPortletEnvironment`] -similarly has access to portlet config and portlet context parameters as property sources. -Both can optionally enable a {javadoc-baseurl}/org/springframework/jndi/JndiPropertySource.html[`JndiPropertySource`]. -See Javadoc for details. -==== - -Concretely, when using the `StandardEnvironment`, the call to `env.containsProperty("foo")` -will return true if a `foo` system property or `foo` environment variable is present at -runtime. - -[TIP] -==== -The search performed is hierarchical. By default, system properties have precedence over -environment variables, so if the `foo` property happens to be set in both places during -a call to `env.getProperty("foo")`, the system property value will 'win' and be returned -preferentially over the environment variable. -==== - -Most importantly, the entire mechanism is configurable. Perhaps you have a custom source -of properties that you'd like to integrate into this search. No problem -- simply implement -and instantiate your own `PropertySource` and add it to the set of `PropertySources` for the -current `Environment`: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- -ConfigurableApplicationContext ctx = new GenericApplicationContext(); -MutablePropertySources sources = ctx.getEnvironment().getPropertySources(); -sources.addFirst(new MyPropertySource()); ----- - -In the code above, `MyPropertySource` has been added with highest precedence in the -search. If it contains a `foo` property, it will be detected and returned ahead of -any `foo` property in any other `PropertySource`. The -{javadoc-baseurl}/org/springframework/core/env/MutablePropertySources.html[`MutablePropertySources`] -API exposes a number of methods that allow for precise manipulation of the set of -property sources. - -==== @PropertySource - -The {javadoc-baseurl}/org/springframework/context/annotation/PropertySource.html[`@PropertySource`] -annotation provides a convenient and declarative mechanism for adding a `PropertySource` -to Spring's `Environment`. - -Given a file "app.properties" containing the key/value pair `testbean.name=myTestBean`, -the following `@Configuration` class uses `@PropertySource` in such a way that -a call to `testBean.getName()` will return "myTestBean". - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Configuration - **@PropertySource("classpath:/com/myco/app.properties")** - public class AppConfig { - @Autowired - Environment env; - - @Bean - public TestBean testBean() { - TestBean testBean = new TestBean(); - testBean.setName(env.getProperty("testbean.name")); - return testBean; - } - } ----- - -Any `${...}` placeholders present in a `@PropertySource` resource location will -be resolved against the set of property sources already registered against the -environment. For example: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Configuration - @PropertySource("classpath:/com/${my.placeholder:default/path}/app.properties") - public class AppConfig { - @Autowired - Environment env; - - @Bean - public TestBean testBean() { - TestBean testBean = new TestBean(); - testBean.setName(env.getProperty("testbean.name")); - return testBean; - } - } ----- - -Assuming that "my.placeholder" is present in one of the property sources already -registered, e.g. system properties or environment variables, the placeholder will -be resolved to the corresponding value. If not, then "default/path" will be used -as a default. If no default is specified and a property cannot be resolved, an -`IllegalArgumentException` will be thrown. - - -==== Placeholder resolution in statements - -Historically, the value of placeholders in elements could be resolved only against -JVM system properties or environment variables. No longer is this the case. Because -the Environment abstraction is integrated throughout the container, it's easy to -route resolution of placeholders through it. This means that you may configure the -resolution process in any way you like: change the precedence of searching through -system properties and environment variables, or remove them entirely; add your -own property sources to the mix as appropriate. - -Concretely, the following statement works regardless of where the `customer` -property is defined, as long as it is available in the `Environment`: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - ----- - - -[[context-load-time-weaver]] -=== Registering a LoadTimeWeaver - -The `LoadTimeWeaver` is used by Spring to dynamically transform classes as they are -loaded into the Java virtual machine (JVM). - -To enable load-time weaving add the `@EnableLoadTimeWeaving` to one of your -`@Configuration` classes: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Configuration - @EnableLoadTimeWeaving - public class AppConfig { - - } ----- - -Alternatively for XML configuration use the `context:load-time-weaver` element: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - ----- - -Once configured for the `ApplicationContext`. Any bean within that `ApplicationContext` -may implement `LoadTimeWeaverAware`, thereby receiving a reference to the load-time -weaver instance. This is particularly useful in combination with <> where load-time weaving may be necessary for JPA class transformation. Consult -the `LocalContainerEntityManagerFactoryBean` javadocs for more detail. For more on -AspectJ load-time weaving, see <>. - - - - -[[context-introduction]] -=== Additional Capabilities of the ApplicationContext - -As was discussed in the chapter introduction, the `org.springframework.beans.factory` -package provides basic functionality for managing and manipulating beans, including in a -programmatic way. The `org.springframework.context` package adds the -{javadoc-baseurl}/org/springframework/context/ApplicationContext.html[`ApplicationContext`] -interface, which extends the `BeanFactory` interface, in addition to extending other -interfaces to provide additional functionality in a more __application -framework-oriented style__. Many people use the `ApplicationContext` in a completely -declarative fashion, not even creating it programmatically, but instead relying on -support classes such as `ContextLoader` to automatically instantiate an -`ApplicationContext` as part of the normal startup process of a Java EE web application. - -To enhance `BeanFactory` functionality in a more framework-oriented style the context -package also provides the following functionality: - -* __Access to messages in i18n-style__, through the `MessageSource` interface. -* __Access to resources__, such as URLs and files, through the `ResourceLoader` interface. -* __Event publication__ to beans implementing the `ApplicationListener` interface, - through the use of the `ApplicationEventPublisher` interface. -* __Loading of multiple (hierarchical) contexts__, allowing each to be focused on one - particular layer, such as the web layer of an application, through the - `HierarchicalBeanFactory` interface. - - - -[[context-functionality-messagesource]] -==== Internationalization using MessageSource - -The `ApplicationContext` interface extends an interface called `MessageSource`, and -therefore provides internationalization (i18n) functionality. Spring also provides the -interface `HierarchicalMessageSource`, which can resolve messages hierarchically. -Together these interfaces provide the foundation upon which Spring effects message -resolution. The methods defined on these interfaces include: - -* `String getMessage(String code, Object[] args, String default, Locale loc)`: The basic - method used to retrieve a message from the `MessageSource`. When no message is found - for the specified locale, the default message is used. Any arguments passed in become - replacement values, using the `MessageFormat` functionality provided by the standard - library. -* `String getMessage(String code, Object[] args, Locale loc)`: Essentially the same as - the previous method, but with one difference: no default message can be specified; if - the message cannot be found, a `NoSuchMessageException` is thrown. -* `String getMessage(MessageSourceResolvable resolvable, Locale locale)`: All properties - used in the preceding methods are also wrapped in a class named - `MessageSourceResolvable`, which you can use with this method. - -When an `ApplicationContext` is loaded, it automatically searches for a `MessageSource` -bean defined in the context. The bean must have the name `messageSource`. If such a bean -is found, all calls to the preceding methods are delegated to the message source. If no -message source is found, the `ApplicationContext` attempts to find a parent containing a -bean with the same name. If it does, it uses that bean as the `MessageSource`. If the -`ApplicationContext` cannot find any source for messages, an empty -`DelegatingMessageSource` is instantiated in order to be able to accept calls to the -methods defined above. - -Spring provides two `MessageSource` implementations, `ResourceBundleMessageSource` and -`StaticMessageSource`. Both implement `HierarchicalMessageSource` in order to do nested -messaging. The `StaticMessageSource` is rarely used but provides programmatic ways to -add messages to the source. The `ResourceBundleMessageSource` is shown in the following -example: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - format - exceptions - windows - - - - ----- - -In the example it is assumed you have three resource bundles defined in your classpath -called `format`, `exceptions` and `windows`. Any request to resolve a message will be -handled in the JDK standard way of resolving messages through ResourceBundles. For the -purposes of the example, assume the contents of two of the above resource bundle files -are... - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - # in format.properties - message=Alligators rock! ----- - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - # in exceptions.properties - argument.required=The '{0}' argument is required. ----- - -A program to execute the `MessageSource` functionality is shown in the next example. -Remember that all `ApplicationContext` implementations are also `MessageSource` -implementations and so can be cast to the `MessageSource` interface. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public static void main(String[] args) { - MessageSource resources = new ClassPathXmlApplicationContext("beans.xml"); - String message = resources.getMessage("message", null, "Default", null); - System.out.println(message); - } ----- - -The resulting output from the above program will be... - -[literal] -[subs="verbatim,quotes"] ----- -Alligators rock! ----- - -So to summarize, the `MessageSource` is defined in a file called `beans.xml`, which -exists at the root of your classpath. The `messageSource` bean definition refers to a -number of resource bundles through its `basenames` property. The three files that are -passed in the list to the `basenames` property exist as files at the root of your -classpath and are called `format.properties`, `exceptions.properties`, and -`windows.properties` respectively. - -The next example shows arguments passed to the message lookup; these arguments will be -converted into Strings and inserted into placeholders in the lookup message. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - - - - - - ----- - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class Example { - - private MessageSource messages; - - public void setMessages(MessageSource messages) { - this.messages = messages; - } - - public void execute() { - String message = this.messages.getMessage("argument.required", - new Object [] {"userDao"}, "Required", null); - System.out.println(message); - } - - } ----- - -The resulting output from the invocation of the `execute()` method will be... - -[literal] -[subs="verbatim,quotes"] ----- -The userDao argument is required. ----- - -With regard to internationalization (i18n), Spring's various `MessageResource` -implementations follow the same locale resolution and fallback rules as the standard JDK -`ResourceBundle`. In short, and continuing with the example `messageSource` defined -previously, if you want to resolve messages against the British (`en-GB`) locale, you -would create files called `format_en_GB.properties`, `exceptions_en_GB.properties`, and -`windows_en_GB.properties` respectively. - -Typically, locale resolution is managed by the surrounding environment of the -application. In this example, the locale against which (British) messages will be -resolved is specified manually. - -[literal] -[subs="verbatim,quotes"] ----- -# in exceptions_en_GB.properties -argument.required=Ebagum lad, the '{0}' argument is required, I say, required. ----- - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public static void main(final String[] args) { - MessageSource resources = new ClassPathXmlApplicationContext("beans.xml"); - String message = resources.getMessage("argument.required", - new Object [] {"userDao"}, "Required", Locale.UK); - System.out.println(message); - } ----- - -The resulting output from the running of the above program will be... - -[literal] -[subs="verbatim,quotes"] ----- -Ebagum lad, the 'userDao' argument is required, I say, required. ----- - -You can also use the `MessageSourceAware` interface to acquire a reference to any -`MessageSource` that has been defined. Any bean that is defined in an -`ApplicationContext` that implements the `MessageSourceAware` interface is injected with -the application context's `MessageSource` when the bean is created and configured. - -[NOTE] -==== -__As an alternative to `ResourceBundleMessageSource`, Spring provides a -`ReloadableResourceBundleMessageSource` class. This variant supports the same bundle -file format but is more flexible than the standard JDK based -`ResourceBundleMessageSource` implementation.__ In particular, it allows for reading -files from any Spring resource location (not just from the classpath) and supports hot -reloading of bundle property files (while efficiently caching them in between). Check -out the `ReloadableResourceBundleMessageSource` javadocs for details. -==== - - - -[[context-functionality-events]] -==== Standard and Custom Events -Event handling in the `ApplicationContext` is provided through the `ApplicationEvent` -class and `ApplicationListener` interface. If a bean that implements the -`ApplicationListener` interface is deployed into the context, every time an -`ApplicationEvent` gets published to the `ApplicationContext`, that bean is notified. -Essentially, this is the standard __Observer__ design pattern. Spring provides the -following standard events: - -[[beans-ctx-events-tbl]] -.Built-in Events -|=== -| Event| Explanation - -| `ContextRefreshedEvent` -| Published when the `ApplicationContext` is initialized or refreshed, for example, - using the `refresh()` method on the `ConfigurableApplicationContext` interface. - "Initialized" here means that all beans are loaded, post-processor beans are detected - and activated, singletons are pre-instantiated, and the `ApplicationContext` object is - ready for use. As long as the context has not been closed, a refresh can be triggered - multiple times, provided that the chosen `ApplicationContext` actually supports such - "hot" refreshes. For example, `XmlWebApplicationContext` supports hot refreshes, but - `GenericApplicationContext` does not. - -| `ContextStartedEvent` -| Published when the `ApplicationContext` is started, using the `start()` method on the - `ConfigurableApplicationContext` interface. "Started" here means that all `Lifecycle` - beans receive an explicit start signal. Typically this signal is used to restart beans - after an explicit stop, but it may also be used to start components that have not been - configured for autostart , for example, components that have not already started on - initialization. - -| `ContextStoppedEvent` -| Published when the `ApplicationContext` is stopped, using the `stop()` method on the - `ConfigurableApplicationContext` interface. "Stopped" here means that all `Lifecycle` - beans receive an explicit stop signal. A stopped context may be restarted through a - `start()` call. - -| `ContextClosedEvent` -| Published when the `ApplicationContext` is closed, using the `close()` method on the - `ConfigurableApplicationContext` interface. "Closed" here means that all singleton - beans are destroyed. A closed context reaches its end of life; it cannot be refreshed - or restarted. - -| `RequestHandledEvent` -| A web-specific event telling all beans that an HTTP request has been serviced. This - event is published __after__ the request is complete. This event is only applicable to - web applications using Spring's `DispatcherServlet`. -|=== - -You can also create and publish your own custom events. This example demonstrates a -simple class that extends Spring's `ApplicationEvent` base class: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class BlackListEvent extends ApplicationEvent { - - private final String address; - private final String test; - - public BlackListEvent(Object source, String address, String test) { - super(source); - this.address = address; - this.test = test; - } - - // accessor and other methods... - - } ----- - -To publish a custom `ApplicationEvent`, call the `publishEvent()` method on an -`ApplicationEventPublisher`. Typically this is done by creating a class that implements -`ApplicationEventPublisherAware` and registering it as a Spring bean. The following -example demonstrates such a class: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class EmailService implements ApplicationEventPublisherAware { - - private List blackList; - private ApplicationEventPublisher publisher; - - public void setBlackList(List blackList) { - this.blackList = blackList; - } - - public void setApplicationEventPublisher(ApplicationEventPublisher publisher) { - this.publisher = publisher; - } - - public void sendEmail(String address, String text) { - if (blackList.contains(address)) { - BlackListEvent event = new BlackListEvent(this, address, text); - publisher.publishEvent(event); - return; - } - // send email... - } - - } ----- - -At configuration time, the Spring container will detect that `EmailService` implements -`ApplicationEventPublisherAware` and will automatically call -`setApplicationEventPublisher()`. In reality, the parameter passed in will be the Spring -container itself; you're simply interacting with the application context via its -`ApplicationEventPublisher` interface. - -To receive the custom `ApplicationEvent`, create a class that implements -`ApplicationListener` and register it as a Spring bean. The following example -demonstrates such a class: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class BlackListNotifier implements ApplicationListener { - - private String notificationAddress; - - public void setNotificationAddress(String notificationAddress) { - this.notificationAddress = notificationAddress; - } - - public void onApplicationEvent(BlackListEvent event) { - // notify appropriate parties via notificationAddress... - } - - } ----- - -Notice that `ApplicationListener` is generically parameterized with the type of your -custom event, `BlackListEvent`. This means that the `onApplicationEvent()` method can -remain type-safe, avoiding any need for downcasting. You may register as many event -listeners as you wish, but note that by default event listeners receive events -synchronously. This means the `publishEvent()` method blocks until all listeners have -finished processing the event. One advantage of this synchronous and single-threaded -approach is that when a listener receives an event, it operates inside the transaction -context of the publisher if a transaction context is available. If another strategy for -event publication becomes necessary, refer to the JavaDoc for Spring's -`ApplicationEventMulticaster` interface. - -The following example shows the bean definitions used to register and configure each of -the classes above: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - known.spammer@example.org - known.hacker@example.org - john.doe@example.org - - - - - - - ----- - -Putting it all together, when the `sendEmail()` method of the `emailService` bean is -called, if there are any emails that should be blacklisted, a custom event of type -`BlackListEvent` is published. The `blackListNotifier` bean is registered as an -`ApplicationListener` and thus receives the `BlackListEvent`, at which point it can -notify appropriate parties. - -[NOTE] -==== -Spring's eventing mechanism is designed for simple communication between Spring beans -within the same application context. However, for more sophisticated enterprise -integration needs, the separately-maintained -http://projects.spring.io/spring-integration/[Spring Integration] project provides -complete support for building lightweight, -http://www.enterpriseintegrationpatterns.com[pattern-oriented], event-driven -architectures that build upon the well-known Spring programming model. -==== - - - -[[context-functionality-resources]] -==== Convenient access to low-level resources -For optimal usage and understanding of application contexts, users should generally -familiarize themselves with Spring's `Resource` abstraction, as described in the chapter -<>. - -An application context is a `ResourceLoader`, which can be used to load ++Resource++s. A -`Resource` is essentially a more feature rich version of the JDK class `java.net.URL`, -in fact, the implementations of the `Resource` wrap an instance of `java.net.URL` where -appropriate. A `Resource` can obtain low-level resources from almost any location in a -transparent fashion, including from the classpath, a filesystem location, anywhere -describable with a standard URL, and some other variations. If the resource location -string is a simple path without any special prefixes, where those resources come from is -specific and appropriate to the actual application context type. - -You can configure a bean deployed into the application context to implement the special -callback interface, `ResourceLoaderAware`, to be automatically called back at -initialization time with the application context itself passed in as the -`ResourceLoader`. You can also expose properties of type `Resource`, to be used to -access static resources; they will be injected into it like any other properties. You -can specify those `Resource` properties as simple String paths, and rely on a special -JavaBean `PropertyEditor` that is automatically registered by the context, to convert -those text strings to actual `Resource` objects when the bean is deployed. - -The location path or paths supplied to an `ApplicationContext` constructor are actually -resource strings, and in simple form are treated appropriately to the specific context -implementation. `ClassPathXmlApplicationContext` treats a simple location path as a -classpath location. You can also use location paths (resource strings) with special -prefixes to force loading of definitions from the classpath or a URL, regardless of the -actual context type. - - - -[[context-create]] -==== Convenient ApplicationContext instantiation for web applications - -You can create `ApplicationContext` instances declaratively by using, for example, a -`ContextLoader`. Of course you can also create `ApplicationContext` instances -programmatically by using one of the `ApplicationContext` implementations. - -You can register an `ApplicationContext` using the `ContextLoaderListener` as follows: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - contextConfigLocation - /WEB-INF/daoContext.xml /WEB-INF/applicationContext.xml - - - - org.springframework.web.context.ContextLoaderListener - - - ----- - -The listener inspects the `contextConfigLocation` parameter. If the parameter does not -exist, the listener uses `/WEB-INF/applicationContext.xml` as a default. When the -parameter __does__ exist, the listener separates the String by using predefined -delimiters (comma, semicolon and whitespace) and uses the values as locations where -application contexts will be searched. Ant-style path patterns are supported as well. -Examples are `/WEB-INF/*Context.xml` for all files with names ending with "Context.xml", -residing in the "WEB-INF" directory, and `/WEB-INF/**/*Context.xml`, for all such files -in any subdirectory of "WEB-INF". - -You can use `ContextLoaderServlet` instead of `ContextLoaderListener`. The Servlet uses -the `contextConfigLocation` parameter just as the listener does. - - - -[[context-deploy-rar]] -==== Deploying a Spring ApplicationContext as a Java EE RAR file -It is possible to deploy a Spring ApplicationContext as a RAR file, encapsulating the -context and all of its required bean classes and library JARs in a Java EE RAR deployment -unit. This is the equivalent of bootstrapping a standalone ApplicationContext, just hosted -in Java EE environment, being able to access the Java EE servers facilities. RAR deployment -is more natural alternative to scenario of deploying a headless WAR file, in effect, a WAR -file without any HTTP entry points that is used only for bootstrapping a Spring -ApplicationContext in a Java EE environment. - -RAR deployment is ideal for application contexts that do not need HTTP entry points but -rather consist only of message endpoints and scheduled jobs. Beans in such a context can -use application server resources such as the JTA transaction manager and JNDI-bound JDBC -DataSources and JMS ConnectionFactory instances, and may also register with the -platform's JMX server - all through Spring's standard transaction management and JNDI -and JMX support facilities. Application components can also interact with the -application server's JCA WorkManager through Spring's `TaskExecutor` abstraction. - -Check out the JavaDoc of the -{javadoc-baseurl}/org/springframework/jca/context/SpringContextResourceAdapter.html[`SpringContextResourceAdapter`] -class for the configuration details involved in RAR deployment. - -__For a simple deployment of a Spring ApplicationContext as a Java EE RAR file:__ package -all application classes into a RAR file, which is a standard JAR file with a different -file extension. Add all required library JARs into the root of the RAR archive. Add a -"META-INF/ra.xml" deployment descriptor (as shown in ++SpringContextResourceAdapter++'s -JavaDoc) and the corresponding Spring XML bean definition file(s) (typically -"META-INF/applicationContext.xml"), and drop the resulting RAR file into your -application server's deployment directory. - -[NOTE] -==== -Such RAR deployment units are usually self-contained; they do not expose components to -the outside world, not even to other modules of the same application. Interaction with a -RAR-based ApplicationContext usually occurs through JMS destinations that it shares with -other modules. A RAR-based ApplicationContext may also, for example, schedule some jobs, -reacting to new files in the file system (or the like). If it needs to allow synchronous -access from the outside, it could for example export RMI endpoints, which of course may -be used by other application modules on the same machine. -==== - - - - -[[beans-beanfactory]] -=== The BeanFactory -The `BeanFactory` provides the underlying basis for Spring's IoC functionality but it is -only used directly in integration with other third-party frameworks and is now largely -historical in nature for most users of Spring. The `BeanFactory` and related interfaces, -such as `BeanFactoryAware`, `InitializingBean`, `DisposableBean`, are still present in -Spring for the purposes of backward compatibility with the large number of third-party -frameworks that integrate with Spring. Often third-party components that can not use -more modern equivalents such as `@PostConstruct` or `@PreDestroy` in order to remain -compatible with JDK 1.4 or to avoid a dependency on JSR-250. - -This section provides additional background into the differences between the -`BeanFactory` and `ApplicationContext` and how one might access the IoC container -directly through a classic singleton lookup. - - - -[[context-introduction-ctx-vs-beanfactory]] -==== BeanFactory or ApplicationContext? - -Use an `ApplicationContext` unless you have a good reason for not doing so. - -Because the `ApplicationContext` includes all functionality of the `BeanFactory`, it is -generally recommended over the `BeanFactory`, except for a few situations such as in an -`Applet` where memory consumption might be critical and a few extra kilobytes might make -a difference. However, for most typical enterprise applications and systems, the -`ApplicationContext` is what you will want to use. Spring makes __heavy__ -use of the <> (to -effect proxying and so on). If you use only a plain `BeanFactory`, a fair amount of -support such as transactions and AOP will not take effect, at least not without some -extra steps on your part. This situation could be confusing because nothing is actually -wrong with the configuration. - -The following table lists features provided by the `BeanFactory` and -`ApplicationContext` interfaces and implementations. - -[[context-introduction-ctx-vs-beanfactory-feature-matrix]] -.Feature Matrix -|=== -| Feature| `BeanFactory`| `ApplicationContext` - -| Bean instantiation/wiring -| Yes -| Yes - -| Automatic `BeanPostProcessor` registration -| No -| Yes - -| Automatic `BeanFactoryPostProcessor` registration -| No -| Yes - -| Convenient `MessageSource` access (for i18n) -| No -| Yes - -| `ApplicationEvent` publication -| No -| Yes -|=== - -To explicitly register a bean post-processor with a `BeanFactory` implementation, you -must write code like this: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - ConfigurableBeanFactory factory = new XmlBeanFactory(...); - - // now register any needed BeanPostProcessor instances - MyBeanPostProcessor postProcessor = new MyBeanPostProcessor(); - factory.addBeanPostProcessor(postProcessor); - - // now start using the factory ----- - -To explicitly register a `BeanFactoryPostProcessor` when using a `BeanFactory` -implementation, you must write code like this: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - XmlBeanFactory factory = new XmlBeanFactory(new FileSystemResource("beans.xml")); - - // bring in some property values from a Properties file - PropertyPlaceholderConfigurer cfg = new PropertyPlaceholderConfigurer(); - cfg.setLocation(new FileSystemResource("jdbc.properties")); - - // now actually do the replacement - cfg.postProcessBeanFactory(factory); ----- - -In both cases, the explicit registration step is inconvenient, which is one reason why -the various `ApplicationContext` implementations are preferred above plain `BeanFactory` -implementations in the vast majority of Spring-backed applications, especially when -using `BeanFactoryPostProcessors` and `BeanPostProcessors`. These mechanisms implement -important functionality such as property placeholder replacement and AOP. - - - -[[beans-servicelocator]] -==== Glue code and the evil singleton -It is best to write most application code in a dependency-injection (DI) style, where -that code is served out of a Spring IoC container, has its own dependencies supplied by -the container when it is created, and is completely unaware of the container. However, -for the small glue layers of code that are sometimes needed to tie other code together, -you sometimes need a singleton (or quasi-singleton) style access to a Spring IoC -container. For example, third-party code may try to construct new objects directly ( -`Class.forName()` style), without the ability to get these objects out of a Spring IoC -container.If the object constructed by the third-party code is a small stub or proxy, -which then uses a singleton style access to a Spring IoC container to get a real object -to delegate to, then inversion of control has still been achieved for the majority of -the code (the object coming out of the container). Thus most code is still unaware of -the container or how it is accessed, and remains decoupled from other code, with all -ensuing benefits. EJBs may also use this stub/proxy approach to delegate to a plain Java -implementation object, retrieved from a Spring IoC container. While the Spring IoC -container itself ideally does not have to be a singleton, it may be unrealistic in terms -of memory usage or initialization times (when using beans in the Spring IoC container -such as a Hibernate `SessionFactory`) for each bean to use its own, non-singleton Spring -IoC container. - -Looking up the application context in a service locator style is sometimes the only -option for accessing shared Spring-managed components, such as in an EJB 2.1 -environment, or when you want to share a single ApplicationContext as a parent to -WebApplicationContexts across WAR files. In this case you should look into using the -utility class -{javadoc-baseurl}/org/springframework/context/access/ContextSingletonBeanFactoryLocator.html[`ContextSingletonBeanFactoryLocator`] -locator that is described in this -https://spring.io/blog/2007/06/11/using-a-shared-parent-application-context-in-a-multi-war-spring-application/[Spring -team blog entry]. - - - - - -[[resources]] -== Resources - - - - -[[resources-introduction]] -=== Introduction -Java's standard `java.net.URL` class and standard handlers for various URL prefixes -unfortunately are not quite adequate enough for all access to low-level resources. For -example, there is no standardized `URL` implementation that may be used to access a -resource that needs to be obtained from the classpath, or relative to a -`ServletContext`. While it is possible to register new handlers for specialized `URL` -prefixes (similar to existing handlers for prefixes such as `http:`), this is generally -quite complicated, and the `URL` interface still lacks some desirable functionality, -such as a method to check for the existence of the resource being pointed to. - - - - -[[resources-resource]] -=== The Resource interface - -Spring's `Resource` interface is meant to be a more capable interface for abstracting -access to low-level resources. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public interface Resource extends InputStreamSource { - - boolean exists(); - - boolean isOpen(); - - URL getURL() throws IOException; - - File getFile() throws IOException; - - Resource createRelative(String relativePath) throws IOException; - - String getFilename(); - - String getDescription(); - - } ----- - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public interface InputStreamSource { - - InputStream getInputStream() throws IOException; - - } ----- - -Some of the most important methods from the `Resource` interface are: - -* `getInputStream()`: locates and opens the resource, returning an `InputStream` for - reading from the resource. It is expected that each invocation returns a fresh - `InputStream`. It is the responsibility of the caller to close the stream. -* `exists()`: returns a `boolean` indicating whether this resource actually exists in - physical form. -* `isOpen()`: returns a `boolean` indicating whether this resource represents a handle - with an open stream. If `true`, the `InputStream` cannot be read multiple times, and - must be read once only and then closed to avoid resource leaks. Will be `false` for - all usual resource implementations, with the exception of `InputStreamResource`. -* `getDescription()`: returns a description for this resource, to be used for error - output when working with the resource. This is often the fully qualified file name or - the actual URL of the resource. - -Other methods allow you to obtain an actual `URL` or `File` object representing the -resource (if the underlying implementation is compatible, and supports that -functionality). - -The `Resource` abstraction is used extensively in Spring itself, as an argument type in -many method signatures when a resource is needed. Other methods in some Spring APIs -(such as the constructors to various `ApplicationContext` implementations), take a -`String` which in unadorned or simple form is used to create a `Resource` appropriate to -that context implementation, or via special prefixes on the `String` path, allow the -caller to specify that a specific `Resource` implementation must be created and used. - -While the `Resource` interface is used a lot with Spring and by Spring, it's actually -very useful to use as a general utility class by itself in your own code, for access to -resources, even when your code doesn't know or care about any other parts of Spring. -While this couples your code to Spring, it really only couples it to this small set of -utility classes, which are serving as a more capable replacement for `URL`, and can be -considered equivalent to any other library you would use for this purpose. - -It is important to note that the `Resource` abstraction does not replace functionality: -it wraps it where possible. For example, a `UrlResource` wraps a URL, and uses the -wrapped `URL` to do its work. - - - - -[[resources-implementations]] -=== Built-in Resource implementations - -There are a number of `Resource` implementations that come supplied straight out of the -box in Spring: - - - -[[resources-implementations-urlresource]] -==== UrlResource - -The `UrlResource` wraps a `java.net.URL`, and may be used to access any object that is -normally accessible via a URL, such as files, an HTTP target, an FTP target, etc. All -URLs have a standardized `String` representation, such that appropriate standardized -prefixes are used to indicate one URL type from another. This includes `file:` for -accessing filesystem paths, `http:` for accessing resources via the HTTP protocol, -`ftp:` for accessing resources via FTP, etc. - -A `UrlResource` is created by Java code explicitly using the `UrlResource` constructor, -but will often be created implicitly when you call an API method which takes a `String` -argument which is meant to represent a path. For the latter case, a JavaBeans -`PropertyEditor` will ultimately decide which type of `Resource` to create. If the path -string contains a few well-known (to it, that is) prefixes such as `classpath:`, it will -create an appropriate specialized `Resource` for that prefix. However, if it doesn't -recognize the prefix, it will assume the this is just a standard URL string, and will -create a `UrlResource`. - - - -[[resources-implementations-classpathresource]] -==== ClassPathResource - -This class represents a resource which should be obtained from the classpath. This uses -either the thread context class loader, a given class loader, or a given class for -loading resources. - -This `Resource` implementation supports resolution as `java.io.File` if the class path -resource resides in the file system, but not for classpath resources which reside in a -jar and have not been expanded (by the servlet engine, or whatever the environment is) -to the filesystem. To address this the various `Resource` implementations always support -resolution as a `java.net.URL`. - -A `ClassPathResource` is created by Java code explicitly using the `ClassPathResource` -constructor, but will often be created implicitly when you call an API method which -takes a `String` argument which is meant to represent a path. For the latter case, a -JavaBeans `PropertyEditor` will recognize the special prefix `classpath:` on the string -path, and create a `ClassPathResource` in that case. - - - -[[resources-implementations-filesystemresource]] -==== FileSystemResource - -This is a `Resource` implementation for `java.io.File` handles. It obviously supports -resolution as a `File`, and as a `URL`. - - - -[[resources-implementations-servletcontextresource]] -==== ServletContextResource - -This is a `Resource` implementation for `ServletContext` resources, interpreting -relative paths within the relevant web application's root directory. - -This always supports stream access and URL access, but only allows `java.io.File` access -when the web application archive is expanded and the resource is physically on the -filesystem. Whether or not it's expanded and on the filesystem like this, or accessed -directly from the JAR or somewhere else like a DB (it's conceivable) is actually -dependent on the Servlet container. - - - -[[resources-implementations-inputstreamresource]] -==== InputStreamResource - -A `Resource` implementation for a given `InputStream`. This should only be used if no -specific `Resource` implementation is applicable. In particular, prefer -`ByteArrayResource` or any of the file-based `Resource` implementations where possible. - -In contrast to other `Resource` implementations, this is a descriptor for an __already__ -opened resource - therefore returning `true` from `isOpen()`. Do not use it if you need -to keep the resource descriptor somewhere, or if you need to read a stream multiple -times. - - - -[[resources-implementations-bytearrayresource]] -==== ByteArrayResource - -This is a `Resource` implementation for a given byte array. It creates a -`ByteArrayInputStream` for the given byte array. - -It's useful for loading content from any given byte array, without having to resort to a -single-use `InputStreamResource`. - - - - -[[resources-resourceloader]] -=== The ResourceLoader - -The `ResourceLoader` interface is meant to be implemented by objects that can return -(i.e. load) `Resource` instances. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public interface ResourceLoader { - - Resource getResource(String location); - - } ----- - -All application contexts implement the `ResourceLoader` interface, and therefore all -application contexts may be used to obtain `Resource` instances. - -When you call `getResource()` on a specific application context, and the location path -specified doesn't have a specific prefix, you will get back a `Resource` type that is -appropriate to that particular application context. For example, assume the following -snippet of code was executed against a `ClassPathXmlApplicationContext` instance: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - Resource template = ctx.getResource("some/resource/path/myTemplate.txt"); ----- - -What would be returned would be a `ClassPathResource`; if the same method was executed -against a `FileSystemXmlApplicationContext` instance, you'd get back a -`FileSystemResource`. For a `WebApplicationContext`, you'd get back a -`ServletContextResource`, and so on. - -As such, you can load resources in a fashion appropriate to the particular application -context. - -On the other hand, you may also force `ClassPathResource` to be used, regardless of the -application context type, by specifying the special `classpath:` prefix: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - Resource template = ctx.getResource("classpath:some/resource/path/myTemplate.txt"); ----- - -Similarly, one can force a `UrlResource` to be used by specifying any of the standard -`java.net.URL` prefixes: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - Resource template = ctx.getResource("file:/some/resource/path/myTemplate.txt"); ----- - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - Resource template = ctx.getResource("http://myhost.com/resource/path/myTemplate.txt"); ----- - -The following table summarizes the strategy for converting ++String++s to ++Resource++s: - -[[resources-resource-strings]] -.Resource strings -|=== -| Prefix| Example| Explanation - -| classpath: -| `classpath:com/myapp/config.xml` -| Loaded from the classpath. - -| file: -| `file:/data/config.xml` -| Loaded as a `URL`, from the filesystem. footnote:[But see also - pass:specialcharacters,macros[<>].] - -| http: -| `http://myserver/logo.png` -| Loaded as a `URL`. - -| (none) -| `/data/config.xml` -| Depends on the underlying `ApplicationContext`. -|=== - - - - -[[resources-resourceloaderaware]] -=== The ResourceLoaderAware interface - -The `ResourceLoaderAware` interface is a special marker interface, identifying objects -that expect to be provided with a `ResourceLoader` reference. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public interface ResourceLoaderAware { - - void setResourceLoader(ResourceLoader resourceLoader); - } ----- - -When a class implements `ResourceLoaderAware` and is deployed into an application -context (as a Spring-managed bean), it is recognized as `ResourceLoaderAware` by the -application context. The application context will then invoke the -`setResourceLoader(ResourceLoader)`, supplying itself as the argument (remember, all -application contexts in Spring implement the `ResourceLoader` interface). - -Of course, since an `ApplicationContext` is a `ResourceLoader`, the bean could also -implement the `ApplicationContextAware` interface and use the supplied application -context directly to load resources, but in general, it's better to use the specialized -`ResourceLoader` interface if that's all that's needed. The code would just be coupled -to the resource loading interface, which can be considered a utility interface, and not -the whole Spring `ApplicationContext` interface. - -As of Spring 2.5, you can rely upon autowiring of the `ResourceLoader` as an alternative -to implementing the `ResourceLoaderAware` interface. The "traditional" `constructor` and -`byType` autowiring modes (as described in <>) are now capable -of providing a dependency of type `ResourceLoader` for either a constructor argument or -setter method parameter respectively. For more flexibility (including the ability to -autowire fields and multiple parameter methods), consider using the new annotation-based -autowiring features. In that case, the `ResourceLoader` will be autowired into a field, -constructor argument, or method parameter that is expecting the `ResourceLoader` type as -long as the field, constructor, or method in question carries the `@Autowired` -annotation. For more information, see <>. - - - - -[[resources-as-dependencies]] -=== Resources as dependencies - -If the bean itself is going to determine and supply the resource path through some sort -of dynamic process, it probably makes sense for the bean to use the `ResourceLoader` -interface to load resources. Consider as an example the loading of a template of some -sort, where the specific resource that is needed depends on the role of the user. If the -resources are static, it makes sense to eliminate the use of the `ResourceLoader` -interface completely, and just have the bean expose the `Resource` properties it needs, -and expect that they will be injected into it. - -What makes it trivial to then inject these properties, is that all application contexts -register and use a special JavaBeans `PropertyEditor` which can convert `String` paths -to `Resource` objects. So if `myBean` has a template property of type `Resource`, it can -be configured with a simple string for that resource, as follows: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - ----- - -Note that the resource path has no prefix, so because the application context itself is -going to be used as the `ResourceLoader`, the resource itself will be loaded via a -`ClassPathResource`, `FileSystemResource`, or `ServletContextResource` (as appropriate) -depending on the exact type of the context. - -If there is a need to force a specific `Resource` type to be used, then a prefix may be -used. The following two examples show how to force a `ClassPathResource` and a -`UrlResource` (the latter being used to access a filesystem file). - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - ----- - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - ----- - - - - -[[resources-app-ctx]] -=== Application contexts and Resource paths - - - -[[resources-app-ctx-construction]] -==== Constructing application contexts -An application context constructor (for a specific application context type) generally -takes a string or array of strings as the location path(s) of the resource(s) such as -XML files that make up the definition of the context. - -When such a location path doesn't have a prefix, the specific `Resource` type built from -that path and used to load the bean definitions, depends on and is appropriate to the -specific application context. For example, if you create a -`ClassPathXmlApplicationContext` as follows: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - ApplicationContext ctx = new ClassPathXmlApplicationContext("conf/appContext.xml"); ----- - -The bean definitions will be loaded from the classpath, as a `ClassPathResource` will be -used. But if you create a `FileSystemXmlApplicationContext` as follows: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - ApplicationContext ctx = - new FileSystemXmlApplicationContext("conf/appContext.xml"); ----- - -The bean definition will be loaded from a filesystem location, in this case relative to -the current working directory. - -Note that the use of the special classpath prefix or a standard URL prefix on the -location path will override the default type of `Resource` created to load the -definition. So this `FileSystemXmlApplicationContext`... - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - ApplicationContext ctx = - new FileSystemXmlApplicationContext("classpath:conf/appContext.xml"); ----- - -... will actually load its bean definitions from the classpath. However, it is still a -`FileSystemXmlApplicationContext`. If it is subsequently used as a `ResourceLoader`, any -unprefixed paths will still be treated as filesystem paths. - - -[[resources-app-ctx-classpathxml]] -===== Constructing ClassPathXmlApplicationContext instances - shortcuts - -The `ClassPathXmlApplicationContext` exposes a number of constructors to enable -convenient instantiation. The basic idea is that one supplies merely a string array -containing just the filenames of the XML files themselves (without the leading path -information), and one __also__ supplies a `Class`; the `ClassPathXmlApplicationContext` -will derive the path information from the supplied class. - -An example will hopefully make this clear. Consider a directory layout that looks like -this: - -[literal] -[subs="verbatim,quotes"] ----- -com/ - foo/ - services.xml - daos.xml - MessengerService.class ----- - -A `ClassPathXmlApplicationContext` instance composed of the beans defined in the -`'services.xml'` and `'daos.xml'` could be instantiated like so... - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - ApplicationContext ctx = new ClassPathXmlApplicationContext( - new String[] {"services.xml", "daos.xml"}, MessengerService.class); ----- - -Please do consult the `ClassPathXmlApplicationContext` javadocs for details -on the various constructors. - - - -[[resources-app-ctx-wildcards-in-resource-paths]] -==== Wildcards in application context constructor resource paths -The resource paths in application context constructor values may be a simple path (as -shown above) which has a one-to-one mapping to a target Resource, or alternately may -contain the special "classpath*:" prefix and/or internal Ant-style regular expressions -(matched using Spring's `PathMatcher` utility). Both of the latter are effectively -wildcards - -One use for this mechanism is when doing component-style application assembly. All -components can 'publish' context definition fragments to a well-known location path, and -when the final application context is created using the same path prefixed via -`classpath*:`, all component fragments will be picked up automatically. - -Note that this wildcarding is specific to use of resource paths in application context -constructors (or when using the `PathMatcher` utility class hierarchy directly), and is -resolved at construction time. It has nothing to do with the `Resource` type itself. -It's not possible to use the `classpath*:` prefix to construct an actual `Resource`, as -a resource points to just one resource at a time. - - -[[resources-app-ctx-ant-patterns-in-paths]] -===== Ant-style Patterns -When the path location contains an Ant-style pattern, for example: - -[literal] -[subs="verbatim,quotes"] ----- -/WEB-INF/*-context.xml - com/mycompany/**/applicationContext.xml - file:C:/some/path/*-context.xml - classpath:com/mycompany/**/applicationContext.xml ----- - -... the resolver follows a more complex but defined procedure to try to resolve the -wildcard. It produces a Resource for the path up to the last non-wildcard segment and -obtains a URL from it. If this URL is not a "jar:" URL or container-specific variant -(e.g. " `zip:`" in WebLogic, " `wsjar`" in WebSphere, etc.), then a `java.io.File` is -obtained from it and used to resolve the wildcard by traversing the filesystem. In the -case of a jar URL, the resolver either gets a `java.net.JarURLConnection` from it or -manually parses the jar URL and then traverses the contents of the jar file to resolve -the wildcards. - -[[resources-app-ctx-portability]] -====== Implications on portability -If the specified path is already a file URL (either explicitly, or implicitly because -the base `ResourceLoader` is a filesystem one, then wildcarding is guaranteed to work in -a completely portable fashion. - -If the specified path is a classpath location, then the resolver must obtain the last -non-wildcard path segment URL via a `Classloader.getResource()` call. Since this is just -a node of the path (not the file at the end) it is actually undefined (in the -`ClassLoader` javadocs) exactly what sort of a URL is returned in this case. In -practice, it is always a `java.io.File` representing the directory, where the classpath -resource resolves to a filesystem location, or a jar URL of some sort, where the -classpath resource resolves to a jar location. Still, there is a portability concern on -this operation. - -If a jar URL is obtained for the last non-wildcard segment, the resolver must be able to -get a `java.net.JarURLConnection` from it, or manually parse the jar URL, to be able to -walk the contents of the jar, and resolve the wildcard. This will work in most -environments, but will fail in others, and it is strongly recommended that the wildcard -resolution of resources coming from jars be thoroughly tested in your specific -environment before you rely on it. - - -[[resources-classpath-wildcards]] -===== The Classpath*: portability classpath*: prefix - -When constructing an XML-based application context, a location string may use the -special `classpath*:` prefix: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - ApplicationContext ctx = - new ClassPathXmlApplicationContext("classpath*:conf/appContext.xml"); ----- - -This special prefix specifies that all classpath resources that match the given name -must be obtained (internally, this essentially happens via a -`ClassLoader.getResources(...)` call), and then merged to form the final application -context definition. - -[NOTE] -==== -The wildcard classpath relies on the `getResources()` method of the underlying -classloader. As most application servers nowadays supply their own classloader -implementation, the behavior might differ especially when dealing with jar files. A -simple test to check if `classpath*` works is to use the classloader to load a file from -within a jar on the classpath: -`getClass().getClassLoader().getResources("")`. Try this test with -files that have the same name but are placed inside two different locations. In case an -inappropriate result is returned, check the application server documentation for -settings that might affect the classloader behavior. -==== - -The " `classpath*:`" prefix can also be combined with a `PathMatcher` pattern in the -rest of the location path, for example " `classpath*:META-INF/*-beans.xml`". In this -case, the resolution strategy is fairly simple: a ClassLoader.getResources() call is -used on the last non-wildcard path segment to get all the matching resources in the -class loader hierarchy, and then off each resource the same PathMatcher resolution -strategy described above is used for the wildcard subpath. - - -[[resources-wildcards-in-path-other-stuff]] -===== Other notes relating to wildcards -Please note that " `classpath*:`" when combined with Ant-style patterns will only work -reliably with at least one root directory before the pattern starts, unless the actual -target files reside in the file system. This means that a pattern like " -`classpath*:*.xml`" will not retrieve files from the root of jar files but rather only -from the root of expanded directories. This originates from a limitation in the JDK's -`ClassLoader.getResources()` method which only returns file system locations for a -passed-in empty string (indicating potential roots to search). - -Ant-style patterns with " `classpath:`" resources are not guaranteed to find matching -resources if the root package to search is available in multiple class path locations. -This is because a resource such as - -[literal] -[subs="verbatim,quotes"] ----- -com/mycompany/package1/service-context.xml ----- - -may be in only one location, but when a path such as - -[literal] -[subs="verbatim,quotes"] ----- -classpath:com/mycompany/**/service-context.xml ----- - -is used to try to resolve it, the resolver will work off the (first) URL returned by -`getResource("com/mycompany")`;. If this base package node exists in multiple -classloader locations, the actual end resource may not be underneath. Therefore, -preferably, use " `classpath*:`" with the same Ant-style pattern in such a case, which -will search all class path locations that contain the root package. - - - -[[resources-filesystemresource-caveats]] -==== FileSystemResource caveats - -A `FileSystemResource` that is not attached to a `FileSystemApplicationContext` (that -is, a `FileSystemApplicationContext` is not the actual `ResourceLoader`) will treat -absolute vs. relative paths as you would expect. Relative paths are relative to the -current working directory, while absolute paths are relative to the root of the -filesystem. - -For backwards compatibility (historical) reasons however, this changes when the -`FileSystemApplicationContext` is the `ResourceLoader`. The -`FileSystemApplicationContext` simply forces all attached `FileSystemResource` instances -to treat all location paths as relative, whether they start with a leading slash or not. -In practice, this means the following are equivalent: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - ApplicationContext ctx = - new FileSystemXmlApplicationContext("conf/context.xml"); ----- - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - ApplicationContext ctx = - new FileSystemXmlApplicationContext("/conf/context.xml"); ----- - -As are the following: (Even though it would make sense for them to be different, as one -case is relative and the other absolute.) - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - FileSystemXmlApplicationContext ctx = ...; - ctx.getResource("some/resource/path/myTemplate.txt"); ----- - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - FileSystemXmlApplicationContext ctx = ...; - ctx.getResource("/some/resource/path/myTemplate.txt"); ----- - -In practice, if true absolute filesystem paths are needed, it is better to forgo the use -of absolute paths with `FileSystemResource` / `FileSystemXmlApplicationContext`, and -just force the use of a `UrlResource`, by using the `file:` URL prefix. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - // actual context type doesn't matter, the Resource will always be UrlResource - ctx.getResource("file:/some/resource/path/myTemplate.txt"); ----- - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - // force this FileSystemXmlApplicationContext to load its definition via a UrlResource - ApplicationContext ctx = - new FileSystemXmlApplicationContext("file:/conf/context.xml"); ----- - - - - - -[[validation]] -== Validation, Data Binding, and Type Conversion - - - - -[[validation-introduction]] -=== Introduction - -.JSR-303/JSR-349 Bean Validation -**** -Spring Framework 4.0 supports Bean Validation 1.0 (JSR-303) and Bean Validation 1.1 -(JSR-349) in terms of setup support, also adapting it to Spring's `Validator` interface. - -An application can choose to enable Bean Validation once globally, as described in -<>, and use it exclusively for all validation needs. - -An application can also register additional Spring `Validator` instances per -`DataBinder` instance, as described in <>. This may be useful for -plugging in validation logic without the use of annotations. -**** - -There are pros and cons for considering validation as business logic, and Spring offers -a design for validation (and data binding) that does not exclude either one of them. -Specifically validation should not be tied to the web tier, should be easy to localize -and it should be possible to plug in any validator available. Considering the above, -Spring has come up with a `Validator` interface that is both basic ands eminently usable -in every layer of an application. - -Data binding is useful for allowing user input to be dynamically bound to the domain -model of an application (or whatever objects you use to process user input). Spring -provides the so-called `DataBinder` to do exactly that. The `Validator` and the -`DataBinder` make up the `validation` package, which is primarily used in but not -limited to the MVC framework. - -The `BeanWrapper` is a fundamental concept in the Spring Framework and is used in a lot -of places. However, you probably will not have the need to use the `BeanWrapper` -directly. Because this is reference documentation however, we felt that some explanation -might be in order. We will explain the `BeanWrapper` in this chapter since, if you were -going to use it at all, you would most likely do so when trying to bind data to objects. - -Spring's DataBinder and the lower-level BeanWrapper both use PropertyEditors to parse -and format property values. The `PropertyEditor` concept is part of the JavaBeans -specification, and is also explained in this chapter. Spring 3 introduces a -"core.convert" package that provides a general type conversion facility, as well as a -higher-level "format" package for formatting UI field values. These new packages may be -used as simpler alternatives to PropertyEditors, and will also be discussed in this -chapter. - - - - -[[validator]] -=== Validation using Spring's Validator interface - -Spring features a `Validator` interface that you can use to validate objects. The -`Validator` interface works using an `Errors` object so that while validating, -validators can report validation failures to the `Errors` object. - -Let's consider a small data object: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class Person { - - private String name; - private int age; - - // the usual getters and setters... - } ----- - -We're going to provide validation behavior for the `Person` class by implementing the -following two methods of the `org.springframework.validation.Validator` interface: - -* `supports(Class)` - Can this `Validator` validate instances of the supplied `Class`? -* `validate(Object, org.springframework.validation.Errors)` - validates the given object - and in case of validation errors, registers those with the given `Errors` object - -Implementing a `Validator` is fairly straightforward, especially when you know of the -`ValidationUtils` helper class that the Spring Framework also provides. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class PersonValidator implements Validator { - - /** - * This Validator validates *just* Person instances - */ - public boolean supports(Class clazz) { - return Person.class.equals(clazz); - } - - public void validate(Object obj, Errors e) { - ValidationUtils.rejectIfEmpty(e, "name", "name.empty"); - Person p = (Person) obj; - if (p.getAge() < 0) { - e.rejectValue("age", "negativevalue"); - } else if (p.getAge() > 110) { - e.rejectValue("age", "too.darn.old"); - } - } - } ----- - -As you can see, the `static` `rejectIfEmpty(..)` method on the `ValidationUtils` class -is used to reject the `'name'` property if it is `null` or the empty string. Have a look -at the `ValidationUtils` javadocs to see what functionality it provides besides the -example shown previously. - -While it is certainly possible to implement a single `Validator` class to validate each -of the nested objects in a rich object, it may be better to encapsulate the validation -logic for each nested class of object in its own `Validator` implementation. A simple -example of a __'rich'__ object would be a `Customer` that is composed of two `String` -properties (a first and second name) and a complex `Address` object. `Address` objects -may be used independently of `Customer` objects, and so a distinct `AddressValidator` -has been implemented. If you want your `CustomerValidator` to reuse the logic contained -within the `AddressValidator` class without resorting to copy-and-paste, you can -dependency-inject or instantiate an `AddressValidator` within your `CustomerValidator`, -and use it like so: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class CustomerValidator implements Validator { - - private final Validator addressValidator; - - public CustomerValidator(Validator addressValidator) { - if (addressValidator == null) { - throw new IllegalArgumentException("The supplied [Validator] is " + - "required and must not be null."); - } - if (!addressValidator.supports(Address.class)) { - throw new IllegalArgumentException("The supplied [Validator] must " + - support the validation of [Address] instances."); - } - this.addressValidator = addressValidator; - } - - /** - * This Validator validates Customer instances, and any subclasses of Customer too - */ - public boolean supports(Class clazz) { - return Customer.class.isAssignableFrom(clazz); - } - - public void validate(Object target, Errors errors) { - ValidationUtils.rejectIfEmptyOrWhitespace(errors, "firstName", "field.required"); - ValidationUtils.rejectIfEmptyOrWhitespace(errors, "surname", "field.required"); - Customer customer = (Customer) target; - try { - errors.pushNestedPath("address"); - ValidationUtils.invokeValidator(this.addressValidator, customer.getAddress(), errors); - } finally { - errors.popNestedPath(); - } - } - } ----- - -Validation errors are reported to the `Errors` object passed to the validator. In case -of Spring Web MVC you can use `` tag to inspect the error messages, but of -course you can also inspect the errors object yourself. More information about the -methods it offers can be found in the javadocs. - - - - -[[validation-conversion]] -=== Resolving codes to error messages -We've talked about databinding and validation. Outputting messages corresponding to -validation errors is the last thing we need to discuss. In the example we've shown -above, we rejected the `name` and the `age` field. If we're going to output the error -messages by using a `MessageSource`, we will do so using the error code we've given when -rejecting the field ('name' and 'age' in this case). When you call (either directly, or -indirectly, using for example the `ValidationUtils` class) `rejectValue` or one of the -other `reject` methods from the `Errors` interface, the underlying implementation will -not only register the code you've passed in, but also a number of additional error -codes. What error codes it registers is determined by the `MessageCodesResolver` that is -used. By default, the `DefaultMessageCodesResolver` is used, which for example not only -registers a message with the code you gave, but also messages that include the field -name you passed to the reject method. So in case you reject a field using -`rejectValue("age", "too.darn.old")`, apart from the `too.darn.old` code, Spring will -also register `too.darn.old.age` and `too.darn.old.age.int` (so the first will include -the field name and the second will include the type of the field); this is done as a -convenience to aid developers in targeting error messages and suchlike. - -More information on the `MessageCodesResolver` and the default strategy can be found -online in the javadocs of -{javadoc-baseurl}/org/springframework/validation/MessageCodesResolver.html[`MessageCodesResolver`] -and -{javadoc-baseurl}/org/springframework/validation/DefaultMessageCodesResolver.html[`DefaultMessageCodesResolver`], -respectively. - - - - -[[beans-beans]] -=== Bean manipulation and the BeanWrapper - -The `org.springframework.beans` package adheres to the JavaBeans standard provided by -Oracle. A JavaBean is simply a class with a default no-argument constructor, which follows -a naming convention where (by way of an example) a property named `bingoMadness` would -have a setter method `setBingoMadness(..)` and a getter method `getBingoMadness()`. For -more information about JavaBeans and the specification, please refer to Oracle's website ( -http://docs.oracle.com/javase/6/docs/api/java/beans/package-summary.html[javabeans]). - -One quite important class in the beans package is the `BeanWrapper` interface and its -corresponding implementation ( `BeanWrapperImpl`). As quoted from the javadocs, the -`BeanWrapper` offers functionality to set and get property values (individually or in -bulk), get property descriptors, and to query properties to determine if they are -readable or writable. Also, the `BeanWrapper` offers support for nested properties, -enabling the setting of properties on sub-properties to an unlimited depth. Then, the -`BeanWrapper` supports the ability to add standard JavaBeans `PropertyChangeListeners` -and `VetoableChangeListeners`, without the need for supporting code in the target class. -Last but not least, the `BeanWrapper` provides support for the setting of indexed -properties. The `BeanWrapper` usually isn't used by application code directly, but by -the `DataBinder` and the `BeanFactory`. - -The way the `BeanWrapper` works is partly indicated by its name: __it wraps a bean__ to -perform actions on that bean, like setting and retrieving properties. - - - -[[beans-beans-conventions]] -==== Setting and getting basic and nested properties -Setting and getting properties is done using the `setPropertyValue(s)` and -`getPropertyValue(s)` methods that both come with a couple of overloaded variants. -They're all described in more detail in the javadocs Spring comes with. What's important -to know is that there are a couple of conventions for indicating properties of an -object. A couple of examples: - -[[beans-beans-conventions-properties-tbl]] -.Examples of properties -|=== -| Expression| Explanation - -| `name` -| Indicates the property `name` corresponding to the methods `getName()` or `isName()` - and `setName(..)` - -| `account.name` -| Indicates the nested property `name` of the property `account` corresponding e.g. to - the methods `getAccount().setName()` or `getAccount().getName()` - -| `account[2]` -| Indicates the __third__ element of the indexed property `account`. Indexed properties - can be of type `array`, `list` or other __naturally ordered__ collection - -| `account[COMPANYNAME]` -| Indicates the value of the map entry indexed by the key __COMPANYNAME__ of the Map - property `account` -|=== - -Below you'll find some examples of working with the `BeanWrapper` to get and set -properties. - -__(This next section is not vitally important to you if you're not planning to work with -the `BeanWrapper` directly. If you're just using the `DataBinder` and the `BeanFactory` -and their out-of-the-box implementation, you should skip ahead to the section about -`PropertyEditors`.)__ - -Consider the following two classes: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class Company { - - private String name; - private Employee managingDirector; - - public String getName() { - return this.name; - } - - public void setName(String name) { - this.name = name; - } - - public Employee getManagingDirector() { - return this.managingDirector; - } - - public void setManagingDirector(Employee managingDirector) { - this.managingDirector = managingDirector; - } - } ----- - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class Employee { - - private String name; - - private float salary; - - public String getName() { - return this.name; - } - - public void setName(String name) { - this.name = name; - } - - public float getSalary() { - return salary; - } - - public void setSalary(float salary) { - this.salary = salary; - } - } ----- - -The following code snippets show some examples of how to retrieve and manipulate some of -the properties of instantiated `Companies` and `Employees`: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - BeanWrapper company = BeanWrapperImpl(new Company()); - // setting the company name.. - company.setPropertyValue("name", "Some Company Inc."); - // ... can also be done like this: - PropertyValue value = new PropertyValue("name", "Some Company Inc."); - company.setPropertyValue(value); - - // ok, let's create the director and tie it to the company: - BeanWrapper jim = BeanWrapperImpl(new Employee()); - jim.setPropertyValue("name", "Jim Stravinsky"); - company.setPropertyValue("managingDirector", jim.getWrappedInstance()); - - // retrieving the salary of the managingDirector through the company - Float salary = (Float) company.getPropertyValue("managingDirector.salary"); ----- - - - -[[beans-beans-conversion]] -==== Built-in PropertyEditor implementations - -Spring uses the concept of `PropertyEditors` to effect the conversion between an -`Object` and a `String`. If you think about it, it sometimes might be handy to be able -to represent properties in a different way than the object itself. For example, a `Date` -can be represented in a human readable way (as the `String` ' `2007-14-09`'), while -we're still able to convert the human readable form back to the original date (or even -better: convert any date entered in a human readable form, back to `Date` objects). This -behavior can be achieved by __registering custom editors__, of type -`java.beans.PropertyEditor`. Registering custom editors on a `BeanWrapper` or -alternately in a specific IoC container as mentioned in the previous chapter, gives it -the knowledge of how to convert properties to the desired type. Read more about -`PropertyEditors` in the javadocs of the `java.beans` package provided by Oracle. - -A couple of examples where property editing is used in Spring: - -* __setting properties on beans__ is done using `PropertyEditors`. When mentioning - `java.lang.String` as the value of a property of some bean you're declaring in XML - file, Spring will (if the setter of the corresponding property has a - `Class`-parameter) use the `ClassEditor` to try to resolve the parameter to a `Class` - object. -* __parsing HTTP request parameters__ in Spring's MVC framework is done using all kinds - of `PropertyEditors` that you can manually bind in all subclasses of the - `CommandController`. - -Spring has a number of built-in `PropertyEditors` to make life easy. Each of those is -listed below and they are all located in the `org.springframework.beans.propertyeditors` -package. Most, but not all (as indicated below), are registered by default by -`BeanWrapperImpl`. Where the property editor is configurable in some fashion, you can of -course still register your own variant to override the default one: - -[[beans-beans-property-editors-tbl]] -.Built-in PropertyEditors -|=== -| Class| Explanation - -| `ByteArrayPropertyEditor` -| Editor for byte arrays. Strings will simply be converted to their corresponding byte - representations. Registered by default by `BeanWrapperImpl`. - -| `ClassEditor` -| Parses Strings representing classes to actual classes and the other way around. When a - class is not found, an `IllegalArgumentException` is thrown. Registered by default by - `BeanWrapperImpl`. - -| `CustomBooleanEditor` -| Customizable property editor for `Boolean` properties. Registered by default by - `BeanWrapperImpl`, but, can be overridden by registering custom instance of it as - custom editor. - -| `CustomCollectionEditor` -| Property editor for Collections, converting any source `Collection` to a given target - `Collection` type. - -| `CustomDateEditor` -| Customizable property editor for java.util.Date, supporting a custom DateFormat. NOT - registered by default. Must be user registered as needed with appropriate format. - -| `CustomNumberEditor` -| Customizable property editor for any Number subclass like `Integer`, `Long`, `Float`, - `Double`. Registered by default by `BeanWrapperImpl`, but can be overridden by - registering custom instance of it as a custom editor. - -| `FileEditor` -| Capable of resolving Strings to `java.io.File` objects. Registered by default by - `BeanWrapperImpl`. - -| `InputStreamEditor` -| One-way property editor, capable of taking a text string and producing (via an - intermediate `ResourceEditor` and `Resource`) an `InputStream`, so `InputStream` - properties may be directly set as Strings. Note that the default usage will not close - the `InputStream` for you! Registered by default by `BeanWrapperImpl`. - -| `LocaleEditor` -| Capable of resolving Strings to `Locale` objects and vice versa (the String format is - [language]_[country]_[variant], which is the same thing the toString() method of - Locale provides). Registered by default by `BeanWrapperImpl`. - -| `PatternEditor` -| Capable of resolving Strings to `java.util.regex.Pattern` objects and vice versa. - -| `PropertiesEditor` -| Capable of converting Strings (formatted using the format as defined in the javadocs - of the `java.util.Properties` class) to `Properties` objects. Registered by default - by `BeanWrapperImpl`. - -| `StringTrimmerEditor` -| Property editor that trims Strings. Optionally allows transforming an empty string - into a `null` value. NOT registered by default; must be user registered as needed. - -| `URLEditor` -| Capable of resolving a String representation of a URL to an actual `URL` object. - Registered by default by `BeanWrapperImpl`. -|=== - -Spring uses the `java.beans.PropertyEditorManager` to set the search path for property -editors that might be needed. The search path also includes `sun.bean.editors`, which -includes `PropertyEditor` implementations for types such as `Font`, `Color`, and most of -the primitive types. Note also that the standard JavaBeans infrastructure will -automatically discover `PropertyEditor` classes (without you having to register them -explicitly) if they are in the same package as the class they handle, and have the same -name as that class, with `'Editor'` appended; for example, one could have the following -class and package structure, which would be sufficient for the `FooEditor` class to be -recognized and used as the `PropertyEditor` for `Foo`-typed properties. - -[literal] -[subs="verbatim,quotes"] ----- -com - chank - pop - Foo - FooEditor // the PropertyEditor for the Foo class ----- - -Note that you can also use the standard `BeanInfo` JavaBeans mechanism here as well -(described -http://docs.oracle.com/javase/tutorial/javabeans/advanced/customization.html[in -not-amazing-detail here]). Find below an example of using the `BeanInfo` mechanism for -explicitly registering one or more `PropertyEditor` instances with the properties of an -associated class. - -[literal] -[subs="verbatim,quotes"] ----- -com - chank - pop - Foo - FooBeanInfo // the BeanInfo for the Foo class ----- - -Here is the Java source code for the referenced `FooBeanInfo` class. This would -associate a `CustomNumberEditor` with the `age` property of the `Foo` class. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class FooBeanInfo extends SimpleBeanInfo { - - public PropertyDescriptor[] getPropertyDescriptors() { - try { - final PropertyEditor numberPE = new CustomNumberEditor(Integer.class, true); - PropertyDescriptor ageDescriptor = new PropertyDescriptor("age", Foo.class) { - public PropertyEditor createPropertyEditor(Object bean) { - return numberPE; - }; - }; - return new PropertyDescriptor[] { ageDescriptor }; - } - catch (IntrospectionException ex) { - throw new Error(ex.toString()); - } - } - } ----- - - -[[beans-beans-conversion-customeditor-registration]] -===== Registering additional custom PropertyEditors - -When setting bean properties as a string value, a Spring IoC container ultimately uses -standard JavaBeans `PropertyEditors` to convert these Strings to the complex type of the -property. Spring pre-registers a number of custom `PropertyEditors` (for example, to -convert a classname expressed as a string into a real `Class` object). Additionally, -Java's standard JavaBeans `PropertyEditor` lookup mechanism allows a `PropertyEditor` -for a class simply to be named appropriately and placed in the same package as the class -it provides support for, to be found automatically. - -If there is a need to register other custom `PropertyEditors`, there are several -mechanisms available. The most manual approach, which is not normally convenient or -recommended, is to simply use the `registerCustomEditor()` method of the -`ConfigurableBeanFactory` interface, assuming you have a `BeanFactory` reference. -Another, slightly more convenient, mechanism is to use a special bean factory -post-processor called `CustomEditorConfigurer`. Although bean factory post-processors -can be used with `BeanFactory` implementations, the `CustomEditorConfigurer` has a -nested property setup, so it is strongly recommended that it is used with the -`ApplicationContext`, where it may be deployed in similar fashion to any other bean, and -automatically detected and applied. - -Note that all bean factories and application contexts automatically use a number of -built-in property editors, through their use of something called a `BeanWrapper` to -handle property conversions. The standard property editors that the `BeanWrapper` -registers are listed in <>. Additionally, -`ApplicationContexts` also override or add an additional number of editors to handle -resource lookups in a manner appropriate to the specific application context type. - -Standard JavaBeans `PropertyEditor` instances are used to convert property values -expressed as strings to the actual complex type of the property. -`CustomEditorConfigurer`, a bean factory post-processor, may be used to conveniently add -support for additional `PropertyEditor` instances to an `ApplicationContext`. - -Consider a user class `ExoticType`, and another class `DependsOnExoticType` which needs -`ExoticType` set as a property: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - package example; - - public class ExoticType { - - private String name; - - public ExoticType(String name) { - this.name = name; - } - } - - public class DependsOnExoticType { - - private ExoticType type; - - public void setType(ExoticType type) { - this.type = type; - } - } ----- - -When things are properly set up, we want to be able to assign the type property as a -string, which a `PropertyEditor` will behind the scenes convert into an actual -`ExoticType` instance: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - ----- - -The `PropertyEditor` implementation could look similar to this: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - // converts string representation to ExoticType object - package example; - - public class ExoticTypeEditor extends PropertyEditorSupport { - - public void setAsText(String text) { - setValue(new ExoticType(text.toUpperCase())); - } - } ----- - -Finally, we use `CustomEditorConfigurer` to register the new `PropertyEditor` with the -`ApplicationContext`, which will then be able to use it as needed: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - ----- - -[[beans-beans-conversion-customeditor-registration-per]] -====== Using PropertyEditorRegistrars - -Another mechanism for registering property editors with the Spring container is to -create and use a `PropertyEditorRegistrar`. This interface is particularly useful when -you need to use the same set of property editors in several different situations: write -a corresponding registrar and reuse that in each case. `PropertyEditorRegistrars` work -in conjunction with an interface called `PropertyEditorRegistry`, an interface that is -implemented by the Spring `BeanWrapper` (and `DataBinder`). `PropertyEditorRegistrars` -are particularly convenient when used in conjunction with the `CustomEditorConfigurer` -(introduced <>), which exposes a -property called `setPropertyEditorRegistrars(..)`: `PropertyEditorRegistrars` added to a -`CustomEditorConfigurer` in this fashion can easily be shared with `DataBinder` and -Spring MVC `Controllers`. Furthermore, it avoids the need for synchronization on custom -editors: a `PropertyEditorRegistrar` is expected to create fresh `PropertyEditor` -instances for each bean creation attempt. - -Using a `PropertyEditorRegistrar` is perhaps best illustrated with an example. First -off, you need to create your own `PropertyEditorRegistrar` implementation: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - package com.foo.editors.spring; - - public final class CustomPropertyEditorRegistrar implements PropertyEditorRegistrar { - - public void registerCustomEditors(PropertyEditorRegistry registry) { - - // it is expected that new PropertyEditor instances are created - registry.registerCustomEditor(ExoticType.class, new ExoticTypeEditor()); - - // you could register as many custom property editors as are required here... - } - } ----- - -See also the `org.springframework.beans.support.ResourceEditorRegistrar` for an example -`PropertyEditorRegistrar` implementation. Notice how in its implementation of the -`registerCustomEditors(..)` method it creates new instances of each property editor. - -Next we configure a `CustomEditorConfigurer` and inject an instance of our -`CustomPropertyEditorRegistrar` into it: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - - ----- - -Finally, and in a bit of a departure from the focus of this chapter, for those of you -using <>, using `PropertyEditorRegistrars` in -conjunction with data-binding `Controllers` (such as `SimpleFormController`) can be very -convenient. Find below an example of using a `PropertyEditorRegistrar` in the -implementation of an `initBinder(..)` method: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public final class RegisterUserController extends SimpleFormController { - - private final PropertyEditorRegistrar customPropertyEditorRegistrar; - - public RegisterUserController(PropertyEditorRegistrar propertyEditorRegistrar) { - this.customPropertyEditorRegistrar = propertyEditorRegistrar; - } - - protected void initBinder(HttpServletRequest request, - ServletRequestDataBinder binder) throws Exception { - **this.customPropertyEditorRegistrar.registerCustomEditors(binder);** - } - - // other methods to do with registering a User - } ----- - -This style of `PropertyEditor` registration can lead to concise code (the implementation -of `initBinder(..)` is just one line long!), and allows common `PropertyEditor` -registration code to be encapsulated in a class and then shared amongst as many -`Controllers` as needed. - - - - -[[core-convert]] -=== Spring Type Conversion -Spring 3 introduces a `core.convert` package that provides a general type conversion -system. The system defines an SPI to implement type conversion logic, as well as an API -to execute type conversions at runtime. Within a Spring container, this system can be -used as an alternative to PropertyEditors to convert externalized bean property value -strings to required property types. The public API may also be used anywhere in your -application where type conversion is needed. - - - -[[core-convert-Converter-API]] -==== Converter SPI -The SPI to implement type conversion logic is simple and strongly typed: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - package org.springframework.core.convert.converter; - - public interface Converter { - - T convert(S source); - - } ----- - -To create your own converter, simply implement the interface above. Parameterize `S` -as the type you are converting from, and `T` as the type you are converting to. Such a -converter can also be applied transparently if a collection or array of `S` needs to be -converted to an array or collection of `T`, provided that a delegating array/collection -converter has been registered as well (which `DefaultConversionService` does by default). - -For each call to `convert(S)`, the source argument is guaranteed to be NOT null. Your -Converter may throw any unchecked exception if conversion fails; specifically, an -`IllegalArgumentException` should be thrown to report an invalid source value. -Take care to ensure that your `Converter` implementation is thread-safe. - -Several converter implementations are provided in the `core.convert.support` package as -a convenience. These include converters from Strings to Numbers and other common types. -Consider `StringToInteger` as an example for a typical `Converter` implementation: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - package org.springframework.core.convert.support; - - final class StringToInteger implements Converter { - - public Integer convert(String source) { - return Integer.valueOf(source); - } - - } ----- - - - -[[core-convert-ConverterFactory-SPI]] -==== ConverterFactory -When you need to centralize the conversion logic for an entire class hierarchy, for -example, when converting from String to java.lang.Enum objects, implement -`ConverterFactory`: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - package org.springframework.core.convert.converter; - - public interface ConverterFactory { - - Converter getConverter(Class targetType); - - } ----- - -Parameterize S to be the type you are converting from and R to be the base type defining -the __range__ of classes you can convert to. Then implement getConverter(Class), -where T is a subclass of R. - -Consider the `StringToEnum` ConverterFactory as an example: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - package org.springframework.core.convert.support; - - final class StringToEnumConverterFactory implements ConverterFactory { - - public Converter getConverter(Class targetType) { - return new StringToEnumConverter(targetType); - } - - private final class StringToEnumConverter implements Converter { - - private Class enumType; - - public StringToEnumConverter(Class enumType) { - this.enumType = enumType; - } - - public T convert(String source) { - return (T) Enum.valueOf(this.enumType, source.trim()); - } - } - } ----- - - - -[[core-convert-GenericConverter-SPI]] -==== GenericConverter -When you require a sophisticated Converter implementation, consider the GenericConverter -interface. With a more flexible but less strongly typed signature, a GenericConverter -supports converting between multiple source and target types. In addition, a -GenericConverter makes available source and target field context you can use when -implementing your conversion logic. Such context allows a type conversion to be driven -by a field annotation, or generic information declared on a field signature. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - package org.springframework.core.convert.converter; - - public interface GenericConverter { - - public Set getConvertibleTypes(); - - Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType); - - } ----- - -To implement a GenericConverter, have getConvertibleTypes() return the supported -source->target type pairs. Then implement convert(Object, TypeDescriptor, -TypeDescriptor) to implement your conversion logic. The source TypeDescriptor provides -access to the source field holding the value being converted. The target TypeDescriptor -provides access to the target field where the converted value will be set. - -A good example of a GenericConverter is a converter that converts between a Java Array -and a Collection. Such an ArrayToCollectionConverter introspects the field that declares -the target Collection type to resolve the Collection's element type. This allows each -element in the source array to be converted to the Collection element type before the -Collection is set on the target field. - -[NOTE] -==== -Because GenericConverter is a more complex SPI interface, only use it when you need it. -Favor Converter or ConverterFactory for basic type conversion needs. -==== - - -[[core-convert-ConditionalGenericConverter-SPI]] -===== ConditionalGenericConverter -Sometimes you only want a Converter to execute if a specific condition holds true. For -example, you might only want to execute a Converter if a specific annotation is present -on the target field. Or you might only want to execute a Converter if a specific method, -such as static valueOf method, is defined on the target class. -ConditionalGenericConverter is an subinterface of GenericConverter that allows you to -define such custom matching criteria: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public interface ConditionalGenericConverter extends GenericConverter { - - boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType); - - } ----- - -A good example of a ConditionalGenericConverter is an EntityConverter that converts -between an persistent entity identifier and an entity reference. Such a EntityConverter -might only match if the target entity type declares a static finder method e.g. -findAccount(Long). You would perform such a finder method check in the implementation of -matches(TypeDescriptor, TypeDescriptor). - - - -[[core-convert-ConversionService-API]] -==== ConversionService API -The ConversionService defines a unified API for executing type conversion logic at -runtime. Converters are often executed behind this facade interface: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - package org.springframework.core.convert; - - public interface ConversionService { - - boolean canConvert(Class sourceType, Class targetType); - - T convert(Object source, Class targetType); - - boolean canConvert(TypeDescriptor sourceType, TypeDescriptor targetType); - - Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType); - - } ----- - -Most ConversionService implementations also implement `ConverterRegistry`, which -provides an SPI for registering converters. Internally, a ConversionService -implementation delegates to its registered converters to carry out type conversion logic. - -A robust ConversionService implementation is provided in the `core.convert.support` -package. `GenericConversionService` is the general-purpose implementation suitable for -use in most environments. `ConversionServiceFactory` provides a convenient factory for -creating common ConversionService configurations. - - - -[[core-convert-Spring-config]] -==== Configuring a ConversionService -A ConversionService is a stateless object designed to be instantiated at application -startup, then shared between multiple threads. In a Spring application, you typically -configure a ConversionService instance per Spring container (or ApplicationContext). -That ConversionService will be picked up by Spring and then used whenever a type -conversion needs to be performed by the framework. You may also inject this -ConversionService into any of your beans and invoke it directly. - -[NOTE] -==== -If no ConversionService is registered with Spring, the original PropertyEditor-based -system is used. -==== - -To register a default ConversionService with Spring, add the following bean definition -with id `conversionService`: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - ----- - -A default ConversionService can convert between strings, numbers, enums, collections, -maps, and other common types. To supplement or override the default converters with your -own custom converter(s), set the `converters` property. Property values may implement -either of the Converter, ConverterFactory, or GenericConverter interfaces. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - ----- - -It is also common to use a ConversionService within a Spring MVC application. See -<> for details on use with ``. - -In certain situations you may wish to apply formatting during conversion. See -<> for details on using -`FormattingConversionServiceFactoryBean`. - - - -[[core-convert-programmatic-usage]] -==== Using a ConversionService programmatically -To work with a ConversionService instance programmatically, simply inject a reference to -it like you would for any other bean: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Service - public class MyService { - - @Autowired - public MyService(ConversionService conversionService) { - this.conversionService = conversionService; - } - - public void doIt() { - this.conversionService.convert(...) - } - } ----- - -For most use cases, the `convert` method specifying the _targetType_ can be used but it -will not work with more complex types such as a collection of a parameterized element. -If you want to convert a `List` of `Integer` to a `List` of `String` programmatically, -for instance, you need to provide a formal definition of the source and target types. - -Fortunately, `TypeDescriptor` provides various options to make that straightforward: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - DefaultConversionService cs = new DefaultConversionService(); - - List input = .... - cs.convert(input, - TypeDescriptor.forObject(input), // List type descriptor - TypeDescriptor.collection(List.class, TypeDescriptor.valueOf(String.class))); ----- - -Note that `DefaultConversionService` registers converters automatically which are -appropriate for most environments. This includes collection converters, scalar -converters, and also basic `Object` to `String` converters. The same converters can -be registered with any `ConverterRegistry` using the _static_ `addDefaultConverters` -method on the `DefaultConversionService` class. - -Converters for value types will be reused for arrays and collections, so there is -no need to create a specific converter to convert from a `Collection` of `S` to a -`Collection` of `T`, assuming that standard collection handling is appropriate. - - - - -[[format]] -=== Spring Field Formatting -As discussed in the previous section, <> is a -general-purpose type conversion system. It provides a unified ConversionService API as -well as a strongly-typed Converter SPI for implementing conversion logic from one type -to another. A Spring Container uses this system to bind bean property values. In -addition, both the Spring Expression Language (SpEL) and DataBinder use this system to -bind field values. For example, when SpEL needs to coerce a `Short` to a `Long` to -complete an `expression.setValue(Object bean, Object value)` attempt, the core.convert -system performs the coercion. - -Now consider the type conversion requirements of a typical client environment such as a -web or desktop application. In such environments, you typically convert __from String__ -to support the client postback process, as well as back __to String__ to support the -view rendering process. In addition, you often need to localize String values. The more -general __core.convert__ Converter SPI does not address such __formatting__ requirements -directly. To directly address them, Spring 3 introduces a convenient Formatter SPI that -provides a simple and robust alternative to PropertyEditors for client environments. - -In general, use the Converter SPI when you need to implement general-purpose type -conversion logic; for example, for converting between a java.util.Date and and -java.lang.Long. Use the Formatter SPI when you're working in a client environment, such -as a web application, and need to parse and print localized field values. The -ConversionService provides a unified type conversion API for both SPIs. - - - -[[format-Formatter-SPI]] -==== Formatter SPI -The Formatter SPI to implement field formatting logic is simple and strongly typed: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - package org.springframework.format; - - public interface Formatter extends Printer, Parser { - } ----- - -Where Formatter extends from the Printer and Parser building-block interfaces: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public interface Printer { - String print(T fieldValue, Locale locale); - } ----- - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - import java.text.ParseException; - - public interface Parser { - T parse(String clientValue, Locale locale) throws ParseException; - } ----- - -To create your own Formatter, simply implement the Formatter interface above. -Parameterize T to be the type of object you wish to format, for example, -`java.util.Date`. Implement the `print()` operation to print an instance of T for -display in the client locale. Implement the `parse()` operation to parse an instance of -T from the formatted representation returned from the client locale. Your Formatter -should throw a ParseException or IllegalArgumentException if a parse attempt fails. Take -care to ensure your Formatter implementation is thread-safe. - -Several Formatter implementations are provided in `format` subpackages as a convenience. -The `number` package provides a `NumberFormatter`, `CurrencyFormatter`, and -`PercentFormatter` to format `java.lang.Number` objects using a `java.text.NumberFormat`. -The `datetime` package provides a `DateFormatter` to format `java.util.Date` objects with -a `java.text.DateFormat`. The `datetime.joda` package provides comprehensive datetime -formatting support based on the http://joda-time.sourceforge.net[Joda Time library]. - -Consider `DateFormatter` as an example `Formatter` implementation: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - package org.springframework.format.datetime; - - public final class DateFormatter implements Formatter { - - private String pattern; - - public DateFormatter(String pattern) { - this.pattern = pattern; - } - - public String print(Date date, Locale locale) { - if (date == null) { - return ""; - } - return getDateFormat(locale).format(date); - } - - public Date parse(String formatted, Locale locale) throws ParseException { - if (formatted.length() == 0) { - return null; - } - return getDateFormat(locale).parse(formatted); - } - - protected DateFormat getDateFormat(Locale locale) { - DateFormat dateFormat = new SimpleDateFormat(this.pattern, locale); - dateFormat.setLenient(false); - return dateFormat; - } - - } ----- - -The Spring team welcomes community-driven `Formatter` contributions; see -https://jira.spring.io/browse/SPR[jira.spring.io] to contribute. - - - -[[format-CustomFormatAnnotations]] -==== Annotation-driven Formatting -As you will see, field formatting can be configured by field type or annotation. To bind -an Annotation to a formatter, implement AnnotationFormatterFactory: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - package org.springframework.format; - - public interface AnnotationFormatterFactory { - - Set> getFieldTypes(); - - Printer getPrinter(A annotation, Class fieldType); - - Parser getParser(A annotation, Class fieldType); - - } ----- - -Parameterize A to be the field annotationType you wish to associate formatting logic -with, for example `org.springframework.format.annotation.DateTimeFormat`. Have -`getFieldTypes()` return the types of fields the annotation may be used on. Have -`getPrinter()` return a Printer to print the value of an annotated field. Have -`getParser()` return a Parser to parse a clientValue for an annotated field. - -The example AnnotationFormatterFactory implementation below binds the @NumberFormat -Annotation to a formatter. This annotation allows either a number style or pattern to be -specified: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public final class NumberFormatAnnotationFormatterFactory - implements AnnotationFormatterFactory { - - public Set> getFieldTypes() { - return new HashSet>(asList(new Class[] { - Short.class, Integer.class, Long.class, Float.class, - Double.class, BigDecimal.class, BigInteger.class })); - } - - public Printer getPrinter(NumberFormat annotation, Class fieldType) { - return configureFormatterFrom(annotation, fieldType); - } - - public Parser getParser(NumberFormat annotation, Class fieldType) { - return configureFormatterFrom(annotation, fieldType); - } - - private Formatter configureFormatterFrom(NumberFormat annotation, - Class fieldType) { - if (!annotation.pattern().isEmpty()) { - return new NumberFormatter(annotation.pattern()); - } else { - Style style = annotation.style(); - if (style == Style.PERCENT) { - return new PercentFormatter(); - } else if (style == Style.CURRENCY) { - return new CurrencyFormatter(); - } else { - return new NumberFormatter(); - } - } - } - } ----- - -To trigger formatting, simply annotate fields with @NumberFormat: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class MyModel { - - @NumberFormat(style=Style.CURRENCY) - private BigDecimal decimal; - - } ----- - - -[[format-annotations-api]] -===== Format Annotation API -A portable format annotation API exists in the `org.springframework.format.annotation` -package. Use @NumberFormat to format java.lang.Number fields. Use @DateTimeFormat to -format java.util.Date, java.util.Calendar, java.util.Long, or Joda Time fields. - -The example below uses @DateTimeFormat to format a java.util.Date as a ISO Date -(yyyy-MM-dd): - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class MyModel { - - @DateTimeFormat(iso=ISO.DATE) - private Date date; - - } ----- - - - -[[format-FormatterRegistry-SPI]] -==== FormatterRegistry SPI -The FormatterRegistry is an SPI for registering formatters and converters. -`FormattingConversionService` is an implementation of FormatterRegistry suitable for -most environments. This implementation may be configured programmatically or -declaratively as a Spring bean using `FormattingConversionServiceFactoryBean`. Because -this implementation also implements `ConversionService`, it can be directly configured -for use with Spring's DataBinder and the Spring Expression Language (SpEL). - -Review the FormatterRegistry SPI below: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - package org.springframework.format; - - public interface FormatterRegistry extends ConverterRegistry { - - void addFormatterForFieldType(Class fieldType, Printer printer, Parser parser); - - void addFormatterForFieldType(Class fieldType, Formatter formatter); - - void addFormatterForFieldType(Formatter formatter); - - void addFormatterForAnnotation(AnnotationFormatterFactory factory); - - } ----- - -As shown above, Formatters can be registered by fieldType or annotation. - -The FormatterRegistry SPI allows you to configure Formatting rules centrally, instead of -duplicating such configuration across your Controllers. For example, you might want to -enforce that all Date fields are formatted a certain way, or fields with a specific -annotation are formatted in a certain way. With a shared FormatterRegistry, you define -these rules once and they are applied whenever formatting is needed. - - - -[[format-FormatterRegistrar-SPI]] -==== FormatterRegistrar SPI -The FormatterRegistrar is an SPI for registering formatters and converters through the -FormatterRegistry: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - package org.springframework.format; - - public interface FormatterRegistrar { - - void registerFormatters(FormatterRegistry registry); - - } ----- - -A FormatterRegistrar is useful when registering multiple related converters and -formatters for a given formatting category, such as Date formatting. It can also be -useful where declarative registration is insufficient. For example when a formatter -needs to be indexed under a specific field type different from its own or when -registering a Printer/Parser pair. The next section provides more information on -converter and formatter registration. - - - -[[format-configuring-formatting-mvc]] -==== Configuring Formatting in Spring MVC -In a Spring MVC application, you may configure a custom ConversionService instance -explicitly as an attribute of the `annotation-driven` element of the MVC namespace. This -ConversionService will then be used anytime a type conversion is required during -Controller model binding. If not configured explicitly, Spring MVC will automatically -register default formatters and converters for common types such as numbers and dates. - -To rely on default formatting rules, no custom configuration is required in your Spring -MVC config XML: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - ----- - -With this one-line of configuration, default formatters for Numbers and Date types will -be installed, including support for the @NumberFormat and @DateTimeFormat annotations. -Full support for the Joda Time formatting library is also installed if Joda Time is -present on the classpath. - -To inject a ConversionService instance with custom formatters and converters registered, -set the conversion-service attribute and then specify custom converters, formatters, or -FormatterRegistrars as properties of the FormattingConversionServiceFactoryBean: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - - - - - - - - - - - - - - - - - - ----- - -[NOTE] -==== -See <> and the `FormattingConversionServiceFactoryBean` -for more information on when to use FormatterRegistrars. -==== - - - - -[[format-configuring-formatting-globaldatetimeformat]] -=== Configuring a global date & time format -By default, date and time fields that are not annotated with `@DateTimeFormat` are -converted from strings using the the `DateFormat.SHORT` style. If you prefer, you can -change this by defining your own global format. - -You will need to ensure that Spring does not register default formatters, and instead -you should register all formatters manually. Use the -`org.springframework.format.datetime.joda.JodaTimeFormatterRegistrar` or -`org.springframework.format.datetime.DateFormatterRegistrar` class depending on whether -you use the Joda Time library. - -For example, the following Java configuration will register a global ' `yyyyMMdd`' -format. This example does not depend on the Joda Time library: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Configuration - public class AppConfig { - - @Bean - public FormattingConversionService conversionService() { - - // Use the DefaultFormattingConversionService but do not register defaults - DefaultFormattingConversionService conversionService = new DefaultFormattingConversionService(false); - - // Ensure @NumberFormat is still supported - conversionService.addFormatterForFieldAnnotation(new NumberFormatAnnotationFormatterFactory()); - - // Register date conversion with a specific global format - DateFormatterRegistrar registrar = new DateFormatterRegistrar(); - registrar.setFormatter(new DateFormatter("yyyyMMdd")); - registrar.registerFormatters(conversionService); - - return conversionService; - } - } ----- - -If you prefer XML based configuration you can use a -`FormattingConversionServiceFactoryBean`. Here is the same example, this time using Joda -Time: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - - - - - - - - - - - - - - ----- - -[NOTE] -==== -Joda Time provides separate distinct types to represent `date`, `time` and `date-time` -values. The `dateFormatter`, `timeFormatter` and `dateTimeFormatter` properties of the -`JodaTimeFormatterRegistrar` should be used to configure the different formats for each -type. The `DateTimeFormatterFactoryBean` provides a convenient way to create formatters. -==== - -If you are using Spring MVC remember to explicitly configure the conversion service that -is used. For Java based `@Configuration` this means extending the -`WebMvcConfigurationSupport` class and overriding the `mvcConversionService()` method. -For XML you should use the `'conversion-service'` attribute of the -`mvc:annotation-driven` element. See <> for details. - - - - -[[validation-beanvalidation]] -=== Spring Validation -Spring 3 introduces several enhancements to its validation support. First, the JSR-303 -Bean Validation API is now fully supported. Second, when used programmatically, Spring's -DataBinder can now validate objects as well as bind to them. Third, Spring MVC now has -support for declaratively validating `@Controller` inputs. - - - -[[validation-beanvalidation-overview]] -==== Overview of the JSR-303 Bean Validation API -JSR-303 standardizes validation constraint declaration and metadata for the Java -platform. Using this API, you annotate domain model properties with declarative -validation constraints and the runtime enforces them. There are a number of built-in -constraints you can take advantage of. You may also define your own custom constraints. - -To illustrate, consider a simple PersonForm model with two properties: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class PersonForm { - private String name; - private int age; - } ----- - -JSR-303 allows you to define declarative validation constraints against such properties: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class PersonForm { - - @NotNull - @Size(max=64) - private String name; - - @Min(0) - private int age; - - } ----- - -When an instance of this class is validated by a JSR-303 Validator, these constraints -will be enforced. - -For general information on JSR-303/JSR-349, see the http://beanvalidation.org/[Bean -Validation website]. For information on the specific capabilities of the default -reference implementation, see the https://www.hibernate.org/412.html[Hibernate -Validator] documentation. To learn how to setup a Bean Validation provider as a Spring -bean, keep reading. - - - -[[validation-beanvalidation-spring]] -==== Configuring a Bean Validation Provider -Spring provides full support for the Bean Validation API. This includes convenient -support for bootstrapping a JSR-303/JSR-349 Bean Validation provider as a Spring bean. -This allows for a `javax.validation.ValidatorFactory` or `javax.validation.Validator` to -be injected wherever validation is needed in your application. - -Use the `LocalValidatorFactoryBean` to configure a default Validator as a Spring bean: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - ----- - -The basic configuration above will trigger Bean Validation to initialize using its -default bootstrap mechanism. A JSR-303/JSR-349 provider, such as Hibernate Validator, -is expected to be present in the classpath and will be detected automatically. - - -[[validation-beanvalidation-spring-inject]] -===== Injecting a Validator -`LocalValidatorFactoryBean` implements both `javax.validation.ValidatorFactory` and -`javax.validation.Validator`, as well as Spring's -`org.springframework.validation.Validator`. You may inject a reference to either of -these interfaces into beans that need to invoke validation logic. - -Inject a reference to `javax.validation.Validator` if you prefer to work with the Bean -Validation API directly: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - import javax.validation.Validator; - - @Service - public class MyService { - - @Autowired - private Validator validator; ----- - -Inject a reference to `org.springframework.validation.Validator` if your bean requires -the Spring Validation API: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - import org.springframework.validation.Validator; - - @Service - public class MyService { - - @Autowired - private Validator validator; - - } ----- - - -[[validation-beanvalidation-spring-constraints]] -===== Configuring Custom Constraints -Each Bean Validation constraint consists of two parts. First, a `@Constraint` annotation -that declares the constraint and its configurable properties. Second, an implementation -of the `javax.validation.ConstraintValidator` interface that implements the constraint's -behavior. To associate a declaration with an implementation, each `@Constraint` annotation -references a corresponding ValidationConstraint implementation class. At runtime, a -`ConstraintValidatorFactory` instantiates the referenced implementation when the -constraint annotation is encountered in your domain model. - -By default, the `LocalValidatorFactoryBean` configures a `SpringConstraintValidatorFactory` -that uses Spring to create ConstraintValidator instances. This allows your custom -ConstraintValidators to benefit from dependency injection like any other Spring bean. - -Shown below is an example of a custom `@Constraint` declaration, followed by an associated -`ConstraintValidator` implementation that uses Spring for dependency injection: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Target({ElementType.METHOD, ElementType.FIELD}) - @Retention(RetentionPolicy.RUNTIME) - @Constraint(validatedBy=MyConstraintValidator.class) - public @interface MyConstraint { - } ----- - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - import javax.validation.ConstraintValidator; - - public class MyConstraintValidator implements ConstraintValidator { - - @Autowired; - private Foo aDependency; - - ... - } ----- - -As you can see, a ConstraintValidator implementation may have its dependencies -@Autowired like any other Spring bean. - - -[[validation-beanvalidation-spring-method]] -===== Spring-driven Method Validation -The method validation feature supported by Bean Validation 1.1, and as a custom -extension also by Hibernate Validator 4.3, can be integrated into a Spring context -through a `MethodValidationPostProcessor` bean definition: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - ----- - -In order to be eligible for Spring-driven method validation, all target classes need -to be annotated with Spring's `@Validated` annotation, optionally declaring the -validation groups to use. Check out the `MethodValidationPostProcessor` javadocs -for setup details with Hibernate Validator and Bean Validation 1.1 providers. - - -[[validation-beanvalidation-spring-other]] -===== Additional Configuration Options -The default `LocalValidatorFactoryBean` configuration should prove sufficient for most -cases. There are a number of configuration options for various Bean Validation -constructs, from message interpolation to traversal resolution. See the -`LocalValidatorFactoryBean` javadocs for more information on these options. - - - -[[validation-binder]] -==== Configuring a DataBinder -Since Spring 3, a DataBinder instance can be configured with a Validator. Once -configured, the Validator may be invoked by calling `binder.validate()`. Any validation -Errors are automatically added to the binder's BindingResult. - -When working with the DataBinder programmatically, this can be used to invoke validation -logic after binding to a target object: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - Foo target = new Foo(); - DataBinder binder = new DataBinder(target); - binder.setValidator(new FooValidator()); - - // bind to the target object - binder.bind(propertyValues); - - // validate the target object - binder.validate(); - - // get BindingResult that includes any validation errors - BindingResult results = binder.getBindingResult(); ----- - -A DataBinder can also be configured with multiple `Validator` instances via -`dataBinder.addValidators` and `dataBinder.replaceValidators`. This is useful when -combining globally configured Bean Validation with a Spring `Validator` configured -locally on a DataBinder instance. See <>. - - - -[[validation-mvc]] -==== Spring MVC 3 Validation -Beginning with Spring 3, Spring MVC has the ability to automatically validate -`@Controller` inputs. In previous versions it was up to the developer to manually invoke -validation logic. - - -[[validation-mvc-triggering]] -===== Triggering @Controller Input Validation -To trigger validation of a `@Controller` input, simply annotate the input argument as -++@Valid++: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Controller - public class MyController { - - @RequestMapping("/foo", method=RequestMethod.POST) - public void processFoo(**@Valid** Foo foo) { /* ... */ } ----- - -Spring MVC will validate a @Valid object after binding so-long as an appropriate -Validator has been configured. - -[NOTE] -==== -The @Valid annotation is part of the standard JSR-303 Bean Validation API, and is not a -Spring-specific construct. -==== - - -[[validation-mvc-configuring]] -===== Configuring a Validator for use by Spring MVC -The `Validator` instance invoked when a `@Valid` method argument is encountered may be -configured in two ways. First, you may call `binder.setValidator(Validator)` within a -++@Controller++'s `@InitBinder` callback. This allows you to configure a `Validator` -instance per `@Controller` class: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Controller - public class MyController { - - @InitBinder - protected void initBinder(WebDataBinder binder) { - binder.setValidator(new FooValidator()); - } - - @RequestMapping("/foo", method=RequestMethod.POST) - public void processFoo(@Valid Foo foo) { ... } - - } ----- - -Second, you may call `setValidator(Validator)` on the global `WebBindingInitializer`. This -allows you to configure a `Validator` instance across all `@Controller` classes. This can be -achieved easily by using the Spring MVC namespace: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - ----- - -To combine a global and a local validator, configure the global validator as shown above -and then add a local validator: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Controller - public class MyController { - - @InitBinder - protected void initBinder(WebDataBinder binder) { - binder.addValidators(new FooValidator()); - } - - } ----- - - -[[validation-mvc-jsr303]] -===== Configuring a JSR-303/JSR-349 Validator for use by Spring MVC -With Bean Validation, a single `javax.validation.Validator` instance typically validates -__all__ model objects that declare validation constraints. To configure such a JSR-303 -backed Validator with Spring MVC, simply add a Bean Validation provider, such as -Hibernate Validator, to your classpath. Spring MVC will detect it and automatically -enable Bean Validation support across all Controllers. - -The Spring MVC configuration required to enable Bean Validation support is shown below: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - ----- - -With this minimal configuration, anytime a `@Valid` `@Controller` input is encountered, it -will be validated by the Bean Validation provider. That provider, in turn, will enforce -any constraints declared against the input. Any ++ConstraintViolation++s will automatically -be exposed as errors in the `BindingResult` renderable by standard Spring MVC form tags. - - - - - -[[expressions]] -== Spring Expression Language (SpEL) - - - - -[[expressions-intro]] -=== Introduction -The Spring Expression Language (SpEL for short) is a powerful expression language that -supports querying and manipulating an object graph at runtime. The language syntax is -similar to Unified EL but offers additional features, most notably method invocation and -basic string templating functionality. - -While there are several other Java expression languages available, OGNL, MVEL, and JBoss -EL, to name a few, the Spring Expression Language was created to provide the Spring -community with a single well supported expression language that can be used across all -the products in the Spring portfolio. Its language features are driven by the -requirements of the projects in the Spring portfolio, including tooling requirements for -code completion support within the eclipse based Spring Tool Suite. That said, -SpEL is based on a technology agnostic API allowing other expression language -implementations to be integrated should the need arise. - -While SpEL serves as the foundation for expression evaluation within the Spring -portfolio, it is not directly tied to Spring and can be used independently. In order to -be self contained, many of the examples in this chapter use SpEL as if it were an -independent expression language. This requires creating a few bootstrapping -infrastructure classes such as the parser. Most Spring users will not need to deal with -this infrastructure and will instead only author expression strings for evaluation. An -example of this typical use is the integration of SpEL into creating XML or annotated -based bean definitions as shown in the section <> - -This chapter covers the features of the expression language, its API, and its language -syntax. In several places an Inventor and Inventor's Society class are used as the -target objects for expression evaluation. These class declarations and the data used to -populate them are listed at the end of the chapter. - - - - -[[expressions-features]] -=== Feature Overview -The expression language supports the following functionality - -* Literal expressions -* Boolean and relational operators -* Regular expressions -* Class expressions -* Accessing properties, arrays, lists, maps -* Method invocation -* Relational operators -* Assignment -* Calling constructors -* Bean references -* Array construction -* Inline lists -* Inline maps -* Ternary operator -* Variables -* User defined functions -* Collection projection -* Collection selection -* Templated expressions - - - - -[[expressions-evaluation]] -=== Expression Evaluation using Spring's Expression Interface -This section introduces the simple use of SpEL interfaces and its expression language. -The complete language reference can be found in the section -<>. - -The following code introduces the SpEL API to evaluate the literal string expression -'Hello World'. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - ExpressionParser parser = new SpelExpressionParser(); - Expression exp = parser.parseExpression("**\'Hello World'**"); - String message = (String) exp.getValue(); ----- - -The value of the message variable is simply 'Hello World'. - -The SpEL classes and interfaces you are most likely to use are located in the packages -`org.springframework.expression` and its sub packages and `spel.support`. - -The interface `ExpressionParser` is responsible for parsing an expression string. In -this example the expression string is a string literal denoted by the surrounding single -quotes. The interface `Expression` is responsible for evaluating the previously defined -expression string. There are two exceptions that can be thrown, `ParseException` and -`EvaluationException` when calling ' `parser.parseExpression`' and ' `exp.getValue`' -respectively. - -SpEL supports a wide range of features, such as calling methods, accessing properties, -and calling constructors. - -As an example of method invocation, we call the 'concat' method on the string literal. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - ExpressionParser parser = new SpelExpressionParser(); - Expression exp = parser.parseExpression("**\'Hello World'.concat(\'!')**"); - String message = (String) exp.getValue(); ----- - -The value of message is now 'Hello World!'. - -As an example of calling a JavaBean property, the String property 'Bytes' can be called -as shown below. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - ExpressionParser parser = new SpelExpressionParser(); - - // invokes 'getBytes()' - Expression exp = parser.parseExpression("**\'Hello World'.bytes**"); - byte[] bytes = (byte[]) exp.getValue(); ----- - -SpEL also supports nested properties using standard 'dot' notation, i.e. -prop1.prop2.prop3 and the setting of property values - -Public fields may also be accessed. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - ExpressionParser parser = new SpelExpressionParser(); - - // invokes 'getBytes().length' - Expression exp = parser.parseExpression("**\'Hello World'.bytes.length**"); - int length = (Integer) exp.getValue(); ----- - -The String's constructor can be called instead of using a string literal. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - ExpressionParser parser = new SpelExpressionParser(); - Expression exp = parser.parseExpression("**new String(\'hello world').toUpperCase()**"); - String message = exp.getValue(String.class); ----- - -Note the use of the generic method `public T getValue(Class desiredResultType)`. -Using this method removes the need to cast the value of the expression to the desired -result type. An `EvaluationException` will be thrown if the value cannot be cast to the -type `T` or converted using the registered type converter. - -The more common usage of SpEL is to provide an expression string that is evaluated -against a specific object instance (called the root object). There are two options here -and which to choose depends on whether the object against which the expression is being -evaluated will be changing with each call to evaluate the expression. In the following -example we retrieve the `name` property from an instance of the Inventor class. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - // Create and set a calendar - GregorianCalendar c = new GregorianCalendar(); - c.set(1856, 7, 9); - - // The constructor arguments are name, birthday, and nationality. - Inventor tesla = new Inventor("Nikola Tesla", c.getTime(), "Serbian"); - - ExpressionParser parser = new SpelExpressionParser(); - Expression exp = parser.parseExpression("**name**"); - - EvaluationContext context = new StandardEvaluationContext(tesla); - String name = (String) exp.getValue(context); ----- - -In the last line, the value of the string variable 'name' will be set to "Nikola Tesla". -The class StandardEvaluationContext is where you can specify which object the "name" -property will be evaluated against. This is the mechanism to use if the root object is -unlikely to change, it can simply be set once in the evaluation context. If the root -object is likely to change repeatedly, it can be supplied on each call to `getValue`, as -this next example shows: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - / Create and set a calendar - GregorianCalendar c = new GregorianCalendar(); - c.set(1856, 7, 9); - - // The constructor arguments are name, birthday, and nationality. - Inventor tesla = new Inventor("Nikola Tesla", c.getTime(), "Serbian"); - - ExpressionParser parser = new SpelExpressionParser(); - Expression exp = parser.parseExpression("**name**"); - String name = (String) exp.getValue(tesla); ----- - -In this case the inventor `tesla` has been supplied directly to `getValue` and the -expression evaluation infrastructure creates and manages a default evaluation context -internally - it did not require one to be supplied. - -The StandardEvaluationContext is relatively expensive to construct and during repeated -usage it builds up cached state that enables subsequent expression evaluations to be -performed more quickly. For this reason it is better to cache and reuse them where -possible, rather than construct a new one for each expression evaluation. - -In some cases it can be desirable to use a configured evaluation context and yet still -supply a different root object on each call to `getValue`. `getValue` allows both to be -specified on the same call. In these situations the root object passed on the call is -considered to override any (which maybe null) specified on the evaluation context. - -[NOTE] -==== -In standalone usage of SpEL there is a need to create the parser, parse expressions and -perhaps provide evaluation contexts and a root context object. However, more common -usage is to provide only the SpEL expression string as part of a configuration file, for -example for Spring bean or Spring Web Flow definitions. In this case, the parser, -evaluation context, root object and any predefined variables are all set up implicitly, -requiring the user to specify nothing other than the expressions. -==== -As a final introductory example, the use of a boolean operator is shown using the -Inventor object in the previous example. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - Expression exp = parser.parseExpression("name == 'Nikola Tesla'"); - boolean result = exp.getValue(context, Boolean.class); // evaluates to true ----- - - - -[[expressions-evaluation-context]] -==== The EvaluationContext interface -The interface `EvaluationContext` is used when evaluating an expression to resolve -properties, methods, fields, and to help perform type conversion. The out-of-the-box -implementation, `StandardEvaluationContext`, uses reflection to manipulate the object, -caching `java.lang.reflect`'s `Method`, `Field`, and `Constructor` instances for -increased performance. - -The `StandardEvaluationContext` is where you may specify the root object to evaluate -against via the method `setRootObject()` or passing the root object into the -constructor. You can also specify variables and functions that will be used in the -expression using the methods `setVariable()` and `registerFunction()`. The use of -variables and functions are described in the language reference sections -<> and <>. The -`StandardEvaluationContext` is also where you can register custom -++ConstructorResolver++s, ++MethodResolver++s, and ++PropertyAccessor++s to extend how SpEL -evaluates expressions. Please refer to the JavaDoc of these classes for more details. - - -[[expressions-type-conversion]] -===== Type Conversion -By default SpEL uses the conversion service available in Spring core ( -`org.springframework.core.convert.ConversionService`). This conversion service comes -with many converters built in for common conversions but is also fully extensible so -custom conversions between types can be added. Additionally it has the key capability -that it is generics aware. This means that when working with generic types in -expressions, SpEL will attempt conversions to maintain type correctness for any objects -it encounters. - -What does this mean in practice? Suppose assignment, using `setValue()`, is being used -to set a `List` property. The type of the property is actually `List`. SpEL -will recognize that the elements of the list need to be converted to `Boolean` before -being placed in it. A simple example: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - class Simple { - public List booleanList = new ArrayList(); - } - - Simple simple = new Simple(); - - simple.booleanList.add(true); - - StandardEvaluationContext simpleContext = new StandardEvaluationContext(simple); - - // false is passed in here as a string. SpEL and the conversion service will - // correctly recognize that it needs to be a Boolean and convert it - parser.parseExpression("booleanList[0]").setValue(simpleContext, "false"); - - // b will be false - Boolean b = simple.booleanList.get(0); ----- - - - - -[[expressions-beandef]] -=== Expression support for defining bean definitions -SpEL expressions can be used with XML or annotation-based configuration metadata for -defining ++BeanDefinition++s. In both cases the syntax to define the expression is of the -form `#{ }`. - - - -[[expressions-beandef-xml-based]] -==== XML based configuration -A property or constructor-arg value can be set using expressions as shown below. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - ----- - -The variable `systemProperties` is predefined, so you can use it in your expressions as -shown below. Note that you do not have to prefix the predefined variable with the `#` -symbol in this context. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - ----- - -You can also refer to other bean properties by name, for example. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - - - - ----- - - - -[[expressions-beandef-annotation-based]] -==== Annotation-based configuration -The `@Value` annotation can be placed on fields, methods and method/constructor -parameters to specify a default value. - -Here is an example to set the default value of a field variable. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public static class FieldValueTestBean - - @Value("#{ systemProperties['user.region'] }") - private String defaultLocale; - - public void setDefaultLocale(String defaultLocale) { - this.defaultLocale = defaultLocale; - } - - public String getDefaultLocale() { - return this.defaultLocale; - } - - } ----- - -The equivalent but on a property setter method is shown below. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public static class PropertyValueTestBean - - private String defaultLocale; - - @Value("#{ systemProperties['user.region'] }") - public void setDefaultLocale(String defaultLocale) { - this.defaultLocale = defaultLocale; - } - - public String getDefaultLocale() { - return this.defaultLocale; - } - - } ----- - -Autowired methods and constructors can also use the `@Value` annotation. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class SimpleMovieLister { - - private MovieFinder movieFinder; - private String defaultLocale; - - @Autowired - public void configure(MovieFinder movieFinder, - @Value("#{ systemProperties['user.region'] }") String defaultLocale) { - this.movieFinder = movieFinder; - this.defaultLocale = defaultLocale; - } - - // ... - } ----- - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class MovieRecommender { - - private String defaultLocale; - - private CustomerPreferenceDao customerPreferenceDao; - - @Autowired - public MovieRecommender(CustomerPreferenceDao customerPreferenceDao, - @Value("#{systemProperties['user.country']}") String defaultLocale) { - this.customerPreferenceDao = customerPreferenceDao; - this.defaultLocale = defaultLocale; - } - - // ... - } ----- - - - - -[[expressions-language-ref]] -=== Language Reference - - - -[[expressions-ref-literal]] -==== Literal expressions -The types of literal expressions supported are strings, dates, numeric values (int, -real, and hex), boolean and null. Strings are delimited by single quotes. To put a -single quote itself in a string use two single quote characters. The following listing -shows simple usage of literals. Typically they would not be used in isolation like this, -but as part of a more complex expression, for example using a literal on one side of a -logical comparison operator. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - ExpressionParser parser = new SpelExpressionParser(); - - // evals to "Hello World" - String helloWorld = (String) parser.parseExpression("'Hello World'").getValue(); - - double avogadrosNumber = (Double) parser.parseExpression("6.0221415E+23").getValue(); - - // evals to 2147483647 - int maxValue = (Integer) parser.parseExpression("0x7FFFFFFF").getValue(); - - boolean trueValue = (Boolean) parser.parseExpression("true").getValue(); - - Object nullValue = parser.parseExpression("null").getValue(); ----- - -Numbers support the use of the negative sign, exponential notation, and decimal points. -By default real numbers are parsed using Double.parseDouble(). - - - -[[expressions-properties-arrays]] -==== Properties, Arrays, Lists, Maps, Indexers -Navigating with property references is easy: just use a period to indicate a nested -property value. The instances of the `Inventor` class, pupin, and tesla, were populated with -data listed in the section <>. -To navigate "down" and get Tesla's year of birth and Pupin's city of birth the following -expressions are used. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - // evals to 1856 - int year = (Integer) parser.parseExpression("Birthdate.Year + 1900").getValue(context); - - String city = (String) parser.parseExpression("placeOfBirth.City").getValue(context); ----- - -Case insensitivity is allowed for the first letter of property names. The contents of -arrays and lists are obtained using square bracket notation. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - ExpressionParser parser = new SpelExpressionParser(); - - // Inventions Array - StandardEvaluationContext teslaContext = new StandardEvaluationContext(tesla); - - // evaluates to "Induction motor" - String invention = parser.parseExpression("inventions[3]").getValue( - teslaContext, String.class); - - // Members List - StandardEvaluationContext societyContext = new StandardEvaluationContext(ieee); - - // evaluates to "Nikola Tesla" - String name = parser.parseExpression("Members[0].Name").getValue( - societyContext, String.class); - - // List and Array navigation - // evaluates to "Wireless communication" - String invention = parser.parseExpression("Members[0].Inventions[6]").getValue( - societyContext, String.class); ----- - -The contents of maps are obtained by specifying the literal key value within the -brackets. In this case, because keys for the Officers map are strings, we can specify -string literals. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - // Officer's Dictionary - - Inventor pupin = parser.parseExpression("Officers['president']").getValue( - societyContext, Inventor.class); - - // evaluates to "Idvor" - String city = parser.parseExpression("Officers['president'].PlaceOfBirth.City").getValue( - societyContext, String.class); - - // setting values - parser.parseExpression("Officers['advisors'][0].PlaceOfBirth.Country").setValue( - societyContext, "Croatia"); ----- - - - -[[expressions-inline-lists]] -==== Inline lists -Lists can be expressed directly in an expression using `{}` notation. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - // evaluates to a Java list containing the four numbers - List numbers = (List) parser.parseExpression("{1,2,3,4}").getValue(context); - - List listOfLists = (List) parser.parseExpression("{{'a','b'},{'x','y'}}").getValue(context); ----- - -`{}` by itself means an empty list. For performance reasons, if the list is itself -entirely composed of fixed literals then a constant list is created to represent the -expression, rather than building a new list on each evaluation. - -[[expressions-inline-maps]] -==== Inline Maps -Maps can also be expressed directly in an expression using `{key:value}` notation. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - // evaluates to a Java map containing the two entries - Map inventorInfo = (Map) parser.parseExpression("{name:'Nikola',dob:'10-July-1856'}").getValue(context); - - Map mapOfMaps = (Map) parser.parseExpression("{name:{first:'Nikola',last:'Tesla'},dob:{day:10,month:'July',year:1856}}").getValue(context); ----- -`{:}` by itself means an empty map. For performance reasons, if the map is itself composed -of fixed literals or other nested constant structures (lists or maps) then a constant map is created -to represent the expression, rather than building a new map on each evaluation. Quoting of the map keys -is optional, the examples above are not using quoted keys. - -[[expressions-array-construction]] -==== Array construction -Arrays can be built using the familiar Java syntax, optionally supplying an initializer -to have the array populated at construction time. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - int[] numbers1 = (int[]) parser.parseExpression("new int[4]").getValue(context); - - // Array with initializer - int[] numbers2 = (int[]) parser.parseExpression("new int[]{1,2,3}").getValue(context); - - // Multi dimensional array - int[][] numbers3 = (int[][]) parser.parseExpression("new int[4][5]").getValue(context); ----- - -It is not currently allowed to supply an initializer when constructing a -multi-dimensional array. - - - -[[expressions-methods]] -==== Methods -Methods are invoked using typical Java programming syntax. You may also invoke methods -on literals. Varargs are also supported. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - // string literal, evaluates to "bc" - String c = parser.parseExpression("'abc'.substring(2, 3)").getValue(String.class); - - // evaluates to true - boolean isMember = parser.parseExpression("isMember('Mihajlo Pupin')").getValue( - societyContext, Boolean.class); ----- - - - -[[expressions-operators]] -==== Operators - - -[[expressions-operators-relational]] -===== Relational operators -The relational operators; equal, not equal, less than, less than or equal, greater than, -and greater than or equal are supported using standard operator notation. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - // evaluates to true - boolean trueValue = parser.parseExpression("2 == 2").getValue(Boolean.class); - - // evaluates to false - boolean falseValue = parser.parseExpression("2 < -5.0").getValue(Boolean.class); - - // evaluates to true - boolean trueValue = parser.parseExpression("'black' < 'block'").getValue(Boolean.class); ----- - -In addition to standard relational operators SpEL supports the `instanceof` and regular -expression based `matches` operator. - -[source,java,indent=0] -[subs="none"] ----- - // evaluates to false - boolean falseValue = parser.parseExpression( - "'xyz' instanceof T(int)").getValue(Boolean.class); - - // evaluates to true - boolean trueValue = parser.parseExpression( - "'5.00' matches '^-?\\d+(\\.\\d{2})?$'").getValue(Boolean.class); - - //evaluates to false - boolean falseValue = parser.parseExpression( - "'5.0067' matches '^-?\\d+(\\.\\d{2})?$'").getValue(Boolean.class); ----- - -Each symbolic operator can also be specified as a purely alphabetic equivalent. This -avoids problems where the symbols used have special meaning for the document type in -which the expression is embedded (eg. an XML document). The textual equivalents are -shown here: `lt` (`<`), `gt` (`>`), `le` (`<=`), `ge` (`>=`), `eq` (`==`), -`ne` (`!=`), `div` (`/`), `mod` (`%`), `not` (`!`). These are case insensitive. - - -[[expressions-operators-logical]] -===== Logical operators -The logical operators that are supported are and, or, and not. Their use is demonstrated -below. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - // -- AND -- - - // evaluates to false - boolean falseValue = parser.parseExpression("true and false").getValue(Boolean.class); - - // evaluates to true - String expression = "isMember('Nikola Tesla') and isMember('Mihajlo Pupin')"; - boolean trueValue = parser.parseExpression(expression).getValue(societyContext, Boolean.class); - - // -- OR -- - - // evaluates to true - boolean trueValue = parser.parseExpression("true or false").getValue(Boolean.class); - - // evaluates to true - String expression = "isMember('Nikola Tesla') or isMember('Albert Einstein')"; - boolean trueValue = parser.parseExpression(expression).getValue(societyContext, Boolean.class); - - // -- NOT -- - - // evaluates to false - boolean falseValue = parser.parseExpression("!true").getValue(Boolean.class); - - // -- AND and NOT -- - String expression = "isMember('Nikola Tesla') and !isMember('Mihajlo Pupin')"; - boolean falseValue = parser.parseExpression(expression).getValue(societyContext, Boolean.class); ----- - - -[[expressions-operators-mathematical]] -===== Mathematical operators -The addition operator can be used on both numbers and strings. Subtraction, multiplication -and division can be used only on numbers. Other mathematical operators supported are -modulus (%) and exponential power (^). Standard operator precedence is enforced. These -operators are demonstrated below. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - // Addition - int two = parser.parseExpression("1 + 1").getValue(Integer.class); // 2 - - String testString = parser.parseExpression( - "'test' + ' ' + 'string'").getValue(String.class); // 'test string' - - // Subtraction - int four = parser.parseExpression("1 - -3").getValue(Integer.class); // 4 - - double d = parser.parseExpression("1000.00 - 1e4").getValue(Double.class); // -9000 - - // Multiplication - int six = parser.parseExpression("-2 * -3").getValue(Integer.class); // 6 - - double twentyFour = parser.parseExpression("2.0 * 3e0 * 4").getValue(Double.class); // 24.0 - - // Division - int minusTwo = parser.parseExpression("6 / -3").getValue(Integer.class); // -2 - - double one = parser.parseExpression("8.0 / 4e0 / 2").getValue(Double.class); // 1.0 - - // Modulus - int three = parser.parseExpression("7 % 4").getValue(Integer.class); // 3 - - int one = parser.parseExpression("8 / 5 % 2").getValue(Integer.class); // 1 - - // Operator precedence - int minusTwentyOne = parser.parseExpression("1+2-3*8").getValue(Integer.class); // -21 ----- - - - -[[expressions-assignment]] -==== Assignment -Setting of a property is done by using the assignment operator. This would typically be -done within a call to `setValue` but can also be done inside a call to `getValue`. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - Inventor inventor = new Inventor(); - StandardEvaluationContext inventorContext = new StandardEvaluationContext(inventor); - - parser.parseExpression("Name").setValue(inventorContext, "Alexander Seovic2"); - - // alternatively - - String aleks = parser.parseExpression( - "Name = 'Alexandar Seovic'").getValue(inventorContext, String.class); ----- - - - -[[expressions-types]] -==== Types -The special `T` operator can be used to specify an instance of java.lang.Class (the -_type_). Static methods are invoked using this operator as well. The -`StandardEvaluationContext` uses a `TypeLocator` to find types and the -`StandardTypeLocator` (which can be replaced) is built with an understanding of the -java.lang package. This means T() references to types within java.lang do not need to be -fully qualified, but all other type references must be. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - Class dateClass = parser.parseExpression("T(java.util.Date)").getValue(Class.class); - - Class stringClass = parser.parseExpression("T(String)").getValue(Class.class); - - boolean trueValue = parser.parseExpression( - "T(java.math.RoundingMode).CEILING < T(java.math.RoundingMode).FLOOR") - .getValue(Boolean.class); ----- - - - -[[expressions-constructors]] -==== Constructors -Constructors can be invoked using the new operator. The fully qualified class name -should be used for all but the primitive type and String (where int, float, etc, can be -used). - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - Inventor einstein = p.parseExpression( - "new org.spring.samples.spel.inventor.Inventor('Albert Einstein', 'German')") - .getValue(Inventor.class); - - //create new inventor instance within add method of List - p.parseExpression( - "Members.add(new org.spring.samples.spel.inventor.Inventor( - 'Albert Einstein', 'German'))").getValue(societyContext); ----- - - - -[[expressions-ref-variables]] -==== Variables -Variables can be referenced in the expression using the syntax `#variableName`. Variables -are set using the method setVariable on the `StandardEvaluationContext`. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - Inventor tesla = new Inventor("Nikola Tesla", "Serbian"); - StandardEvaluationContext context = new StandardEvaluationContext(tesla); - context.setVariable("newName", "Mike Tesla"); - - parser.parseExpression("Name = #newName").getValue(context); - - System.out.println(tesla.getName()) // "Mike Tesla" ----- - - -[[expressions-this-root]] -===== The #this and #root variables -The variable #this is always defined and refers to the current evaluation object -(against which unqualified references are resolved). The variable #root is always -defined and refers to the root context object. Although #this may vary as components of -an expression are evaluated, #root always refers to the root. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - // create an array of integers - List primes = new ArrayList(); - primes.addAll(Arrays.asList(2,3,5,7,11,13,17)); - - // create parser and set variable 'primes' as the array of integers - ExpressionParser parser = new SpelExpressionParser(); - StandardEvaluationContext context = new StandardEvaluationContext(); - context.setVariable("primes",primes); - - // all prime numbers > 10 from the list (using selection ?{...}) - // evaluates to [11, 13, 17] - List primesGreaterThanTen = (List) parser.parseExpression( - "#primes.?[#this>10]").getValue(context); ----- - - - -[[expressions-ref-functions]] -==== Functions -You can extend SpEL by registering user defined functions that can be called within the -expression string. The function is registered with the `StandardEvaluationContext` using -the method. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public void registerFunction(String name, Method m) ----- - -A reference to a Java Method provides the implementation of the function. For example, a -utility method to reverse a string is shown below. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public abstract class StringUtils { - - public static String reverseString(String input) { - StringBuilder backwards = new StringBuilder(); - for (int i = 0; i < input.length(); i++) - backwards.append(input.charAt(input.length() - 1 - i)); - } - return backwards.toString(); - } - } ----- - -This method is then registered with the evaluation context and can be used within an -expression string. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - ExpressionParser parser = new SpelExpressionParser(); - StandardEvaluationContext context = new StandardEvaluationContext(); - - context.registerFunction("reverseString", - StringUtils.class.getDeclaredMethod("reverseString", new Class[] { String.class })); - - String helloWorldReversed = parser.parseExpression( - "#reverseString('hello')").getValue(context, String.class); ----- - - - -[[expressions-bean-references]] -==== Bean references -If the evaluation context has been configured with a bean resolver it is possible to -lookup beans from an expression using the (@) symbol. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - ExpressionParser parser = new SpelExpressionParser(); - StandardEvaluationContext context = new StandardEvaluationContext(); - context.setBeanResolver(new MyBeanResolver()); - - // This will end up calling resolve(context,"foo") on MyBeanResolver during evaluation - Object bean = parser.parseExpression("@foo").getValue(context); ----- - - - -[[expressions-operator-ternary]] -==== Ternary Operator (If-Then-Else) -You can use the ternary operator for performing if-then-else conditional logic inside -the expression. A minimal example is: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - String falseString = parser.parseExpression( - "false ? 'trueExp' : 'falseExp'").getValue(String.class); ----- - -In this case, the boolean false results in returning the string value 'falseExp'. A more -realistic example is shown below. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - parser.parseExpression("Name").setValue(societyContext, "IEEE"); - societyContext.setVariable("queryName", "Nikola Tesla"); - - expression = "isMember(#queryName)? #queryName + ' is a member of the ' " + - "+ Name + ' Society' : #queryName + ' is not a member of the ' + Name + ' Society'"; - - String queryResultString = parser.parseExpression(expression) - .getValue(societyContext, String.class); - // queryResultString = "Nikola Tesla is a member of the IEEE Society" ----- - -Also see the next section on the Elvis operator for an even shorter syntax for the -ternary operator. - - - -[[expressions-operator-elvis]] -==== The Elvis Operator -The Elvis operator is a shortening of the ternary operator syntax and is used in the -http://groovy.codehaus.org/Operators#Operators-ElvisOperator(%3F%3A)[Groovy] language. -With the ternary operator syntax you usually have to repeat a variable twice, for -example: - -[source,groovy,indent=0] -[subs="verbatim,quotes"] ----- - String name = "Elvis Presley"; - String displayName = name != null ? name : "Unknown"; ----- - -Instead you can use the Elvis operator, named for the resemblance to Elvis' hair style. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - ExpressionParser parser = new SpelExpressionParser(); - - String name = parser.parseExpression("null?:'Unknown'").getValue(String.class); - - System.out.println(name); // 'Unknown' ----- - -Here is a more complex example. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - ExpressionParser parser = new SpelExpressionParser(); - - Inventor tesla = new Inventor("Nikola Tesla", "Serbian"); - StandardEvaluationContext context = new StandardEvaluationContext(tesla); - - String name = parser.parseExpression("Name?:'Elvis Presley'").getValue(context, String.class); - - System.out.println(name); // Nikola Tesla - - tesla.setName(null); - - name = parser.parseExpression("Name?:'Elvis Presley'").getValue(context, String.class); - - System.out.println(name); // Elvis Presley ----- - - - -[[expressions-operator-safe-navigation]] -==== Safe Navigation operator -The Safe Navigation operator is used to avoid a `NullPointerException` and comes from -the http://groovy.codehaus.org/Operators#Operators-SafeNavigationOperator(%3F.)[Groovy] -language. Typically when you have a reference to an object you might need to verify that -it is not null before accessing methods or properties of the object. To avoid this, the -safe navigation operator will simply return null instead of throwing an exception. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - ExpressionParser parser = new SpelExpressionParser(); - - Inventor tesla = new Inventor("Nikola Tesla", "Serbian"); - tesla.setPlaceOfBirth(new PlaceOfBirth("Smiljan")); - - StandardEvaluationContext context = new StandardEvaluationContext(tesla); - - String city = parser.parseExpression("PlaceOfBirth?.City").getValue(context, String.class); - System.out.println(city); // Smiljan - - tesla.setPlaceOfBirth(null); - - city = parser.parseExpression("PlaceOfBirth?.City").getValue(context, String.class); - - System.out.println(city); // null - does not throw NullPointerException!!! ----- - -[NOTE] -==== -The Elvis operator can be used to apply default values in expressions, e.g. in an -`@Value` expression: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Value("#{systemProperties['pop3.port'] ?: 25}") ----- - -This will inject a system property `pop3.port` if it is defined or 25 if not. -==== - - - -[[expressions-collection-selection]] -==== Collection Selection -Selection is a powerful expression language feature that allows you to transform some -source collection into another by selecting from its entries. - -Selection uses the syntax `?[selectionExpression]`. This will filter the collection and -return a new collection containing a subset of the original elements. For example, -selection would allow us to easily get a list of Serbian inventors: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - List list = (List) parser.parseExpression( - "Members.?[Nationality == 'Serbian']").getValue(societyContext); ----- - -Selection is possible upon both lists and maps. In the former case the selection -criteria is evaluated against each individual list element whilst against a map the -selection criteria is evaluated against each map entry (objects of the Java type -`Map.Entry`). Map entries have their key and value accessible as properties for use in -the selection. - -This expression will return a new map consisting of those elements of the original map -where the entry value is less than 27. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - Map newMap = parser.parseExpression("map.?[value<27]").getValue(); ----- - -In addition to returning all the selected elements, it is possible to retrieve just the -first or the last value. To obtain the first entry matching the selection the syntax is -`^[...]` whilst to obtain the last matching selection the syntax is `$[...]`. - - - -[[expressions-collection-projection]] -==== Collection Projection -Projection allows a collection to drive the evaluation of a sub-expression and the -result is a new collection. The syntax for projection is `![projectionExpression]`. Most -easily understood by example, suppose we have a list of inventors but want the list of -cities where they were born. Effectively we want to evaluate 'placeOfBirth.city' for -every entry in the inventor list. Using projection: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - // returns ['Smiljan', 'Idvor' ] - List placesOfBirth = (List)parser.parseExpression("Members.![placeOfBirth.city]"); ----- - -A map can also be used to drive projection and in this case the projection expression is -evaluated against each entry in the map (represented as a Java `Map.Entry`). The result -of a projection across a map is a list consisting of the evaluation of the projection -expression against each map entry. - - - -[[expressions-templating]] -==== Expression templating -Expression templates allow a mixing of literal text with one or more evaluation blocks. -Each evaluation block is delimited with prefix and suffix characters that you can -define, a common choice is to use `#{ }` as the delimiters. For example, - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - String randomPhrase = parser.parseExpression( - "random number is #{T(java.lang.Math).random()}", - new TemplateParserContext()).getValue(String.class); - - // evaluates to "random number is 0.7038186818312008" ----- - -The string is evaluated by concatenating the literal text 'random number is ' with the -result of evaluating the expression inside the #{ } delimiter, in this case the result -of calling that random() method. The second argument to the method `parseExpression()` -is of the type `ParserContext`. The `ParserContext` interface is used to influence how -the expression is parsed in order to support the expression templating functionality. -The definition of `TemplateParserContext` is shown below. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class TemplateParserContext implements ParserContext { - - public String getExpressionPrefix() { - return "#{"; - } - - public String getExpressionSuffix() { - return "}"; - } - - public boolean isTemplate() { - return true; - } - } ----- - - - - -[[expressions-example-classes]] -=== Classes used in the examples -Inventor.java - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - package org.spring.samples.spel.inventor; - - import java.util.Date; - import java.util.GregorianCalendar; - - public class Inventor { - - private String name; - private String nationality; - private String[] inventions; - private Date birthdate; - private PlaceOfBirth placeOfBirth; - - public Inventor(String name, String nationality) { - GregorianCalendar c= new GregorianCalendar(); - this.name = name; - this.nationality = nationality; - this.birthdate = c.getTime(); - } - - public Inventor(String name, Date birthdate, String nationality) { - this.name = name; - this.nationality = nationality; - this.birthdate = birthdate; - } - - public Inventor() { - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getNationality() { - return nationality; - } - - public void setNationality(String nationality) { - this.nationality = nationality; - } - - public Date getBirthdate() { - return birthdate; - } - - public void setBirthdate(Date birthdate) { - this.birthdate = birthdate; - } - - public PlaceOfBirth getPlaceOfBirth() { - return placeOfBirth; - } - - public void setPlaceOfBirth(PlaceOfBirth placeOfBirth) { - this.placeOfBirth = placeOfBirth; - } - - public void setInventions(String[] inventions) { - this.inventions = inventions; - } - - public String[] getInventions() { - return inventions; - } - } ----- - -PlaceOfBirth.java - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - package org.spring.samples.spel.inventor; - - public class PlaceOfBirth { - - private String city; - private String country; - - public PlaceOfBirth(String city) { - this.city=city; - } - - public PlaceOfBirth(String city, String country) { - this(city); - this.country = country; - } - - public String getCity() { - return city; - } - - public void setCity(String s) { - this.city = s; - } - - public String getCountry() { - return country; - } - - public void setCountry(String country) { - this.country = country; - } - - } ----- - -Society.java - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - package org.spring.samples.spel.inventor; - - import java.util.*; - - public class Society { - - private String name; - - public static String Advisors = "advisors"; - public static String President = "president"; - - private List members = new ArrayList(); - private Map officers = new HashMap(); - - public List getMembers() { - return members; - } - - public Map getOfficers() { - return officers; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public boolean isMember(String name) { - for (Inventor inventor : members) { - if (inventor.getName().equals(name)) { - return true; - } - } - return false; - } - - } ----- - - - - - -[[aop]] -== Aspect Oriented Programming with Spring - - - - -[[aop-introduction]] -=== Introduction -__Aspect-Oriented Programming__ (AOP) complements Object-Oriented Programming (OOP) by -providing another way of thinking about program structure. The key unit of modularity in -OOP is the class, whereas in AOP the unit of modularity is the __aspect__. Aspects -enable the modularization of concerns such as transaction management that cut across -multiple types and objects. (Such concerns are often termed __crosscutting__ concerns in -AOP literature.) - -One of the key components of Spring is the __AOP framework__. While the Spring IoC -container does not depend on AOP, meaning you do not need to use AOP if you don't want -to, AOP complements Spring IoC to provide a very capable middleware solution. - -.Spring 2.0 AOP -**** -Spring 2.0 introduces a simpler and more powerful way of writing custom aspects using -either a <> or the <>. Both of these styles offer fully typed advice and use of the AspectJ pointcut -language, while still using Spring AOP for weaving. - -The Spring 2.0 schema- and @AspectJ-based AOP support is discussed in this chapter. -Spring 2.0 AOP remains fully backwards compatible with Spring 1.2 AOP, and the -lower-level AOP support offered by the Spring 1.2 APIs is discussed in <>. -**** - -AOP is used in the Spring Framework to... - -* ... provide declarative enterprise services, especially as a replacement for EJB - declarative services. The most important such service is - <>. -* ... allow users to implement custom aspects, complementing their use of OOP with AOP. - -[NOTE] -==== -If you are interested only in generic declarative services or other pre-packaged -declarative middleware services such as pooling, you do not need to work directly with -Spring AOP, and can skip most of this chapter. -==== - - - -[[aop-introduction-defn]] -==== AOP concepts -Let us begin by defining some central AOP concepts and terminology. These terms are not -Spring-specific... unfortunately, AOP terminology is not particularly intuitive; -however, it would be even more confusing if Spring used its own terminology. - -* __Aspect__: a modularization of a concern that cuts across multiple classes. - Transaction management is a good example of a crosscutting concern in enterprise Java - applications. In Spring AOP, aspects are implemented using regular classes - (the <>) or regular classes annotated with the - `@Aspect` annotation (the <>). -* __Join point__: a point during the execution of a program, such as the execution of a - method or the handling of an exception. In Spring AOP, a join point __always__ - represents a method execution. -* __Advice__: action taken by an aspect at a particular join point. Different types of - advice include "around," "before" and "after" advice. (Advice types are discussed - below.) Many AOP frameworks, including Spring, model an advice as an __interceptor__, - maintaining a chain of interceptors __around__ the join point. -* __Pointcut__: a predicate that matches join points. Advice is associated with a - pointcut expression and runs at any join point matched by the pointcut (for example, - the execution of a method with a certain name). The concept of join points as matched - by pointcut expressions is central to AOP, and Spring uses the AspectJ pointcut - expression language by default. -* __Introduction__: declaring additional methods or fields on behalf of a type. Spring - AOP allows you to introduce new interfaces (and a corresponding implementation) to any - advised object. For example, you could use an introduction to make a bean implement an - `IsModified` interface, to simplify caching. (An introduction is known as an - inter-type declaration in the AspectJ community.) -* __Target object__: object being advised by one or more aspects. Also referred to as - the __advised__ object. Since Spring AOP is implemented using runtime proxies, this - object will always be a __proxied__ object. -* __AOP proxy__: an object created by the AOP framework in order to implement the aspect - contracts (advise method executions and so on). In the Spring Framework, an AOP proxy - will be a JDK dynamic proxy or a CGLIB proxy. -* __Weaving__: linking aspects with other application types or objects to create an - advised object. This can be done at compile time (using the AspectJ compiler, for - example), load time, or at runtime. Spring AOP, like other pure Java AOP frameworks, - performs weaving at runtime. - -Types of advice: - -* __Before advice__: Advice that executes before a join point, but which does not have - the ability to prevent execution flow proceeding to the join point (unless it throws - an exception). -* __After returning advice__: Advice to be executed after a join point completes - normally: for example, if a method returns without throwing an exception. -* __After throwing advice__: Advice to be executed if a method exits by throwing an - exception. -* __After (finally) advice__: Advice to be executed regardless of the means by which a - join point exits (normal or exceptional return). -* __Around advice__: Advice that surrounds a join point such as a method invocation. - This is the most powerful kind of advice. Around advice can perform custom behavior - before and after the method invocation. It is also responsible for choosing whether to - proceed to the join point or to shortcut the advised method execution by returning its - own return value or throwing an exception. - -Around advice is the most general kind of advice. Since Spring AOP, like AspectJ, -provides a full range of advice types, we recommend that you use the least powerful -advice type that can implement the required behavior. For example, if you need only to -update a cache with the return value of a method, you are better off implementing an -after returning advice than an around advice, although an around advice can accomplish -the same thing. Using the most specific advice type provides a simpler programming model -with less potential for errors. For example, you do not need to invoke the `proceed()` -method on the `JoinPoint` used for around advice, and hence cannot fail to invoke it. - -In Spring 2.0, all advice parameters are statically typed, so that you work with advice -parameters of the appropriate type (the type of the return value from a method execution -for example) rather than `Object` arrays. - -The concept of join points, matched by pointcuts, is the key to AOP which distinguishes -it from older technologies offering only interception. Pointcuts enable advice to be -targeted independently of the Object-Oriented hierarchy. For example, an around advice -providing declarative transaction management can be applied to a set of methods spanning -multiple objects (such as all business operations in the service layer). - - - -[[aop-introduction-spring-defn]] -==== Spring AOP capabilities and goals -Spring AOP is implemented in pure Java. There is no need for a special compilation -process. Spring AOP does not need to control the class loader hierarchy, and is thus -suitable for use in a Servlet container or application server. - -Spring AOP currently supports only method execution join points (advising the execution -of methods on Spring beans). Field interception is not implemented, although support for -field interception could be added without breaking the core Spring AOP APIs. If you need -to advise field access and update join points, consider a language such as AspectJ. - -Spring AOP's approach to AOP differs from that of most other AOP frameworks. The aim is -not to provide the most complete AOP implementation (although Spring AOP is quite -capable); it is rather to provide a close integration between AOP implementation and -Spring IoC to help solve common problems in enterprise applications. - -Thus, for example, the Spring Framework's AOP functionality is normally used in -conjunction with the Spring IoC container. Aspects are configured using normal bean -definition syntax (although this allows powerful "autoproxying" capabilities): this is a -crucial difference from other AOP implementations. There are some things you cannot do -easily or efficiently with Spring AOP, such as advise very fine-grained objects (such as -domain objects typically): AspectJ is the best choice in such cases. However, our -experience is that Spring AOP provides an excellent solution to most problems in -enterprise Java applications that are amenable to AOP. - -Spring AOP will never strive to compete with AspectJ to provide a comprehensive AOP -solution. We believe that both proxy-based frameworks like Spring AOP and full-blown -frameworks such as AspectJ are valuable, and that they are complementary, rather than in -competition. Spring seamlessly integrates Spring AOP and IoC with AspectJ, to enable -all uses of AOP to be catered for within a consistent Spring-based application -architecture. This integration does not affect the Spring AOP API or the AOP Alliance -API: Spring AOP remains backward-compatible. See <> for a -discussion of the Spring AOP APIs. - -[NOTE] -==== -One of the central tenets of the Spring Framework is that of __non-invasiveness__; this -is the idea that you should not be forced to introduce framework-specific classes and -interfaces into your business/domain model. However, in some places the Spring Framework -does give you the option to introduce Spring Framework-specific dependencies into your -codebase: the rationale in giving you such options is because in certain scenarios it -might be just plain easier to read or code some specific piece of functionality in such -a way. The Spring Framework (almost) always offers you the choice though: you have the -freedom to make an informed decision as to which option best suits your particular use -case or scenario. - -One such choice that is relevant to this chapter is that of which AOP framework (and -which AOP style) to choose. You have the choice of AspectJ and/or Spring AOP, and you -also have the choice of either the @AspectJ annotation-style approach or the Spring XML -configuration-style approach. The fact that this chapter chooses to introduce the -@AspectJ-style approach first should not be taken as an indication that the Spring team -favors the @AspectJ annotation-style approach over the Spring XML configuration-style. - -See <> for a more complete discussion of the whys and wherefores of each -style. -==== - - - -[[aop-introduction-proxies]] -==== AOP Proxies -Spring AOP defaults to using standard JDK __dynamic proxies__ for AOP proxies. This -enables any interface (or set of interfaces) to be proxied. - -Spring AOP can also use CGLIB proxies. This is necessary to proxy classes, rather than -interfaces. CGLIB is used by default if a business object does not implement an -interface. As it is good practice to program to interfaces rather than classes, business -classes normally will implement one or more business interfaces. It is possible to -<>, in those (hopefully rare) cases -where you need to advise a method that is not declared on an interface, or where you -need to pass a proxied object to a method as a concrete type. - -It is important to grasp the fact that Spring AOP is __proxy-based__. See -<> for a thorough examination of exactly what this -implementation detail actually means. - - - - -[[aop-ataspectj]] -=== @AspectJ support -@AspectJ refers to a style of declaring aspects as regular Java classes annotated with -annotations. The @AspectJ style was introduced by the -http://www.eclipse.org/aspectj[AspectJ project] as part of the AspectJ 5 release. Spring -interprets the same annotations as AspectJ 5, using a library supplied by AspectJ -for pointcut parsing and matching. The AOP runtime is still pure Spring AOP though, and -there is no dependency on the AspectJ compiler or weaver. - -[NOTE] -==== -Using the AspectJ compiler and weaver enables use of the full AspectJ language, and is -discussed in <>. -==== - - - -[[aop-aspectj-support]] -==== Enabling @AspectJ Support -To use @AspectJ aspects in a Spring configuration you need to enable Spring support for -configuring Spring AOP based on @AspectJ aspects, and __autoproxying__ beans based on -whether or not they are advised by those aspects. By autoproxying we mean that if Spring -determines that a bean is advised by one or more aspects, it will automatically generate -a proxy for that bean to intercept method invocations and ensure that advice is executed -as needed. - -The @AspectJ support can be enabled with XML or Java style configuration. In either -case you will also need to ensure that AspectJ's `aspectjweaver.jar` library is on the -classpath of your application (version 1.6.8 or later). This library is available in the -`'lib'` directory of an AspectJ distribution or via the Maven Central repository. - - -[[aop-enable-aspectj-java]] -===== Enabling @AspectJ Support with Java configuration -To enable @AspectJ support with Java `@Configuration` add the `@EnableAspectJAutoProxy` -annotation: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Configuration - @EnableAspectJAutoProxy - public class AppConfig { - - } ----- - - -[[aop-enable-aspectj-xml]] -===== Enabling @AspectJ Support with XML configuration -To enable @AspectJ support with XML based configuration use the `aop:aspectj-autoproxy` -element: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - ----- - -This assumes that you are using schema support as described in <>. See -<> for how to import the tags in the aop namespace. - - - -[[aop-at-aspectj]] -==== Declaring an aspect - -With the @AspectJ support enabled, any bean defined in your application context with a -class that is an @AspectJ aspect (has the `@Aspect` annotation) will be automatically -detected by Spring and used to configure Spring AOP. The following example shows the -minimal definition required for a not-very-useful aspect: - -A regular bean definition in the application context, pointing to a bean class that has -the `@Aspect` annotation: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - ----- - -And the `NotVeryUsefulAspect` class definition, annotated with -`org.aspectj.lang.annotation.Aspect` annotation; - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - package org.xyz; - import org.aspectj.lang.annotation.Aspect; - - @Aspect - public class NotVeryUsefulAspect { - - } ----- - -Aspects (classes annotated with `@Aspect`) may have methods and fields just like any -other class. They may also contain pointcut, advice, and introduction (inter-type) -declarations. - -.Autodetecting aspects through component scanning -[NOTE] -==== -You may register aspect classes as regular beans in your Spring XML configuration, or -autodetect them through classpath scanning - just like any other Spring-managed bean. -However, note that the __@Aspect__ annotation is __not__ sufficient for autodetection in -the classpath: For that purpose, you need to add a separate __@Component__ annotation -(or alternatively a custom stereotype annotation that qualifies, as per the rules of -Spring's component scanner). -==== - -.Advising aspects with other aspects? -[NOTE] -==== -In Spring AOP, it is __not__ possible to have aspects themselves be the target of advice -from other aspects. The __@Aspect__ annotation on a class marks it as an aspect, and -hence excludes it from auto-proxying. -==== - - - -[[aop-pointcuts]] -==== Declaring a pointcut -Recall that pointcuts determine join points of interest, and thus enable us to control -when advice executes. __Spring AOP only supports method execution join points for Spring -beans__, so you can think of a pointcut as matching the execution of methods on Spring -beans. A pointcut declaration has two parts: a signature comprising a name and any -parameters, and a pointcut expression that determines __exactly__ which method -executions we are interested in. In the @AspectJ annotation-style of AOP, a pointcut -signature is provided by a regular method definition, and the pointcut expression is -indicated using the `@Pointcut` annotation (the method serving as the pointcut signature -__must__ have a `void` return type). - -An example will help make this distinction between a pointcut signature and a pointcut -expression clear. The following example defines a pointcut named `'anyOldTransfer'` that -will match the execution of any method named `'transfer'`: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Pointcut("execution(* transfer(..))")// the pointcut expression - private void anyOldTransfer() {}// the pointcut signature ----- - -The pointcut expression that forms the value of the `@Pointcut` annotation is a regular -AspectJ 5 pointcut expression. For a full discussion of AspectJ's pointcut language, see -the http://www.eclipse.org/aspectj/doc/released/progguide/index.html[AspectJ -Programming Guide] (and for extensions, the -http://www.eclipse.org/aspectj/doc/released/adk15notebook/index.html[AspectJ 5 -Developers Notebook]) or one of the books on AspectJ such as "Eclipse AspectJ" by Colyer -et. al. or "AspectJ in Action" by Ramnivas Laddad. - - -[[aop-pointcuts-designators]] -===== Supported Pointcut Designators -Spring AOP supports the following AspectJ pointcut designators (PCD) for use in pointcut -expressions: - -.Other pointcut types -**** -The full AspectJ pointcut language supports additional pointcut designators that are not -supported in Spring. These are: `call, get, set, preinitialization, -staticinitialization, initialization, handler, adviceexecution, withincode, cflow, -cflowbelow, if, @this`, and `@withincode`. Use of these pointcut designators in pointcut -expressions interpreted by Spring AOP will result in an `IllegalArgumentException` being -thrown. - -The set of pointcut designators supported by Spring AOP may be extended in future -releases to support more of the AspectJ pointcut designators. -**** - -* __execution__ - for matching method execution join points, this is the primary - pointcut designator you will use when working with Spring AOP -* __within__ - limits matching to join points within certain types (simply the execution - of a method declared within a matching type when using Spring AOP) -* __this__ - limits matching to join points (the execution of methods when using Spring - AOP) where the bean reference (Spring AOP proxy) is an instance of the given type -* __target__ - limits matching to join points (the execution of methods when using - Spring AOP) where the target object (application object being proxied) is an instance - of the given type -* __args__ - limits matching to join points (the execution of methods when using Spring - AOP) where the arguments are instances of the given types -* __@target__ - limits matching to join points (the execution of methods when using - Spring AOP) where the class of the executing object has an annotation of the given type -* __@args__ - limits matching to join points (the execution of methods when using Spring - AOP) where the runtime type of the actual arguments passed have annotations of the - given type(s) -* __@within__ - limits matching to join points within types that have the given - annotation (the execution of methods declared in types with the given annotation when - using Spring AOP) -* __@annotation__ - limits matching to join points where the subject of the join point - (method being executed in Spring AOP) has the given annotation - -Because Spring AOP limits matching to only method execution join points, the discussion -of the pointcut designators above gives a narrower definition than you will find in the -AspectJ programming guide. In addition, AspectJ itself has type-based semantics and at -an execution join point both '++this++' and '++target++' refer to the same object - the -object executing the method. Spring AOP is a proxy-based system and differentiates -between the proxy object itself (bound to '++this++') and the target object behind the -proxy (bound to '++target++'). - -[NOTE] -==== -Due to the proxy-based nature of Spring's AOP framework, protected methods are by -definition __not__ intercepted, neither for JDK proxies (where this isn't applicable) -nor for CGLIB proxies (where this is technically possible but not recommendable for AOP -purposes). As a consequence, any given pointcut will be matched against __public methods -only__! - -If your interception needs include protected/private methods or even constructors, -consider the use of Spring-driven <> instead of -Spring's proxy-based AOP framework. This constitutes a different mode of AOP usage with -different characteristics, so be sure to make yourself familiar with weaving first -before making a decision. -==== - -Spring AOP also supports an additional PCD named '++bean++'. This PCD allows you to limit -the matching of join points to a particular named Spring bean, or to a set of named -Spring beans (when using wildcards). The '++bean++' PCD has the following form: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - bean(idOrNameOfBean) ----- - -The '++idOrNameOfBean++' token can be the name of any Spring bean: limited wildcard -support using the '++*++' character is provided, so if you establish some naming -conventions for your Spring beans you can quite easily write a '++bean++' PCD expression -to pick them out. As is the case with other pointcut designators, the '++bean++' PCD can -be &&'ed, ||'ed, and ! (negated) too. - -[NOTE] -==== -Please note that the '++bean++' PCD is __only__ supported in Spring AOP - and __not__ in -native AspectJ weaving. It is a Spring-specific extension to the standard PCDs that -AspectJ defines. - -The '++bean++' PCD operates at the __instance__ level (building on the Spring bean name -concept) rather than at the type level only (which is what weaving-based AOP is limited -to). Instance-based pointcut designators are a special capability of Spring's -proxy-based AOP framework and its close integration with the Spring bean factory, where -it is natural and straightforward to identify specific beans by name. -==== - - -[[aop-pointcuts-combining]] -===== Combining pointcut expressions -Pointcut expressions can be combined using '&&', '||' and '!'. It is also possible to -refer to pointcut expressions by name. The following example shows three pointcut -expressions: `anyPublicOperation` (which matches if a method execution join point -represents the execution of any public method); `inTrading` (which matches if a method -execution is in the trading module), and `tradingOperation` (which matches if a method -execution represents any public method in the trading module). - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Pointcut("execution(public * *(..))") - private void anyPublicOperation() {} - - @Pointcut("within(com.xyz.someapp.trading..*)") - private void inTrading() {} - - @Pointcut("anyPublicOperation() && inTrading()") - private void tradingOperation() {} ----- - -It is a best practice to build more complex pointcut expressions out of smaller named -components as shown above. When referring to pointcuts by name, normal Java visibility -rules apply (you can see private pointcuts in the same type, protected pointcuts in the -hierarchy, public pointcuts anywhere and so on). Visibility does not affect pointcut -__matching__. - - -[[aop-common-pointcuts]] -===== Sharing common pointcut definitions -When working with enterprise applications, you often want to refer to modules of the -application and particular sets of operations from within several aspects. We recommend -defining a "SystemArchitecture" aspect that captures common pointcut expressions for -this purpose. A typical such aspect would look as follows: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - package com.xyz.someapp; - - import org.aspectj.lang.annotation.Aspect; - import org.aspectj.lang.annotation.Pointcut; - - @Aspect - public class SystemArchitecture { - - /** - * A join point is in the web layer if the method is defined - * in a type in the com.xyz.someapp.web package or any sub-package - * under that. - */ - @Pointcut("within(com.xyz.someapp.web..*)") - public void inWebLayer() {} - - /** - * A join point is in the service layer if the method is defined - * in a type in the com.xyz.someapp.service package or any sub-package - * under that. - */ - @Pointcut("within(com.xyz.someapp.service..*)") - public void inServiceLayer() {} - - /** - * A join point is in the data access layer if the method is defined - * in a type in the com.xyz.someapp.dao package or any sub-package - * under that. - */ - @Pointcut("within(com.xyz.someapp.dao..*)") - public void inDataAccessLayer() {} - - /** - * A business service is the execution of any method defined on a service - * interface. This definition assumes that interfaces are placed in the - * "service" package, and that implementation types are in sub-packages. - * - * If you group service interfaces by functional area (for example, - * in packages com.xyz.someapp.abc.service and com.xyz.someapp.def.service) then - * the pointcut expression "execution(* com.xyz.someapp..service.*.*(..))" - * could be used instead. - * - * Alternatively, you can write the expression using the 'bean' - * PCD, like so "bean(*Service)". (This assumes that you have - * named your Spring service beans in a consistent fashion.) - */ - @Pointcut("execution(* com.xyz.someapp..service.*.*(..))") - public void businessService() {} - - /** - * A data access operation is the execution of any method defined on a - * dao interface. This definition assumes that interfaces are placed in the - * "dao" package, and that implementation types are in sub-packages. - */ - @Pointcut("execution(* com.xyz.someapp.dao.*.*(..))") - public void dataAccessOperation() {} - - } ----- - -The pointcuts defined in such an aspect can be referred to anywhere that you need a -pointcut expression. For example, to make the service layer transactional, you could -write: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - - ----- - -The `` and `` elements are discussed in <>. The -transaction elements are discussed in <>. - - -[[aop-pointcuts-examples]] -===== Examples -Spring AOP users are likely to use the `execution` pointcut designator the most often. -The format of an execution expression is: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - execution(modifiers-pattern? ret-type-pattern declaring-type-pattern? name-pattern(param-pattern) - throws-pattern?) ----- - -All parts except the returning type pattern (ret-type-pattern in the snippet above), -name pattern, and parameters pattern are optional. The returning type pattern determines -what the return type of the method must be in order for a join point to be matched. Most -frequently you will use `*` as the returning type pattern, which matches any return -type. A fully-qualified type name will match only when the method returns the given -type. The name pattern matches the method name. You can use the `*` wildcard as all or -part of a name pattern. The parameters pattern is slightly more complex: `()` matches a -method that takes no parameters, whereas `(..)` matches any number of parameters (zero -or more). The pattern `(*)` matches a method taking one parameter of any type, -`(*,String)` matches a method taking two parameters, the first can be of any type, the -second must be a String. Consult the -http://www.eclipse.org/aspectj/doc/released/progguide/semantics-pointcuts.html[Language -Semantics] section of the AspectJ Programming Guide for more information. - -Some examples of common pointcut expressions are given below. - -* the execution of any public method: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - execution(public * *(..)) ----- - -* the execution of any method with a name beginning with "set": - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - execution(* set*(..)) ----- - -* the execution of any method defined by the `AccountService` interface: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - execution(* com.xyz.service.AccountService.*(..)) ----- - -* the execution of any method defined in the service package: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - execution(* com.xyz.service.*.*(..)) ----- - -* the execution of any method defined in the service package or a sub-package: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - execution(* com.xyz.service..*.*(..)) ----- - -* any join point (method execution only in Spring AOP) within the service package: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - within(com.xyz.service.*) ----- - -* any join point (method execution only in Spring AOP) within the service package or a - sub-package: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - within(com.xyz.service..*) ----- - -* any join point (method execution only in Spring AOP) where the proxy implements the - `AccountService` interface: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - this(com.xyz.service.AccountService) ----- - -[NOTE] -==== -'this' is more commonly used in a binding form :- see the following section on advice -for how to make the proxy object available in the advice body. -==== - -* any join point (method execution only in Spring AOP) where the target object - implements the `AccountService` interface: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - target(com.xyz.service.AccountService) ----- - -[NOTE] -==== -'target' is more commonly used in a binding form :- see the following section on advice -for how to make the target object available in the advice body. -==== - -* any join point (method execution only in Spring AOP) which takes a single parameter, - and where the argument passed at runtime is `Serializable`: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - args(java.io.Serializable) ----- - -[NOTE] -==== -'args' is more commonly used in a binding form :- see the following section on advice -for how to make the method arguments available in the advice body. -==== - -Note that the pointcut given in this example is different to `execution(* -*(java.io.Serializable))`: the args version matches if the argument passed at runtime is -Serializable, the execution version matches if the method signature declares a single -parameter of type `Serializable`. - -* any join point (method execution only in Spring AOP) where the target object has an - `@Transactional` annotation: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @target(org.springframework.transaction.annotation.Transactional) ----- - -[NOTE] -==== -'@target' can also be used in a binding form :- see the following section on advice for -how to make the annotation object available in the advice body. -==== - -* any join point (method execution only in Spring AOP) where the declared type of the - target object has an `@Transactional` annotation: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @within(org.springframework.transaction.annotation.Transactional) ----- - -[NOTE] -==== -'@within' can also be used in a binding form :- see the following section on advice for -how to make the annotation object available in the advice body. -==== - -* any join point (method execution only in Spring AOP) where the executing method has an - `@Transactional` annotation: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @annotation(org.springframework.transaction.annotation.Transactional) ----- - -[NOTE] -==== -'@annotation' can also be used in a binding form :- see the following section on advice -for how to make the annotation object available in the advice body. -==== - -* any join point (method execution only in Spring AOP) which takes a single parameter, - and where the runtime type of the argument passed has the `@Classified` annotation: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @args(com.xyz.security.Classified) ----- - -[NOTE] -==== -'@args' can also be used in a binding form :- see the following section on advice for -how to make the annotation object(s) available in the advice body. -==== - -* any join point (method execution only in Spring AOP) on a Spring bean named - '++tradeService++': - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - bean(tradeService) ----- - -* any join point (method execution only in Spring AOP) on Spring beans having names that - match the wildcard expression '++*Service++': - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - bean(*Service) ----- - - -[[writing-good-pointcuts]] -===== Writing good pointcuts -During compilation, AspectJ processes pointcuts in order to try and optimize matching -performance. Examining code and determining if each join point matches (statically or -dynamically) a given pointcut is a costly process. (A dynamic match means the match -cannot be fully determined from static analysis and a test will be placed in the code to -determine if there is an actual match when the code is running). On first encountering a -pointcut declaration, AspectJ will rewrite it into an optimal form for the matching -process. What does this mean? Basically pointcuts are rewritten in DNF (Disjunctive -Normal Form) and the components of the pointcut are sorted such that those components -that are cheaper to evaluate are checked first. This means you do not have to worry -about understanding the performance of various pointcut designators and may supply them -in any order in a pointcut declaration. - -However, AspectJ can only work with what it is told, and for optimal performance of -matching you should think about what they are trying to achieve and narrow the search -space for matches as much as possible in the definition. The existing designators -naturally fall into one of three groups: kinded, scoping and context: - -* Kinded designators are those which select a particular kind of join point. For - example: execution, get, set, call, handler -* Scoping designators are those which select a group of join points of interest (of - probably many kinds). For example: within, withincode -* Contextual designators are those that match (and optionally bind) based on context. - For example: this, target, @annotation - -A well written pointcut should try and include at least the first two types (kinded and -scoping), whilst the contextual designators may be included if wishing to match based on -join point context, or bind that context for use in the advice. Supplying either just a -kinded designator or just a contextual designator will work but could affect weaving -performance (time and memory used) due to all the extra processing and analysis. Scoping -designators are very fast to match and their usage means AspectJ can very quickly -dismiss groups of join points that should not be further processed - that is why a good -pointcut should always include one if possible. - - - -[[aop-advice]] -==== Declaring advice -Advice is associated with a pointcut expression, and runs before, after, or around -method executions matched by the pointcut. The pointcut expression may be either a -simple reference to a named pointcut, or a pointcut expression declared in place. - - -[[aop-advice-before]] -===== Before advice -Before advice is declared in an aspect using the `@Before` annotation: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - import org.aspectj.lang.annotation.Aspect; - import org.aspectj.lang.annotation.Before; - - @Aspect - public class BeforeExample { - - @Before("com.xyz.myapp.SystemArchitecture.dataAccessOperation()") - public void doAccessCheck() { - // ... - } - - } ----- - -If using an in-place pointcut expression we could rewrite the above example as: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - import org.aspectj.lang.annotation.Aspect; - import org.aspectj.lang.annotation.Before; - - @Aspect - public class BeforeExample { - - @Before("execution(* com.xyz.myapp.dao.*.*(..))") - public void doAccessCheck() { - // ... - } - - } ----- - - -[[aop-advice-after-returning]] -===== After returning advice -After returning advice runs when a matched method execution returns normally. It is -declared using the `@AfterReturning` annotation: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - import org.aspectj.lang.annotation.Aspect; - import org.aspectj.lang.annotation.AfterReturning; - - @Aspect - public class AfterReturningExample { - - @AfterReturning("com.xyz.myapp.SystemArchitecture.dataAccessOperation()") - public void doAccessCheck() { - // ... - } - - } ----- - -[NOTE] -==== -Note: it is of course possible to have multiple advice declarations, and other members -as well, all inside the same aspect. We're just showing a single advice declaration in -these examples to focus on the issue under discussion at the time. -==== - -Sometimes you need access in the advice body to the actual value that was returned. You -can use the form of `@AfterReturning` that binds the return value for this: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - import org.aspectj.lang.annotation.Aspect; - import org.aspectj.lang.annotation.AfterReturning; - - @Aspect - public class AfterReturningExample { - - @AfterReturning( - pointcut="com.xyz.myapp.SystemArchitecture.dataAccessOperation()", - returning="retVal") - public void doAccessCheck(Object retVal) { - // ... - } - - } ----- - -The name used in the `returning` attribute must correspond to the name of a parameter in -the advice method. When a method execution returns, the return value will be passed to -the advice method as the corresponding argument value. A `returning` clause also -restricts matching to only those method executions that return a value of the specified -type ( `Object` in this case, which will match any return value). - -Please note that it is __not__ possible to return a totally different reference when -using after-returning advice. - - -[[aop-advice-after-throwing]] -===== After throwing advice -After throwing advice runs when a matched method execution exits by throwing an -exception. It is declared using the `@AfterThrowing` annotation: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - import org.aspectj.lang.annotation.Aspect; - import org.aspectj.lang.annotation.AfterThrowing; - - @Aspect - public class AfterThrowingExample { - - @AfterThrowing("com.xyz.myapp.SystemArchitecture.dataAccessOperation()") - public void doRecoveryActions() { - // ... - } - - } ----- - -Often you want the advice to run only when exceptions of a given type are thrown, and -you also often need access to the thrown exception in the advice body. Use the -`throwing` attribute to both restrict matching (if desired, use `Throwable` as the -exception type otherwise) and bind the thrown exception to an advice parameter. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - import org.aspectj.lang.annotation.Aspect; - import org.aspectj.lang.annotation.AfterThrowing; - - @Aspect - public class AfterThrowingExample { - - @AfterThrowing( - pointcut="com.xyz.myapp.SystemArchitecture.dataAccessOperation()", - throwing="ex") - public void doRecoveryActions(DataAccessException ex) { - // ... - } - - } ----- - -The name used in the `throwing` attribute must correspond to the name of a parameter in -the advice method. When a method execution exits by throwing an exception, the exception -will be passed to the advice method as the corresponding argument value. A `throwing` -clause also restricts matching to only those method executions that throw an exception -of the specified type ( `DataAccessException` in this case). - - -[[aop-advice-after-finally]] -===== After (finally) advice -After (finally) advice runs however a matched method execution exits. It is declared -using the `@After` annotation. After advice must be prepared to handle both normal and -exception return conditions. It is typically used for releasing resources, etc. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - import org.aspectj.lang.annotation.Aspect; - import org.aspectj.lang.annotation.After; - - @Aspect - public class AfterFinallyExample { - - @After("com.xyz.myapp.SystemArchitecture.dataAccessOperation()") - public void doReleaseLock() { - // ... - } - - } ----- - - -[[aop-ataspectj-around-advice]] -===== Around advice -The final kind of advice is around advice. Around advice runs "around" a matched method -execution. It has the opportunity to do work both before and after the method executes, -and to determine when, how, and even if, the method actually gets to execute at all. -Around advice is often used if you need to share state before and after a method -execution in a thread-safe manner (starting and stopping a timer for example). Always -use the least powerful form of advice that meets your requirements (i.e. don't use -around advice if simple before advice would do). - -Around advice is declared using the `@Around` annotation. The first parameter of the -advice method must be of type `ProceedingJoinPoint`. Within the body of the advice, -calling `proceed()` on the `ProceedingJoinPoint` causes the underlying method to -execute. The `proceed` method may also be called passing in an `Object[]` - the values -in the array will be used as the arguments to the method execution when it proceeds. - -[NOTE] -==== -The behavior of proceed when called with an Object[] is a little different than the -behavior of proceed for around advice compiled by the AspectJ compiler. For around -advice written using the traditional AspectJ language, the number of arguments passed to -proceed must match the number of arguments passed to the around advice (not the number -of arguments taken by the underlying join point), and the value passed to proceed in a -given argument position supplants the original value at the join point for the entity -the value was bound to (Don't worry if this doesn't make sense right now!). The approach -taken by Spring is simpler and a better match to its proxy-based, execution only -semantics. You only need to be aware of this difference if you are compiling @AspectJ -aspects written for Spring and using proceed with arguments with the AspectJ compiler -and weaver. There is a way to write such aspects that is 100% compatible across both -Spring AOP and AspectJ, and this is discussed in the following section on advice -parameters. -==== - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - import org.aspectj.lang.annotation.Aspect; - import org.aspectj.lang.annotation.Around; - import org.aspectj.lang.ProceedingJoinPoint; - - @Aspect - public class AroundExample { - - @Around("com.xyz.myapp.SystemArchitecture.businessService()") - public Object doBasicProfiling(ProceedingJoinPoint pjp) throws Throwable { - // start stopwatch - Object retVal = pjp.proceed(); - // stop stopwatch - return retVal; - } - - } ----- - -The value returned by the around advice will be the return value seen by the caller of -the method. A simple caching aspect for example could return a value from a cache if it -has one, and invoke proceed() if it does not. Note that proceed may be invoked once, -many times, or not at all within the body of the around advice, all of these are quite -legal. - - -[[aop-ataspectj-advice-params]] -===== Advice parameters -Spring offers fully typed advice - meaning that you declare the parameters you need -in the advice signature (as we saw for the returning and throwing examples above) rather -than work with `Object[]` arrays all the time. We'll see how to make argument and other -contextual values available to the advice body in a moment. First let's take a look at -how to write generic advice that can find out about the method the advice is currently -advising. - -[[aop-ataspectj-advice-params-the-joinpoint]] -====== Access to the current JoinPoint - -Any advice method may declare as its first parameter, a parameter of type -`org.aspectj.lang.JoinPoint` (please note that around advice is __required__ to declare -a first parameter of type `ProceedingJoinPoint`, which is a subclass of `JoinPoint`. The -`JoinPoint` interface provides a number of useful methods such as `getArgs()` (returns -the method arguments), `getThis()` (returns the proxy object), `getTarget()` (returns -the target object), `getSignature()` (returns a description of the method that is being -advised) and `toString()` (prints a useful description of the method being advised). -Please do consult the javadocs for full details. - -[[aop-ataspectj-advice-params-passing]] -====== Passing parameters to advice -We've already seen how to bind the returned value or exception value (using after -returning and after throwing advice). To make argument values available to the advice -body, you can use the binding form of `args`. If a parameter name is used in place of a -type name in an args expression, then the value of the corresponding argument will be -passed as the parameter value when the advice is invoked. An example should make this -clearer. Suppose you want to advise the execution of dao operations that take an Account -object as the first parameter, and you need access to the account in the advice body. -You could write the following: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Before("com.xyz.myapp.SystemArchitecture.dataAccessOperation() && args(account,..)") - public void validateAccount(Account account) { - // ... - } ----- - -The `args(account,..)` part of the pointcut expression serves two purposes: firstly, it -restricts matching to only those method executions where the method takes at least one -parameter, and the argument passed to that parameter is an instance of `Account`; -secondly, it makes the actual `Account` object available to the advice via the `account` -parameter. - -Another way of writing this is to declare a pointcut that "provides" the `Account` -object value when it matches a join point, and then just refer to the named pointcut -from the advice. This would look as follows: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Pointcut("com.xyz.myapp.SystemArchitecture.dataAccessOperation() && args(account,..)") - private void accountDataAccessOperation(Account account) {} - - @Before("accountDataAccessOperation(account)") - public void validateAccount(Account account) { - // ... - } ----- - -The interested reader is once more referred to the AspectJ programming guide for more -details. - -The proxy object ( `this`), target object ( `target`), and annotations ( `@within, -@target, @annotation, @args`) can all be bound in a similar fashion. The following -example shows how you could match the execution of methods annotated with an -`@Auditable` annotation, and extract the audit code. - -First the definition of the `@Auditable` annotation: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Retention(RetentionPolicy.RUNTIME) - @Target(ElementType.METHOD) - public @interface Auditable { - AuditCode value(); - } ----- - -And then the advice that matches the execution of `@Auditable` methods: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Before("com.xyz.lib.Pointcuts.anyPublicMethod() && @annotation(auditable)") - public void audit(Auditable auditable) { - AuditCode code = auditable.value(); - // ... - } ----- - -[[aop-ataspectj-advice-params-generics]] -====== Advice parameters and generics -Spring AOP can handle generics used in class declarations and method parameters. Suppose -you have a generic type like this: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public interface Sample { - void sampleGenericMethod(T param); - void sampleGenericCollectionMethod(Collection>T> param); - } ----- - -You can restrict interception of method types to certain parameter types by simply -typing the advice parameter to the parameter type you want to intercept the method for: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Before("execution(* ..Sample+.sampleGenericMethod(*)) && args(param)") - public void beforeSampleMethod(MyType param) { - // Advice implementation - } ----- - -That this works is pretty obvious as we already discussed above. However, it's worth -pointing out that this won't work for generic collections. So you cannot define a -pointcut like this: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Before("execution(* ..Sample+.sampleGenericCollectionMethod(*)) && args(param)") - public void beforeSampleMethod(Collection param) { - // Advice implementation - } ----- - -To make this work we would have to inspect every element of the collection, which is not -reasonable as we also cannot decide how to treat `null` values in general. To achieve -something similar to this you have to type the parameter to `Collection` and manually -check the type of the elements. - -[[aop-ataspectj-advice-params-names]] -====== Determining argument names -The parameter binding in advice invocations relies on matching names used in pointcut -expressions to declared parameter names in (advice and pointcut) method signatures. -Parameter names are __not__ available through Java reflection, so Spring AOP uses the -following strategies to determine parameter names: - -* If the parameter names have been specified by the user explicitly, then the specified - parameter names are used: both the advice and the pointcut annotations have - an optional "argNames" attribute which can be used to specify the argument names of - the annotated method - these argument names __are__ available at runtime. For example: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Before(value="com.xyz.lib.Pointcuts.anyPublicMethod() && target(bean) && @annotation(auditable)", - argNames="bean,auditable") - public void audit(Object bean, Auditable auditable) { - AuditCode code = auditable.value(); - // ... use code and bean - } ----- - -If the first parameter is of the `JoinPoint`, `ProceedingJoinPoint`, or -`JoinPoint.StaticPart` type, you may leave out the name of the parameter from the value -of the "argNames" attribute. For example, if you modify the preceding advice to receive -the join point object, the "argNames" attribute need not include it: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Before(value="com.xyz.lib.Pointcuts.anyPublicMethod() && target(bean) && @annotation(auditable)", - argNames="bean,auditable") - public void audit(JoinPoint jp, Object bean, Auditable auditable) { - AuditCode code = auditable.value(); - // ... use code, bean, and jp - } ----- - -The special treatment given to the first parameter of the `JoinPoint`, -`ProceedingJoinPoint`, and `JoinPoint.StaticPart` types is particularly convenient for -advice that do not collect any other join point context. In such situations, you may -simply omit the "argNames" attribute. For example, the following advice need not declare -the "argNames" attribute: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Before("com.xyz.lib.Pointcuts.anyPublicMethod()") - public void audit(JoinPoint jp) { - // ... use jp - } ----- - -* Using the `'argNames'` attribute is a little clumsy, so if the `'argNames'` attribute - has not been specified, then Spring AOP will look at the debug information for the - class and try to determine the parameter names from the local variable table. This - information will be present as long as the classes have been compiled with debug - information ( `'-g:vars'` at a minimum). The consequences of compiling with this flag - on are: (1) your code will be slightly easier to understand (reverse engineer), (2) - the class file sizes will be very slightly bigger (typically inconsequential), (3) the - optimization to remove unused local variables will not be applied by your compiler. In - other words, you should encounter no difficulties building with this flag on. - -[NOTE] -==== -If an @AspectJ aspect has been compiled by the AspectJ compiler (ajc) even without the -debug information then there is no need to add the argNames attribute as the compiler -will retain the needed information. -==== - -* If the code has been compiled without the necessary debug information, then Spring AOP - will attempt to deduce the pairing of binding variables to parameters (for example, if - only one variable is bound in the pointcut expression, and the advice method only - takes one parameter, the pairing is obvious!). If the binding of variables is - ambiguous given the available information, then an `AmbiguousBindingException` will be - thrown. -* If all of the above strategies fail then an `IllegalArgumentException` will be thrown. - -[[aop-ataspectj-advice-proceeding-with-the-call]] -====== Proceeding with arguments -We remarked earlier that we would describe how to write a proceed call __with -arguments__ that works consistently across Spring AOP and AspectJ. The solution is -simply to ensure that the advice signature binds each of the method parameters in order. -For example: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Around("execution(List find*(..)) && " + - "com.xyz.myapp.SystemArchitecture.inDataAccessLayer() && " + - "args(accountHolderNamePattern)") - public Object preProcessQueryPattern(ProceedingJoinPoint pjp, - String accountHolderNamePattern) throws Throwable { - String newPattern = preProcess(accountHolderNamePattern); - return pjp.proceed(new Object[] {newPattern}); - } ----- - -In many cases you will be doing this binding anyway (as in the example above). - - -[[aop-ataspectj-advice-ordering]] -===== Advice ordering -What happens when multiple pieces of advice all want to run at the same join point? -Spring AOP follows the same precedence rules as AspectJ to determine the order of advice -execution. The highest precedence advice runs first "on the way in" (so given two pieces -of before advice, the one with highest precedence runs first). "On the way out" from a -join point, the highest precedence advice runs last (so given two pieces of after -advice, the one with the highest precedence will run second). - -When two pieces of advice defined in __different__ aspects both need to run at the same -join point, unless you specify otherwise the order of execution is undefined. You can -control the order of execution by specifying precedence. This is done in the normal -Spring way by either implementing the `org.springframework.core.Ordered` interface in -the aspect class or annotating it with the `Order` annotation. Given two aspects, the -aspect returning the lower value from `Ordered.getValue()` (or the annotation value) has -the higher precedence. - -When two pieces of advice defined in __the same__ aspect both need to run at the same -join point, the ordering is undefined (since there is no way to retrieve the declaration -order via reflection for javac-compiled classes). Consider collapsing such advice -methods into one advice method per join point in each aspect class, or refactor the -pieces of advice into separate aspect classes - which can be ordered at the aspect level. - - - -[[aop-introductions]] -==== Introductions -Introductions (known as inter-type declarations in AspectJ) enable an aspect to declare -that advised objects implement a given interface, and to provide an implementation of -that interface on behalf of those objects. - -An introduction is made using the `@DeclareParents` annotation. This annotation is used -to declare that matching types have a new parent (hence the name). For example, given an -interface `UsageTracked`, and an implementation of that interface `DefaultUsageTracked`, -the following aspect declares that all implementors of service interfaces also implement -the `UsageTracked` interface. (In order to expose statistics via JMX for example.) - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Aspect - public class UsageTracking { - - @DeclareParents(value="com.xzy.myapp.service.*+", defaultImpl=DefaultUsageTracked.class) - public static UsageTracked mixin; - - @Before("com.xyz.myapp.SystemArchitecture.businessService() && this(usageTracked)") - public void recordUsage(UsageTracked usageTracked) { - usageTracked.incrementUseCount(); - } - - } ----- - -The interface to be implemented is determined by the type of the annotated field. The -`value` attribute of the `@DeclareParents` annotation is an AspectJ type pattern :- any -bean of a matching type will implement the UsageTracked interface. Note that in the -before advice of the above example, service beans can be directly used as -implementations of the `UsageTracked` interface. If accessing a bean programmatically -you would write the following: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - UsageTracked usageTracked = (UsageTracked) context.getBean("myService"); ----- - - - -[[aop-instantiation-models]] -==== Aspect instantiation models -[NOTE] -==== -(This is an advanced topic, so if you are just starting out with AOP you can safely skip -it until later.) -==== - -By default there will be a single instance of each aspect within the application -context. AspectJ calls this the singleton instantiation model. It is possible to define -aspects with alternate lifecycles :- Spring supports AspectJ's `perthis` and `pertarget` -instantiation models ( `percflow, percflowbelow,` and `pertypewithin` are not currently -supported). - -A "perthis" aspect is declared by specifying a `perthis` clause in the `@Aspect` -annotation. Let's look at an example, and then we'll explain how it works. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Aspect("perthis(com.xyz.myapp.SystemArchitecture.businessService())") - public class MyAspect { - - private int someState; - - @Before(com.xyz.myapp.SystemArchitecture.businessService()) - public void recordServiceUsage() { - // ... - } - - } ----- - -The effect of the `'perthis'` clause is that one aspect instance will be created for -each unique service object executing a business service (each unique object bound to -'this' at join points matched by the pointcut expression). The aspect instance is -created the first time that a method is invoked on the service object. The aspect goes -out of scope when the service object goes out of scope. Before the aspect instance is -created, none of the advice within it executes. As soon as the aspect instance has been -created, the advice declared within it will execute at matched join points, but only -when the service object is the one this aspect is associated with. See the AspectJ -programming guide for more information on per-clauses. - -The `'pertarget'` instantiation model works in exactly the same way as perthis, but -creates one aspect instance for each unique target object at matched join points. - - - -[[aop-ataspectj-example]] -==== Example -Now that you have seen how all the constituent parts work, let's put them together to do -something useful! - -The execution of business services can sometimes fail due to concurrency issues (for -example, deadlock loser). If the operation is retried, it is quite likely to succeed -next time round. For business services where it is appropriate to retry in such -conditions (idempotent operations that don't need to go back to the user for conflict -resolution), we'd like to transparently retry the operation to avoid the client seeing a -`PessimisticLockingFailureException`. This is a requirement that clearly cuts across -multiple services in the service layer, and hence is ideal for implementing via an -aspect. - -Because we want to retry the operation, we will need to use around advice so that we can -call proceed multiple times. Here's how the basic aspect implementation looks: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Aspect - public class ConcurrentOperationExecutor implements Ordered { - - private static final int DEFAULT_MAX_RETRIES = 2; - - private int maxRetries = DEFAULT_MAX_RETRIES; - private int order = 1; - - public void setMaxRetries(int maxRetries) { - this.maxRetries = maxRetries; - } - - public int getOrder() { - return this.order; - } - - public void setOrder(int order) { - this.order = order; - } - - @Around("com.xyz.myapp.SystemArchitecture.businessService()") - public Object doConcurrentOperation(ProceedingJoinPoint pjp) throws Throwable { - int numAttempts = 0; - PessimisticLockingFailureException lockFailureException; - do { - numAttempts++; - try { - return pjp.proceed(); - } - catch(PessimisticLockingFailureException ex) { - lockFailureException = ex; - } - } while(numAttempts <= this.maxRetries); - throw lockFailureException; - } - - } ----- - -Note that the aspect implements the `Ordered` interface so we can set the precedence of -the aspect higher than the transaction advice (we want a fresh transaction each time we -retry). The `maxRetries` and `order` properties will both be configured by Spring. The -main action happens in the `doConcurrentOperation` around advice. Notice that for the -moment we're applying the retry logic to all `businessService()s`. We try to proceed, -and if we fail with an `PessimisticLockingFailureException` we simply try again unless -we have exhausted all of our retry attempts. - -The corresponding Spring configuration is: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - ----- - -To refine the aspect so that it only retries idempotent operations, we might define an -`Idempotent` annotation: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Retention(RetentionPolicy.RUNTIME) - public @interface Idempotent { - // marker annotation - } ----- - -and use the annotation to annotate the implementation of service operations. The change -to the aspect to only retry idempotent operations simply involves refining the pointcut -expression so that only `@Idempotent` operations match: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Around("com.xyz.myapp.SystemArchitecture.businessService() && " + - "@annotation(com.xyz.myapp.service.Idempotent)") - public Object doConcurrentOperation(ProceedingJoinPoint pjp) throws Throwable { - ... - } ----- - - - - -[[aop-schema]] -=== Schema-based AOP support -If you prefer an XML-based format, then Spring also offers support for defining aspects -using the new "aop" namespace tags. The exact same pointcut expressions and advice kinds -are supported as when using the @AspectJ style, hence in this section we will focus on -the new __syntax__ and refer the reader to the discussion in the previous section -(<>) for an understanding of writing pointcut expressions and the binding -of advice parameters. - -To use the aop namespace tags described in this section, you need to import the -spring-aop schema as described in <>. See <> -for how to import the tags in the aop namespace. - -Within your Spring configurations, all aspect and advisor elements must be placed within -an `` element (you can have more than one `` element in an -application context configuration). An `` element can contain pointcut, -advisor, and aspect elements (note these must be declared in that order). - -[WARNING] -==== - -The `` style of configuration makes heavy use of Spring's -<> mechanism. This can cause issues (such as advice not -being woven) if you are already using explicit auto-proxying via the use of -`BeanNameAutoProxyCreator` or suchlike. The recommended usage pattern is to use either -just the `` style, or just the `AutoProxyCreator` style. -==== - - - -[[aop-schema-declaring-an-aspect]] -==== Declaring an aspect -Using the schema support, an aspect is simply a regular Java object defined as a bean in -your Spring application context. The state and behavior is captured in the fields and -methods of the object, and the pointcut and advice information is captured in the XML. - -An aspect is declared using the element, and the backing bean is referenced -using the `ref` attribute: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - ... - - - - - ... - ----- - -The bean backing the aspect (" `aBean`" in this case) can of course be configured and -dependency injected just like any other Spring bean. - - - -[[aop-schema-pointcuts]] -==== Declaring a pointcut -A named pointcut can be declared inside an element, enabling the pointcut -definition to be shared across several aspects and advisors. - -A pointcut representing the execution of any business service in the service layer could -be defined as follows: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - ----- - -Note that the pointcut expression itself is using the same AspectJ pointcut expression -language as described in <>. If you are using the schema based -declaration style, you can refer to named pointcuts defined in types -(@Aspects) within the pointcut expression. Another way of defining the above pointcut -would be: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - ----- - -Assuming you have a `SystemArchitecture` aspect as described in <>. - -Declaring a pointcut inside an aspect is very similar to declaring a top-level pointcut: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - ... - - - - ----- - -Much the same way in an @AspectJ aspect, pointcuts declared using the schema based -definition style may collect join point context. For example, the following pointcut -collects the 'this' object as the join point context and passes it to advice: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - - ... - - - - ----- - -The advice must be declared to receive the collected join point context by including -parameters of the matching names: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public void monitor(Object service) { - ... - } ----- - -When combining pointcut sub-expressions, '&&' is awkward within an XML document, and so -the keywords 'and', 'or' and 'not' can be used in place of '&&', '||' and '!' -respectively. For example, the previous pointcut may be better written as: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - - ... - - ----- - -Note that pointcuts defined in this way are referred to by their XML id and cannot be -used as named pointcuts to form composite pointcuts. The named pointcut support in the -schema based definition style is thus more limited than that offered by the @AspectJ -style. - - - -[[aop-schema-advice]] -==== Declaring advice -The same five advice kinds are supported as for the @AspectJ style, and they have -exactly the same semantics. - - -[[aop-schema-advice-before]] -===== Before advice -Before advice runs before a matched method execution. It is declared inside an -`` using the element. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - ... - - ----- - -Here `dataAccessOperation` is the id of a pointcut defined at the top ( ``) -level. To define the pointcut inline instead, replace the `pointcut-ref` attribute with -a `pointcut` attribute: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - ... - - ----- - -As we noted in the discussion of the @AspectJ style, using named pointcuts can -significantly improve the readability of your code. - -The method attribute identifies a method ( `doAccessCheck`) that provides the body of -the advice. This method must be defined for the bean referenced by the aspect element -containing the advice. Before a data access operation is executed (a method execution -join point matched by the pointcut expression), the "doAccessCheck" method on the aspect -bean will be invoked. - - -[[aop-schema-advice-after-returning]] -===== After returning advice -After returning advice runs when a matched method execution completes normally. It is -declared inside an `` in the same way as before advice. For example: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - ... - - ----- - -Just as in the @AspectJ style, it is possible to get hold of the return value within the -advice body. Use the returning attribute to specify the name of the parameter to which -the return value should be passed: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - ... - - ----- - -The doAccessCheck method must declare a parameter named `retVal`. The type of this -parameter constrains matching in the same way as described for @AfterReturning. For -example, the method signature may be declared as: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public void doAccessCheck(Object retVal) {... ----- - - -[[aop-schema-advice-after-throwing]] -===== After throwing advice -After throwing advice executes when a matched method execution exits by throwing an -exception. It is declared inside an `` using the after-throwing element: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - ... - - ----- - -Just as in the @AspectJ style, it is possible to get hold of the thrown exception within -the advice body. Use the throwing attribute to specify the name of the parameter to -which the exception should be passed: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - ... - - ----- - -The doRecoveryActions method must declare a parameter named `dataAccessEx`. The type of -this parameter constrains matching in the same way as described for @AfterThrowing. For -example, the method signature may be declared as: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public void doRecoveryActions(DataAccessException dataAccessEx) {... ----- - - -[[aop-schema-advice-after-finally]] -===== After (finally) advice -After (finally) advice runs however a matched method execution exits. It is declared -using the `after` element: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - ... - - ----- - - -[[aop-schema-advice-around]] -===== Around advice -The final kind of advice is around advice. Around advice runs "around" a matched method -execution. It has the opportunity to do work both before and after the method executes, -and to determine when, how, and even if, the method actually gets to execute at all. -Around advice is often used if you need to share state before and after a method -execution in a thread-safe manner (starting and stopping a timer for example). Always -use the least powerful form of advice that meets your requirements; don't use around -advice if simple before advice would do. - -Around advice is declared using the `aop:around` element. The first parameter of the -advice method must be of type `ProceedingJoinPoint`. Within the body of the advice, -calling `proceed()` on the `ProceedingJoinPoint` causes the underlying method to -execute. The `proceed` method may also be calling passing in an `Object[]` - the values -in the array will be used as the arguments to the method execution when it proceeds. See -<> for notes on calling proceed with an `Object[]`. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - ... - - ----- - -The implementation of the `doBasicProfiling` advice would be exactly the same as in the -@AspectJ example (minus the annotation of course): - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public Object doBasicProfiling(ProceedingJoinPoint pjp) throws Throwable { - // start stopwatch - Object retVal = pjp.proceed(); - // stop stopwatch - return retVal; - } ----- - - -[[aop-schema-params]] -===== Advice parameters -The schema based declaration style supports fully typed advice in the same way as -described for the @AspectJ support - by matching pointcut parameters by name against -advice method parameters. See <> for details. If you wish -to explicitly specify argument names for the advice methods (not relying on the -detection strategies previously described) then this is done using the `arg-names` -attribute of the advice element, which is treated in the same manner to the "argNames" -attribute in an advice annotation as described in <>. -For example: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - ----- - -The `arg-names` attribute accepts a comma-delimited list of parameter names. - -Find below a slightly more involved example of the XSD-based approach that illustrates -some around advice used in conjunction with a number of strongly typed parameters. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - package x.y.service; - - public interface FooService { - - Foo getFoo(String fooName, int age); - } - - public class DefaultFooService implements FooService { - - public Foo getFoo(String name, int age) { - return new Foo(name, age); - } - } ----- - -Next up is the aspect. Notice the fact that the `profile(..)` method accepts a number of -strongly-typed parameters, the first of which happens to be the join point used to -proceed with the method call: the presence of this parameter is an indication that the -`profile(..)` is to be used as `around` advice: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - package x.y; - - import org.aspectj.lang.ProceedingJoinPoint; - import org.springframework.util.StopWatch; - - public class SimpleProfiler { - - public Object profile(ProceedingJoinPoint call, String name, int age) throws Throwable { - StopWatch clock = new StopWatch("Profiling for '" + name + "' and '" + age + "'"); - try { - clock.start(call.toShortString()); - return call.proceed(); - } finally { - clock.stop(); - System.out.println(clock.prettyPrint()); - } - } - } ----- - -Finally, here is the XML configuration that is required to effect the execution of the -above advice for a particular join point: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - - - - - - - - - - - - ----- - -If we had the following driver script, we would get output something like this on -standard output: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - import org.springframework.beans.factory.BeanFactory; - import org.springframework.context.support.ClassPathXmlApplicationContext; - import x.y.service.FooService; - - public final class Boot { - - public static void main(final String[] args) throws Exception { - BeanFactory ctx = new ClassPathXmlApplicationContext("x/y/plain.xml"); - FooService foo = (FooService) ctx.getBean("fooService"); - foo.getFoo("Pengo", 12); - } - } ----- - -[literal] -[subs="verbatim,quotes"] ----- -StopWatch 'Profiling for 'Pengo' and '12'': running time (millis) = 0 ------------------------------------------ -ms % Task name ------------------------------------------ -00000 ? execution(getFoo) ----- - - -[[aop-ordering]] -===== Advice ordering -When multiple advice needs to execute at the same join point (executing method) the -ordering rules are as described in <>. The precedence -between aspects is determined by either adding the `Order` annotation to the bean -backing the aspect or by having the bean implement the `Ordered` interface. - - - -[[aop-schema-introductions]] -==== Introductions -Introductions (known as inter-type declarations in AspectJ) enable an aspect to declare -that advised objects implement a given interface, and to provide an implementation of -that interface on behalf of those objects. - -An introduction is made using the `aop:declare-parents` element inside an `aop:aspect` -This element is used to declare that matching types have a new parent (hence the name). -For example, given an interface `UsageTracked`, and an implementation of that interface -`DefaultUsageTracked`, the following aspect declares that all implementors of service -interfaces also implement the `UsageTracked` interface. (In order to expose statistics -via JMX for example.) - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - ----- - -The class backing the `usageTracking` bean would contain the method: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public void recordUsage(UsageTracked usageTracked) { - usageTracked.incrementUseCount(); - } ----- - -The interface to be implemented is determined by `implement-interface` attribute. The -value of the `types-matching` attribute is an AspectJ type pattern :- any bean of a -matching type will implement the `UsageTracked` interface. Note that in the before -advice of the above example, service beans can be directly used as implementations of -the `UsageTracked` interface. If accessing a bean programmatically you would write the -following: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - UsageTracked usageTracked = (UsageTracked) context.getBean("myService"); ----- - - - -[[aop-schema-instatiation-models]] -==== Aspect instantiation models -The only supported instantiation model for schema-defined aspects is the singleton -model. Other instantiation models may be supported in future releases. - - - -[[aop-schema-advisors]] -==== Advisors -The concept of "advisors" is brought forward from the AOP support defined in Spring 1.2 -and does not have a direct equivalent in AspectJ. An advisor is like a small -self-contained aspect that has a single piece of advice. The advice itself is -represented by a bean, and must implement one of the advice interfaces described in -<>. Advisors can take advantage of AspectJ pointcut expressions -though. - -Spring supports the advisor concept with the `` element. You will most -commonly see it used in conjunction with transactional advice, which also has its own -namespace support in Spring. Here's how it looks: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - - - - - - ----- - -As well as the `pointcut-ref` attribute used in the above example, you can also use the -`pointcut` attribute to define a pointcut expression inline. - -To define the precedence of an advisor so that the advice can participate in ordering, -use the `order` attribute to define the `Ordered` value of the advisor. - - - -[[aop-schema-example]] -==== Example -Let's see how the concurrent locking failure retry example from -<> looks when rewritten using the schema support. - -The execution of business services can sometimes fail due to concurrency issues (for -example, deadlock loser). If the operation is retried, it is quite likely it will -succeed next time round. For business services where it is appropriate to retry in such -conditions (idempotent operations that don't need to go back to the user for conflict -resolution), we'd like to transparently retry the operation to avoid the client seeing a -`PessimisticLockingFailureException`. This is a requirement that clearly cuts across -multiple services in the service layer, and hence is ideal for implementing via an -aspect. - -Because we want to retry the operation, we'll need to use around advice so that we can -call proceed multiple times. Here's how the basic aspect implementation looks (it's just -a regular Java class using the schema support): - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class ConcurrentOperationExecutor implements Ordered { - - private static final int DEFAULT_MAX_RETRIES = 2; - - private int maxRetries = DEFAULT_MAX_RETRIES; - private int order = 1; - - public void setMaxRetries(int maxRetries) { - this.maxRetries = maxRetries; - } - - public int getOrder() { - return this.order; - } - - public void setOrder(int order) { - this.order = order; - } - - public Object doConcurrentOperation(ProceedingJoinPoint pjp) throws Throwable { - int numAttempts = 0; - PessimisticLockingFailureException lockFailureException; - do { - numAttempts++; - try { - return pjp.proceed(); - } - catch(PessimisticLockingFailureException ex) { - lockFailureException = ex; - } - } while(numAttempts <= this.maxRetries); - throw lockFailureException; - } - - } ----- - -Note that the aspect implements the `Ordered` interface so we can set the precedence of -the aspect higher than the transaction advice (we want a fresh transaction each time we -retry). The `maxRetries` and `order` properties will both be configured by Spring. The -main action happens in the `doConcurrentOperation` around advice method. We try to -proceed, and if we fail with a `PessimisticLockingFailureException` we simply try again -unless we have exhausted all of our retry attempts. - -[NOTE] -==== -This class is identical to the one used in the @AspectJ example, but with the -annotations removed. -==== - -The corresponding Spring configuration is: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - - - - - - - - - ----- - -Notice that for the time being we assume that all business services are idempotent. If -this is not the case we can refine the aspect so that it only retries genuinely -idempotent operations, by introducing an `Idempotent` annotation: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Retention(RetentionPolicy.RUNTIME) - public @interface Idempotent { - // marker annotation - } ----- - -and using the annotation to annotate the implementation of service operations. The -change to the aspect to retry only idempotent operations simply involves refining the -pointcut expression so that only `@Idempotent` operations match: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - ----- - - - - -[[aop-choosing]] -=== Choosing which AOP declaration style to use -Once you have decided that an aspect is the best approach for implementing a given -requirement, how do you decide between using Spring AOP or AspectJ, and between the -Aspect language (code) style, @AspectJ annotation style, or the Spring XML style? These -decisions are influenced by a number of factors including application requirements, -development tools, and team familiarity with AOP. - - - -[[aop-spring-or-aspectj]] -==== Spring AOP or full AspectJ? -Use the simplest thing that can work. Spring AOP is simpler than using full AspectJ as -there is no requirement to introduce the AspectJ compiler / weaver into your development -and build processes. If you only need to advise the execution of operations on Spring -beans, then Spring AOP is the right choice. If you need to advise objects not managed by -the Spring container (such as domain objects typically), then you will need to use -AspectJ. You will also need to use AspectJ if you wish to advise join points other than -simple method executions (for example, field get or set join points, and so on). - -When using AspectJ, you have the choice of the AspectJ language syntax (also known as -the "code style") or the @AspectJ annotation style. Clearly, if you are not using Java -5+ then the choice has been made for you... use the code style. If aspects play a large -role in your design, and you are able to use the http://www.eclipse.org/ajdt/[AspectJ -Development Tools (AJDT)] plugin for Eclipse, then the AspectJ language syntax is the -preferred option: it is cleaner and simpler because the language was purposefully -designed for writing aspects. If you are not using Eclipse, or have only a few aspects -that do not play a major role in your application, then you may want to consider using -the @AspectJ style and sticking with a regular Java compilation in your IDE, and adding -an aspect weaving phase to your build script. - - - -[[aop-ataspectj-or-xml]] -==== @AspectJ or XML for Spring AOP? -If you have chosen to use Spring AOP, then you have a choice of @AspectJ or XML style. -There are various tradeoffs to consider. - -The XML style will be most familiar to existing Spring users and it is backed by genuine -POJOs. When using AOP as a tool to configure enterprise services then XML can be a good -choice (a good test is whether you consider the pointcut expression to be a part of your -configuration you might want to change independently). With the XML style arguably it is -clearer from your configuration what aspects are present in the system. - -The XML style has two disadvantages. Firstly it does not fully encapsulate the -implementation of the requirement it addresses in a single place. The DRY principle says -that there should be a single, unambiguous, authoritative representation of any piece of -knowledge within a system. When using the XML style, the knowledge of __how__ a -requirement is implemented is split across the declaration of the backing bean class, -and the XML in the configuration file. When using the @AspectJ style there is a single -module - the aspect - in which this information is encapsulated. Secondly, the XML style -is slightly more limited in what it can express than the @AspectJ style: only the -"singleton" aspect instantiation model is supported, and it is not possible to combine -named pointcuts declared in XML. For example, in the @AspectJ style you can write -something like: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Pointcut(execution(* get*())) - public void propertyAccess() {} - - @Pointcut(execution(org.xyz.Account+ *(..)) - public void operationReturningAnAccount() {} - - @Pointcut(propertyAccess() && operationReturningAnAccount()) - public void accountPropertyAccess() {} ----- - -In the XML style I can declare the first two pointcuts: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - ----- - -The downside of the XML approach is that you cannot define the -'++accountPropertyAccess++' pointcut by combining these definitions. - -The @AspectJ style supports additional instantiation models, and richer pointcut -composition. It has the advantage of keeping the aspect as a modular unit. It also has -the advantage the @AspectJ aspects can be understood (and thus consumed) both by Spring -AOP and by AspectJ - so if you later decide you need the capabilities of AspectJ to -implement additional requirements then it is very easy to migrate to an AspectJ-based -approach. On balance the Spring team prefer the @AspectJ style whenever you have aspects -that do more than simple "configuration" of enterprise services. - - - - -[[aop-mixing-styles]] -=== Mixing aspect types -It is perfectly possible to mix @AspectJ style aspects using the autoproxying support, -schema-defined `` aspects, `` declared advisors and even -proxies and interceptors defined using the Spring 1.2 style in the same configuration. -All of these are implemented using the same underlying support mechanism and will -co-exist without any difficulty. - - - - -[[aop-proxying]] -=== Proxying mechanisms -Spring AOP uses either JDK dynamic proxies or CGLIB to create the proxy for a given -target object. (JDK dynamic proxies are preferred whenever you have a choice). - -If the target object to be proxied implements at least one interface then a JDK dynamic -proxy will be used. All of the interfaces implemented by the target type will be -proxied. If the target object does not implement any interfaces then a CGLIB proxy will -be created. - -If you want to force the use of CGLIB proxying (for example, to proxy every method -defined for the target object, not just those implemented by its interfaces) you can do -so. However, there are some issues to consider: - -* `final` methods cannot be advised, as they cannot be overridden. -* As of Spring 3.2, it is no longer necessary to add CGLIB to your project classpath, as - CGLIB classes are repackaged under org.springframework and included directly in the - spring-core JAR. This means that CGLIB-based proxy support 'just works' in the same - way that JDK dynamic proxies always have. -* The constructor of your proxied object will be called twice. This is a natural - consequence of the CGLIB proxy model whereby a subclass is generated for each proxied - object. For each proxied instance, two objects are created: the actual proxied object - and an instance of the subclass that implements the advice. This behavior is not - exhibited when using JDK proxies. Usually, calling the constructor of the proxied type - twice, is not an issue, as there are usually only assignments taking place and no real - logic is implemented in the constructor. - -To force the use of CGLIB proxies set the value of the `proxy-target-class` attribute of -the `` element to true: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - ----- - -To force CGLIB proxying when using the @AspectJ autoproxy support, set the -`'proxy-target-class'` attribute of the `` element to `true`: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - ----- - -[NOTE] -==== -Multiple `` sections are collapsed into a single unified auto-proxy creator -at runtime, which applies the __strongest__ proxy settings that any of the -`` sections (typically from different XML bean definition files) specified. -This also applies to the `` and `` -elements. - -To be clear: using '++proxy-target-class="true"++' on ``, -`` or `` elements will force the use of CGLIB -proxies __for all three of them__. -==== - - - -[[aop-understanding-aop-proxies]] -==== Understanding AOP proxies -Spring AOP is __proxy-based__. It is vitally important that you grasp the semantics of -what that last statement actually means before you write your own aspects or use any of -the Spring AOP-based aspects supplied with the Spring Framework. - -Consider first the scenario where you have a plain-vanilla, un-proxied, -nothing-special-about-it, straight object reference, as illustrated by the following -code snippet. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class SimplePojo implements Pojo { - - public void foo() { - // this next method invocation is a direct call on the 'this' reference - this.bar(); - } - - public void bar() { - // some logic... - } - } ----- - -If you invoke a method on an object reference, the method is invoked __directly__ on -that object reference, as can be seen below. - -image::images/aop-proxy-plain-pojo-call.png[width=400] - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class Main { - - public static void main(String[] args) { - - Pojo pojo = new SimplePojo(); - - // this is a direct method call on the 'pojo' reference - pojo.foo(); - } - } ----- - -Things change slightly when the reference that client code has is a proxy. Consider the -following diagram and code snippet. - -image::images/aop-proxy-call.png[width=400] - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class Main { - - public static void main(String[] args) { - - ProxyFactory factory = new ProxyFactory(new SimplePojo()); - factory.addInterface(Pojo.class); - factory.addAdvice(new RetryAdvice()); - - Pojo pojo = (Pojo) factory.getProxy(); - - // this is a method call on the proxy! - pojo.foo(); - } - } ----- - -The key thing to understand here is that the client code inside the `main(..)` of the -`Main` class __has a reference to the proxy__. This means that method calls on that -object reference will be calls on the proxy, and as such the proxy will be able to -delegate to all of the interceptors (advice) that are relevant to that particular method -call. However, once the call has finally reached the target object, the `SimplePojo` -reference in this case, any method calls that it may make on itself, such as -`this.bar()` or `this.foo()`, are going to be invoked against the __this__ reference, -and __not__ the proxy. This has important implications. It means that self-invocation is -__not__ going to result in the advice associated with a method invocation getting a -chance to execute. - -Okay, so what is to be done about this? The best approach (the term best is used loosely -here) is to refactor your code such that the self-invocation does not happen. For sure, -this does entail some work on your part, but it is the best, least-invasive approach. -The next approach is absolutely horrendous, and I am almost reticent to point it out -precisely because it is so horrendous. You can (choke!) totally tie the logic within -your class to Spring AOP by doing this: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class SimplePojo implements Pojo { - - public void foo() { - // this works, but... gah! - ((Pojo) AopContext.currentProxy()).bar(); - } - - public void bar() { - // some logic... - } - } ----- - -This totally couples your code to Spring AOP, __and__ it makes the class itself aware of -the fact that it is being used in an AOP context, which flies in the face of AOP. It -also requires some additional configuration when the proxy is being created: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class Main { - - public static void main(String[] args) { - - ProxyFactory factory = new ProxyFactory(new SimplePojo()); - factory.adddInterface(Pojo.class); - factory.addAdvice(new RetryAdvice()); - factory.setExposeProxy(true); - - Pojo pojo = (Pojo) factory.getProxy(); - - // this is a method call on the proxy! - pojo.foo(); - } - } ----- - -Finally, it must be noted that AspectJ does not have this self-invocation issue because -it is not a proxy-based AOP framework. - - - - -[[aop-aspectj-programmatic]] -=== Programmatic creation of @AspectJ Proxies -In addition to declaring aspects in your configuration using either `` or -``, it is also possible programmatically to create proxies that -advise target objects. For the full details of Spring's AOP API, see the next chapter. -Here we want to focus on the ability to automatically create proxies using @AspectJ -aspects. - -The class `org.springframework.aop.aspectj.annotation.AspectJProxyFactory` can be used -to create a proxy for a target object that is advised by one or more @AspectJ aspects. -Basic usage for this class is very simple, as illustrated below. See the javadocs for -full information. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - // create a factory that can generate a proxy for the given target object - AspectJProxyFactory factory = new AspectJProxyFactory(targetObject); - - // add an aspect, the class must be an @AspectJ aspect - // you can call this as many times as you need with different aspects - factory.addAspect(SecurityManager.class); - - // you can also add existing aspect instances, the type of the object supplied must be an @AspectJ aspect - factory.addAspect(usageTracker); - - // now get the proxy object... - MyInterfaceType proxy = factory.getProxy(); ----- - - - - -[[aop-using-aspectj]] -=== Using AspectJ with Spring applications -Everything we've covered so far in this chapter is pure Spring AOP. In this section, -we're going to look at how you can use the AspectJ compiler/weaver instead of, or in -addition to, Spring AOP if your needs go beyond the facilities offered by Spring AOP -alone. - -Spring ships with a small AspectJ aspect library, which is available standalone in your -distribution as `spring-aspects.jar`; you'll need to add this to your classpath in order -to use the aspects in it. <> and <> discuss the -content of this library and how you can use it. <> discusses how to -dependency inject AspectJ aspects that are woven using the AspectJ compiler. Finally, -<> provides an introduction to load-time weaving for Spring applications -using AspectJ. - - - -[[aop-atconfigurable]] -==== Using AspectJ to dependency inject domain objects with Spring -The Spring container instantiates and configures beans defined in your application -context. It is also possible to ask a bean factory to configure a __pre-existing__ -object given the name of a bean definition containing the configuration to be applied. -The `spring-aspects.jar` contains an annotation-driven aspect that exploits this -capability to allow dependency injection of __any object__. The support is intended to -be used for objects created __outside of the control of any container__. Domain objects -often fall into this category because they are often created programmatically using the -`new` operator, or by an ORM tool as a result of a database query. - -The `@Configurable` annotation marks a class as eligible for Spring-driven -configuration. In the simplest case it can be used just as a marker annotation: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - package com.xyz.myapp.domain; - - import org.springframework.beans.factory.annotation.Configurable; - - @Configurable - public class Account { - // ... - } ----- - -When used as a marker interface in this way, Spring will configure new instances of the -annotated type ( `Account` in this case) using a bean definition (typically -prototype-scoped) with the same name as the fully-qualified type name ( -`com.xyz.myapp.domain.Account`). Since the default name for a bean is the -fully-qualified name of its type, a convenient way to declare the prototype definition -is simply to omit the `id` attribute: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - ----- - -If you want to explicitly specify the name of the prototype bean definition to use, you -can do so directly in the annotation: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - package com.xyz.myapp.domain; - - import org.springframework.beans.factory.annotation.Configurable; - - @Configurable("account") - public class Account { - // ... - } ----- - -Spring will now look for a bean definition named " `account`" and use that as the -definition to configure new `Account` instances. - -You can also use autowiring to avoid having to specify a dedicated bean definition at -all. To have Spring apply autowiring use the '++autowire++' property of the -`@Configurable` annotation: specify either `@Configurable(autowire=Autowire.BY_TYPE)` or -`@Configurable(autowire=Autowire.BY_NAME` for autowiring by type or by name -respectively. As an alternative, as of Spring 2.5 it is preferable to specify explicit, -annotation-driven dependency injection for your `@Configurable` beans by using -`@Autowired` or `@Inject` at the field or method level (see <> -for further details). - -Finally you can enable Spring dependency checking for the object references in the newly -created and configured object by using the `dependencyCheck` attribute (for example: -`@Configurable(autowire=Autowire.BY_NAME,dependencyCheck=true)`). If this attribute is -set to true, then Spring will validate after configuration that all properties (__which -are not primitives or collections__) have been set. - -Using the annotation on its own does nothing of course. It is the -`AnnotationBeanConfigurerAspect` in `spring-aspects.jar` that acts on the presence of -the annotation. In essence the aspect says "after returning from the initialization of a -new object of a type annotated with `@Configurable`, configure the newly created object -using Spring in accordance with the properties of the annotation". In this context, -__initialization__ refers to newly instantiated objects (e.g., objects instantiated with -the '++new++' operator) as well as to `Serializable` objects that are undergoing -deserialization (e.g., via -http://docs.oracle.com/javase/6/docs/api/java/io/Serializable.html[readResolve()]). - -[NOTE] -==== -One of the key phrases in the above paragraph is '__in essence__'. For most cases, the -exact semantics of '__after returning from the initialization of a new object__' will be -fine... in this context, '__after initialization__' means that the dependencies will be -injected __after__ the object has been constructed - this means that the dependencies -will not be available for use in the constructor bodies of the class. If you want the -dependencies to be injected __before__ the constructor bodies execute, and thus be -available for use in the body of the constructors, then you need to define this on the -`@Configurable` declaration like so: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Configurable(preConstruction=true) ----- - -You can find out more information about the language semantics of the various pointcut -types in AspectJ -http://www.eclipse.org/aspectj/doc/next/progguide/semantics-joinPoints.html[in this -appendix] of the http://www.eclipse.org/aspectj/doc/next/progguide/index.html[AspectJ -Programming Guide]. -==== - -For this to work the annotated types must be woven with the AspectJ weaver - you can -either use a build-time Ant or Maven task to do this (see for example the -http://www.eclipse.org/aspectj/doc/released/devguide/antTasks.html[AspectJ Development -Environment Guide]) or load-time weaving (see <>). The -`AnnotationBeanConfigurerAspect` itself needs configuring by Spring (in order to obtain -a reference to the bean factory that is to be used to configure new objects). If you are -using Java based configuration simply add `@EnableSpringConfigured` to any -`@Configuration` class. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Configuration - @EnableSpringConfigured - public class AppConfig { - - } ----- - -If you prefer XML based configuration, the Spring <> defines a convenient `context:spring-configured` element: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - ----- - -Instances of `@Configurable` objects created __before__ the aspect has been configured -will result in a message being issued to the debug log and no configuration of the -object taking place. An example might be a bean in the Spring configuration that creates -domain objects when it is initialized by Spring. In this case you can use the -"depends-on" bean attribute to manually specify that the bean depends on the -configuration aspect. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - ----- - -[NOTE] -==== -Do not activate `@Configurable` processing through the bean configurer aspect unless you -really mean to rely on its semantics at runtime. In particular, make sure that you do -not use `@Configurable` on bean classes which are registered as regular Spring beans -with the container: You would get double initialization otherwise, once through the -container and once through the aspect. -==== - - -[[aop-configurable-testing]] -===== Unit testing @Configurable objects - -One of the goals of the `@Configurable` support is to enable independent unit testing of -domain objects without the difficulties associated with hard-coded lookups. If -`@Configurable` types have not been woven by AspectJ then the annotation has no affect -during unit testing, and you can simply set mock or stub property references in the -object under test and proceed as normal. If `@Configurable` types __have__ been woven by -AspectJ then you can still unit test outside of the container as normal, but you will -see a warning message each time that you construct an `@Configurable` object indicating -that it has not been configured by Spring. - - -[[aop-configurable-container]] -===== Working with multiple application contexts -The `AnnotationBeanConfigurerAspect` used to implement the `@Configurable` support is an -AspectJ singleton aspect. The scope of a singleton aspect is the same as the scope of -`static` members, that is to say there is one aspect instance per classloader that -defines the type. This means that if you define multiple application contexts within the -same classloader hierarchy you need to consider where to define the -`@EnableSpringConfigured` bean and where to place `spring-aspects.jar` on the classpath. - -Consider a typical Spring web-app configuration with a shared parent application context -defining common business services and everything needed to support them, and one child -application context per servlet containing definitions particular to that servlet. All -of these contexts will co-exist within the same classloader hierarchy, and so the -`AnnotationBeanConfigurerAspect` can only hold a reference to one of them. In this case -we recommend defining the `@EnableSpringConfigured` bean in the shared (parent) -application context: this defines the services that you are likely to want to inject -into domain objects. A consequence is that you cannot configure domain objects with -references to beans defined in the child (servlet-specific) contexts using the -@Configurable mechanism (probably not something you want to do anyway!). - -When deploying multiple web-apps within the same container, ensure that each -web-application loads the types in `spring-aspects.jar` using its own classloader (for -example, by placing `spring-aspects.jar` in `'WEB-INF/lib'`). If `spring-aspects.jar` is -only added to the container wide classpath (and hence loaded by the shared parent -classloader), all web applications will share the same aspect instance which is probably -not what you want. - - - -[[aop-ajlib-other]] -==== Other Spring aspects for AspectJ -In addition to the `@Configurable` aspect, `spring-aspects.jar` contains an AspectJ -aspect that can be used to drive Spring's transaction management for types and methods -annotated with the `@Transactional` annotation. This is primarily intended for users who -want to use the Spring Framework's transaction support outside of the Spring container. - -The aspect that interprets `@Transactional` annotations is the -`AnnotationTransactionAspect`. When using this aspect, you must annotate the -__implementation__ class (and/or methods within that class), __not__ the interface (if -any) that the class implements. AspectJ follows Java's rule that annotations on -interfaces are __not inherited__. - -A `@Transactional` annotation on a class specifies the default transaction semantics for -the execution of any __public__ operation in the class. - -A `@Transactional` annotation on a method within the class overrides the default -transaction semantics given by the class annotation (if present). Methods with `public`, -`protected`, and default visibility may all be annotated. Annotating `protected` and -default visibility methods directly is the only way to get transaction demarcation for -the execution of such methods. - -For AspectJ programmers that want to use the Spring configuration and transaction -management support but don't want to (or cannot) use annotations, `spring-aspects.jar` -also contains `abstract` aspects you can extend to provide your own pointcut -definitions. See the sources for the `AbstractBeanConfigurerAspect` and -`AbstractTransactionAspect` aspects for more information. As an example, the following -excerpt shows how you could write an aspect to configure all instances of objects -defined in the domain model using prototype bean definitions that match the -fully-qualified class names: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public aspect DomainObjectConfiguration extends AbstractBeanConfigurerAspect { - - public DomainObjectConfiguration() { - setBeanWiringInfoResolver(new ClassNameBeanWiringInfoResolver()); - } - - // the creation of a new bean (any object in the domain model) - protected pointcut beanCreation(Object beanInstance) : - initialization(new(..)) && - SystemArchitecture.inDomainModel() && - this(beanInstance); - - } ----- - - - -[[aop-aj-configure]] -==== Configuring AspectJ aspects using Spring IoC -When using AspectJ aspects with Spring applications, it is natural to both want and -expect to be able to configure such aspects using Spring. The AspectJ runtime itself is -responsible for aspect creation, and the means of configuring the AspectJ created -aspects via Spring depends on the AspectJ instantiation model (the '++per-xxx++' clause) -used by the aspect. - -The majority of AspectJ aspects are __singleton__ aspects. Configuration of these -aspects is very easy: simply create a bean definition referencing the aspect type as -normal, and include the bean attribute `'factory-method="aspectOf"'`. This ensures that -Spring obtains the aspect instance by asking AspectJ for it rather than trying to create -an instance itself. For example: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - ----- - -Non-singleton aspects are harder to configure: however it is possible to do so by -creating prototype bean definitions and using the `@Configurable` support from -`spring-aspects.jar` to configure the aspect instances once they have bean created by -the AspectJ runtime. - -If you have some @AspectJ aspects that you want to weave with AspectJ (for example, -using load-time weaving for domain model types) and other @AspectJ aspects that you want -to use with Spring AOP, and these aspects are all configured using Spring, then you will -need to tell the Spring AOP @AspectJ autoproxying support which exact subset of the -@AspectJ aspects defined in the configuration should be used for autoproxying. You can -do this by using one or more `` elements inside the `` -declaration. Each `` element specifies a name pattern, and only beans with -names matched by at least one of the patterns will be used for Spring AOP autoproxy -configuration: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - ----- - -[NOTE] -==== -Do not be misled by the name of the `` element: using it will -result in the creation of __Spring AOP proxies__. The @AspectJ style of aspect -declaration is just being used here, but the AspectJ runtime is __not__ involved. -==== - - - -[[aop-aj-ltw]] -==== Load-time weaving with AspectJ in the Spring Framework -Load-time weaving (LTW) refers to the process of weaving AspectJ aspects into an -application's class files as they are being loaded into the Java virtual machine (JVM). -The focus of this section is on configuring and using LTW in the specific context of the -Spring Framework: this section is not an introduction to LTW though. For full details on -the specifics of LTW and configuring LTW with just AspectJ (with Spring not being -involved at all), see the -http://www.eclipse.org/aspectj/doc/released/devguide/ltw.html[LTW section of the AspectJ -Development Environment Guide]. - -The value-add that the Spring Framework brings to AspectJ LTW is in enabling much -finer-grained control over the weaving process. 'Vanilla' AspectJ LTW is effected using -a Java (5+) agent, which is switched on by specifying a VM argument when starting up a -JVM. It is thus a JVM-wide setting, which may be fine in some situations, but often is a -little too coarse. Spring-enabled LTW enables you to switch on LTW on a -__per-ClassLoader__ basis, which obviously is more fine-grained and which can make more -sense in a 'single-JVM-multiple-application' environment (such as is found in a typical -application server environment). - -Further, <>, this support enables -load-time weaving __without making any modifications to the application server's launch -script__ that will be needed to add `-javaagent:path/to/aspectjweaver.jar` or (as we -describe later in this section) -`-javaagent:path/to/org.springframework.instrument-{version}.jar` (previously named -`spring-agent.jar`). Developers simply modify one or more files that form the -application context to enable load-time weaving instead of relying on administrators who -typically are in charge of the deployment configuration such as the launch script. - -Now that the sales pitch is over, let us first walk through a quick example of AspectJ -LTW using Spring, followed by detailed specifics about elements introduced in the -following example. For a complete example, please see the -https://github.com/spring-projects/spring-petclinic[Petclinic sample application]. - - -[[aop-aj-ltw-first-example]] -===== A first example -Let us assume that you are an application developer who has been tasked with diagnosing -the cause of some performance problems in a system. Rather than break out a profiling -tool, what we are going to do is switch on a simple profiling aspect that will enable us -to very quickly get some performance metrics, so that we can then apply a finer-grained -profiling tool to that specific area immediately afterwards. - -[NOTE] -==== -The example presented here uses XML style configuration, it is also possible to -configure and use @AspectJ with <>. Specifically the -`@EnableLoadTimeWeaving` annotation can be used as an alternative to -`` (see <> for details). -==== - -Here is the profiling aspect. Nothing too fancy, just a quick-and-dirty time-based -profiler, using the @AspectJ-style of aspect declaration. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - package foo; - - import org.aspectj.lang.ProceedingJoinPoint; - import org.aspectj.lang.annotation.Aspect; - import org.aspectj.lang.annotation.Around; - import org.aspectj.lang.annotation.Pointcut; - import org.springframework.util.StopWatch; - import org.springframework.core.annotation.Order; - - @Aspect - public class ProfilingAspect { - - @Around("methodsToBeProfiled()") - public Object profile(ProceedingJoinPoint pjp) throws Throwable { - StopWatch sw = new StopWatch(getClass().getSimpleName()); - try { - sw.start(pjp.getSignature().getName()); - return pjp.proceed(); - } finally { - sw.stop(); - System.out.println(sw.prettyPrint()); - } - } - - @Pointcut("execution(public * foo..*.*(..))") - public void methodsToBeProfiled(){} - } ----- - -We will also need to create an '++META-INF/aop.xml++' file, to inform the AspectJ weaver -that we want to weave our `ProfilingAspect` into our classes. This file convention, -namely the presence of a file (or files) on the Java classpath called -'++META-INF/aop.xml++' is standard AspectJ. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - - - - - - - ----- - -Now to the Spring-specific portion of the configuration. We need to configure a -`LoadTimeWeaver` (all explained later, just take it on trust for now). This load-time -weaver is the essential component responsible for weaving the aspect configuration in -one or more '++META-INF/aop.xml++' files into the classes in your application. The good -thing is that it does not require a lot of configuration, as can be seen below (there -are some more options that you can specify, but these are detailed later). - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - **** - ----- - -Now that all the required artifacts are in place - the aspect, the '++META-INF/aop.xml++' -file, and the Spring configuration -, let us create a simple driver class with a -`main(..)` method to demonstrate the LTW in action. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - package foo; - - import org.springframework.context.support.ClassPathXmlApplicationContext; - - public final class Main { - - public static void main(String[] args) { - - ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml", Main.class); - - EntitlementCalculationService entitlementCalculationService - = (EntitlementCalculationService) ctx.getBean("entitlementCalculationService"); - - // the profiling aspect is 'woven' around this method execution - entitlementCalculationService.calculateEntitlement(); - } - } ----- - -There is one last thing to do. The introduction to this section did say that one could -switch on LTW selectively on a per- `ClassLoader` basis with Spring, and this is true. -However, just for this example, we are going to use a Java agent (supplied with Spring) -to switch on the LTW. This is the command line we will use to run the above `Main` class: - -[literal] -[subs="verbatim,quotes"] ----- -java -javaagent:C:/projects/foo/lib/global/spring-instrument.jar foo.Main ----- - -The '++-javaagent++' is a flag for specifying and enabling -http://docs.oracle.com/javase/6/docs/api/java/lang/instrument/package-summary.html[agents -to instrument programs running on the JVM]. The Spring Framework ships with such an -agent, the `InstrumentationSavingAgent`, which is packaged in the -`spring-instrument.jar` that was supplied as the value of the `-javaagent` argument in -the above example. - -The output from the execution of the `Main` program will look something like that below. -(I have introduced a `Thread.sleep(..)` statement into the `calculateEntitlement()` -implementation so that the profiler actually captures something other than 0 -milliseconds - the `01234` milliseconds is __not__ an overhead introduced by the AOP :) ) - -[literal] -[subs="verbatim,quotes"] ----- -Calculating entitlement - -StopWatch 'ProfilingAspect': running time (millis) = 1234 ------- ----- ---------------------------- -ms % Task name ------- ----- ---------------------------- -01234 100% calculateEntitlement ----- - -Since this LTW is effected using full-blown AspectJ, we are not just limited to advising -Spring beans; the following slight variation on the `Main` program will yield the same -result. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - package foo; - - import org.springframework.context.support.ClassPathXmlApplicationContext; - - public final class Main { - - public static void main(String[] args) { - - new ClassPathXmlApplicationContext("beans.xml", Main.class); - - EntitlementCalculationService entitlementCalculationService = - new StubEntitlementCalculationService(); - - // the profiling aspect will be 'woven' around this method execution - entitlementCalculationService.calculateEntitlement(); - } - } ----- - -Notice how in the above program we are simply bootstrapping the Spring container, and -then creating a new instance of the `StubEntitlementCalculationService` totally outside -the context of Spring... the profiling advice still gets woven in. - -The example admittedly is simplistic... however the basics of the LTW support in Spring -have all been introduced in the above example, and the rest of this section will explain -the 'why' behind each bit of configuration and usage in detail. - -[NOTE] -==== -The `ProfilingAspect` used in this example may be basic, but it is quite useful. It is a -nice example of a development-time aspect that developers can use during development (of -course), and then quite easily exclude from builds of the application being deployed -into UAT or production. -==== - - -[[aop-aj-ltw-the-aspects]] -===== Aspects -The aspects that you use in LTW have to be AspectJ aspects. They can be written in -either the AspectJ language itself or you can write your aspects in the @AspectJ-style. -It means that your aspects are then both valid AspectJ __and__ Spring AOP aspects. -Furthermore, the compiled aspect classes need to be available on the classpath. - - -[[aop-aj-ltw-aop_dot_xml]] -===== 'META-INF/aop.xml' - -The AspectJ LTW infrastructure is configured using one or more '++META-INF/aop.xml++' -files, that are on the Java classpath (either directly, or more typically in jar files). - -The structure and contents of this file is detailed in the main AspectJ reference -documentation, and the interested reader is -http://www.eclipse.org/aspectj/doc/released/devguide/ltw-configuration.html[referred to -that resource]. (I appreciate that this section is brief, but the '++aop.xml++' file is -100% AspectJ - there is no Spring-specific information or semantics that apply to it, -and so there is no extra value that I can contribute either as a result), so rather than -rehash the quite satisfactory section that the AspectJ developers wrote, I am just -directing you there.) - - -[[aop-aj-ltw-libraries]] -===== Required libraries (JARS) -At a minimum you will need the following libraries to use the Spring Framework's support -for AspectJ LTW: - -* `spring-aop.jar` (version 2.5 or later, plus all mandatory dependencies) -* `aspectjweaver.jar` (version 1.6.8 or later) - -If you are using the <>, you will also need: - -* `spring-instrument.jar` - - -[[aop-aj-ltw-spring]] -===== Spring configuration -The key component in Spring's LTW support is the `LoadTimeWeaver` interface (in the -`org.springframework.instrument.classloading` package), and the numerous implementations -of it that ship with the Spring distribution. A `LoadTimeWeaver` is responsible for -adding one or more `java.lang.instrument.ClassFileTransformers` to a `ClassLoader` at -runtime, which opens the door to all manner of interesting applications, one of which -happens to be the LTW of aspects. - -[TIP] -==== - -If you are unfamiliar with the idea of runtime class file transformation, you are -encouraged to read the javadoc API documentation for the `java.lang.instrument` package -before continuing. This is not a huge chore because there is - rather annoyingly - -precious little documentation there... the key interfaces and classes will at least be -laid out in front of you for reference as you read through this section. -==== - -Configuring a `LoadTimeWeaver` for a particular `ApplicationContext` can be as easy as -adding one line. (Please note that you almost certainly will need to be using an -`ApplicationContext` as your Spring container - typically a `BeanFactory` will not be -enough because the LTW support makes use of `BeanFactoryPostProcessors`.) - -To enable the Spring Framework's LTW support, you need to configure a `LoadTimeWeaver`, -which typically is done using the `@EnableLoadTimeWeaving` annotation. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Configuration - @EnableLoadTimeWeaving - public class AppConfig { - - } ----- - -Alternatively, if you prefer XML based configuration, use the -`` element. Note that the element is defined in the -'++context++' namespace. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - ----- - -The above configuration will define and register a number of LTW-specific infrastructure -beans for you automatically, such as a `LoadTimeWeaver` and an `AspectJWeavingEnabler`. -The default `LoadTimeWeaver` is the `DefaultContextLoadTimeWeaver` class, which attempts -to decorate an automatically detected `LoadTimeWeaver`: the exact type of -`LoadTimeWeaver` that will be 'automatically detected' is dependent upon your runtime -environment (summarized in the following table). - -[[aop-aj-ltw-spring-env-impls]] -.DefaultContextLoadTimeWeaver LoadTimeWeavers -|=== -| Runtime Environment| `LoadTimeWeaver` implementation - -| Running in - http://www.bea.com/framework.jsp?CNT=index.htm&FP=/content/products/weblogic/server[BEA's - Weblogic 10] -| `WebLogicLoadTimeWeaver` - -| Running in http://www-01.ibm.com/software/webservers/appserv/was/[IBM WebSphere - Application Server 7] -| `WebSphereLoadTimeWeaver` - -| Running in http://glassfish.dev.java.net/[GlassFish] -| `GlassFishLoadTimeWeaver` - -| Running in http://www.jboss.org/jbossas/[JBoss AS] -| `JBossLoadTimeWeaver` - -| JVM started with Spring `InstrumentationSavingAgent` __(java - -javaagent:path/to/spring-instrument.jar)__ -| `InstrumentationLoadTimeWeaver` - -| Fallback, expecting the underlying ClassLoader to follow common conventions (e.g. - applicable to `TomcatInstrumentableClassLoader` and http://www.caucho.com/[Resin]) -| `ReflectiveLoadTimeWeaver` -|=== - -Note that these are just the `LoadTimeWeavers` that are autodetected when using the -`DefaultContextLoadTimeWeaver`: it is of course possible to specify exactly which -`LoadTimeWeaver` implementation that you wish to use. - -To specify a specific `LoadTimeWeaver` with Java configuration implement the -`LoadTimeWeavingConfigurer` interface and override the `getLoadTimeWeaver()` method: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Configuration - @EnableLoadTimeWeaving - public class AppConfig implements LoadTimeWeavingConfigurer { - - @Override - public LoadTimeWeaver getLoadTimeWeaver() { - return new ReflectiveLoadTimeWeaver(); - } - } ----- - -If you are using XML based configuration you can specify the fully-qualified classname -as the value of the '++weaver-class++' attribute on the `` -element: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - ----- - -The `LoadTimeWeaver` that is defined and registered by the configuration can be later -retrieved from the Spring container using the well-known name '++loadTimeWeaver++'. -Remember that the `LoadTimeWeaver` exists just as a mechanism for Spring's LTW -infrastructure to add one or more `ClassFileTransformers`. The actual -`ClassFileTransformer` that does the LTW is the `ClassPreProcessorAgentAdapter` (from -the `org.aspectj.weaver.loadtime` package) class. See the class-level javadocs of the -`ClassPreProcessorAgentAdapter` class for further details, because the specifics of how -the weaving is actually effected is beyond the scope of this section. - -There is one final attribute of the configuration left to discuss: the -'++aspectjWeaving++' attribute (or '++aspectj-weaving++' if you are using XML). This is a -simple attribute that controls whether LTW is enabled or not; it is as simple as that. -It accepts one of three possible values, summarized below, with the default value being -'++autodetect++' if the attribute is not present. - -[[aop-aj-ltw-ltw-tag-attrs]] -.AspectJ weaving attribute values -|=== -| Annotation Value| XML Value| Explanation - -| `ENABLED` -| `on` -| AspectJ weaving is on, and aspects will be woven at load-time as appropriate. - -| `DISABLED` -| `off` -| LTW is off... no aspect will be woven at load-time. - -| `AUTODETECT` -| `autodetect` -| If the Spring LTW infrastructure can find at least one '++META-INF/aop.xml++' file, - then AspectJ weaving is on, else it is off. This is the default value. -|=== - - -[[aop-aj-ltw-environments]] -===== Environment-specific configuration -This last section contains any additional settings and configuration that you will need -when using Spring's LTW support in environments such as application servers and web -containers. - -[[aop-aj-ltw-environment-tomcat]] -====== Tomcat -http://tomcat.apache.org/[Apache Tomcat]'s default class loader does not support class -transformation which is why Spring provides an enhanced implementation that addresses -this need. Named `TomcatInstrumentableClassLoader`, the loader works on Tomcat 5.0 and -above and can be registered individually for __each__ web application as follows: - -* Tomcat 6.0.x or higher -* Copy `org.springframework.instrument.tomcat.jar` into __$CATALINA_HOME__/lib, where - __$CATALINA_HOME__ represents the root of the Tomcat installation) -* Instruct Tomcat to use the custom class loader (instead of the default) by editing the - web application context file: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - ----- - -Apache Tomcat (6.0+) supports several context locations: - -* server configuration file - __$CATALINA_HOME/conf/server.xml__ -* default context configuration - __$CATALINA_HOME/conf/context.xml__ - that affects all - deployed web applications -* per-web application configuration which can be deployed either on the server-side at - __$CATALINA_HOME/conf/[enginename]/[hostname]/[webapp]-context.xml__ or embedded - inside the web-app archive at __META-INF/context.xml__ - -For efficiency, the embedded per-web-app configuration style is recommended because it -will impact only applications that use the custom class loader and does not require any -changes to the server configuration. See the Tomcat 6.0.x -http://tomcat.apache.org/tomcat-6.0-doc/config/context.html[documentation] for more -details about available context locations. - -Alternatively, consider the use of the Spring-provided generic VM agent, to be specified -in Tomcat's launch script (see above). This will make instrumentation available to all -deployed web applications, no matter what ClassLoader they happen to run on. - -[[aop-aj-ltw-environments-weblogic-oc4j-resin-glassfish-jboss]] -====== WebLogic, WebSphere, Resin, GlassFish, JBoss -Recent versions of WebLogic Server (version 10 and above), IBM WebSphere Application -Server (version 7 and above), Resin (3.1 and above) and JBoss (6.x or above) provide a -ClassLoader that is capable of local instrumentation. Spring's native LTW leverages such -ClassLoaders to enable AspectJ weaving. You can enable LTW by simply activating -load-time weaving as described earlier. Specifically, you do __not__ need to modify the -launch script to add `-javaagent:path/to/spring-instrument.jar`. - -Note that GlassFish instrumentation-capable ClassLoader is available only in its EAR -environment. For GlassFish web applications, follow the Tomcat setup instructions as -outlined above. - -Note that on JBoss 6.x, the app server scanning needs to be disabled to prevent it from -loading the classes before the application actually starts. A quick workaround is to add -to your artifact a file named `WEB-INF/jboss-scanning.xml` with the following content: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - ----- - -[[aop-aj-ltw-environment-generic]] -====== Generic Java applications -When class instrumentation is required in environments that do not support or are not -supported by the existing `LoadTimeWeaver` implementations, a JDK agent can be the only -solution. For such cases, Spring provides `InstrumentationLoadTimeWeaver`, which -requires a Spring-specific (but very general) VM agent, -`org.springframework.instrument-{version}.jar` (previously named `spring-agent.jar`). - -To use it, you must start the virtual machine with the Spring agent, by supplying the -following JVM options: - -[literal] -[subs="verbatim,quotes"] ----- --javaagent:/path/to/org.springframework.instrument-{version}.jar ----- - -Note that this requires modification of the VM launch script which may prevent you from -using this in application server environments (depending on your operation policies). -Additionally, the JDK agent will instrument the __entire__ VM which can prove expensive. - -For performance reasons, it is recommended to use this configuration only if your target -environment (such as http://www.eclipse.org/jetty/[Jetty]) does not have (or does not -support) a dedicated LTW. - - - - -[[aop-resources]] -=== Further Resources -More information on AspectJ can be found on the http://www.eclipse.org/aspectj[AspectJ -website]. - -The book __Eclipse AspectJ__ by Adrian Colyer et. al. (Addison-Wesley, 2005) provides a -comprehensive introduction and reference for the AspectJ language. - -The book __AspectJ in Action__ by Ramnivas Laddad (Manning, 2003) comes highly -recommended; the focus of the book is on AspectJ, but a lot of general AOP themes are -explored (in some depth). - - - - - -[[aop-api]] -== Spring AOP APIs - - - - -[[aop-api-introduction]] -=== Introduction -The previous chapter described the Spring's support for AOP using -@AspectJ and schema-based aspect definitions. In this chapter we discuss the lower-level -Spring AOP APIs and the AOP support used in Spring 1.2 applications. For new -applications, we recommend the use of the Spring 2.0 and later AOP support described in -the previous chapter, but when working with existing applications, or when reading books -and articles, you may come across Spring 1.2 style examples. Spring 4.0 is backwards -compatible with Spring 1.2 and everything described in this chapter is fully supported -in Spring 4.0. - - - - -[[aop-api-pointcuts]] -=== Pointcut API in Spring -Let's look at how Spring handles the crucial pointcut concept. - - - -[[aop-api-concepts]] -==== Concepts -Spring's pointcut model enables pointcut reuse independent of advice types. It's -possible to target different advice using the same pointcut. - -The `org.springframework.aop.Pointcut` interface is the central interface, used to -target advices to particular classes and methods. The complete interface is shown below: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public interface Pointcut { - - ClassFilter getClassFilter(); - - MethodMatcher getMethodMatcher(); - - } ----- - -Splitting the `Pointcut` interface into two parts allows reuse of class and method -matching parts, and fine-grained composition operations (such as performing a "union" -with another method matcher). - -The `ClassFilter` interface is used to restrict the pointcut to a given set of target -classes. If the `matches()` method always returns true, all target classes will be -matched: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public interface ClassFilter { - - boolean matches(Class clazz); - } ----- - -The `MethodMatcher` interface is normally more important. The complete interface is -shown below: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public interface MethodMatcher { - - boolean matches(Method m, Class targetClass); - - boolean isRuntime(); - - boolean matches(Method m, Class targetClass, Object[] args); - } ----- - -The `matches(Method, Class)` method is used to test whether this pointcut will ever -match a given method on a target class. This evaluation can be performed when an AOP -proxy is created, to avoid the need for a test on every method invocation. If the -2-argument matches method returns true for a given method, and the `isRuntime()` method -for the MethodMatcher returns true, the 3-argument matches method will be invoked on -every method invocation. This enables a pointcut to look at the arguments passed to the -method invocation immediately before the target advice is to execute. - -Most MethodMatchers are static, meaning that their `isRuntime()` method returns false. -In this case, the 3-argument matches method will never be invoked. - -[TIP] -==== - -If possible, try to make pointcuts static, allowing the AOP framework to cache the -results of pointcut evaluation when an AOP proxy is created. -==== - - - -[[aop-api-pointcut-ops]] -==== Operations on pointcuts -Spring supports operations on pointcuts: notably, __union__ and __intersection__. - -* Union means the methods that either pointcut matches. -* Intersection means the methods that both pointcuts match. -* Union is usually more useful. -* Pointcuts can be composed using the static methods in the - __org.springframework.aop.support.Pointcuts__ class, or using the - __ComposablePointcut__ class in the same package. However, using AspectJ pointcut - expressions is usually a simpler approach. - - - -[[aop-api-pointcuts-aspectj]] -==== AspectJ expression pointcuts -Since 2.0, the most important type of pointcut used by Spring is -`org.springframework.aop.aspectj.AspectJExpressionPointcut`. This is a pointcut that -uses an AspectJ supplied library to parse an AspectJ pointcut expression string. - -See the previous chapter for a discussion of supported AspectJ pointcut primitives. - - - -[[aop-api-pointcuts-impls]] -==== Convenience pointcut implementations -Spring provides several convenient pointcut implementations. Some can be used out of the -box; others are intended to be subclassed in application-specific pointcuts. - - -[[aop-api-pointcuts-static]] -===== Static pointcuts -Static pointcuts are based on method and target class, and cannot take into account the -method's arguments. Static pointcuts are sufficient - __and best__ - for most usages. -It's possible for Spring to evaluate a static pointcut only once, when a method is first -invoked: after that, there is no need to evaluate the pointcut again with each method -invocation. - -Let's consider some static pointcut implementations included with Spring. - -[[aop-api-pointcuts-regex]] -====== Regular expression pointcuts -One obvious way to specify static pointcuts is regular expressions. Several AOP -frameworks besides Spring make this possible. -`org.springframework.aop.support.JdkRegexpMethodPointcut` is a generic regular -expression pointcut, using the regular expression support in JDK 1.4+. - -Using the `JdkRegexpMethodPointcut` class, you can provide a list of pattern Strings. If -any of these is a match, the pointcut will evaluate to true. (So the result is -effectively the union of these pointcuts.) - -The usage is shown below: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - .*set.* - .*absquatulate - - - ----- - -Spring provides a convenience class, `RegexpMethodPointcutAdvisor`, that allows us to -also reference an Advice (remember that an Advice can be an interceptor, before advice, -throws advice etc.). Behind the scenes, Spring will use a `JdkRegexpMethodPointcut`. -Using `RegexpMethodPointcutAdvisor` simplifies wiring, as the one bean encapsulates both -pointcut and advice, as shown below: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - .*set.* - .*absquatulate - - - ----- - -__RegexpMethodPointcutAdvisor__ can be used with any Advice type. - -[[aop-api-pointcuts-attribute-driven]] -====== Attribute-driven pointcuts -An important type of static pointcut is a __metadata-driven__ pointcut. This uses the -values of metadata attributes: typically, source-level metadata. - - -[[aop-api-pointcuts-dynamic]] -===== Dynamic pointcuts -Dynamic pointcuts are costlier to evaluate than static pointcuts. They take into account -method __arguments__, as well as static information. This means that they must be -evaluated with every method invocation; the result cannot be cached, as arguments will -vary. - -The main example is the `control flow` pointcut. - -[[aop-api-pointcuts-cflow]] -====== Control flow pointcuts -Spring control flow pointcuts are conceptually similar to AspectJ __cflow__ pointcuts, -although less powerful. (There is currently no way to specify that a pointcut executes -below a join point matched by another pointcut.) A control flow pointcut matches the -current call stack. For example, it might fire if the join point was invoked by a method -in the `com.mycompany.web` package, or by the `SomeCaller` class. Control flow pointcuts -are specified using the `org.springframework.aop.support.ControlFlowPointcut` class. -[NOTE] -==== -Control flow pointcuts are significantly more expensive to evaluate at runtime than even -other dynamic pointcuts. In Java 1.4, the cost is about 5 times that of other dynamic -pointcuts. -==== - - - -[[aop-api-pointcuts-superclasses]] -==== Pointcut superclasses -Spring provides useful pointcut superclasses to help you to implement your own pointcuts. - -Because static pointcuts are most useful, you'll probably subclass -StaticMethodMatcherPointcut, as shown below. This requires implementing just one -abstract method (although it's possible to override other methods to customize behavior): - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - class TestStaticPointcut extends StaticMethodMatcherPointcut { - - public boolean matches(Method m, Class targetClass) { - // return true if custom criteria match - } - } ----- - -There are also superclasses for dynamic pointcuts. - -You can use custom pointcuts with any advice type in Spring 1.0 RC2 and above. - - - -[[aop-api-pointcuts-custom]] -==== Custom pointcuts -Because pointcuts in Spring AOP are Java classes, rather than language features (as in -AspectJ) it's possible to declare custom pointcuts, whether static or dynamic. Custom -pointcuts in Spring can be arbitrarily complex. However, using the AspectJ pointcut -expression language is recommended if possible. - -[NOTE] -==== -Later versions of Spring may offer support for "semantic pointcuts" as offered by JAC: -for example, "all methods that change instance variables in the target object." -==== - - - - -[[aop-api-advice]] -=== Advice API in Spring -Let's now look at how Spring AOP handles advice. - - - -[[aop-api-advice-lifecycle]] -==== Advice lifecycles -Each advice is a Spring bean. An advice instance can be shared across all advised -objects, or unique to each advised object. This corresponds to __per-class__ or -__per-instance__ advice. - -Per-class advice is used most often. It is appropriate for generic advice such as -transaction advisors. These do not depend on the state of the proxied object or add new -state; they merely act on the method and arguments. - -Per-instance advice is appropriate for introductions, to support mixins. In this case, -the advice adds state to the proxied object. - -It's possible to use a mix of shared and per-instance advice in the same AOP proxy. - - - -[[aop-api-advice-types]] -==== Advice types in Spring -Spring provides several advice types out of the box, and is extensible to support -arbitrary advice types. Let us look at the basic concepts and standard advice types. - - -[[aop-api-advice-around]] -===== Interception around advice -The most fundamental advice type in Spring is __interception around advice__. - -Spring is compliant with the AOP Alliance interface for around advice using method -interception. MethodInterceptors implementing around advice should implement the -following interface: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public interface MethodInterceptor extends Interceptor { - - Object invoke(MethodInvocation invocation) throws Throwable; - } ----- - -The `MethodInvocation` argument to the `invoke()` method exposes the method being -invoked; the target join point; the AOP proxy; and the arguments to the method. The -`invoke()` method should return the invocation's result: the return value of the join -point. - -A simple `MethodInterceptor` implementation looks as follows: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class DebugInterceptor implements MethodInterceptor { - - public Object invoke(MethodInvocation invocation) throws Throwable { - System.out.println("Before: invocation=[" + invocation + "]"); - Object rval = invocation.proceed(); - System.out.println("Invocation returned"); - return rval; - } - } ----- - -Note the call to the MethodInvocation's `proceed()` method. This proceeds down the -interceptor chain towards the join point. Most interceptors will invoke this method, and -return its return value. However, a MethodInterceptor, like any around advice, can -return a different value or throw an exception rather than invoke the proceed method. -However, you don't want to do this without good reason! - -[NOTE] -==== -MethodInterceptors offer interoperability with other AOP Alliance-compliant AOP -implementations. The other advice types discussed in the remainder of this section -implement common AOP concepts, but in a Spring-specific way. While there is an advantage -in using the most specific advice type, stick with MethodInterceptor around advice if -you are likely to want to run the aspect in another AOP framework. Note that pointcuts -are not currently interoperable between frameworks, and the AOP Alliance does not -currently define pointcut interfaces. -==== - - -[[aop-api-advice-before]] -===== Before advice -A simpler advice type is a __before advice__. This does not need a `MethodInvocation` -object, since it will only be called before entering the method. - -The main advantage of a before advice is that there is no need to invoke the `proceed()` -method, and therefore no possibility of inadvertently failing to proceed down the -interceptor chain. - -The `MethodBeforeAdvice` interface is shown below. (Spring's API design would allow for -field before advice, although the usual objects apply to field interception and it's -unlikely that Spring will ever implement it). - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public interface MethodBeforeAdvice extends BeforeAdvice { - - void before(Method m, Object[] args, Object target) throws Throwable; - } ----- - -Note the return type is `void`. Before advice can insert custom behavior before the join -point executes, but cannot change the return value. If a before advice throws an -exception, this will abort further execution of the interceptor chain. The exception -will propagate back up the interceptor chain. If it is unchecked, or on the signature of -the invoked method, it will be passed directly to the client; otherwise it will be -wrapped in an unchecked exception by the AOP proxy. - -An example of a before advice in Spring, which counts all method invocations: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class CountingBeforeAdvice implements MethodBeforeAdvice { - - private int count; - - public void before(Method m, Object[] args, Object target) throws Throwable { - ++count; - } - - public int getCount() { - return count; - } - } ----- - -[TIP] -==== - -Before advice can be used with any pointcut. -==== - - -[[aop-api-advice-throws]] -===== Throws advice -__Throws advice__ is invoked after the return of the join point if the join point threw -an exception. Spring offers typed throws advice. Note that this means that the -`org.springframework.aop.ThrowsAdvice` interface does not contain any methods: It is a -tag interface identifying that the given object implements one or more typed throws -advice methods. These should be in the form of: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - afterThrowing([Method, args, target], subclassOfThrowable) ----- - -Only the last argument is required. The method signatures may have either one or four -arguments, depending on whether the advice method is interested in the method and -arguments. The following classes are examples of throws advice. - -The advice below is invoked if a `RemoteException` is thrown (including subclasses): - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class RemoteThrowsAdvice implements ThrowsAdvice { - - public void afterThrowing(RemoteException ex) throws Throwable { - // Do something with remote exception - } - } ----- - -The following advice is invoked if a `ServletException` is thrown. Unlike the above -advice, it declares 4 arguments, so that it has access to the invoked method, method -arguments and target object: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class ServletThrowsAdviceWithArguments implements ThrowsAdvice { - - public void afterThrowing(Method m, Object[] args, Object target, ServletException ex) { - // Do something with all arguments - } - } ----- - -The final example illustrates how these two methods could be used in a single class, -which handles both `RemoteException` and `ServletException`. Any number of throws advice -methods can be combined in a single class. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public static class CombinedThrowsAdvice implements ThrowsAdvice { - - public void afterThrowing(RemoteException ex) throws Throwable { - // Do something with remote exception - } - - public void afterThrowing(Method m, Object[] args, Object target, ServletException ex) { - // Do something with all arguments - } - } ----- - -[NOTE] -==== -If a throws-advice method throws an exception itself, it will override the -original exception (i.e. change the exception thrown to the user). The overriding -exception will typically be a RuntimeException; this is compatible with any method -signature. However, if a throws-advice method throws a checked exception, it will have -to match the declared exceptions of the target method and is hence to some degree -coupled to specific target method signatures. __Do not throw an undeclared checked -exception that is incompatible with the target method's signature!__ -==== - -[TIP] -==== - -Throws advice can be used with any pointcut. -==== - - -[[aop-api-advice-after-returning]] -===== After Returning advice -An after returning advice in Spring must implement the -__org.springframework.aop.AfterReturningAdvice__ interface, shown below: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public interface AfterReturningAdvice extends Advice { - - void afterReturning(Object returnValue, Method m, Object[] args, Object target) - throws Throwable; - } ----- - -An after returning advice has access to the return value (which it cannot modify), -invoked method, methods arguments and target. - -The following after returning advice counts all successful method invocations that have -not thrown exceptions: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class CountingAfterReturningAdvice implements AfterReturningAdvice { - - private int count; - - public void afterReturning(Object returnValue, Method m, Object[] args, Object target) - throws Throwable { - ++count; - } - - public int getCount() { - return count; - } - } ----- - -This advice doesn't change the execution path. If it throws an exception, this will be -thrown up the interceptor chain instead of the return value. - -[TIP] -==== - -After returning advice can be used with any pointcut. -==== - - -[[aop-api-advice-introduction]] -===== Introduction advice -Spring treats introduction advice as a special kind of interception advice. - -Introduction requires an `IntroductionAdvisor`, and an `IntroductionInterceptor`, -implementing the following interface: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public interface IntroductionInterceptor extends MethodInterceptor { - - boolean implementsInterface(Class intf); - } ----- - -The `invoke()` method inherited from the AOP Alliance `MethodInterceptor` interface must -implement the introduction: that is, if the invoked method is on an introduced -interface, the introduction interceptor is responsible for handling the method call - it -cannot invoke `proceed()`. - -Introduction advice cannot be used with any pointcut, as it applies only at class, -rather than method, level. You can only use introduction advice with the -`IntroductionAdvisor`, which has the following methods: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public interface IntroductionAdvisor extends Advisor, IntroductionInfo { - - ClassFilter getClassFilter(); - - void validateInterfaces() throws IllegalArgumentException; - } - - public interface IntroductionInfo { - - Class[] getInterfaces(); - } ----- - -There is no `MethodMatcher`, and hence no `Pointcut`, associated with introduction -advice. Only class filtering is logical. - -The `getInterfaces()` method returns the interfaces introduced by this advisor. - -The `validateInterfaces()` method is used internally to see whether or not the -introduced interfaces can be implemented by the configured `IntroductionInterceptor`. - -Let's look at a simple example from the Spring test suite. Let's suppose we want to -introduce the following interface to one or more objects: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public interface Lockable { - void lock(); - void unlock(); - boolean locked(); - } ----- - -This illustrates a __mixin__. We want to be able to cast advised objects to Lockable, -whatever their type, and call lock and unlock methods. If we call the lock() method, we -want all setter methods to throw a `LockedException`. Thus we can add an aspect that -provides the ability to make objects immutable, without them having any knowledge of it: -a good example of AOP. - -Firstly, we'll need an `IntroductionInterceptor` that does the heavy lifting. In this -case, we extend the `org.springframework.aop.support.DelegatingIntroductionInterceptor` -convenience class. We could implement IntroductionInterceptor directly, but using -`DelegatingIntroductionInterceptor` is best for most cases. - -The `DelegatingIntroductionInterceptor` is designed to delegate an introduction to an -actual implementation of the introduced interface(s), concealing the use of interception -to do so. The delegate can be set to any object using a constructor argument; the -default delegate (when the no-arg constructor is used) is this. Thus in the example -below, the delegate is the `LockMixin` subclass of `DelegatingIntroductionInterceptor`. -Given a delegate (by default itself), a `DelegatingIntroductionInterceptor` instance -looks for all interfaces implemented by the delegate (other than -IntroductionInterceptor), and will support introductions against any of them. It's -possible for subclasses such as `LockMixin` to call the `suppressInterface(Class intf)` -method to suppress interfaces that should not be exposed. However, no matter how many -interfaces an `IntroductionInterceptor` is prepared to support, the -`IntroductionAdvisor` used will control which interfaces are actually exposed. An -introduced interface will conceal any implementation of the same interface by the target. - -Thus `LockMixin` extends `DelegatingIntroductionInterceptor` and implements `Lockable` -itself. The superclass automatically picks up that Lockable can be supported for -introduction, so we don't need to specify that. We could introduce any number of -interfaces in this way. - -Note the use of the `locked` instance variable. This effectively adds additional state -to that held in the target object. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class LockMixin extends DelegatingIntroductionInterceptor implements Lockable { - - private boolean locked; - - public void lock() { - this.locked = true; - } - - public void unlock() { - this.locked = false; - } - - public boolean locked() { - return this.locked; - } - - public Object invoke(MethodInvocation invocation) throws Throwable { - if (locked() && invocation.getMethod().getName().indexOf("set") == 0) { - throw new LockedException(); - } - return super.invoke(invocation); - } - - } ----- - -Often it isn't necessary to override the `invoke()` method: the -`DelegatingIntroductionInterceptor` implementation - which calls the delegate method if -the method is introduced, otherwise proceeds towards the join point - is usually -sufficient. In the present case, we need to add a check: no setter method can be invoked -if in locked mode. - -The introduction advisor required is simple. All it needs to do is hold a distinct -`LockMixin` instance, and specify the introduced interfaces - in this case, just -`Lockable`. A more complex example might take a reference to the introduction -interceptor (which would be defined as a prototype): in this case, there's no -configuration relevant for a `LockMixin`, so we simply create it using `new`. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class LockMixinAdvisor extends DefaultIntroductionAdvisor { - - public LockMixinAdvisor() { - super(new LockMixin(), Lockable.class); - } - } ----- - -We can apply this advisor very simply: it requires no configuration. (However, it __is__ -necessary: It's impossible to use an `IntroductionInterceptor` without an -__IntroductionAdvisor__.) As usual with introductions, the advisor must be per-instance, -as it is stateful. We need a different instance of `LockMixinAdvisor`, and hence -`LockMixin`, for each advised object. The advisor comprises part of the advised object's -state. - -We can apply this advisor programmatically, using the `Advised.addAdvisor()` method, or -(the recommended way) in XML configuration, like any other advisor. All proxy creation -choices discussed below, including "auto proxy creators," correctly handle introductions -and stateful mixins. - - - - -[[aop-api-advisor]] -=== Advisor API in Spring -In Spring, an Advisor is an aspect that contains just a single advice object associated -with a pointcut expression. - -Apart from the special case of introductions, any advisor can be used with any advice. -`org.springframework.aop.support.DefaultPointcutAdvisor` is the most commonly used -advisor class. For example, it can be used with a `MethodInterceptor`, `BeforeAdvice` or -`ThrowsAdvice`. - -It is possible to mix advisor and advice types in Spring in the same AOP proxy. For -example, you could use a interception around advice, throws advice and before advice in -one proxy configuration: Spring will automatically create the necessary interceptor -chain. - - - - -[[aop-pfb]] -=== Using the ProxyFactoryBean to create AOP proxies -If you're using the Spring IoC container (an ApplicationContext or BeanFactory) for your -business objects - and you should be! - you will want to use one of Spring's AOP -FactoryBeans. (Remember that a factory bean introduces a layer of indirection, enabling -it to create objects of a different type.) - -[NOTE] -==== -The Spring AOP support also uses factory beans under the covers. -==== - -The basic way to create an AOP proxy in Spring is to use the -__org.springframework.aop.framework.ProxyFactoryBean__. This gives complete control over -the pointcuts and advice that will apply, and their ordering. However, there are simpler -options that are preferable if you don't need such control. - - - -[[aop-pfb-1]] -==== Basics -The `ProxyFactoryBean`, like other Spring `FactoryBean` implementations, introduces a -level of indirection. If you define a `ProxyFactoryBean` with name `foo`, what objects -referencing `foo` see is not the `ProxyFactoryBean` instance itself, but an object -created by the `ProxyFactoryBean`'s implementation of the `getObject()` method. This -method will create an AOP proxy wrapping a target object. - -One of the most important benefits of using a `ProxyFactoryBean` or another IoC-aware -class to create AOP proxies, is that it means that advices and pointcuts can also be -managed by IoC. This is a powerful feature, enabling certain approaches that are hard to -achieve with other AOP frameworks. For example, an advice may itself reference -application objects (besides the target, which should be available in any AOP -framework), benefiting from all the pluggability provided by Dependency Injection. - - - -[[aop-pfb-2]] -==== JavaBean properties -In common with most `FactoryBean` implementations provided with Spring, the -`ProxyFactoryBean` class is itself a JavaBean. Its properties are used to: - -* Specify the target you want to proxy. -* Specify whether to use CGLIB (see below and also <>). - -Some key properties are inherited from `org.springframework.aop.framework.ProxyConfig` -(the superclass for all AOP proxy factories in Spring). These key properties include: - -* `proxyTargetClass`: `true` if the target class is to be proxied, rather than the - target class' interfaces. If this property value is set to `true`, then CGLIB proxies - will be created (but see also <>). -* `optimize`: controls whether or not aggressive optimizations are applied to proxies - __created via CGLIB__. One should not blithely use this setting unless one fully - understands how the relevant AOP proxy handles optimization. This is currently used - only for CGLIB proxies; it has no effect with JDK dynamic proxies. -* `frozen`: if a proxy configuration is `frozen`, then changes to the configuration are - no longer allowed. This is useful both as a slight optimization and for those cases - when you don't want callers to be able to manipulate the proxy (via the `Advised` - interface) after the proxy has been created. The default value of this property is - `false`, so changes such as adding additional advice are allowed. -* `exposeProxy`: determines whether or not the current proxy should be exposed in a - `ThreadLocal` so that it can be accessed by the target. If a target needs to obtain - the proxy and the `exposeProxy` property is set to `true`, the target can use the - `AopContext.currentProxy()` method. - -Other properties specific to `ProxyFactoryBean` include: - -* `proxyInterfaces`: array of String interface names. If this isn't supplied, a CGLIB - proxy for the target class will be used (but see also <>). -* `interceptorNames`: String array of `Advisor`, interceptor or other advice names to - apply. Ordering is significant, on a first come-first served basis. That is to say - that the first interceptor in the list will be the first to be able to intercept the - invocation. - -The names are bean names in the current factory, including bean names from ancestor -factories. You can't mention bean references here since doing so would result in the -`ProxyFactoryBean` ignoring the singleton setting of the advice. - -You can append an interceptor name with an asterisk ( `*`). This will result in the -application of all advisor beans with names starting with the part before the asterisk -to be applied. An example of using this feature can be found in <>. - -* singleton: whether or not the factory should return a single object, no matter how - often the `getObject()` method is called. Several `FactoryBean` implementations offer - such a method. The default value is `true`. If you want to use stateful advice - for - example, for stateful mixins - use prototype advices along with a singleton value of - `false`. - - - -[[aop-pfb-proxy-types]] -==== JDK- and CGLIB-based proxies -This section serves as the definitive documentation on how the `ProxyFactoryBean` -chooses to create one of either a JDK- and CGLIB-based proxy for a particular target -object (that is to be proxied). - -[NOTE] -==== -The behavior of the `ProxyFactoryBean` with regard to creating JDK- or CGLIB-based -proxies changed between versions 1.2.x and 2.0 of Spring. The `ProxyFactoryBean` now -exhibits similar semantics with regard to auto-detecting interfaces as those of the -`TransactionProxyFactoryBean` class. -==== - -If the class of a target object that is to be proxied (hereafter simply referred to as -the target class) doesn't implement any interfaces, then a CGLIB-based proxy will be -created. This is the easiest scenario, because JDK proxies are interface based, and no -interfaces means JDK proxying isn't even possible. One simply plugs in the target bean, -and specifies the list of interceptors via the `interceptorNames` property. Note that a -CGLIB-based proxy will be created even if the `proxyTargetClass` property of the -`ProxyFactoryBean` has been set to `false`. (Obviously this makes no sense, and is best -removed from the bean definition because it is at best redundant, and at worst -confusing.) - -If the target class implements one (or more) interfaces, then the type of proxy that is -created depends on the configuration of the `ProxyFactoryBean`. - -If the `proxyTargetClass` property of the `ProxyFactoryBean` has been set to `true`, -then a CGLIB-based proxy will be created. This makes sense, and is in keeping with the -principle of least surprise. Even if the `proxyInterfaces` property of the -`ProxyFactoryBean` has been set to one or more fully qualified interface names, the fact -that the `proxyTargetClass` property is set to `true` __will__ cause CGLIB-based -proxying to be in effect. - -If the `proxyInterfaces` property of the `ProxyFactoryBean` has been set to one or more -fully qualified interface names, then a JDK-based proxy will be created. The created -proxy will implement all of the interfaces that were specified in the `proxyInterfaces` -property; if the target class happens to implement a whole lot more interfaces than -those specified in the `proxyInterfaces` property, that is all well and good but those -additional interfaces will not be implemented by the returned proxy. - -If the `proxyInterfaces` property of the `ProxyFactoryBean` has __not__ been set, but -the target class __does implement one (or more)__ interfaces, then the -`ProxyFactoryBean` will auto-detect the fact that the target class does actually -implement at least one interface, and a JDK-based proxy will be created. The interfaces -that are actually proxied will be __all__ of the interfaces that the target class -implements; in effect, this is the same as simply supplying a list of each and every -interface that the target class implements to the `proxyInterfaces` property. However, -it is significantly less work, and less prone to typos. - - - -[[aop-api-proxying-intf]] -==== Proxying interfaces -Let's look at a simple example of `ProxyFactoryBean` in action. This example involves: - -* A __target bean__ that will be proxied. This is the "personTarget" bean definition in - the example below. -* An Advisor and an Interceptor used to provide advice. -* An AOP proxy bean definition specifying the target object (the personTarget bean) and - the interfaces to proxy, along with the advices to apply. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - - - - - - - - - - - - myAdvisor - debugInterceptor - - - ----- - -Note that the `interceptorNames` property takes a list of String: the bean names of the -interceptor or advisors in the current factory. Advisors, interceptors, before, after -returning and throws advice objects can be used. The ordering of advisors is significant. - -[NOTE] -==== -You might be wondering why the list doesn't hold bean references. The reason for this is -that if the ProxyFactoryBean's singleton property is set to false, it must be able to -return independent proxy instances. If any of the advisors is itself a prototype, an -independent instance would need to be returned, so it's necessary to be able to obtain -an instance of the prototype from the factory; holding a reference isn't sufficient. -==== - -The "person" bean definition above can be used in place of a Person implementation, as -follows: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - Person person = (Person) factory.getBean("person"); ----- - -Other beans in the same IoC context can express a strongly typed dependency on it, as -with an ordinary Java object: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - ----- - -The `PersonUser` class in this example would expose a property of type Person. As far as -it's concerned, the AOP proxy can be used transparently in place of a "real" person -implementation. However, its class would be a dynamic proxy class. It would be possible -to cast it to the `Advised` interface (discussed below). - -It's possible to conceal the distinction between target and proxy using an anonymous -__inner bean__, as follows. Only the `ProxyFactoryBean` definition is different; the -advice is included only for completeness: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - - - - - - - - - - - myAdvisor - debugInterceptor - - - ----- - -This has the advantage that there's only one object of type `Person`: useful if we want -to prevent users of the application context from obtaining a reference to the un-advised -object, or need to avoid any ambiguity with Spring IoC __autowiring__. There's also -arguably an advantage in that the ProxyFactoryBean definition is self-contained. -However, there are times when being able to obtain the un-advised target from the -factory might actually be an __advantage__: for example, in certain test scenarios. - - - -[[aop-api-proxying-class]] -==== Proxying classes -What if you need to proxy a class, rather than one or more interfaces? - -Imagine that in our example above, there was no `Person` interface: we needed to advise -a class called `Person` that didn't implement any business interface. In this case, you -can configure Spring to use CGLIB proxying, rather than dynamic proxies. Simply set the -`proxyTargetClass` property on the ProxyFactoryBean above to true. While it's best to -program to interfaces, rather than classes, the ability to advise classes that don't -implement interfaces can be useful when working with legacy code. (In general, Spring -isn't prescriptive. While it makes it easy to apply good practices, it avoids forcing a -particular approach.) - -If you want to, you can force the use of CGLIB in any case, even if you do have -interfaces. - -CGLIB proxying works by generating a subclass of the target class at runtime. Spring -configures this generated subclass to delegate method calls to the original target: the -subclass is used to implement the __Decorator__ pattern, weaving in the advice. - -CGLIB proxying should generally be transparent to users. However, there are some issues -to consider: - -* `Final` methods can't be advised, as they can't be overridden. -* There is no need to add CGLIB to your classpath. As of Spring 3.2, CGLIB is repackaged - and included in the spring-core JAR. In other words, CGLIB-based AOP will work "out of - the box" just as do JDK dynamic proxies. - -There's little performance difference between CGLIB proxying and dynamic proxies. As of -Spring 1.0, dynamic proxies are slightly faster. However, this may change in the future. -Performance should not be a decisive consideration in this case. - - - -[[aop-global-advisors]] -==== Using 'global' advisors -By appending an asterisk to an interceptor name, all advisors with bean names matching -the part before the asterisk, will be added to the advisor chain. This can come in handy -if you need to add a standard set of 'global' advisors: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - global* - - - - - - ----- - - - - -[[aop-concise-proxy]] -=== Concise proxy definitions -Especially when defining transactional proxies, you may end up with many similar proxy -definitions. The use of parent and child bean definitions, along with inner bean -definitions, can result in much cleaner and more concise proxy definitions. - -First a parent, __template__, bean definition is created for the proxy: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - PROPAGATION_REQUIRED - - - ----- - -This will never be instantiated itself, so may actually be incomplete. Then each proxy -which needs to be created is just a child bean definition, which wraps the target of the -proxy as an inner bean definition, since the target will never be used on its own anyway. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - ----- - -It is of course possible to override properties from the parent template, such as in -this case, the transaction propagation settings: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - PROPAGATION_REQUIRED,readOnly - PROPAGATION_REQUIRED,readOnly - PROPAGATION_REQUIRED,readOnly - PROPAGATION_REQUIRED - - - ----- - -Note that in the example above, we have explicitly marked the parent bean definition as -__abstract__ by using the __abstract__ attribute, as described -<>, so that it may not actually ever be -instantiated. Application contexts (but not simple bean factories) will by default -pre-instantiate all singletons. It is therefore important (at least for singleton beans) -that if you have a (parent) bean definition which you intend to use only as a template, -and this definition specifies a class, you must make sure to set the __abstract__ -attribute to __true__, otherwise the application context will actually try to -pre-instantiate it. - - - - -[[aop-prog]] -=== Creating AOP proxies programmatically with the ProxyFactory -It's easy to create AOP proxies programmatically using Spring. This enables you to use -Spring AOP without dependency on Spring IoC. - -The following listing shows creation of a proxy for a target object, with one -interceptor and one advisor. The interfaces implemented by the target object will -automatically be proxied: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - ProxyFactory factory = new ProxyFactory(myBusinessInterfaceImpl); - factory.addAdvice(myMethodInterceptor); - factory.addAdvisor(myAdvisor); - MyBusinessInterface tb = (MyBusinessInterface) factory.getProxy(); ----- - -The first step is to construct an object of type -`org.springframework.aop.framework.ProxyFactory`. You can create this with a target -object, as in the above example, or specify the interfaces to be proxied in an alternate -constructor. - -You can add advices (with interceptors as a specialized kind of advice) and/or advisors, -and manipulate them for the life of the ProxyFactory. If you add an -IntroductionInterceptionAroundAdvisor, you can cause the proxy to implement additional -interfaces. - -There are also convenience methods on ProxyFactory (inherited from `AdvisedSupport`) -which allow you to add other advice types such as before and throws advice. -AdvisedSupport is the superclass of both ProxyFactory and ProxyFactoryBean. - -[TIP] -==== - -Integrating AOP proxy creation with the IoC framework is best practice in most -applications. We recommend that you externalize configuration from Java code with AOP, -as in general. -==== - - - - -[[aop-api-advised]] -=== Manipulating advised objects -However you create AOP proxies, you can manipulate them using the -`org.springframework.aop.framework.Advised` interface. Any AOP proxy can be cast to this -interface, whichever other interfaces it implements. This interface includes the -following methods: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - Advisor[] getAdvisors(); - - void addAdvice(Advice advice) throws AopConfigException; - - void addAdvice(int pos, Advice advice) throws AopConfigException; - - void addAdvisor(Advisor advisor) throws AopConfigException; - - void addAdvisor(int pos, Advisor advisor) throws AopConfigException; - - int indexOf(Advisor advisor); - - boolean removeAdvisor(Advisor advisor) throws AopConfigException; - - void removeAdvisor(int index) throws AopConfigException; - - boolean replaceAdvisor(Advisor a, Advisor b) throws AopConfigException; - - boolean isFrozen(); ----- - -The `getAdvisors()` method will return an Advisor for every advisor, interceptor or -other advice type that has been added to the factory. If you added an Advisor, the -returned advisor at this index will be the object that you added. If you added an -interceptor or other advice type, Spring will have wrapped this in an advisor with a -pointcut that always returns true. Thus if you added a `MethodInterceptor`, the advisor -returned for this index will be an `DefaultPointcutAdvisor` returning your -`MethodInterceptor` and a pointcut that matches all classes and methods. - -The `addAdvisor()` methods can be used to add any Advisor. Usually the advisor holding -pointcut and advice will be the generic `DefaultPointcutAdvisor`, which can be used with -any advice or pointcut (but not for introductions). - -By default, it's possible to add or remove advisors or interceptors even once a proxy -has been created. The only restriction is that it's impossible to add or remove an -introduction advisor, as existing proxies from the factory will not show the interface -change. (You can obtain a new proxy from the factory to avoid this problem.) - -A simple example of casting an AOP proxy to the `Advised` interface and examining and -manipulating its advice: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - Advised advised = (Advised) myObject; - Advisor[] advisors = advised.getAdvisors(); - int oldAdvisorCount = advisors.length; - System.out.println(oldAdvisorCount + " advisors"); - - // Add an advice like an interceptor without a pointcut - // Will match all proxied methods - // Can use for interceptors, before, after returning or throws advice - advised.addAdvice(new DebugInterceptor()); - - // Add selective advice using a pointcut - advised.addAdvisor(new DefaultPointcutAdvisor(mySpecialPointcut, myAdvice)); - - assertEquals("Added two advisors", oldAdvisorCount + 2, advised.getAdvisors().length); ----- - -[NOTE] -==== -It's questionable whether it's advisable (no pun intended) to modify advice on a -business object in production, although there are no doubt legitimate usage cases. -However, it can be very useful in development: for example, in tests. I have sometimes -found it very useful to be able to add test code in the form of an interceptor or other -advice, getting inside a method invocation I want to test. (For example, the advice can -get inside a transaction created for that method: for example, to run SQL to check that -a database was correctly updated, before marking the transaction for roll back.) -==== - -Depending on how you created the proxy, you can usually set a `frozen` flag, in which -case the `Advised` `isFrozen()` method will return true, and any attempts to modify -advice through addition or removal will result in an `AopConfigException`. The ability -to freeze the state of an advised object is useful in some cases, for example, to -prevent calling code removing a security interceptor. It may also be used in Spring 1.1 -to allow aggressive optimization if runtime advice modification is known not to be -required. - - - - -[[aop-autoproxy]] -=== Using the "auto-proxy" facility -So far we've considered explicit creation of AOP proxies using a `ProxyFactoryBean` or -similar factory bean. - -Spring also allows us to use "auto-proxy" bean definitions, which can automatically -proxy selected bean definitions. This is built on Spring "bean post processor" -infrastructure, which enables modification of any bean definition as the container loads. - -In this model, you set up some special bean definitions in your XML bean definition file -to configure the auto proxy infrastructure. This allows you just to declare the targets -eligible for auto-proxying: you don't need to use `ProxyFactoryBean`. - -There are two ways to do this: - -* Using an auto-proxy creator that refers to specific beans in the current context. -* A special case of auto-proxy creation that deserves to be considered separately; - auto-proxy creation driven by source-level metadata attributes. - - - -[[aop-autoproxy-choices]] -==== Autoproxy bean definitions -The `org.springframework.aop.framework.autoproxy` package provides the following -standard auto-proxy creators. - - -[[aop-api-autoproxy]] -===== BeanNameAutoProxyCreator -The `BeanNameAutoProxyCreator` class is a `BeanPostProcessor` that automatically creates -AOP proxies for beans with names matching literal values or wildcards. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - myInterceptor - - - ----- - -As with `ProxyFactoryBean`, there is an `interceptorNames` property rather than a list -of interceptors, to allow correct behavior for prototype advisors. Named "interceptors" -can be advisors or any advice type. - -As with auto proxying in general, the main point of using `BeanNameAutoProxyCreator` is -to apply the same configuration consistently to multiple objects, with minimal volume of -configuration. It is a popular choice for applying declarative transactions to multiple -objects. - -Bean definitions whose names match, such as "jdkMyBean" and "onlyJdk" in the above -example, are plain old bean definitions with the target class. An AOP proxy will be -created automatically by the `BeanNameAutoProxyCreator`. The same advice will be applied -to all matching beans. Note that if advisors are used (rather than the interceptor in -the above example), the pointcuts may apply differently to different beans. - - -[[aop-api-autoproxy-default]] -===== DefaultAdvisorAutoProxyCreator -A more general and extremely powerful auto proxy creator is -`DefaultAdvisorAutoProxyCreator`. This will automagically apply eligible advisors in the -current context, without the need to include specific bean names in the auto-proxy -advisor's bean definition. It offers the same merit of consistent configuration and -avoidance of duplication as `BeanNameAutoProxyCreator`. - -Using this mechanism involves: - -* Specifying a `DefaultAdvisorAutoProxyCreator` bean definition. -* Specifying any number of Advisors in the same or related contexts. Note that these - __must__ be Advisors, not just interceptors or other advices. This is necessary - because there must be a pointcut to evaluate, to check the eligibility of each advice - to candidate bean definitions. - -The `DefaultAdvisorAutoProxyCreator` will automatically evaluate the pointcut contained -in each advisor, to see what (if any) advice it should apply to each business object -(such as "businessObject1" and "businessObject2" in the example). - -This means that any number of advisors can be applied automatically to each business -object. If no pointcut in any of the advisors matches any method in a business object, -the object will not be proxied. As bean definitions are added for new business objects, -they will automatically be proxied if necessary. - -Autoproxying in general has the advantage of making it impossible for callers or -dependencies to obtain an un-advised object. Calling getBean("businessObject1") on this -ApplicationContext will return an AOP proxy, not the target business object. (The "inner -bean" idiom shown earlier also offers this benefit.) - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - - - - - - ----- - -The `DefaultAdvisorAutoProxyCreator` is very useful if you want to apply the same advice -consistently to many business objects. Once the infrastructure definitions are in place, -you can simply add new business objects without including specific proxy configuration. -You can also drop in additional aspects very easily - for example, tracing or -performance monitoring aspects - with minimal change to configuration. - -The DefaultAdvisorAutoProxyCreator offers support for filtering (using a naming -convention so that only certain advisors are evaluated, allowing use of multiple, -differently configured, AdvisorAutoProxyCreators in the same factory) and ordering. -Advisors can implement the `org.springframework.core.Ordered` interface to ensure -correct ordering if this is an issue. The TransactionAttributeSourceAdvisor used in the -above example has a configurable order value; the default setting is unordered. - - -[[aop-api-autoproxy-abstract]] -===== AbstractAdvisorAutoProxyCreator -This is the superclass of DefaultAdvisorAutoProxyCreator. You can create your own -auto-proxy creators by subclassing this class, in the unlikely event that advisor -definitions offer insufficient customization to the behavior of the framework -`DefaultAdvisorAutoProxyCreator`. - - - -[[aop-autoproxy-metadata]] -==== Using metadata-driven auto-proxying -A particularly important type of auto-proxying is driven by metadata. This produces a -similar programming model to .NET `ServicedComponents`. Instead of defining metadata in -XML descriptors, configuration for transaction management and other enterprise services -is held in source-level attributes. - -In this case, you use the `DefaultAdvisorAutoProxyCreator`, in combination with Advisors -that understand metadata attributes. The metadata specifics are held in the pointcut -part of the candidate advisors, rather than in the auto-proxy creation class itself. - -This is really a special case of the `DefaultAdvisorAutoProxyCreator`, but deserves -consideration on its own. (The metadata-aware code is in the pointcuts contained in the -advisors, not the AOP framework itself.) - -The `/attributes` directory of the JPetStore sample application shows the use of -attribute-driven auto-proxying. In this case, there's no need to use the -`TransactionProxyFactoryBean`. Simply defining transactional attributes on business -objects is sufficient, because of the use of metadata-aware pointcuts. The bean -definitions include the following code, in `/WEB-INF/declarativeServices.xml`. Note that -this is generic, and can be used outside the JPetStore: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - - - - - - - - - ----- - -The `DefaultAdvisorAutoProxyCreator` bean definition (the name is not significant, hence -it can even be omitted) will pick up all eligible pointcuts in the current application -context. In this case, the "transactionAdvisor" bean definition, of type -`TransactionAttributeSourceAdvisor`, will apply to classes or methods carrying a -transaction attribute. The TransactionAttributeSourceAdvisor depends on a -TransactionInterceptor, via constructor dependency. The example resolves this via -autowiring. The `AttributesTransactionAttributeSource` depends on an implementation of -the `org.springframework.metadata.Attributes` interface. In this fragment, the -"attributes" bean satisfies this, using the Jakarta Commons Attributes API to obtain -attribute information. (The application code must have been compiled using the Commons -Attributes compilation task.) - -The `/annotation` directory of the JPetStore sample application contains an analogous -example for auto-proxying driven by JDK 1.5+ annotations. The following configuration -enables automatic detection of Spring's `Transactional` annotation, leading to implicit -proxies for beans containing that annotation: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - - - - - ----- - -The `TransactionInterceptor` defined here depends on a `PlatformTransactionManager` -definition, which is not included in this generic file (although it could be) because it -will be specific to the application's transaction requirements (typically JTA, as in -this example, or Hibernate, JDO or JDBC): - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - ----- - -[TIP] -==== - -If you require only declarative transaction management, using these generic XML -definitions will result in Spring automatically proxying all classes or methods with -transaction attributes. You won't need to work directly with AOP, and the programming -model is similar to that of .NET ServicedComponents. -==== - -This mechanism is extensible. It's possible to do auto-proxying based on custom -attributes. You need to: - -* Define your custom attribute. -* Specify an Advisor with the necessary advice, including a pointcut that is triggered - by the presence of the custom attribute on a class or method. You may be able to use - an existing advice, merely implementing a static pointcut that picks up the custom - attribute. - -It's possible for such advisors to be unique to each advised class (for example, mixins): -they simply need to be defined as prototype, rather than singleton, bean definitions. -For example, the `LockMixin` introduction interceptor from the Spring test suite, -shown above, could be used in conjunction with a generic `DefaultIntroductionAdvisor`: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - ----- - -Note that both `lockMixin` and `lockableAdvisor` are defined as prototypes. - - - - -[[aop-targetsource]] -=== Using TargetSources -Spring offers the concept of a __TargetSource__, expressed in the -`org.springframework.aop.TargetSource` interface. This interface is responsible for -returning the "target object" implementing the join point. The `TargetSource` -implementation is asked for a target instance each time the AOP proxy handles a method -invocation. - -Developers using Spring AOP don't normally need to work directly with TargetSources, but -this provides a powerful means of supporting pooling, hot swappable and other -sophisticated targets. For example, a pooling TargetSource can return a different target -instance for each invocation, using a pool to manage instances. - -If you do not specify a TargetSource, a default implementation is used that wraps a -local object. The same target is returned for each invocation (as you would expect). - -Let's look at the standard target sources provided with Spring, and how you can use them. - -[TIP] -==== - -When using a custom target source, your target will usually need to be a prototype -rather than a singleton bean definition. This allows Spring to create a new target -instance when required. -==== - - - -[[aop-ts-swap]] -==== Hot swappable target sources -The `org.springframework.aop.target.HotSwappableTargetSource` exists to allow the target -of an AOP proxy to be switched while allowing callers to keep their references to it. - -Changing the target source's target takes effect immediately. The -`HotSwappableTargetSource` is threadsafe. - -You can change the target via the `swap()` method on HotSwappableTargetSource as follows: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - HotSwappableTargetSource swapper = (HotSwappableTargetSource) beanFactory.getBean("swapper"); - Object oldTarget = swapper.swap(newTarget); ----- - -The XML definitions required look as follows: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - - ----- - -The above `swap()` call changes the target of the swappable bean. Clients who hold a -reference to that bean will be unaware of the change, but will immediately start hitting -the new target. - -Although this example doesn't add any advice - and it's not necessary to add advice to -use a `TargetSource` - of course any `TargetSource` can be used in conjunction with -arbitrary advice. - - - -[[aop-ts-pool]] -==== Pooling target sources -Using a pooling target source provides a similar programming model to stateless session -EJBs, in which a pool of identical instances is maintained, with method invocations -going to free objects in the pool. - -A crucial difference between Spring pooling and SLSB pooling is that Spring pooling can -be applied to any POJO. As with Spring in general, this service can be applied in a -non-invasive way. - -Spring provides out-of-the-box support for Jakarta Commons Pool 1.3, which provides a -fairly efficient pooling implementation. You'll need the commons-pool Jar on your -application's classpath to use this feature. It's also possible to subclass -`org.springframework.aop.target.AbstractPoolingTargetSource` to support any other -pooling API. - -Sample configuration is shown below: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - ... properties omitted - - - - - - - - - - - ----- - -Note that the target object - "businessObjectTarget" in the example - __must__ be a -prototype. This allows the `PoolingTargetSource` implementation to create new instances -of the target to grow the pool as necessary. See the javadocs of -`AbstractPoolingTargetSource` and the concrete subclass you wish to use for information -about its properties: "maxSize" is the most basic, and always guaranteed to be present. - -In this case, "myInterceptor" is the name of an interceptor that would need to be -defined in the same IoC context. However, it isn't necessary to specify interceptors to -use pooling. If you want only pooling, and no other advice, don't set the -interceptorNames property at all. - -It's possible to configure Spring so as to be able to cast any pooled object to the -`org.springframework.aop.target.PoolingConfig` interface, which exposes information -about the configuration and current size of the pool through an introduction. You'll -need to define an advisor like this: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - ----- - -This advisor is obtained by calling a convenience method on the -`AbstractPoolingTargetSource` class, hence the use of MethodInvokingFactoryBean. This -advisor's name ("poolConfigAdvisor" here) must be in the list of interceptors names in -the ProxyFactoryBean exposing the pooled object. - -The cast will look as follows: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - PoolingConfig conf = (PoolingConfig) beanFactory.getBean("businessObject"); - System.out.println("Max pool size is " + conf.getMaxSize()); ----- - -[NOTE] -==== -Pooling stateless service objects is not usually necessary. We don't believe it should -be the default choice, as most stateless objects are naturally thread safe, and instance -pooling is problematic if resources are cached. -==== - -Simpler pooling is available using auto-proxying. It's possible to set the TargetSources -used by any auto-proxy creator. - - - -[[aop-ts-prototype]] -==== Prototype target sources -Setting up a "prototype" target source is similar to a pooling TargetSource. In this -case, a new instance of the target will be created on every method invocation. Although -the cost of creating a new object isn't high in a modern JVM, the cost of wiring up the -new object (satisfying its IoC dependencies) may be more expensive. Thus you shouldn't -use this approach without very good reason. - -To do this, you could modify the `poolTargetSource` definition shown above as follows. -(I've also changed the name, for clarity.) - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - ----- - -There's only one property: the name of the target bean. Inheritance is used in the -TargetSource implementations to ensure consistent naming. As with the pooling target -source, the target bean must be a prototype bean definition. - - - -[[aop-ts-threadlocal]] -==== ThreadLocal target sources - -`ThreadLocal` target sources are useful if you need an object to be created for each -incoming request (per thread that is). The concept of a `ThreadLocal` provide a JDK-wide -facility to transparently store resource alongside a thread. Setting up a -`ThreadLocalTargetSource` is pretty much the same as was explained for the other types -of target source: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - ----- - -[NOTE] -==== -ThreadLocals come with serious issues (potentially resulting in memory leaks) when -incorrectly using them in a multi-threaded and multi-classloader environments. One -should always consider wrapping a threadlocal in some other class and never directly use -the `ThreadLocal` itself (except of course in the wrapper class). Also, one should -always remember to correctly set and unset (where the latter simply involved a call to -`ThreadLocal.set(null)`) the resource local to the thread. Unsetting should be done in -any case since not unsetting it might result in problematic behavior. Spring's -ThreadLocal support does this for you and should always be considered in favor of using -ThreadLocals without other proper handling code. -==== - - - - -[[aop-extensibility]] -=== Defining new Advice types - -Spring AOP is designed to be extensible. While the interception implementation strategy -is presently used internally, it is possible to support arbitrary advice types in -addition to the out-of-the-box interception around advice, before, throws advice and -after returning advice. - -The `org.springframework.aop.framework.adapter` package is an SPI package allowing -support for new custom advice types to be added without changing the core framework. -The only constraint on a custom `Advice` type is that it must implement the -`org.aopalliance.aop.Advice` marker interface. - -Please refer to the `org.springframework.aop.framework.adapter` javadocs for further -information. - - - - -[[aop-api-resources]] -=== Further resources -Please refer to the Spring sample applications for further examples of Spring AOP: - -* The JPetStore's default configuration illustrates the use of the - `TransactionProxyFactoryBean` for declarative transaction management. -* The `/attributes` directory of the JPetStore illustrates the use of attribute-driven - declarative transaction management. - - - - - -[[testing]] -== Testing - - - - -[[testing-introduction]] -=== Introduction to Spring Testing -Testing is an integral part of enterprise software development. This chapter focuses on -the value-add of the IoC principle to <> and on the benefits -of the Spring Framework's support for <>. __(A -thorough treatment of testing in the enterprise is beyond the scope of this reference -manual.)__ - - - - -[[unit-testing]] -=== Unit Testing -Dependency Injection should make your code less dependent on the container than it would -be with traditional Java EE development. The POJOs that make up your application should -be testable in JUnit or TestNG tests, with objects simply instantiated using the `new` -operator, __without Spring or any other container__. You can use <> (in conjunction with other valuable testing techniques) to test your code in -isolation. If you follow the architecture recommendations for Spring, the resulting -clean layering and componentization of your codebase will facilitate easier unit -testing. For example, you can test service layer objects by stubbing or mocking DAO or -Repository interfaces, without needing to access persistent data while running unit -tests. - -True unit tests typically run extremely quickly, as there is no runtime infrastructure -to set up. Emphasizing true unit tests as part of your development methodology will -boost your productivity. You may not need this section of the testing chapter to help -you write effective unit tests for your IoC-based applications. For certain unit testing -scenarios, however, the Spring Framework provides the following mock objects and testing -support classes. - - - -[[mock-objects]] -==== Mock Objects - - -[[mock-objects-env]] -===== Environment -The `org.springframework.mock.env` package contains mock implementations of the -`Environment` and `PropertySource` abstractions (see <> -and <>). `MockEnvironment` and -`MockPropertySource` are useful for developing __out-of-container__ tests for code that -depends on environment-specific properties. - - -[[mock-objects-jndi]] -===== JNDI -The `org.springframework.mock.jndi` package contains an implementation of the JNDI SPI, -which you can use to set up a simple JNDI environment for test suites or stand-alone -applications. If, for example, JDBC ++DataSource++s get bound to the same JNDI names in -test code as within a Java EE container, you can reuse both application code and -configuration in testing scenarios without modification. - - -[[mock-objects-servlet]] -===== Servlet API -The `org.springframework.mock.web` package contains a comprehensive set of Servlet API -mock objects, targeted at usage with Spring's Web MVC framework, which are useful for -testing web contexts and controllers. These mock objects are generally more convenient -to use than dynamic mock objects such as http://www.easymock.org[EasyMock] or existing -Servlet API mock objects such as http://www.mockobjects.com[MockObjects]. - - -[[mock-objects-portlet]] -===== Portlet API -The `org.springframework.mock.web.portlet` package contains a set of Portlet API mock -objects, targeted at usage with Spring's Portlet MVC framework. - - - -[[unit-testing-support-classes]] -==== Unit Testing support Classes - - -[[unit-testing-utilities]] -===== General utilities -The `org.springframework.test.util` package contains `ReflectionTestUtils`, which is a -collection of reflection-based utility methods. Developers use these methods in unit and -integration testing scenarios in which they need to set a non- `public` field or invoke -a non- `public` setter method when testing application code involving, for example: - -* ORM frameworks such as JPA and Hibernate that condone `private` or `protected` field - access as opposed to `public` setter methods for properties in a domain entity. -* Spring's support for annotations such as `@Autowired`, `@Inject`, and `@Resource,` - which provides dependency injection for `private` or `protected` fields, setter - methods, and configuration methods. - - -[[unit-testing-spring-mvc]] -===== Spring MVC -The `org.springframework.test.web` package contains `ModelAndViewAssert`, which you can -use in combination with JUnit, TestNG, or any other testing framework for unit tests -dealing with Spring MVC `ModelAndView` objects. - -.Unit testing Spring MVC Controllers -[TIP] -==== -To test your Spring MVC ++Controller++s, use `ModelAndViewAssert` combined with -`MockHttpServletRequest`, `MockHttpSession`, and so on from the <> package. - -Note: As of Spring 4.0, the set of mocks in the `org.springframework.mock.web` package -is now based on the Servlet 3.0 API. -==== - - - - -[[integration-testing]] -=== Integration Testing - - - -[[integration-testing-overview]] -==== Overview -It is important to be able to perform some integration testing without requiring -deployment to your application server or connecting to other enterprise infrastructure. -This will enable you to test things such as: - -* The correct wiring of your Spring IoC container contexts. -* Data access using JDBC or an ORM tool. This would include such things as the - correctness of SQL statements, Hibernate queries, JPA entity mappings, etc. - -The Spring Framework provides first-class support for integration testing in the -`spring-test` module. The name of the actual JAR file might include the release version -and might also be in the long `org.springframework.test` form, depending on where you -get it from (see the <> for an -explanation). This library includes the `org.springframework.test` package, which -contains valuable classes for integration testing with a Spring container. This testing -does not rely on an application server or other deployment environment. Such tests are -slower to run than unit tests but much faster than the equivalent Selenium tests or remote -tests that rely on deployment to an application server. - -In Spring 2.5 and later, unit and integration testing support is provided in the form of -the annotation-driven <>. The -TestContext framework is agnostic of the actual testing framework in use, thus allowing -instrumentation of tests in various environments including JUnit, TestNG, and so on. - - - -[[integration-testing-goals]] -==== Goals of Integration Testing -Spring's integration testing support has the following primary goals: - -* To manage <> between test - execution. -* To provide <>. -* To provide <> appropriate to integration testing. -* To supply <> that assist - developers in writing integration tests. - -The next few sections describe each goal and provide links to implementation and -configuration details. - - -[[testing-ctx-management]] -===== Context management and caching -The Spring TestContext Framework provides consistent loading of Spring -++ApplicationContext++s and ++WebApplicationContext++s as well as caching of those -contexts. Support for the caching of loaded contexts is important, because startup time -can become an issue -- not because of the overhead of Spring itself, but because the -objects instantiated by the Spring container take time to instantiate. For example, a -project with 50 to 100 Hibernate mapping files might take 10 to 20 seconds to load the -mapping files, and incurring that cost before running every test in every test fixture -leads to slower overall test runs that reduce developer productivity. - -Test classes typically declare either an array of __resource locations__ for XML -configuration metadata -- often in the classpath -- or an array of __annotated classes__ -that is used to configure the application. These locations or classes are the same as or -similar to those specified in `web.xml` or other deployment configuration files. - -By default, once loaded, the configured `ApplicationContext` is reused for each test. -Thus the setup cost is incurred only once per test suite, and subsequent test execution -is much faster. In this context, the term __test suite__ means all tests run in the same -JVM -- for example, all tests run from an Ant, Maven, or Gradle build for a given -project or module. In the unlikely case that a test corrupts the application context and -requires reloading -- for example, by modifying a bean definition or the state of an -application object -- the TestContext framework can be configured to reload the -configuration and rebuild the application context before executing the next test. - -See <> and <> with the -TestContext framework. - - -[[testing-fixture-di]] -===== Dependency Injection of test fixtures -When the TestContext framework loads your application context, it can optionally -configure instances of your test classes via Dependency Injection. This provides a -convenient mechanism for setting up test fixtures using preconfigured beans from your -application context. A strong benefit here is that you can reuse application contexts -across various testing scenarios (e.g., for configuring Spring-managed object graphs, -transactional proxies, ++DataSource++s, etc.), thus avoiding the need to duplicate -complex test fixture setup for individual test cases. - -As an example, consider the scenario where we have a class, `HibernateTitleRepository`, -that implements data access logic for a `Title` domain entity. We want to write -integration tests that test the following areas: - -* The Spring configuration: basically, is everything related to the configuration of the - `HibernateTitleRepository` bean correct and present? -* The Hibernate mapping file configuration: is everything mapped correctly, and are the - correct lazy-loading settings in place? -* The logic of the `HibernateTitleRepository`: does the configured instance of this - class perform as anticipated? - -See dependency injection of test fixtures with the <>. - - -[[testing-tx]] -===== Transaction management -One common issue in tests that access a real database is their effect on the state of -the persistence store. Even when you're using a development database, changes to the -state may affect future tests. Also, many operations -- such as inserting or modifying -persistent data -- cannot be performed (or verified) outside a transaction. - -The TestContext framework addresses this issue. By default, the framework will create -and roll back a transaction for each test. You simply write code that can assume the -existence of a transaction. If you call transactionally proxied objects in your tests, -they will behave correctly, according to their configured transactional semantics. In -addition, if a test method deletes the contents of selected tables while running within -the transaction managed for the test, the transaction will roll back by default, and the -database will return to its state prior to execution of the test. Transactional support -is provided to a test via a `PlatformTransactionManager` bean defined in the test's -application context. - -If you want a transaction to commit -- unusual, but occasionally useful when you want a -particular test to populate or modify the database -- the TestContext framework can be -instructed to cause the transaction to commit instead of roll back via the -<> and -<> annotations. - -See transaction management with the <>. - - -[[testing-support-classes]] -===== Support classes for integration testing -The Spring TestContext Framework provides several `abstract` support classes that -simplify the writing of integration tests. These base test classes provide well-defined -hooks into the testing framework as well as convenient instance variables and methods, -which enable you to access: - -* The `ApplicationContext`, for performing explicit bean lookups or testing the state of - the context as a whole. -* A `JdbcTemplate`, for executing SQL statements to query the database. Such queries can - be used to confirm database state both __prior to__ and __after__ execution of - database-related application code, and Spring ensures that such queries run in the - scope of the same transaction as the application code. When used in conjunction with - an ORM tool, be sure to avoid <>. - -In addition, you may want to create your own custom, application-wide superclass with -instance variables and methods specific to your project. - -See support classes for the <>. - - - -[[integration-testing-support-jdbc]] -==== JDBC Testing Support -The `org.springframework.test.jdbc` package contains `JdbcTestUtils`, which is a -collection of JDBC related utility functions intended to simplify standard database -testing scenarios. Specifically, `JdbcTestUtils` provides the following static utility -methods. - -* `countRowsInTable(..)`: counts the number of rows in the given table -* `countRowsInTableWhere(..)`: counts the number of rows in the given table, using -the provided `WHERE` clause -* `deleteFromTables(..)`: deletes all rows from the specified tables -* `deleteFromTableWhere(..)`: deletes rows from the given table, using the provided -`WHERE` clause -* `dropTables(..)`: drops the specified tables - -__Note that <> and -<> -provide convenience methods which delegate to the aforementioned methods in -`JdbcTestUtils`.__ - -The `spring-jdbc` module provides support for configuring and launching an embedded -database which can be used in integration tests that interact with a database. For -details, see <> and -<>. - - - -[[integration-testing-annotations]] -==== Annotations - - -[[integration-testing-annotations-spring]] -===== Spring Testing Annotations -The Spring Framework provides the following set of __Spring-specific__ annotations that -you can use in your unit and integration tests in conjunction with the TestContext -framework. Refer to the corresponding javadocs for further information, including -default attribute values, attribute aliases, and so on. - -* `@ContextConfiguration` - -+ - -Defines class-level metadata that is used to determine how to load and configure an -`ApplicationContext` for integration tests. Specifically, `@ContextConfiguration` -declares the application context resource `locations` or the annotated `classes` -that will be used to load the context. - -+ - -Resource locations are typically XML configuration files located in the classpath; -whereas, annotated classes are typically `@Configuration` classes. However, resource -locations can also refer to files in the file system, and annotated classes can be -component classes, etc. - -+ - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - **@ContextConfiguration**("/test-config.xml") - public class XmlApplicationContextTests { - // class body... - } ----- - -+ - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - **@ContextConfiguration**(**classes** = TestConfig.class) - public class ConfigClassApplicationContextTests { - // class body... - } ----- - -+ - -As an alternative or in addition to declaring resource locations or annotated classes, -`@ContextConfiguration` may be used to declare `ApplicationContextInitializer` classes. - -+ - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - **@ContextConfiguration**(**initializers** = CustomContextIntializer.class) - public class ContextInitializerTests { - // class body... - } ----- - -+ - -`@ContextConfiguration` may optionally be used to declare the `ContextLoader` strategy -as well. Note, however, that you typically do not need to explicitly configure the -loader since the default loader supports either resource `locations` or annotated -`classes` as well as `initializers`. - -+ - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - **@ContextConfiguration**(**locations** = "/test-context.xml", **loader** = CustomContextLoader.class) - public class CustomLoaderXmlApplicationContextTests { - // class body... - } ----- - -+ - -[NOTE] -==== -`@ContextConfiguration` provides support for __inheriting__ resource locations or -configuration classes as well as context initializers declared by superclasses by -default. -==== - -+ - -See <> and the `@ContextConfiguration` javadocs for -further details. - -* `@WebAppConfiguration` - -+ - -A class-level annotation that is used to declare that the `ApplicationContext` loaded -for an integration test should be a `WebApplicationContext`. The mere presence of -`@WebAppConfiguration` on a test class ensures that a `WebApplicationContext` will be -loaded for the test, using the default value of `"file:src/main/webapp"` for the path to -the root of the web application (i.e., the __resource base path__). The resource base -path is used behind the scenes to create a `MockServletContext` which serves as the -`ServletContext` for the test's `WebApplicationContext`. - -+ - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @ContextConfiguration - **@WebAppConfiguration** - public class WebAppTests { - // class body... - } ----- - -+ - -To override the default, specify a different base resource path via the __implicit__ -`value` attribute. Both `classpath:` and `file:` resource prefixes are supported. If no -resource prefix is supplied the path is assumed to be a file system resource. - -+ - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @ContextConfiguration - **@WebAppConfiguration("classpath:test-web-resources")** - public class WebAppTests { - // class body... - } ----- - -+ - -Note that `@WebAppConfiguration` must be used in conjunction with -`@ContextConfiguration`, either within a single test class or within a test class -hierarchy. See the `@WebAppConfiguration` javadocs for further details. - -+ - -* `@ContextHierarchy` - -+ - -A class-level annotation that is used to define a hierarchy of ++ApplicationContext++s -for integration tests. `@ContextHierarchy` should be declared with a list of one or more -`@ContextConfiguration` instances, each of which defines a level in the context -hierarchy. The following examples demonstrate the use of `@ContextHierarchy` within a -single test class; however, `@ContextHierarchy` can also be used within a test class -hierarchy. - -+ - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @ContextHierarchy({ - @ContextConfiguration("/parent-config.xml"), - @ContextConfiguration("/child-config.xml") - }) - public class ContextHierarchyTests { - // class body... - } ----- - -+ - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @WebAppConfiguration - @ContextHierarchy({ - @ContextConfiguration(classes = AppConfig.class), - @ContextConfiguration(classes = WebConfig.class) - }) - public class WebIntegrationTests { - // class body... - } ----- - -+ - -If you need to merge or override the configuration for a given level of the context -hierarchy within a test class hierarchy, you must explicitly name that level by -supplying the same value to the `name` attribute in `@ContextConfiguration` at each -corresponding level in the class hierarchy. See -<> and the `@ContextHierarchy` javadocs -for further examples. - -* `@ActiveProfiles` - -+ - -A class-level annotation that is used to declare which __bean definition profiles__ -should be active when loading an `ApplicationContext` for test classes. - -+ - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @ContextConfiguration - **@ActiveProfiles**("dev") - public class DeveloperTests { - // class body... - } ----- - -+ - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @ContextConfiguration - **@ActiveProfiles**({"dev", "integration"}) - public class DeveloperIntegrationTests { - // class body... - } ----- - -+ - -[NOTE] -==== -`@ActiveProfiles` provides support for __inheriting__ active bean definition profiles -declared by superclasses by default. It is also possible to resolve active bean -definition profiles programmatically by implementing a custom -<> -and registering it via the `resolver` attribute of `@ActiveProfiles`. -==== - -+ - -See <> and the `@ActiveProfiles` javadocs -for examples and further details. - -* `@TestPropertySource` - -+ - -A class-level annotation that is used to configure the locations of properties files and -inlined properties to be added to the `Environment`'s set of `PropertySources` for an -`ApplicationContext` loaded for an integration test. - -+ - -Test property sources have higher precedence than those loaded from the operating -system's environment or Java system properties as well as property sources added by the -application declaratively via `@PropertySource` or programmatically. Thus, test property -sources can be used to selectively override properties defined in system and application -property sources. Furthermore, inlined properties have higher precedence than properties -loaded from resource locations. - -+ - -The following example demonstrates how to declare a properties file from the classpath. - -+ - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @ContextConfiguration - **@TestPropertySource**("/test.properties") - public class MyIntegrationTests { - // class body... - } ----- - -+ - -The following example demonstrates how to declare _inlined_ properties. - -+ - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @ContextConfiguration - **@TestPropertySource**(properties = { "timezone = GMT", "port: 4242" }) - public class MyIntegrationTests { - // class body... - } ----- - -* `@DirtiesContext` - -+ - -Indicates that the underlying Spring `ApplicationContext` has been __dirtied__ during -the execution of a test (i.e., modified or corrupted in some manner -- for example, by -changing the state of a singleton bean) and should be closed, regardless of whether the -test passed. When an application context is marked __dirty__, it is removed from the -testing framework's cache and closed. As a consequence, the underlying Spring container -will be rebuilt for any subsequent test that requires a context with the same -configuration metadata. - -+ - -`@DirtiesContext` can be used as both a class-level and method-level annotation within -the same test class. In such scenarios, the `ApplicationContext` is marked as __dirty__ -after any such annotated method as well as after the entire class. If the `ClassMode` is -set to `AFTER_EACH_TEST_METHOD`, the context is marked dirty after each test method in -the class. - -+ - -The following examples explain when the context would be dirtied for various -configuration scenarios: - -+ - -** After the current test class, when declared on a class with class mode set to -`AFTER_CLASS` (i.e., the default class mode). - -+ - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - **@DirtiesContext** - public class ContextDirtyingTests { - // some tests that result in the Spring container being dirtied - } ----- - -+ - -** After each test method in the current test class, when declared on a class with class -mode set to `AFTER_EACH_TEST_METHOD.` - -+ - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - **@DirtiesContext**(**classMode** = ClassMode.AFTER_EACH_TEST_METHOD) - public class ContextDirtyingTests { - // some tests that result in the Spring container being dirtied - } ----- - -+ - -** After the current test, when declared on a method. - -+ - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - **@DirtiesContext** - @Test - public void testProcessWhichDirtiesAppCtx() { - // some logic that results in the Spring container being dirtied - } ----- - -+ - -If `@DirtiesContext` is used in a test whose context is configured as part of a context -hierarchy via `@ContextHierarchy`, the `hierarchyMode` flag can be used to control how -the context cache is cleared. By default an __exhaustive__ algorithm will be used that -clears the context cache including not only the current level but also all other context -hierarchies that share an ancestor context common to the current test; all -++ApplicationContext++s that reside in a sub-hierarchy of the common ancestor context -will be removed from the context cache and closed. If the __exhaustive__ algorithm is -overkill for a particular use case, the simpler __current level__ algorithm can be -specified instead, as seen below. - -+ - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @ContextHierarchy({ - @ContextConfiguration("/parent-config.xml"), - @ContextConfiguration("/child-config.xml") - }) - public class BaseTests { - // class body... - } - - public class ExtendedTests extends BaseTests { - - @Test - @DirtiesContext(**hierarchyMode = HierarchyMode.CURRENT_LEVEL**) - public void test() { - // some logic that results in the child context being dirtied - } - } ----- - -+ - -For further details regarding the `EXHAUSTIVE` and `CURRENT_LEVEL` algorithms see the -`DirtiesContext.HierarchyMode` javadocs. - -* `@TestExecutionListeners` - -+ - -Defines class-level metadata for configuring which ++TestExecutionListener++s should be -registered with the `TestContextManager`. Typically, `@TestExecutionListeners` is used -in conjunction with `@ContextConfiguration`. - -+ - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @ContextConfiguration - **@TestExecutionListeners**({CustomTestExecutionListener.class, AnotherTestExecutionListener.class}) - public class CustomTestExecutionListenerTests { - // class body... - } ----- - -+ - -`@TestExecutionListeners` supports __inherited__ listeners by default. See the javadocs -for an example and further details. - -* `@TransactionConfiguration` - -+ - -Defines class-level metadata for configuring transactional tests. Specifically, the bean -name of the `PlatformTransactionManager` that should be used to drive transactions can -be explicitly specified if there are multiple beans of type `PlatformTransactionManager` -in the test's `ApplicationContext` and if the bean name of the desired -`PlatformTransactionManager` is not "transactionManager". In addition, you can change -the `defaultRollback` flag to `false`. Typically, `@TransactionConfiguration` is used in -conjunction with `@ContextConfiguration`. - -+ - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @ContextConfiguration - **@TransactionConfiguration**(**transactionManager** = "txMgr", **defaultRollback** = false) - public class CustomConfiguredTransactionalTests { - // class body... - } ----- - -+ - -[NOTE] -==== -If the default conventions are sufficient for your test configuration, you can avoid -using `@TransactionConfiguration` altogether. In other words, if you have only one -transaction manager -- or if you have multiple transaction managers but the transaction -manager for tests is named "transactionManager" or specified via a -`TransactionManagementConfigurer` -- and if you want transactions to roll back -automatically, then there is no need to annotate your test class with -`@TransactionConfiguration`. -==== - -+ - -* `@Rollback` - -+ - -Indicates whether the transaction for the annotated test method should be __rolled -back__ after the test method has completed. If `true`, the transaction is rolled back; -otherwise, the transaction is committed. Use `@Rollback` to override the default -rollback flag configured at the class level. - -+ - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - **@Rollback**(false) - @Test - public void testProcessWithoutRollback() { - // ... - } ----- - -* `@BeforeTransaction` - -+ - -Indicates that the annotated `public void` method should be executed __before__ a -transaction is started for test methods configured to run within a transaction via the -`@Transactional` annotation. - -+ - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - **@BeforeTransaction** - public void beforeTransaction() { - // logic to be executed before a transaction is started - } ----- - -* `@AfterTransaction` - -+ - -Indicates that the annotated `public void` method should be executed __after__ a -transaction has ended for test methods configured to run within a transaction via the -`@Transactional` annotation. - -+ - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - **@AfterTransaction** - public void afterTransaction() { - // logic to be executed after a transaction has ended - } ----- - -* `@Sql` - -+ - -Used to annotate a test class or test method to configure SQL scripts to be executed -against a given database during integration tests. - -+ - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Test - **@Sql**({"/test-schema.sql", "/test-user-data.sql"}) - public void userTest { - // execute code that relies on the test schema and test data - } ----- - -+ - -See <> for further details. - -* `@SqlConfig` - -+ - -Defines metadata that is used to determine how to parse and execute SQL scripts -configured via the `@Sql` annotation. - -+ - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Test - @Sql( - scripts = "/test-user-data.sql", - config = **@SqlConfig**(commentPrefix = "`", separator = "@@") - ) - public void userTest { - // execute code that relies on the test data - } ----- - -* `@SqlGroup` - -+ - -A container annotation that aggregates several `@Sql` annotations. Can be used natively, -declaring several nested `@Sql` annotations. Can also be used in conjunction with Java -8's support for repeatable annotations, where `@Sql` can simply be declared several times -on the same class or method, implicitly generating this container annotation. - -+ - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Test - **@SqlGroup**({ - @Sql(scripts = "/test-schema.sql", config = @SqlConfig(commentPrefix = "`")), - @Sql("/test-user-data.sql") - )} - public void userTest { - // execute code that uses the test schema and test data - } ----- - - -[[integration-testing-annotations-standard]] -===== Standard Annotation Support -The following annotations are supported with standard semantics for all configurations -of the Spring TestContext Framework. Note that these annotations are not specific to -tests and can be used anywhere in the Spring Framework. - -* `@Autowired` -* `@Qualifier` -* `@Resource` (javax.annotation) _if JSR-250 is present_ -* `@Inject` (javax.inject) _if JSR-330 is present_ -* `@Named` (javax.inject) _if JSR-330 is present_ -* `@PersistenceContext` (javax.persistence) _if JPA is present_ -* `@PersistenceUnit` (javax.persistence) _if JPA is present_ -* `@Required` -* `@Transactional` - -.JSR-250 Lifecycle Annotations -[NOTE] -==== -In the Spring TestContext Framework `@PostConstruct` and `@PreDestroy` may be used with -standard semantics on any application components configured in the `ApplicationContext`; -however, these lifecycle annotations have limited usage within an actual test class. - -If a method within a test class is annotated with `@PostConstruct`, that method will be -executed before any __before__ methods of the underlying test framework (e.g., methods -annotated with JUnit's `@Before`), and that will apply for every test method in the test -class. On the other hand, if a method within a test class is annotated with -`@PreDestroy`, that method will __never__ be executed. Within a test class it is -therefore recommended to use test lifecycle callbacks from the underlying test framework -instead of `@PostConstruct` and `@PreDestroy`. -==== - - -[[integration-testing-annotations-junit]] -===== Spring JUnit Testing Annotations -The following annotations are __only__ supported when used in conjunction with the -<> or the -<> support classes. - -* `@IfProfileValue` - -+ - -Indicates that the annotated test is enabled for a specific testing environment. If the -configured `ProfileValueSource` returns a matching `value` for the provided `name`, the -test is enabled. This annotation can be applied to an entire class or to individual -methods. Class-level usage overrides method-level usage. - -+ - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - **@IfProfileValue**(**name**="java.vendor", **value**="Oracle Corporation") - @Test - public void testProcessWhichRunsOnlyOnOracleJvm() { - // some logic that should run only on Java VMs from Oracle Corporation - } ----- - -+ - -Alternatively, you can configure `@IfProfileValue` with a list of `values` (with __OR__ -semantics) to achieve TestNG-like support for __test groups__ in a JUnit environment. -Consider the following example: - -+ - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - **@IfProfileValue**(**name**="test-groups", **values**={"unit-tests", "integration-tests"}) - @Test - public void testProcessWhichRunsForUnitOrIntegrationTestGroups() { - // some logic that should run only for unit and integration test groups - } ----- - -+ - -* `@ProfileValueSourceConfiguration` - -+ - -Class-level annotation that specifies what type of `ProfileValueSource` to use when -retrieving __profile values__ configured through the `@IfProfileValue` annotation. If -`@ProfileValueSourceConfiguration` is not declared for a test, -`SystemProfileValueSource` is used by default. - -+ - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - **@ProfileValueSourceConfiguration**(CustomProfileValueSource.class) - public class CustomProfileValueSourceTests { - // class body... - } ----- - -* `@Timed` - -+ - -Indicates that the annotated test method must finish execution in a specified time -period (in milliseconds). If the text execution time exceeds the specified time period, -the test fails. - -+ - -The time period includes execution of the test method itself, any repetitions of the -test (see `@Repeat`), as well as any __set up__ or __tear down__ of the test fixture. - -+ - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - **@Timed**(millis=1000) - public void testProcessWithOneSecondTimeout() { - // some logic that should not take longer than 1 second to execute - } ----- - -+ - -Spring's `@Timed` annotation has different semantics than JUnit's `@Test(timeout=...)` -support. Specifically, due to the manner in which JUnit handles test execution timeouts -(that is, by executing the test method in a separate `Thread`), `@Test(timeout=...)` -preemptively fails the test if the test takes too long. Spring's `@Timed`, on the other -hand, does not preemptively fail the test but rather waits for the test to complete -before failing. - -* `@Repeat` - -+ - -Indicates that the annotated test method must be executed repeatedly. The number of -times that the test method is to be executed is specified in the annotation. - -+ - -The scope of execution to be repeated includes execution of the test method itself as -well as any __set up__ or __tear down__ of the test fixture. - -+ - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - **@Repeat**(10) - @Test - public void testProcessRepeatedly() { - // ... - } ----- - - -[[integration-testing-annotations-meta]] -===== Meta-Annotation Support for Testing -As of Spring Framework 4.0, it is possible to use test-related annotations as -<> in order to create custom _composed annotations_ -and reduce configuration duplication across a test suite. - -Each of the following may be used as meta-annotations in conjunction with the -<>. - -* `@ContextConfiguration` -* `@ContextHierarchy` -* `@ActiveProfiles` -* `@TestPropertySource` -* `@DirtiesContext` -* `@WebAppConfiguration` -* `@TestExecutionListeners` -* `@Transactional` -* `@BeforeTransaction` -* `@AfterTransaction` -* `@TransactionConfiguration` -* `@Rollback` -* `@Sql` -* `@SqlConfig` -* `@SqlGroup` -* `@Repeat` -* `@Timed` -* `@IfProfileValue` -* `@ProfileValueSourceConfiguration` - -For example, if we discover that we are repeating the following configuration -across our JUnit-based test suite... - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @RunWith(SpringJUnit4ClassRunner.class) - @ContextConfiguration({"/app-config.xml", "/test-data-access-config.xml"}) - @ActiveProfiles("dev") - @Transactional - public class OrderRepositoryTests { } - - @RunWith(SpringJUnit4ClassRunner.class) - @ContextConfiguration({"/app-config.xml", "/test-data-access-config.xml"}) - @ActiveProfiles("dev") - @Transactional - public class UserRepositoryTests { } ----- - -We can reduce the above duplication by introducing a custom _composed annotation_ -that centralizes the common test configuration like this: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Target(ElementType.TYPE) - @Retention(RetentionPolicy.RUNTIME) - @ContextConfiguration({"/app-config.xml", "/test-data-access-config.xml"}) - @ActiveProfiles("dev") - @Transactional - public @interface TransactionalDevTest { } ----- - -Then we can use our custom `@TransactionalDevTest` annotation to simplify the -configuration of individual test classes as follows: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @RunWith(SpringJUnit4ClassRunner.class) - @TransactionalDevTest - public class OrderRepositoryTests { } - - @RunWith(SpringJUnit4ClassRunner.class) - @TransactionalDevTest - public class UserRepositoryTests { } ----- - - - -[[testcontext-framework]] -==== Spring TestContext Framework -The __Spring TestContext Framework__ (located in the -`org.springframework.test.context` package) provides generic, annotation-driven unit and -integration testing support that is agnostic of the testing framework in use. The -TestContext framework also places a great deal of importance on __convention over -configuration__ with reasonable defaults that can be overridden through annotation-based -configuration. - -In addition to generic testing infrastructure, the TestContext framework provides -explicit support for JUnit and TestNG in the form of `abstract` support classes. For -JUnit, Spring also provides a custom JUnit `Runner` that allows one to write so-called -__POJO test classes__. POJO test classes are not required to extend a particular class -hierarchy. - -The following section provides an overview of the internals of the TestContext -framework. If you are only interested in using the framework and not necessarily -interested in extending it with your own custom listeners or custom loaders, feel free -to go directly to the configuration (<>, -<>, <>), <>, and -<> sections. - - -[[testcontext-key-abstractions]] -===== Key abstractions -The core of the framework consists of the `TestContext` and `TestContextManager` classes -and the `TestExecutionListener`, `ContextLoader`, and `SmartContextLoader` interfaces. A -`TestContextManager` is created on a per-test basis (e.g., for the execution of a single -test method in JUnit). The `TestContextManager` in turn manages a `TestContext` that -holds the context of the current test. The `TestContextManager` also updates the state -of the `TestContext` as the test progresses and delegates to ++TestExecutionListener++s, -which instrument the actual test execution by providing dependency injection, managing -transactions, and so on. A `ContextLoader` (or `SmartContextLoader`) is responsible for -loading an `ApplicationContext` for a given test class. Consult the javadocs and the -Spring test suite for further information and examples of various implementations. - -* `TestContext`: Encapsulates the context in which a test is executed, agnostic of the - actual testing framework in use, and provides context management and caching support - for the test instance for which it is responsible. The `TestContext` also delegates to - a `ContextLoader` (or `SmartContextLoader`) to load an `ApplicationContext` if - requested. -* `TestContextManager`: The main entry point into the __Spring TestContext Framework__, - which manages a single `TestContext` and signals events to all registered - ++TestExecutionListener++s at well-defined test execution points: -** prior to any __before class methods__ of a particular testing framework -** test instance preparation -** prior to any __before methods__ of a particular testing framework -** after any __after methods__ of a particular testing framework -** after any __after class methods__ of a particular testing framework -* `TestExecutionListener`: Defines a __listener__ API for reacting to test execution - events published by the `TestContextManager` with which the listener is registered. See - <>. -* `ContextLoader`: Strategy interface introduced in Spring 2.5 for loading an - `ApplicationContext` for an integration test managed by the Spring TestContext - Framework. - -+ - -Implement `SmartContextLoader` instead of this interface in order to provide support for -annotated classes, active bean definition profiles, test property sources, context -hierarchies, and ++WebApplicationContext++s. - -* `SmartContextLoader`: Extension of the `ContextLoader` interface introduced in Spring - 3.1. - -+ - -The `SmartContextLoader` SPI supersedes the `ContextLoader` SPI that was introduced in -Spring 2.5. Specifically, a `SmartContextLoader` can choose to process resource -`locations`, annotated `classes`, or context `initializers`. Furthermore, a -`SmartContextLoader` can set active bean definition profiles and test property sources in -the context that it loads. - -+ - -Spring provides the following implementations: - -+ - -** `DelegatingSmartContextLoader`: one of two default loaders which delegates internally -to an `AnnotationConfigContextLoader`, a `GenericXmlContextLoader`, or a -`GenericGroovyXmlContextLoader` depending either on the configuration declared for the -test class or on the presence of default locations or default configuration classes. -Groovy support is only enabled if Groovy is on the classpath. -** `WebDelegatingSmartContextLoader`: one of two default loaders which delegates -internally to an `AnnotationConfigWebContextLoader`, a `GenericXmlWebContextLoader`, or a -`GenericGroovyXmlWebContextLoader` depending either on the configuration declared for the -test class or on the presence of default locations or default configuration classes. A -web `ContextLoader` will only be used if `@WebAppConfiguration` is present on the test -class. Groovy support is only enabled if Groovy is on the classpath. -** `AnnotationConfigContextLoader`: loads a standard `ApplicationContext` from -__annotated classes__. -** `AnnotationConfigWebContextLoader`: loads a `WebApplicationContext` from __annotated -classes__. -** `GenericGroovyXmlContextLoader`: loads a standard `ApplicationContext` from __resource -locations__ that are either Groovy scripts or XML configuration files. -** `GenericGroovyXmlWebContextLoader`: loads a `WebApplicationContext` from __resource -locations__ that are either Groovy scripts or XML configuration files. -** `GenericXmlContextLoader`: loads a standard `ApplicationContext` from XML __resource -locations__. -** `GenericXmlWebContextLoader`: loads a `WebApplicationContext` from XML __resource -locations__. -** `GenericPropertiesContextLoader`: loads a standard `ApplicationContext` from Java -Properties files. - -The following sections explain how to configure the TestContext framework through -annotations and provide working examples of how to write unit and integration tests with -the framework. - -[[testcontext-tel-config]] -===== TestExecutionListener configuration - -Spring provides the following `TestExecutionListener` implementations that are registered -by default, exactly in this order. - -* `ServletTestExecutionListener`: configures Servlet API mocks for a - `WebApplicationContext` -* `DependencyInjectionTestExecutionListener`: provides dependency injection for the test - instance -* `DirtiesContextTestExecutionListener`: handles the `@DirtiesContext` annotation -* `TransactionalTestExecutionListener`: provides transactional test execution with - default rollback semantics -* `SqlScriptsTestExecutionListener`: executes SQL scripts configured via the `@Sql` - annotation - -[[testcontext-tel-config-registering-tels]] -====== Registering custom TestExecutionListeners - -Custom ++TestExecutionListener++s can be registered for a test class and its subclasses -via the `@TestExecutionListeners` annotation. See -<> and the javadocs for -`@TestExecutionListeners` for details and examples. - -[[testcontext-tel-config-automatic-discovery]] -====== Automatic discovery of default TestExecutionListeners - -Registering custom ++TestExecutionListener++s via `@TestExecutionListeners` is suitable -for custom listeners that are used in limited testing scenarios; however, it can become -cumbersome if a custom listener needs to be used across a test suite. To address this -issue, Spring Framework 4.1 supports automatic discovery of _default_ -`TestExecutionListener` implementations via the `SpringFactoriesLoader` mechanism. - -Specifically, the `spring-test` module declares all core default -++TestExecutionListener++s under the -`org.springframework.test.context.TestExecutionListener` key in its -`META-INF/spring.factories` properties file. Third-party frameworks and developers can -contribute their own ++TestExecutionListener++s to the list of default listeners in the -same manner via their own `META-INF/spring.factories` properties file. - -[[testcontext-tel-config-ordering]] -====== Ordering TestExecutionListeners - -When the TestContext framework discovers default ++TestExecutionListeners++ via the -aforementioned `SpringFactoriesLoader` mechanism, the instantiated listeners are sorted -using Spring's `AnnotationAwareOrderComparator` which honors Spring's `Ordered` interface -and `@Order` annotation for ordering. `AbstractTestExecutionListener` and all default -++TestExecutionListener++s provided by Spring implement `Ordered` with appropriate -values. Third-party frameworks and developers should therefore make sure that their -_default_ ++TestExecutionListener++s are registered in the proper order by implementing -`Ordered` or declaring `@Order`. Consult the javadocs for the `getOrder()` methods of the -core default ++TestExecutionListener++s for details on what values are assigned to each -core listener. - -[[testcontext-tel-config-merging]] -====== Merging TestExecutionListeners - -If a custom `TestExecutionListener` is registered via `@TestExecutionListeners`, the -_default_ listeners will not be registered. In most common testing scenarios, this -effectively forces the developer to manually declare all default listeners in addition to -any custom listeners. The following listing demonstrates this style of configuration. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @ContextConfiguration - @TestExecutionListeners({ - MyCustomTestExecutionListener.class, - ServletTestExecutionListener.class, - DependencyInjectionTestExecutionListener.class, - DirtiesContextTestExecutionListener.class, - TransactionalTestExecutionListener.class, - SqlScriptsTestExecutionListener.class - }) - public class MyTest { - // class body... - } ----- - -The challenge with this approach is that it requires that the developer know exactly -which listeners are registered by default. Moreover, the set of default listeners can -change from release to release -- for example, `SqlScriptsTestExecutionListener` was -introduced in Spring Framework 4.1. Furthermore, third-party frameworks like Spring -Security register their own default ++TestExecutionListener++s via the aforementioned -<>. - -To avoid having to be aware of and re-declare **all** _default_ listeners, the -`mergeMode` attribute of `@TestExecutionListeners` can be set to -`MergeMode.MERGE_WITH_DEFAULTS`. `MERGE_WITH_DEFAULTS` indicates that locally declared -listeners should be merged with the default listeners. The merging algorithm ensures that -duplicates are removed from the list and that the resulting set of merged listeners is -sorted according to the semantics of `AnnotationAwareOrderComparator` as described in -<>. If a listener implements `Ordered` or is annotated -with `@Order` it can influence the position in which it is merged with the defaults; -otherwise, locally declared listeners will simply be appended to the list of default -listeners when merged. - -For example, if the `MyCustomTestExecutionListener` class in the previous example -configures its `order` value (for example, `500`) to be less than the order of the -`ServletTestExecutionListener` (which happens to be `1000`), the -`MyCustomTestExecutionListener` can then be automatically merged with the list of -defaults _in front of_ the `ServletTestExecutionListener`, and the previous example could -be replaced with the following. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @ContextConfiguration - @TestExecutionListeners( - listeners = MyCustomTestExecutionListener.class, - mergeMode = MERGE_WITH_DEFAULTS, - ) - public class MyTest { - // class body... - } ----- - - -[[testcontext-ctx-management]] -===== Context management - -Each `TestContext` provides context management and caching support for the test instance -it is responsible for. Test instances do not automatically receive access to the -configured `ApplicationContext`. However, if a test class implements the -`ApplicationContextAware` interface, a reference to the `ApplicationContext` is supplied -to the test instance. Note that `AbstractJUnit4SpringContextTests` and -`AbstractTestNGSpringContextTests` implement `ApplicationContextAware` and therefore -provide access to the `ApplicationContext` automatically. - -.@Autowired ApplicationContext -[TIP] -==== -As an alternative to implementing the `ApplicationContextAware` interface, you can -inject the application context for your test class through the `@Autowired` annotation -on either a field or setter method. For example: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @RunWith(SpringJUnit4ClassRunner.class) - @ContextConfiguration - public class MyTest { - - **@Autowired** - private ApplicationContext applicationContext; - - // class body... - } ----- - -Similarly, if your test is configured to load a `WebApplicationContext`, you can inject -the web application context into your test as follows: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @RunWith(SpringJUnit4ClassRunner.class) - **@WebAppConfiguration** - @ContextConfiguration - public class MyWebAppTest { - **@Autowired** - private WebApplicationContext wac; - - // class body... - } ----- - -Dependency injection via `@Autowired` is provided by the -`DependencyInjectionTestExecutionListener` which is configured by default (see -<>). -==== - -Test classes that use the TestContext framework do not need to extend any particular -class or implement a specific interface to configure their application context. Instead, -configuration is achieved simply by declaring the `@ContextConfiguration` annotation at -the class level. If your test class does not explicitly declare application context -resource `locations` or annotated `classes`, the configured `ContextLoader` determines -how to load a context from a default location or default configuration classes. In -addition to context resource `locations` and annotated `classes`, an application context -can also be configured via application context `initializers`. - -The following sections explain how to configure an `ApplicationContext` via XML -configuration files, annotated classes (typically `@Configuration` classes), or context -initializers using Spring's `@ContextConfiguration` annotation. Alternatively, you can -implement and configure your own custom `SmartContextLoader` for advanced use cases. - -[[testcontext-ctx-management-xml]] -====== Context configuration with XML resources - -To load an `ApplicationContext` for your tests using XML configuration files, annotate -your test class with `@ContextConfiguration` and configure the `locations` attribute with -an array that contains the resource locations of XML configuration metadata. A plain or -relative path -- for example `"context.xml"` -- will be treated as a classpath resource -that is relative to the package in which the test class is defined. A path starting with -a slash is treated as an absolute classpath location, for example -`"/org/example/config.xml"`. A path which represents a resource URL (i.e., a path -prefixed with `classpath:`, `file:`, `http:`, etc.) will be used __as is__. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @RunWith(SpringJUnit4ClassRunner.class) - // ApplicationContext will be loaded from "/app-config.xml" and - // "/test-config.xml" in the root of the classpath - **@ContextConfiguration(locations={"/app-config.xml", "/test-config.xml"})** - public class MyTest { - // class body... - } ----- - -`@ContextConfiguration` supports an alias for the `locations` attribute through the -standard Java `value` attribute. Thus, if you do not need to declare additional -attributes in `@ContextConfiguration`, you can omit the declaration of the `locations` -attribute name and declare the resource locations by using the shorthand format -demonstrated in the following example. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @RunWith(SpringJUnit4ClassRunner.class) - **@ContextConfiguration({"/app-config.xml", "/test-config.xml"})** - public class MyTest { - // class body... - } ----- - -If you omit both the `locations` and `value` attributes from the `@ContextConfiguration` -annotation, the TestContext framework will attempt to detect a default XML resource -location. Specifically, `GenericXmlContextLoader` and `GenericXmlWebContextLoader` detect -a default location based on the name of the test class. If your class is named -`com.example.MyTest`, `GenericXmlContextLoader` loads your application context from -`"classpath:com/example/MyTest-context.xml"`. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - package com.example; - - @RunWith(SpringJUnit4ClassRunner.class) - // ApplicationContext will be loaded from - // "classpath:com/example/MyTest-context.xml" - **@ContextConfiguration** - public class MyTest { - // class body... - } ----- - -[[testcontext-ctx-management-groovy]] -====== Context configuration with Groovy scripts - -To load an `ApplicationContext` for your tests using Groovy scripts that utilize the -<>, annotate your test class with -`@ContextConfiguration` and configure the `locations` or `value` attribute with an array -that contains the resource locations of Groovy scripts. Resource lookup semantics for -Groovy scripts are the same as those described for <>. - - -.Enabling Groovy script support -[TIP] -==== -Support for using Groovy scripts to load an `ApplicationContext` in the Spring -TestContext Framework is enabled automatically if Groovy is on the classpath. -==== - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @RunWith(SpringJUnit4ClassRunner.class) - // ApplicationContext will be loaded from "/AppConfig.groovy" and - // "/TestConfig.groovy" in the root of the classpath - **@ContextConfiguration({"/AppConfig.groovy", "/TestConfig.Groovy"})** - public class MyTest { - // class body... - } ----- - -If you omit both the `locations` and `value` attributes from the `@ContextConfiguration` -annotation, the TestContext framework will attempt to detect a default Groovy script. -Specifically, `GenericGroovyXmlContextLoader` and `GenericGroovyXmlWebContextLoader` -detect a default location based on the name of the test class. If your class is named -`com.example.MyTest`, the Groovy context loader will load your application context from -`"classpath:com/example/MyTestContext.groovy"`. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - package com.example; - - @RunWith(SpringJUnit4ClassRunner.class) - // ApplicationContext will be loaded from - // "classpath:com/example/MyTestContext.groovy" - **@ContextConfiguration** - public class MyTest { - // class body... - } ----- - -.Declaring XML config and Groovy scripts simultaneously -[TIP] -==== -Both XML configuration files and Groovy scripts can be declared simultaneously via the -`locations` or `value` attribute of `@ContextConfiguration`. If the path to a configured -resource location ends with `.xml` it will be loaded using an `XmlBeanDefinitionReader`; -otherwise it will be loaded using a `GroovyBeanDefinitionReader`. - -The following listing demonstrates how to combine both in an integration test. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @RunWith(SpringJUnit4ClassRunner.class) - // ApplicationContext will be loaded from - // "/app-config.xml" and "/TestConfig.groovy" - @ContextConfiguration({ "/app-config.xml", "/TestConfig.groovy" }) - public class MyTest { - // class body... - } ----- -==== - -[[testcontext-ctx-management-javaconfig]] -====== Context configuration with annotated classes - -To load an `ApplicationContext` for your tests using __annotated classes__ (see -<>), annotate your test class with `@ContextConfiguration` and configure the -`classes` attribute with an array that contains references to annotated classes. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @RunWith(SpringJUnit4ClassRunner.class) - // ApplicationContext will be loaded from AppConfig and TestConfig - **@ContextConfiguration(classes = {AppConfig.class, TestConfig.class})** - public class MyTest { - // class body... - } ----- - -.Annotated Classes -[TIP] -==== -The term __annotated class__ can refer to any of the following. - -* A class annotated with `@Configuration` -* A component (i.e., a class annotated with `@Component`, `@Service`, `@Repository`, etc.) -* A JSR-330 compliant class that is annotated with `javax.inject` annotations -* Any other class that contains `@Bean`-methods - -Consult the javadocs of `@Configuration` and `@Bean` for further information regarding -the configuration and semantics of __annotated classes__, paying special attention to -the discussion of __`@Bean` Lite Mode__. -==== - -If you omit the `classes` attribute from the `@ContextConfiguration` annotation, the -TestContext framework will attempt to detect the presence of default configuration -classes. Specifically, `AnnotationConfigContextLoader` and -`AnnotationConfigWebContextLoader` will detect all static inner classes of the test class -that meet the requirements for configuration class implementations as specified in the -`@Configuration` javadocs. In the following example, the `OrderServiceTest` class -declares a static inner configuration class named `Config` that will be automatically -used to load the `ApplicationContext` for the test class. Note that the name of the -configuration class is arbitrary. In addition, a test class can contain more than one -static inner configuration class if desired. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @RunWith(SpringJUnit4ClassRunner.class) - // ApplicationContext will be loaded from the - // static inner Config class - **@ContextConfiguration** - public class OrderServiceTest { - - @Configuration - static class Config { - - // this bean will be injected into the OrderServiceTest class - @Bean - public OrderService orderService() { - OrderService orderService = new OrderServiceImpl(); - // set properties, etc. - return orderService; - } - } - - @Autowired - private OrderService orderService; - - @Test - public void testOrderService() { - // test the orderService - } - - } ----- - -[[testcontext-ctx-management-mixed-config]] -====== Mixing XML, Groovy scripts, and annotated classes - -It may sometimes be desirable to mix XML configuration files, Groovy scripts, and -annotated classes (i.e., typically `@Configuration` classes) to configure an -`ApplicationContext` for your tests. For example, if you use XML configuration in -production, you may decide that you want to use `@Configuration` classes to configure -specific Spring-managed components for your tests, or vice versa. - -Furthermore, some third-party frameworks (like Spring Boot) provide first-class support -for loading an `ApplicationContext` from different types of resources simultaneously -(e.g., XML configuration files, Groovy scripts, and `@Configuration` classes). The Spring -Framework historically has not supported this for standard deployments. Consequently, -most of the `SmartContextLoader` implementations that the Spring Framework delivers in -the `spring-test` module support only one resource type per test context; however, this -does not mean that you cannot use both. One exception to the general rule is that the -`GenericGroovyXmlContextLoader` and `GenericGroovyXmlWebContextLoader` support both XML -configuration files and Groovy scripts simultaneously. Furthermore, third-party -frameworks may choose to support the declaration of both `locations` and `classes` via -`@ContextConfiguration`, and with the standard testing support in the TestContext -framework, you have the following options. - -If you want to use resource locations (e.g., XML or Groovy) __and__ `@Configuration` -classes to configure your tests, you will have to pick one as the __entry point__, and -that one will have to include or import the other. For example, in XML or Groovy scripts -you can include `@Configuration` classes via component scanning or define them as normal -Spring beans; whereas, in a `@Configuration` class you can use `@ImportResource` to -import XML configuration files. Note that this behavior is semantically equivalent to how -you configure your application in production: in production configuration you will define -either a set of XML or Groovy resource locations or a set of `@Configuration` classes -that your production `ApplicationContext` will be loaded from, but you still have the -freedom to include or import the other type of configuration. - -[[testcontext-ctx-management-initializers]] -====== Context configuration with context initializers -To configure an `ApplicationContext` for your tests using context initializers, annotate -your test class with `@ContextConfiguration` and configure the `initializers` attribute -with an array that contains references to classes that implement -`ApplicationContextInitializer`. The declared context initializers will then be used to -initialize the `ConfigurableApplicationContext` that is loaded for your tests. Note that -the concrete `ConfigurableApplicationContext` type supported by each declared -initializer must be compatible with the type of `ApplicationContext` created by the -`SmartContextLoader` in use (i.e., typically a `GenericApplicationContext`). -Furthermore, the order in which the initializers are invoked depends on whether they -implement Spring's `Ordered` interface, are annotated with Spring's `@Order` or the -standard `@Priority` annotation. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @RunWith(SpringJUnit4ClassRunner.class) - // ApplicationContext will be loaded from TestConfig - // and initialized by TestAppCtxInitializer - **@ContextConfiguration( - classes = TestConfig.class, - initializers = TestAppCtxInitializer.class)** - public class MyTest { - // class body... - } ----- - -It is also possible to omit the declaration of XML configuration files or annotated -classes in `@ContextConfiguration` entirely and instead declare only -`ApplicationContextInitializer` classes which are then responsible for registering beans -in the context -- for example, by programmatically loading bean definitions from XML -files or configuration classes. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @RunWith(SpringJUnit4ClassRunner.class) - // ApplicationContext will be initialized by EntireAppInitializer - // which presumably registers beans in the context - **@ContextConfiguration(initializers = EntireAppInitializer.class)** - public class MyTest { - // class body... - } ----- - -[[testcontext-ctx-management-inheritance]] -====== Context configuration inheritance -`@ContextConfiguration` supports boolean `inheritLocations` and `inheritInitializers` -attributes that denote whether resource locations or annotated classes and context -initializers declared by superclasses should be __inherited__. The default value for -both flags is `true`. This means that a test class inherits the resource locations or -annotated classes as well as the context initializers declared by any superclasses. -Specifically, the resource locations or annotated classes for a test class are appended -to the list of resource locations or annotated classes declared by superclasses. -Similarly, the initializers for a given test class will be added to the set of -initializers defined by test superclasses. Thus, subclasses have the option -of __extending__ the resource locations, annotated classes, or context initializers. - -If `@ContextConfiguration`'s `inheritLocations` or `inheritInitializers` attribute is -set to `false`, the resource locations or annotated classes and the context -initializers, respectively, for the test class __shadow__ and effectively replace the -configuration defined by superclasses. - -In the following example that uses XML resource locations, the `ApplicationContext` for -`ExtendedTest` will be loaded from __"base-config.xml"__ __and__ -__"extended-config.xml"__, in that order. Beans defined in __"extended-config.xml"__ may -therefore __override__ (i.e., replace) those defined in __"base-config.xml"__. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @RunWith(SpringJUnit4ClassRunner.class) - // ApplicationContext will be loaded from "/base-config.xml" - // in the root of the classpath - **@ContextConfiguration("/base-config.xml")** - public class BaseTest { - // class body... - } - - // ApplicationContext will be loaded from "/base-config.xml" and - // "/extended-config.xml" in the root of the classpath - **@ContextConfiguration("/extended-config.xml")** - public class ExtendedTest extends BaseTest { - // class body... - } ----- - -Similarly, in the following example that uses annotated classes, the -`ApplicationContext` for `ExtendedTest` will be loaded from the `BaseConfig` __and__ -`ExtendedConfig` classes, in that order. Beans defined in `ExtendedConfig` may therefore -override (i.e., replace) those defined in `BaseConfig`. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @RunWith(SpringJUnit4ClassRunner.class) - // ApplicationContext will be loaded from BaseConfig - **@ContextConfiguration(classes = BaseConfig.class)** - public class BaseTest { - // class body... - } - - // ApplicationContext will be loaded from BaseConfig and ExtendedConfig - **@ContextConfiguration(classes = ExtendedConfig.class)** - public class ExtendedTest extends BaseTest { - // class body... - } ----- - -In the following example that uses context initializers, the `ApplicationContext` for -`ExtendedTest` will be initialized using `BaseInitializer` __and__ -`ExtendedInitializer`. Note, however, that the order in which the initializers are -invoked depends on whether they implement Spring's `Ordered` interface, are annotated -with Spring's `@Order` or the standard `@Priority` annotation. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @RunWith(SpringJUnit4ClassRunner.class) - // ApplicationContext will be initialized by BaseInitializer - **@ContextConfiguration(initializers = BaseInitializer.class)** - public class BaseTest { - // class body... - } - - // ApplicationContext will be initialized by BaseInitializer - // and ExtendedInitializer - **@ContextConfiguration(initializers = ExtendedInitializer.class)** - public class ExtendedTest extends BaseTest { - // class body... - } ----- - -[[testcontext-ctx-management-env-profiles]] -====== Context configuration with environment profiles -Spring 3.1 introduced first-class support in the framework for the notion of -environments and profiles (a.k.a., __bean definition profiles__), and integration tests -can be configured to activate particular bean definition profiles for various testing -scenarios. This is achieved by annotating a test class with the `@ActiveProfiles` -annotation and supplying a list of profiles that should be activated when loading the -`ApplicationContext` for the test. - -[NOTE] -==== -`@ActiveProfiles` may be used with any implementation of the new `SmartContextLoader` -SPI, but `@ActiveProfiles` is not supported with implementations of the older -`ContextLoader` SPI. -==== - -Let's take a look at some examples with XML configuration and `@Configuration` classes. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ----- - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - package com.bank.service; - - @RunWith(SpringJUnit4ClassRunner.class) - // ApplicationContext will be loaded from "classpath:/app-config.xml" - @ContextConfiguration("/app-config.xml") - @ActiveProfiles("dev") - public class TransferServiceTest { - - @Autowired - private TransferService transferService; - - @Test - public void testTransferService() { - // test the transferService - } - } ----- - -When `TransferServiceTest` is run, its `ApplicationContext` will be loaded from the -`app-config.xml` configuration file in the root of the classpath. If you inspect -`app-config.xml` you'll notice that the `accountRepository` bean has a dependency on a -`dataSource` bean; however, `dataSource` is not defined as a top-level bean. Instead, -`dataSource` is defined three times: in the __production__ profile, the -__dev__ profile, and the __default__ profile. - -By annotating `TransferServiceTest` with `@ActiveProfiles("dev")` we instruct the Spring -TestContext Framework to load the `ApplicationContext` with the active profiles set to -`{"dev"}`. As a result, an embedded database will be created and populated with test data, -and the `accountRepository` bean will be wired with a reference to the development -`DataSource`. And that's likely what we want in an integration test. - -It is sometimes useful to assign beans to a `default` profile. Beans within the default profile -are only included when no other profile is specifically activated. This can be used to define -_fallback_ beans to be used in the application's default state. For example, you may -explicitly provide a data source for `dev` and `production` profiles, but define an in-memory -data source as a default when neither of these is active. - -The following code listings demonstrate how to implement the same configuration and -integration test but using `@Configuration` classes instead of XML. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Configuration - @Profile("dev") - public class StandaloneDataConfig { - - @Bean - public DataSource dataSource() { - return new EmbeddedDatabaseBuilder() - .setType(EmbeddedDatabaseType.HSQL) - .addScript("classpath:com/bank/config/sql/schema.sql") - .addScript("classpath:com/bank/config/sql/test-data.sql") - .build(); - } - } ----- - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Configuration - @Profile("production") - public class JndiDataConfig { - - @Bean - public DataSource dataSource() throws Exception { - Context ctx = new InitialContext(); - return (DataSource) ctx.lookup("java:comp/env/jdbc/datasource"); - } - } ----- - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Configuration - @Profile("default") - public class DefaultDataConfig { - - @Bean - public DataSource dataSource() { - return new EmbeddedDatabaseBuilder() - .setType(EmbeddedDatabaseType.HSQL) - .addScript("classpath:com/bank/config/sql/schema.sql") - .build(); - } - } ----- - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Configuration - public class TransferServiceConfig { - - @Autowired DataSource dataSource; - - @Bean - public TransferService transferService() { - return new DefaultTransferService(accountRepository(), feePolicy()); - } - - @Bean - public AccountRepository accountRepository() { - return new JdbcAccountRepository(dataSource); - } - - @Bean - public FeePolicy feePolicy() { - return new ZeroFeePolicy(); - } - - } ----- - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - package com.bank.service; - - @RunWith(SpringJUnit4ClassRunner.class) - @ContextConfiguration(classes = { - TransferServiceConfig.class, - StandaloneDataConfig.class, - JndiDataConfig.class, - DefaultDataConfig.class}) - @ActiveProfiles("dev") - public class TransferServiceTest { - - @Autowired - private TransferService transferService; - - @Test - public void testTransferService() { - // test the transferService - } - } ----- - -In this variation, we have split the XML configuration into four independent -`@Configuration` classes: - -* `TransferServiceConfig`: acquires a `dataSource` via dependency injection using - `@Autowired` -* `StandaloneDataConfig`: defines a `dataSource` for an embedded database suitable for - developer tests -* `JndiDataConfig`: defines a `dataSource` that is retrieved from JNDI in a production - environment -* `DefaultDataConfig`: defines a `dataSource` for a default embedded database in case - no profile is active - -As with the XML-based configuration example, we still annotate `TransferServiceTest` -with `@ActiveProfiles("dev")`, but this time we specify all four configuration classes -via the `@ContextConfiguration` annotation. The body of the test class itself remains -completely unchanged. - -It is often the case that a single set of profiles is used across multiple test classes -within a given project. Thus, to avoid duplicate declarations of the `@ActiveProfiles` -annotation it is possible to declare `@ActiveProfiles` once on a base class, and -subclasses will automatically inherit the `@ActiveProfiles` configuration from the base -class. In the following example, the declaration of `@ActiveProfiles` (as well as other -annotations) has been moved to an abstract superclass, `AbstractIntegrationTest`. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - package com.bank.service; - - @RunWith(SpringJUnit4ClassRunner.class) - @ContextConfiguration(classes = { - TransferServiceConfig.class, - StandaloneDataConfig.class, - JndiDataConfig.class, - DefaultDataConfig.class}) - @ActiveProfiles("dev") - public abstract class AbstractIntegrationTest { - } ----- - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - package com.bank.service; - - // "dev" profile inherited from superclass - public class TransferServiceTest extends AbstractIntegrationTest { - - @Autowired - private TransferService transferService; - - @Test - public void testTransferService() { - // test the transferService - } - } ----- - -`@ActiveProfiles` also supports an `inheritProfiles` attribute that can be used to -disable the inheritance of active profiles. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - package com.bank.service; - - // "dev" profile overridden with "production" - @ActiveProfiles(profiles = "production", inheritProfiles = false) - public class ProductionTransferServiceTest extends AbstractIntegrationTest { - // test body - } ----- - -[[testcontext-ctx-management-env-profiles-ActiveProfilesResolver]] -Furthermore, it is sometimes necessary to resolve active profiles for tests -__programmatically__ instead of declaratively -- for example, based on: - -* the current operating system -* whether tests are being executed on a continuous integration build server -* the presence of certain environment variables -* the presence of custom class-level annotations -* etc. - -To resolve active bean definition profiles programmatically, simply implement a custom -`ActiveProfilesResolver` and register it via the `resolver` attribute of -`@ActiveProfiles`. The following example demonstrates how to implement and register a -custom `OperatingSystemActiveProfilesResolver`. For further information, refer to the -corresponding javadocs. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - package com.bank.service; - - // "dev" profile overridden programmatically via a custom resolver - @ActiveProfiles( - resolver = OperatingSystemActiveProfilesResolver.class, - inheritProfiles = false) - public class TransferServiceTest extends AbstractIntegrationTest { - // test body - } ----- - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - package com.bank.service.test; - - public class OperatingSystemActiveProfilesResolver implements ActiveProfilesResolver { - - @Override - String[] resolve(Class testClass) { - String profile = ...; - // determine the value of profile based on the operating system - return new String[] {profile}; - } - } ----- - -[[testcontext-ctx-management-property-sources]] -====== Context configuration with test property sources - -Spring 3.1 introduced first-class support in the framework for the notion of an -environment with a hierarchy of _property sources_, and since Spring 4.1 integration -tests can be configured with test-specific property sources. In contrast to the -`@PropertySource` annotation used on `@Configuration` classes, the `@TestPropertySource` -annotation can be declared on a test class to declare resource locations for test -properties files or _inlined_ properties. These test property sources will be added to -the `Environment`'s set of `PropertySources` for the `ApplicationContext` loaded for the -annotated integration test. - -[NOTE] -==== -`@TestPropertySource` may be used with any implementation of the `SmartContextLoader` -SPI, but `@TestPropertySource` is not supported with implementations of the older -`ContextLoader` SPI. - -Implementations of `SmartContextLoader` gain access to merged test property source values -via the `getPropertySourceLocations()` and `getPropertySourceProperties()` methods in -`MergedContextConfiguration`. -==== - -*Declaring test property sources* - -Test properties files can be configured via the `locations` or `value` attribute of -`@TestPropertySource` as shown in the following example. - -Both traditional and XML-based properties file formats are supported -- for example, -`"classpath:/com/example/test.properties"` or `"file:/path/to/file.xml"`. - -Each path will be interpreted as a Spring `Resource`. A plain path -- for example, -`"test.properties"` -- will be treated as a classpath resource that is _relative_ to the -package in which the test class is defined. A path starting with a slash will be treated -as an _absolute_ classpath resource, for example: `"/org/example/test.xml"`. A path which -references a URL (e.g., a path prefixed with `classpath:`, `file:`, `http:`, etc.) will -be loaded using the specified resource protocol. Resource location wildcards (e.g. -`**/*.properties`) are not permitted: each location must evaluate to exactly one -`.properties` or `.xml` resource. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @ContextConfiguration - @TestPropertySource("/test.properties") - public class MyIntegrationTests { - // class body... - } ----- - -_Inlined_ properties in the form of key-value pairs can be configured via the -`properties` attribute of `@TestPropertySource` as shown in the following example. All -key-value pairs will be added to the enclosing `Environment` as a single test -`PropertySource` with the highest precedence. - -The supported syntax for key-value pairs is the same as the syntax defined for entries in -a Java properties file: - -* `"key=value"` -* `"key:value"` -* `"key value"` - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @ContextConfiguration - @TestPropertySource(properties = {"timezone = GMT", "port: 4242"}) - public class MyIntegrationTests { - // class body... - } ----- - -*Default properties file detection* - -If `@TestPropertySource` is declared as an empty annotation (i.e., without explicit -values for the `locations` or `properties` attributes), an attempt will be made to detect -a _default_ properties file relative to the class that declared the annotation. For -example, if the annotated test class is `com.example.MyTest`, the corresponding default -properties file is `"classpath:com/example/MyTest.properties"`. If the default cannot be -detected, an `IllegalStateException` will be thrown. - -*Precedence* - -Test property sources have higher precedence than those loaded from the operating -system's environment or Java system properties as well as property sources added by the -application declaratively via `@PropertySource` or programmatically. Thus, test property -sources can be used to selectively override properties defined in system and application -property sources. Furthermore, inlined properties have higher precedence than properties -loaded from resource locations. - -In the following example, the `timezone` and `port` properties as well as any properties -defined in `"/test.properties"` will override any properties of the same name that are -defined in system and application property sources. Furthermore, if the -`"/test.properties"` file defines entries for the `timezone` and `port` properties those -will be overridden by the _inlined_ properties declared via the `properties` attribute. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @ContextConfiguration - @TestPropertySource( - locations = "/test.properties", - properties = {"timezone = GMT", "port: 4242"} - ) - public class MyIntegrationTests { - // class body... - } ----- - -*Inheriting and overriding test property sources* - -`@TestPropertySource` supports boolean `inheritLocations` and `inheritProperties` -attributes that denote whether resource locations for properties files and inlined -properties declared by superclasses should be __inherited__. The default value for both -flags is `true`. This means that a test class inherits the locations and inlined -properties declared by any superclasses. Specifically, the locations and inlined -properties for a test class are appended to the locations and inlined properties declared -by superclasses. Thus, subclasses have the option of __extending__ the locations and -inlined properties. Note that properties that appear later will __shadow__ (i.e.., -override) properties of the same name that appear earlier. In addition, the -aforementioned precedence rules apply for inherited test property sources as well. - -If `@TestPropertySource`'s `inheritLocations` or `inheritProperties` attribute is set to -`false`, the locations or inlined properties, respectively, for the test class __shadow__ -and effectively replace the configuration defined by superclasses. - -In the following example, the `ApplicationContext` for `BaseTest` will be loaded using -only the `"base.properties"` file as a test property source. In contrast, the -`ApplicationContext` for `ExtendedTest` will be loaded using the `"base.properties"` -**and** `"extended.properties"` files as test property source locations. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @TestPropertySource("base.properties") - @ContextConfiguration - public class BaseTest { - // ... - } - - @TestPropertySource("extended.properties") - @ContextConfiguration - public class ExtendedTest extends BaseTest { - // ... - } ----- - -In the following example, the `ApplicationContext` for `BaseTest` will be loaded using only -the _inlined_ `key1` property. In contrast, the `ApplicationContext` for `ExtendedTest` will be -loaded using the _inlined_ `key1` and `key2` properties. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @TestPropertySource(properties = "key1 = value1") - @ContextConfiguration - public class BaseTest { - // ... - } - - @TestPropertySource(properties = "key2 = value2") - @ContextConfiguration - public class ExtendedTest extends BaseTest { - // ... - } ----- - -[[testcontext-ctx-management-web]] -====== Loading a WebApplicationContext -Spring 3.2 introduced support for loading a `WebApplicationContext` in integration -tests. To instruct the TestContext framework to load a `WebApplicationContext` instead -of a standard `ApplicationContext`, simply annotate the respective test class with -`@WebAppConfiguration`. - -The presence of `@WebAppConfiguration` on your test class instructs the TestContext -framework (TCF) that a `WebApplicationContext` (WAC) should be loaded for your -integration tests. In the background the TCF makes sure that a `MockServletContext` is -created and supplied to your test's WAC. By default the base resource path for your -`MockServletContext` will be set to __"src/main/webapp"__. This is interpreted as a path -relative to the root of your JVM (i.e., normally the path to your project). If you're -familiar with the directory structure of a web application in a Maven project, you'll -know that __"src/main/webapp"__ is the default location for the root of your WAR. If you -need to override this default, simply provide an alternate path to the -`@WebAppConfiguration` annotation (e.g., `@WebAppConfiguration("src/test/webapp")`). If -you wish to reference a base resource path from the classpath instead of the file -system, just use Spring's __classpath:__ prefix. - -Please note that Spring's testing support for `WebApplicationContexts` is on par with -its support for standard `ApplicationContexts`. When testing with a -`WebApplicationContext` you are free to declare either XML configuration files or -`@Configuration` classes via `@ContextConfiguration`. You are of course also free to use -any other test annotations such as `@TestExecutionListeners`, -`@TransactionConfiguration`, `@ActiveProfiles`, etc. - -The following examples demonstrate some of the various configuration options for loading -a `WebApplicationContext`. - -.Conventions -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @RunWith(SpringJUnit4ClassRunner.class) - - // defaults to "file:src/main/webapp" - @WebAppConfiguration - - // detects "WacTests-context.xml" in same package - // or static nested @Configuration class - @ContextConfiguration - - public class WacTests { - //... - } ----- - -The above example demonstrates the TestContext framework's support for __convention over -configuration__. If you annotate a test class with `@WebAppConfiguration` without -specifying a resource base path, the resource path will effectively default -to __"file:src/main/webapp"__. Similarly, if you declare `@ContextConfiguration` without -specifying resource `locations`, annotated `classes`, or context `initializers`, Spring -will attempt to detect the presence of your configuration using conventions -(i.e., __"WacTests-context.xml"__ in the same package as the `WacTests` class or static -nested `@Configuration` classes). - -.Default resource semantics -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @RunWith(SpringJUnit4ClassRunner.class) - - // file system resource - @WebAppConfiguration("webapp") - - // classpath resource - @ContextConfiguration("/spring/test-servlet-config.xml") - - public class WacTests { - //... - } ----- - -This example demonstrates how to explicitly declare a resource base path with -`@WebAppConfiguration` and an XML resource location with `@ContextConfiguration`. The -important thing to note here is the different semantics for paths with these two -annotations. By default, `@WebAppConfiguration` resource paths are file system based; -whereas, `@ContextConfiguration` resource locations are classpath based. - -.Explicit resource semantics -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @RunWith(SpringJUnit4ClassRunner.class) - - // classpath resource - @WebAppConfiguration("classpath:test-web-resources") - - // file system resource - @ContextConfiguration("file:src/main/webapp/WEB-INF/servlet-config.xml") - - public class WacTests { - //... - } ----- - -In this third example, we see that we can override the default resource semantics for -both annotations by specifying a Spring resource prefix. Contrast the comments in this -example with the previous example. - -.[[testcontext-ctx-management-web-mocks]]Working with Web Mocks --- -To provide comprehensive web testing support, Spring 3.2 introduced a -`ServletTestExecutionListener` that is enabled by default. When testing against a -`WebApplicationContext` this <> sets -up default thread-local state via Spring Web's `RequestContextHolder` before each test -method and creates a `MockHttpServletRequest`, `MockHttpServletResponse`, and -`ServletWebRequest` based on the base resource path configured via -`@WebAppConfiguration`. `ServletTestExecutionListener` also ensures that the -`MockHttpServletResponse` and `ServletWebRequest` can be injected into the test -instance, and once the test is complete it cleans up thread-local state. - -Once you have a `WebApplicationContext` loaded for your test you might find that you -need to interact with the web mocks -- for example, to set up your test fixture or to -perform assertions after invoking your web component. The following example demonstrates -which mocks can be autowired into your test instance. Note that the -`WebApplicationContext` and `MockServletContext` are both cached across the test suite; -whereas, the other mocks are managed per test method by the -`ServletTestExecutionListener`. - -.Injecting mocks -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @WebAppConfiguration - @ContextConfiguration - public class WacTests { - - @Autowired - WebApplicationContext wac; // cached - - @Autowired - MockServletContext servletContext; // cached - - @Autowired - MockHttpSession session; - - @Autowired - MockHttpServletRequest request; - - @Autowired - MockHttpServletResponse response; - - @Autowired - ServletWebRequest webRequest; - - //... - } ----- --- - -[[testcontext-ctx-management-caching]] -====== Context caching - -Once the TestContext framework loads an `ApplicationContext` (or `WebApplicationContext`) -for a test, that context will be cached and reused for __all__ subsequent tests that -declare the same unique context configuration within the same test suite. To understand -how caching works, it is important to understand what is meant by __unique__ and __test -suite__. - -An `ApplicationContext` can be __uniquely__ identified by the combination of -configuration parameters that are used to load it. Consequently, the unique combination -of configuration parameters are used to generate a __key__ under which the context is -cached. The TestContext framework uses the following configuration parameters to build -the context cache key: - -* `locations` __(from @ContextConfiguration)__ -* `classes` __(from @ContextConfiguration)__ -* `contextInitializerClasses` __(from @ContextConfiguration)__ -* `contextLoader` __(from @ContextConfiguration)__ -* `parent` __(from @ContextHierarchy)__ -* `activeProfiles` __(from @ActiveProfiles)__ -* `propertySourceLocations` __(from @TestPropertySource)__ -* `propertySourceProperties` __(from @TestPropertySource)__ -* `resourceBasePath` __(from @WebAppConfiguration)__ - -For example, if `TestClassA` specifies `{"app-config.xml", "test-config.xml"}` for the -`locations` (or `value`) attribute of `@ContextConfiguration`, the TestContext framework -will load the corresponding `ApplicationContext` and store it in a `static` context cache -under a key that is based solely on those locations. So if `TestClassB` also defines -`{"app-config.xml", "test-config.xml"}` for its locations (either explicitly or -implicitly through inheritance) but does not define `@WebAppConfiguration`, a different -`ContextLoader`, different active profiles, different context initializers, different -test property sources, or a different parent context, then the same `ApplicationContext` -will be shared by both test classes. This means that the setup cost for loading an -application context is incurred only once (per test suite), and subsequent test execution -is much faster. - -.Test suites and forked processes -[NOTE] -==== -The Spring TestContext framework stores application contexts in a __static__ cache. This -means that the context is literally stored in a `static` variable. In other words, if -tests execute in separate processes the static cache will be cleared between each test -execution, and this will effectively disable the caching mechanism. - -To benefit from the caching mechanism, all tests must run within the same process or -test suite. This can be achieved by executing all tests as a group within an IDE. -Similarly, when executing tests with a build framework such as Ant, Maven, or Gradle it -is important to make sure that the build framework does not __fork__ between tests. For -example, if the -http://maven.apache.org/plugins/maven-surefire-plugin/test-mojo.html#forkMode[forkMode] -for the Maven Surefire plug-in is set to `always` or `pertest`, the TestContext -framework will not be able to cache application contexts between test classes and the -build process will run significantly slower as a result. -==== - -In the unlikely case that a test corrupts the application context and requires reloading --- for example, by modifying a bean definition or the state of an application object -- -you can annotate your test class or test method with `@DirtiesContext` (see the -discussion of `@DirtiesContext` in <>). This -instructs Spring to remove the context from the cache and rebuild the application -context before executing the next test. Note that support for the `@DirtiesContext` -annotation is provided by the `DirtiesContextTestExecutionListener` which is enabled by -default. - -[[testcontext-ctx-management-ctx-hierarchies]] -====== Context hierarchies - -When writing integration tests that rely on a loaded Spring `ApplicationContext`, it is -often sufficient to test against a single context; however, there are times when it is -beneficial or even necessary to test against a hierarchy of ++ApplicationContext++s. For -example, if you are developing a Spring MVC web application you will typically have a -root `WebApplicationContext` loaded via Spring's `ContextLoaderListener` and a child -`WebApplicationContext` loaded via Spring's `DispatcherServlet`. This results in a -parent-child context hierarchy where shared components and infrastructure configuration -are declared in the root context and consumed in the child context by web-specific -components. Another use case can be found in Spring Batch applications where you often -have a parent context that provides configuration for shared batch infrastructure and a -child context for the configuration of a specific batch job. - -As of Spring Framework 3.2.2, it is possible to write integration tests that use context -hierarchies by declaring context configuration via the `@ContextHierarchy` annotation, -either on an individual test class or within a test class hierarchy. If a context -hierarchy is declared on multiple classes within a test class hierarchy it is also -possible to merge or override the context configuration for a specific, named level in -the context hierarchy. When merging configuration for a given level in the hierarchy the -configuration resource type (i.e., XML configuration files or annotated classes) must be -consistent; otherwise, it is perfectly acceptable to have different levels in a context -hierarchy configured using different resource types. - -The following JUnit-based examples demonstrate common configuration scenarios for -integration tests that require the use of context hierarchies. - -.Single test class with context hierarchy --- -`ControllerIntegrationTests` represents a typical integration testing scenario for a -Spring MVC web application by declaring a context hierarchy consisting of two levels, -one for the __root__ WebApplicationContext (loaded using the `TestAppConfig` -`@Configuration` class) and one for the __dispatcher servlet__ `WebApplicationContext` -(loaded using the `WebConfig` `@Configuration` class). The `WebApplicationContext` that -is __autowired__ into the test instance is the one for the child context (i.e., the -lowest context in the hierarchy). - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @RunWith(SpringJUnit4ClassRunner.class) - @WebAppConfiguration - @ContextHierarchy({ - @ContextConfiguration(classes = TestAppConfig.class), - @ContextConfiguration(classes = WebConfig.class) - }) - public class ControllerIntegrationTests { - - @Autowired - private WebApplicationContext wac; - - // ... - } ----- - --- - - -.Class hierarchy with implicit parent context --- -The following test classes define a context hierarchy within a test class hierarchy. -`AbstractWebTests` declares the configuration for a root `WebApplicationContext` in a -Spring-powered web application. Note, however, that `AbstractWebTests` does not declare -`@ContextHierarchy`; consequently, subclasses of `AbstractWebTests` can optionally -participate in a context hierarchy or simply follow the standard semantics for -`@ContextConfiguration`. `SoapWebServiceTests` and `RestWebServiceTests` both extend -`AbstractWebTests` and define a context hierarchy via `@ContextHierarchy`. The result is -that three application contexts will be loaded (one for each declaration of -`@ContextConfiguration`), and the application context loaded based on the configuration -in `AbstractWebTests` will be set as the parent context for each of the contexts loaded -for the concrete subclasses. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @RunWith(SpringJUnit4ClassRunner.class) - @WebAppConfiguration - @ContextConfiguration("file:src/main/webapp/WEB-INF/applicationContext.xml") - public abstract class AbstractWebTests {} - - @ContextHierarchy(@ContextConfiguration("/spring/soap-ws-config.xml") - public class SoapWebServiceTests extends AbstractWebTests {} - - @ContextHierarchy(@ContextConfiguration("/spring/rest-ws-config.xml") - public class RestWebServiceTests extends AbstractWebTests {} ----- --- - - -.Class hierarchy with merged context hierarchy configuration --- -The following classes demonstrate the use of __named__ hierarchy levels in order to -__merge__ the configuration for specific levels in a context hierarchy. `BaseTests` -defines two levels in the hierarchy, `parent` and `child`. `ExtendedTests` extends -`BaseTests` and instructs the Spring TestContext Framework to merge the context -configuration for the `child` hierarchy level, simply by ensuring that the names -declared via `ContextConfiguration`'s `name` attribute are both `"child"`. The result is -that three application contexts will be loaded: one for `"/app-config.xml"`, one for -`"/user-config.xml"`, and one for `{"/user-config.xml", "/order-config.xml"}`. As with -the previous example, the application context loaded from `"/app-config.xml"` will be -set as the parent context for the contexts loaded from `"/user-config.xml"` and -`{"/user-config.xml", "/order-config.xml"}`. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @RunWith(SpringJUnit4ClassRunner.class) - @ContextHierarchy({ - @ContextConfiguration(name = "parent", locations = "/app-config.xml"), - @ContextConfiguration(name = "child", locations = "/user-config.xml") - }) - public class BaseTests {} - - @ContextHierarchy( - @ContextConfiguration(name = "child", locations = "/order-config.xml") - ) - public class ExtendedTests extends BaseTests {} ----- --- - -.Class hierarchy with overridden context hierarchy configuration --- -In contrast to the previous example, this example demonstrates how to __override__ the -configuration for a given named level in a context hierarchy by setting -++ContextConfiguration++'s `inheritLocations` flag to `false`. Consequently, the -application context for `ExtendedTests` will be loaded only from -`"/test-user-config.xml"` and will have its parent set to the context loaded from -`"/app-config.xml"`. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @RunWith(SpringJUnit4ClassRunner.class) - @ContextHierarchy({ - @ContextConfiguration(name = "parent", locations = "/app-config.xml"), - @ContextConfiguration(name = "child", locations = "/user-config.xml") - }) - public class BaseTests {} - - @ContextHierarchy( - @ContextConfiguration( - name = "child", - locations = "/test-user-config.xml", - inheritLocations = false - )) - public class ExtendedTests extends BaseTests {} ----- - -.Dirtying a context within a context hierarchy -[NOTE] -==== -If `@DirtiesContext` is used in a test whose context is configured as part of a context -hierarchy, the `hierarchyMode` flag can be used to control how the context cache is -cleared. For further details consult the discussion of `@DirtiesContext` in -<> and the -`@DirtiesContext` javadocs. -==== --- - - -[[testcontext-fixture-di]] -===== Dependency injection of test fixtures -When you use the `DependencyInjectionTestExecutionListener` -- which is configured by -default -- the dependencies of your test instances are __injected__ from beans in the -application context that you configured with `@ContextConfiguration`. You may use setter -injection, field injection, or both, depending on which annotations you choose and -whether you place them on setter methods or fields. For consistency with the annotation -support introduced in Spring 2.5 and 3.0, you can use Spring's `@Autowired` annotation -or the `@Inject` annotation from JSR 300. - -[TIP] -==== - -The TestContext framework does not instrument the manner in which a test instance is -instantiated. Thus the use of `@Autowired` or `@Inject` for constructors has no effect -for test classes. -==== - -Because `@Autowired` is used to perform <>, if you have multiple bean definitions of the same type, you cannot rely on this -approach for those particular beans. In that case, you can use `@Autowired` in -conjunction with `@Qualifier`. As of Spring 3.0 you may also choose to use `@Inject` in -conjunction with `@Named`. Alternatively, if your test class has access to its -`ApplicationContext`, you can perform an explicit lookup by using (for example) a call -to `applicationContext.getBean("titleRepository")`. - -If you do not want dependency injection applied to your test instances, simply do not -annotate fields or setter methods with `@Autowired` or `@Inject`. Alternatively, you can -disable dependency injection altogether by explicitly configuring your class with -`@TestExecutionListeners` and omitting `DependencyInjectionTestExecutionListener.class` -from the list of listeners. - -Consider the scenario of testing a `HibernateTitleRepository` class, as outlined in the -<> section. The next two code listings demonstrate the -use of `@Autowired` on fields and setter methods. The application context configuration -is presented after all sample code listings. - -[NOTE] -==== -The dependency injection behavior in the following code listings is not specific to -JUnit. The same DI techniques can be used in conjunction with any testing framework. - -The following examples make calls to static assertion methods such as `assertNotNull()` -but without prepending the call with `Assert`. In such cases, assume that the method was -properly imported through an `import static` declaration that is not shown in the -example. -==== - -The first code listing shows a JUnit-based implementation of the test class that uses -`@Autowired` for field injection. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @RunWith(SpringJUnit4ClassRunner.class) - // specifies the Spring configuration to load for this test fixture - **@ContextConfiguration("repository-config.xml")** - public class HibernateTitleRepositoryTests { - - // this instance will be dependency injected by type - **@Autowired** - private HibernateTitleRepository titleRepository; - - @Test - public void findById() { - Title title = titleRepository.findById(new Long(10)); - assertNotNull(title); - } - } ----- - -Alternatively, you can configure the class to use `@Autowired` for setter injection as -seen below. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @RunWith(SpringJUnit4ClassRunner.class) - // specifies the Spring configuration to load for this test fixture - **@ContextConfiguration("repository-config.xml")** - public class HibernateTitleRepositoryTests { - - // this instance will be dependency injected by type - private HibernateTitleRepository titleRepository; - - **@Autowired** - public void setTitleRepository(HibernateTitleRepository titleRepository) { - this.titleRepository = titleRepository; - } - - @Test - public void findById() { - Title title = titleRepository.findById(new Long(10)); - assertNotNull(title); - } - } ----- - -The preceding code listings use the same XML context file referenced by the -`@ContextConfiguration` annotation (that is, `repository-config.xml`), which looks like -this: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - - - - - - ----- - -[NOTE] -==== -If you are extending from a Spring-provided test base class that happens to use -`@Autowired` on one of its setter methods, you might have multiple beans of the affected -type defined in your application context: for example, multiple `DataSource` beans. In -such a case, you can override the setter method and use the `@Qualifier` annotation to -indicate a specific target bean as follows, but make sure to delegate to the overridden -method in the superclass as well. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - // ... - - @Autowired - @Override - public void setDataSource(**@Qualifier("myDataSource")** DataSource dataSource) { - **super**.setDataSource(dataSource); - } - - // ... ----- - -The specified qualifier value indicates the specific `DataSource` bean to inject, -narrowing the set of type matches to a specific bean. Its value is matched against -`` declarations within the corresponding `` definitions. The bean name -is used as a fallback qualifier value, so you may effectively also point to a specific -bean by name there (as shown above, assuming that "myDataSource" is the bean id). -==== - - -[[testcontext-web-scoped-beans]] -===== Testing request and session scoped beans - -<> have been supported by -Spring for several years now, but it's always been a bit non-trivial to test them. As of -Spring 3.2 it's a breeze to test your request-scoped and session-scoped beans by -following these steps. - -* Ensure that a `WebApplicationContext` is loaded for your test by annotating your test - class with `@WebAppConfiguration`. -* Inject the mock request or session into your test instance and prepare your test - fixture as appropriate. -* Invoke your web component that you retrieved from the configured - `WebApplicationContext` (i.e., via dependency injection). -* Perform assertions against the mocks. - -The following code snippet displays the XML configuration for a login use case. Note -that the `userService` bean has a dependency on a request-scoped `loginAction` bean. -Also, the `LoginAction` is instantiated using <> that -retrieve the username and password from the current HTTP request. In our test, we will -want to configure these request parameters via the mock managed by the TestContext -framework. - -.Request-scoped bean configuration -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - - ----- - -In `RequestScopedBeanTests` we inject both the `UserService` (i.e., the subject under -test) and the `MockHttpServletRequest` into our test instance. Within our -`requestScope()` test method we set up our test fixture by setting request parameters in -the provided `MockHttpServletRequest`. When the `loginUser()` method is invoked on our -`userService` we are assured that the user service has access to the request-scoped -`loginAction` for the current `MockHttpServletRequest` (i.e., the one we just set -parameters in). We can then perform assertions against the results based on the known -inputs for the username and password. - -.Request-scoped bean test -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @RunWith(SpringJUnit4ClassRunner.class) - @ContextConfiguration - @WebAppConfiguration - public class RequestScopedBeanTests { - - @Autowired UserService userService; - @Autowired MockHttpServletRequest request; - - @Test - public void requestScope() { - - request.setParameter("user", "enigma"); - request.setParameter("pswd", "$pr!ng"); - - LoginResults results = userService.loginUser(); - - // assert results - } - } ----- - -The following code snippet is similar to the one we saw above for a request-scoped bean; -however, this time the `userService` bean has a dependency on a session-scoped -`userPreferences` bean. Note that the `UserPreferences` bean is instantiated using a -SpEL expression that retrieves the __theme__ from the current HTTP session. In our test, -we will need to configure a theme in the mock session managed by the TestContext -framework. - -.Session-scoped bean configuration -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - - ----- - -In `SessionScopedBeanTests` we inject the `UserService` and the `MockHttpSession` into -our test instance. Within our `sessionScope()` test method we set up our test fixture by -setting the expected "theme" attribute in the provided `MockHttpSession`. When the -`processUserPreferences()` method is invoked on our `userService` we are assured that -the user service has access to the session-scoped `userPreferences` for the current -`MockHttpSession`, and we can perform assertions against the results based on the -configured theme. - -.Session-scoped bean test -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @RunWith(SpringJUnit4ClassRunner.class) - @ContextConfiguration - @WebAppConfiguration - public class SessionScopedBeanTests { - - @Autowired UserService userService; - @Autowired MockHttpSession session; - - @Test - public void sessionScope() throws Exception { - - session.setAttribute("theme", "blue"); - - Results results = userService.processUserPreferences(); - - // assert results - } - } ----- - -[[testcontext-tx]] -===== Transaction management - -In the TestContext framework, transactions are managed by the -`TransactionalTestExecutionListener` which is configured by default, even if you do not -explicitly declare `@TestExecutionListeners` on your test class. To enable support for -transactions, however, you must configure a `PlatformTransactionManager` bean in the -`ApplicationContext` that is loaded via `@ContextConfiguration` semantics (further -details are provided below). In addition, you must declare Spring's `@Transactional` -annotation either at the class or method level for your tests. - -[[testcontext-tx-test-managed-transactions]] -====== Test-managed transactions - -_Test-managed transactions_ are transactions that are managed _declaratively_ via the -`TransactionalTestExecutionListener` or _programmatically_ via `TestTransaction` (see -below). Such transactions should not be confused with _Spring-managed transactions_ -(i.e., those managed directly by Spring within the `ApplicationContext` loaded for tests) -or _application-managed transactions_ (i.e., those managed programmatically within -application code that is invoked via tests). Spring-managed and application-managed -transactions will typically participate in test-managed transactions; however, caution -should be taken if Spring-managed or application-managed transactions are configured with -any _propagation_ type other than `REQUIRED` or `SUPPORTS` (see the discussion on -<> for details). - -[[testcontext-tx-enabling-transactions]] -====== Enabling and disabling transactions - -Annotating a test method with `@Transactional` causes the test to be run within a -transaction that will, by default, be automatically rolled back after completion of the -test. If a test class is annotated with `@Transactional`, each test method within that -class hierarchy will be run within a transaction. Test methods that are not annotated -with `@Transactional` (at the class or method level) will not be run within a -transaction. Furthermore, tests that are annotated with `@Transactional` but have the -`propagation` type set to `NOT_SUPPORTED` will not be run within a transaction. - -__Note that <> and -<> -are preconfigured for transactional support at the class level.__ - -The following example demonstrates a common scenario for writing an integration test for -a Hibernate-based `UserRepository`. As explained in -<>, there is no need to clean up the -database after the `createUser()` method is executed since any changes made to the -database will be automatically rolled back by the `TransactionalTestExecutionListener`. -See <> for an additional example. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @RunWith(SpringJUnit4ClassRunner.class) - @ContextConfiguration(classes = TestConfig.class) - @Transactional - public class HibernateUserRepositoryTests { - - @Autowired - HibernateUserRepository repository; - - @Autowired - SessionFactory sessionFactory; - - JdbcTemplate jdbcTemplate; - - @Autowired - public void setDataSource(DataSource dataSource) { - this.jdbcTemplate = new JdbcTemplate(dataSource); - } - - @Test - public void createUser() { - // track initial state in test database: - final int count = countRowsInTable("user"); - - User user = new User(...); - repository.save(user); - - // Manual flush is required to avoid false positive in test - sessionFactory.getCurrentSession().flush(); - assertNumUsers(count + 1); - } - - protected int countRowsInTable(String tableName) { - return JdbcTestUtils.countRowsInTable(this.jdbcTemplate, tableName); - } - - protected void assertNumUsers(int expected) { - assertEquals("Number of rows in the 'user' table.", expected, countRowsInTable("user")); - } - } ----- - -[[testcontext-tx-rollback-and-commit-behavior]] -====== Transaction rollback and commit behavior - -By default, test transactions will be automatically rolled back after completion of the -test; however, transactional commit and rollback behavior can be configured declaratively -via the class-level `@TransactionConfiguration` and method-level `@Rollback` annotations. -See the corresponding entries in the <> section for further details. - -[[testcontext-tx-programmatic-tx-mgt]] -====== Programmatic transaction management -As of Spring Framework 4.1, it is possible to interact with test-managed transactions -_programmatically_ via the static methods in `TestTransaction`. For example, -`TestTransaction` may be used within _test_ methods, _before_ methods, and _after_ -methods to start or end the current test-managed transaction or to configure the current -test-managed transaction for rollback or commit. Support for `TestTransaction` is -automatically available whenever the `TransactionalTestExecutionListener` is enabled. - -The following example demonstrates some of the features of `TestTransaction`. Consult the -javadocs for `TestTransaction` for further details. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @ContextConfiguration(classes = TestConfig.class) - public class ProgrammaticTransactionManagementTests extends - AbstractTransactionalJUnit4SpringContextTests { - - @Test - public void transactionalTest() { - // assert initial state in test database: - assertNumUsers(2); - - deleteFromTables("user"); - - // changes to the database will be committed! - TestTransaction.flagForCommit(); - TestTransaction.end(); - assertFalse(TestTransaction.isActive()); - assertNumUsers(0); - - TestTransaction.start(); - // perform other actions against the database that will - // be automatically rolled back after the test completes... - } - - protected void assertNumUsers(int expected) { - assertEquals("Number of rows in the 'user' table.", expected, countRowsInTable("user")); - } - } ----- - -[[testcontext-tx-before-and-after-tx]] -====== Executing code outside of a transaction - -Occasionally you need to execute certain code before or after a transactional test method -but outside the transactional context -- for example, to verify the initial database state -prior to execution of your test or to verify expected transactional commit behavior after -test execution (if the test was configured not to roll back the transaction). -`TransactionalTestExecutionListener` supports the `@BeforeTransaction` and -`@AfterTransaction` annotations exactly for such scenarios. Simply annotate any `public -void` method in your test class with one of these annotations, and the -`TransactionalTestExecutionListener` ensures that your __before transaction method__ or -__after transaction method__ is executed at the appropriate time. - -[TIP] -==== -Any __before methods__ (such as methods annotated with JUnit's `@Before`) and any __after -methods__ (such as methods annotated with JUnit's `@After`) are executed __within__ a -transaction. In addition, methods annotated with `@BeforeTransaction` or -`@AfterTransaction` are naturally not executed for test methods that are not configured -to run within a transaction. -==== - -[[testcontext-tx-mgr-config]] -====== Configuring a transaction manager - -`TransactionalTestExecutionListener` expects a `PlatformTransactionManager` bean to be -defined in the Spring `ApplicationContext` for the test. In case there are multiple -instances of `PlatformTransactionManager` within the test's `ApplicationContext`, -`@TransactionConfiguration` supports configuring the bean name of the -`PlatformTransactionManager` that should be used to drive transactions. Alternatively, a -_qualifier_ may be declared via `@Transactional("myQualifier")`, or -`TransactionManagementConfigurer` can be implemented by an `@Configuration` class. -Consult the javadocs for `TestContextTransactionUtils.retrieveTransactionManager()` for -details on the algorithm used to look up a transaction manager in the test's -`ApplicationContext`. - -[[testcontext-tx-annotation-demo]] -====== Demonstration of all transaction-related annotations - -The following JUnit-based example displays a fictitious integration testing scenario -highlighting all transaction-related annotations. The example is **not** intended to -demonstrate best practices but rather to demonstrate how these annotations can be used. -Consult the <> section for further -information and configuration examples. <> contains an additional example using `@Sql` for -declarative SQL script execution with default transaction rollback semantics. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @RunWith(SpringJUnit4ClassRunner.class) - @ContextConfiguration - **@TransactionConfiguration(transactionManager="txMgr", defaultRollback=false) - @Transactional** - public class FictitiousTransactionalTest { - - **@BeforeTransaction** - public void verifyInitialDatabaseState() { - // logic to verify the initial state before a transaction is started - } - - @Before - public void setUpTestDataWithinTransaction() { - // set up test data within the transaction - } - - @Test - // overrides the class-level defaultRollback setting - **@Rollback(true)** - public void modifyDatabaseWithinTransaction() { - // logic which uses the test data and modifies database state - } - - @After - public void tearDownWithinTransaction() { - // execute "tear down" logic within the transaction - } - - **@AfterTransaction** - public void verifyFinalDatabaseState() { - // logic to verify the final state after transaction has rolled back - } - - } ----- - -[[testcontext-tx-false-positives]] -.Avoid false positives when testing ORM code -[NOTE] -==== -When you test application code that manipulates the state of the Hibernate session, make -sure to __flush__ the underlying session within test methods that execute that code. -Failing to flush the underlying session can produce __false positives__: your test may -pass, but the same code throws an exception in a live, production environment. In the -following Hibernate-based example test case, one method demonstrates a false positive, -and the other method correctly exposes the results of flushing the session. Note that -this applies to JPA and any other ORM frameworks that maintain an in-memory __unit of -work__. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - // ... - - @Autowired - private SessionFactory sessionFactory; - - @Test // no expected exception! - public void falsePositive() { - updateEntityInHibernateSession(); - // False positive: an exception will be thrown once the session is - // finally flushed (i.e., in production code) - } - - @Test(expected = GenericJDBCException.class) - public void updateWithSessionFlush() { - updateEntityInHibernateSession(); - // Manual flush is required to avoid false positive in test - sessionFactory.getCurrentSession().flush(); - } - - // ... ----- -==== - - -[[testcontext-executing-sql]] -===== Executing SQL scripts - -When writing integration tests against a relational database, it is often beneficial -to execute SQL scripts to modify the database schema or insert test data into tables. -The `spring-jdbc` module provides support for _initializing_ an embedded or existing -database by executing SQL scripts when the Spring `ApplicationContext` is loaded. See -<> and <> for -details. - -Although it is very useful to initialize a database for testing _once_ when the -`ApplicationContext` is loaded, sometimes it is essential to be able to modify the -database _during_ integration tests. The following sections explain how to execute SQL -scripts programmatically and declaratively during integration tests. - -[[testcontext-executing-sql-programmatically]] -====== Executing SQL scripts programmatically - -Spring provides the following options for executing SQL scripts programmatically within -integration test methods. - -* `org.springframework.jdbc.datasource.init.ScriptUtils` -* `org.springframework.jdbc.datasource.init.ResourceDatabasePopulator` -* `org.springframework.test.context.junit4.AbstractTransactionalJUnit4SpringContextTests` -* `org.springframework.test.context.testng.AbstractTransactionalTestNGSpringContextTests` - -`ScriptUtils` provides a collection of static utility methods for working with SQL scripts -and is mainly intended for internal use within the framework. However, if you require -full control over how SQL scripts are parsed and executed, `ScriptUtils` may suit your -needs better than some of the other alternatives described below. Consult the javadocs for -individual methods in `ScriptUtils` for further details. - -`ResourceDatabasePopulator` provides a simple object-based API for programmatically -populating, initializing, or cleaning up a database using SQL scripts defined in -external resources. `ResourceDatabasePopulator` provides options for configuring the -character encoding, statement separator, comment delimiters, and error handling flags -used when parsing and executing the scripts, and each of the configuration options has -a reasonable default value. Consult the javadocs for details on default values. To -execute the scripts configured in a `ResourceDatabasePopulator`, you can invoke either -the `populate(Connection)` method to execute the populator against a -`java.sql.Connection` or the `execute(DataSource)` method to execute the populator -against a `javax.sql.DataSource`. The following example specifies SQL scripts for a test -schema and test data, sets the statement separator to `"@@"`, and then executes the -scripts against a `DataSource`. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Test - public void databaseTest { - ResourceDatabasePopulator populator = new ResourceDatabasePopulator(); - populator.addScripts( - new ClassPathResource("test-schema.sql"), - new ClassPathResource("test-data.sql")); - populator.setSeparator("@@"); - populator.execute(this.dataSource); - // execute code that uses the test schema and data - } ----- - -Note that `ResourceDatabasePopulator` internally delegates to `ScriptUtils` for parsing -and executing SQL scripts. Similarly, the `executeSqlScript(..)` methods in -<> and -<> -internally use a `ResourceDatabasePopulator` for executing SQL scripts. Consult the javadocs -for the various `executeSqlScript(..)` methods for further details. - - -[[testcontext-executing-sql-declaratively]] -====== Executing SQL scripts declaratively with `@Sql` - -In addition to the aforementioned mechanisms for executing SQL scripts -_programmatically_, SQL scripts can also be configured _declaratively_ in the Spring -TestContext Framework. Specifically, the `@Sql` annotation can be declared on a test -class or test method to configure the resource paths to SQL scripts that should be -executed against a given database either before or after an integration test method. Note -that method-level declarations override class-level declarations and that support for -`@Sql` is provided by the `SqlScriptsTestExecutionListener` which is enabled by default. - -*Path resource semantics* - -Each path will be interpreted as a Spring `Resource`. A plain path -- for example, -`"schema.sql"` -- will be treated as a classpath resource that is _relative_ to the -package in which the test class is defined. A path starting with a slash will be treated -as an _absolute_ classpath resource, for example: `"/org/example/schema.sql"`. A path -which references a URL (e.g., a path prefixed with `classpath:`, `file:`, `http:`, etc.) -will be loaded using the specified resource protocol. - -The following example demonstrates how to use `@Sql` at the class level and at the method -level within a JUnit-based integration test class. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @RunWith(SpringJUnit4ClassRunner.class) - @ContextConfiguration - @Sql("/test-schema.sql") - public class DatabaseTests { - - @Test - public void emptySchemaTest { - // execute code that uses the test schema without any test data - } - - @Test - @Sql({"/test-schema.sql", "/test-user-data.sql"}) - public void userTest { - // execute code that uses the test schema and test data - } - } ----- - -*Default script detection* - -If no SQL scripts are specified, an attempt will be made to detect a `default` script -depending on where `@Sql` is declared. If a default cannot be detected, an -`IllegalStateException` will be thrown. - -* __class-level declaration__: if the annotated test class is `com.example.MyTest`, the - corresponding default script is `"classpath:com/example/MyTest.sql"`. -* __method-level declaration__: if the annotated test method is named `testMethod()` and is - defined in the class `com.example.MyTest`, the corresponding default script is - `"classpath:com/example/MyTest.testMethod.sql"`. - -*Declaring multiple `@Sql` sets* - -If multiple sets of SQL scripts need to be configured for a given test class or test -method but with different syntax configuration, different error handling rules, or -different execution phases per set, it is possible to declare multiple instances of -`@Sql`. With Java 8, `@Sql` can be used as a _repeatable_ annotation. Otherwise, the -`@SqlGroup` annotation can be used as an explicit container for declaring multiple -instances of `@Sql`. - -The following example demonstrates the use of `@Sql` as a repeatable annotation using -Java 8. In this scenario the `test-schema.sql` script uses a different syntax for -single-line comments. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Test - @Sql(scripts = "/test-schema.sql", config = @SqlConfig(commentPrefix = "`")) - @Sql("/test-user-data.sql") - public void userTest { - // execute code that uses the test schema and test data - } ----- - -The following example is identical to the above except that the `@Sql` declarations are -grouped together within `@SqlGroup` for compatibility with Java 6 and Java 7. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Test - @SqlGroup({ - @Sql(scripts = "/test-schema.sql", config = @SqlConfig(commentPrefix = "`")), - @Sql("/test-user-data.sql") - )} - public void userTest { - // execute code that uses the test schema and test data - } ----- - -*Script execution phases* - -By default, SQL scripts will be executed _before_ the corresponding test method. However, -if a particular set of scripts needs to be executed _after_ the test method -- for -example, to clean up database state -- the `executionPhase` attribute in `@Sql` can be -used as seen in the following example. Note that `ISOLATED` and `AFTER_TEST_METHOD` are -statically imported from `Sql.TransactionMode` and `Sql.ExecutionPhase` respectively. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Test - @Sql( - scripts = "create-test-data.sql", - config = @SqlConfig(transactionMode = ISOLATED) - ) - @Sql( - scripts = "delete-test-data.sql", - config = @SqlConfig(transactionMode = ISOLATED), - executionPhase = AFTER_TEST_METHOD - ) - public void userTest { - // execute code that needs the test data to be committed - // to the database outside of the test's transaction - } ----- - -*Script configuration with `@SqlConfig`* - -Configuration for script parsing and error handling can be configured via the -`@SqlConfig` annotation. When declared as a class-level annotation on an integration test -class, `@SqlConfig` serves as _global_ configuration for all SQL scripts within the test -class hierarchy. When declared directly via the `config` attribute of the `@Sql` -annotation, `@SqlConfig` serves as _local_ configuration for the SQL scripts declared -within the enclosing `@Sql` annotation. Every attribute in `@SqlConfig` has an implicit -default value which is documented in the javadocs of the corresponding attribute. Due to -the rules defined for annotation attributes in the Java Language Specification, it is -unfortunately not possible to assign a value of `null` to an annotation attribute. Thus, -in order to support overrides of inherited global configuration, `@SqlConfig` attributes -have an explicit default value of either `""` for Strings or `DEFAULT` for Enums. This -approach allows local declarations of `@SqlConfig` to selectively override individual -attributes from global declarations of `@SqlConfig` by providing a value other than `""` -or `DEFAULT`. Global `@SqlConfig` attributes are inherited whenever local `@SqlConfig` -attributes do not supply an explicit value other than `""` or `DEFAULT`. Explicit _local_ -configuration therefore overrides _global_ configuration. - -The configuration options provided by `@Sql` and `@SqlConfig` are equivalent to those -supported by `ScriptUtils` and `ResourceDatabasePopulator` but are a superset of those -provided by the `` XML namespace element. Consult the javadocs -of individual attributes in `@Sql` and `@SqlConfig` for details. - -[[testcontext-executing-sql-declaratively-tx]] -*Transaction management for `@Sql`* - -By default, the `SqlScriptsTestExecutionListener` will infer the desired transaction -semantics for scripts configured via `@Sql`. Specifically, SQL scripts will be executed -without a transaction, within an existing Spring-managed transaction -- for example, a -transaction managed by the `TransactionalTestExecutionListener` for a test annotated with -`@Transactional` -- or within an isolated transaction, depending on the configured value -of the `transactionMode` attribute in `@SqlConfig` and the presence of a -`PlatformTransactionManager` in the test's `ApplicationContext`. As a bare minimum -however, a `javax.sql.DataSource` must be present in the test's `ApplicationContext`. - -If the algorithms used by `SqlScriptsTestExecutionListener` to detect a `DataSource` and -`PlatformTransactionManager` and infer the transaction semantics do not suit your needs, -you may specify explicit names via the `dataSource` and `transactionManager` attributes -of `@SqlConfig`. Furthermore, the transaction propagation behavior can be controlled via -the `transactionMode` attribute of `@SqlConfig` -- for example, if scripts should be -executed in an isolated transaction. Although a thorough discussion of all supported -options for transaction management with `@Sql` is beyond the scope of this reference -manual, the javadocs for `@SqlConfig` and `SqlScriptsTestExecutionListener` provide -detailed information, and the following example demonstrates a typical testing scenario -using JUnit and transactional tests with `@Sql`. Note that there is no need to clean up -the database after the `usersTest()` method is executed since any changes made to the -database (either within the the test method or within the `/test-data.sql` script) will -be automatically rolled back by the `TransactionalTestExecutionListener` (see -<> for details). - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @RunWith(SpringJUnit4ClassRunner.class) - @ContextConfiguration(classes = TestDatabaseConfig.class) - @Transactional - public class TransactionalSqlScriptsTests { - - protected JdbcTemplate jdbcTemplate; - - @Autowired - public void setDataSource(DataSource dataSource) { - this.jdbcTemplate = new JdbcTemplate(dataSource); - } - - @Test - @Sql("/test-data.sql") - public void usersTest() { - // verify state in test database: - assertNumUsers(2); - // execute code that uses the test data... - } - - protected int countRowsInTable(String tableName) { - return JdbcTestUtils.countRowsInTable(this.jdbcTemplate, tableName); - } - - protected void assertNumUsers(int expected) { - assertEquals("Number of rows in the 'user' table.", expected, countRowsInTable("user")); - } - } ----- - - -[[testcontext-support-classes]] -===== TestContext Framework support classes - -[[testcontext-support-classes-junit4]] -====== JUnit support classes -The `org.springframework.test.context.junit4` package provides the following support -classes for JUnit-based test cases. - -* `AbstractJUnit4SpringContextTests` -* `AbstractTransactionalJUnit4SpringContextTests` - -`AbstractJUnit4SpringContextTests` is an abstract base test class that integrates the -__Spring TestContext Framework__ with explicit `ApplicationContext` testing support in -a JUnit 4.9+ environment. When you extend `AbstractJUnit4SpringContextTests`, you can -access a `protected` `applicationContext` instance variable that can be used to perform -explicit bean lookups or to test the state of the context as a whole. - -`AbstractTransactionalJUnit4SpringContextTests` is an abstract __transactional__ extension -of `AbstractJUnit4SpringContextTests` that adds some convenience functionality for JDBC -access. This class expects a `javax.sql.DataSource` bean and a `PlatformTransactionManager` -bean to be defined in the `ApplicationContext`. When you extend -`AbstractTransactionalJUnit4SpringContextTests` you can access a `protected` `jdbcTemplate` -instance variable that can be used to execute SQL statements to query the database. Such -queries can be used to confirm database state both __prior to__ and __after__ execution of -database-related application code, and Spring ensures that such queries run in the scope of -the same transaction as the application code. When used in conjunction with an ORM tool, -be sure to avoid <>. As mentioned in -<>, `AbstractTransactionalJUnit4SpringContextTests` -also provides convenience methods which delegate to methods in `JdbcTestUtils` using the -aforementioned `jdbcTemplate`. Furthermore, `AbstractTransactionalJUnit4SpringContextTests` -provides an `executeSqlScript(..)` method for executing SQL scripts against the configured -`DataSource`. - -[TIP] -==== -These classes are a convenience for extension. If you do not want your test classes to be -tied to a Spring-specific class hierarchy, you can configure your own custom test classes -by using `@RunWith(SpringJUnit4ClassRunner.class)`, `@ContextConfiguration`, -`@TestExecutionListeners`, and so on. -==== - -[[testcontext-junit4-runner]] -====== Spring JUnit Runner -The __Spring TestContext Framework__ offers full integration with JUnit 4.9+ through a -custom runner (tested on JUnit 4.9 -- 4.11). By annotating test classes with -`@RunWith(SpringJUnit4ClassRunner.class)`, developers can implement standard JUnit-based -unit and integration tests and simultaneously reap the benefits of the TestContext -framework such as support for loading application contexts, dependency injection of test -instances, transactional test method execution, and so on. The following code listing -displays the minimal requirements for configuring a test class to run with the custom -Spring Runner. `@TestExecutionListeners` is configured with an empty list in order to -disable the default listeners, which otherwise would require an ApplicationContext to be -configured through `@ContextConfiguration`. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @RunWith(SpringJUnit4ClassRunner.class) - @TestExecutionListeners({}) - public class SimpleTest { - - @Test - public void testMethod() { - // execute test logic... - } - } ----- - -[[testcontext-support-classes-testng]] -====== TestNG support classes -The `org.springframework.test.context.testng` package provides the following support -classes for TestNG based test cases. - -* `AbstractTestNGSpringContextTests` -* `AbstractTransactionalTestNGSpringContextTests` - -`AbstractTestNGSpringContextTests` is an abstract base test class that integrates the -__Spring TestContext Framework__ with explicit `ApplicationContext` testing support in -a TestNG environment. When you extend `AbstractTestNGSpringContextTests`, you can -access a `protected` `applicationContext` instance variable that can be used to perform -explicit bean lookups or to test the state of the context as a whole. - -`AbstractTransactionalTestNGSpringContextTests` is an abstract __transactional__ extension -of `AbstractTestNGSpringContextTests` that adds some convenience functionality for JDBC -access. This class expects a `javax.sql.DataSource` bean and a `PlatformTransactionManager` -bean to be defined in the `ApplicationContext`. When you extend -`AbstractTransactionalTestNGSpringContextTests` you can access a `protected` `jdbcTemplate` -instance variable that can be used to execute SQL statements to query the database. Such -queries can be used to confirm database state both __prior to__ and __after__ execution of -database-related application code, and Spring ensures that such queries run in the scope of -the same transaction as the application code. When used in conjunction with an ORM tool, -be sure to avoid <>. As mentioned in -<>, `AbstractTransactionalTestNGSpringContextTests` -also provides convenience methods which delegate to methods in `JdbcTestUtils` using the -aforementioned `jdbcTemplate`. Furthermore, `AbstractTransactionalTestNGSpringContextTests` -provides an `executeSqlScript(..)` method for executing SQL scripts against the configured -`DataSource`. - - -[TIP] -==== -These classes are a convenience for extension. If you do not want your test classes to be -tied to a Spring-specific class hierarchy, you can configure your own custom test classes -by using `@ContextConfiguration`, `@TestExecutionListeners`, and so on, and by manually -instrumenting your test class with a `TestContextManager`. See the source code of -`AbstractTestNGSpringContextTests` for an example of how to instrument your test class. -==== - - - -[[spring-mvc-test-framework]] -==== Spring MVC Test Framework - -.Standalone project -**** -Before inclusion in Spring Framework 3.2, the Spring MVC Test framework had already -existed as a separate project on GitHub where it grew and evolved through actual use, -feedback, and the contribution of many. - -The standalone https://github.com/spring-projects/spring-test-mvc[spring-test-mvc project] -is still available on GitHub and can be used in conjunction with Spring Framework 3.1.x. -Applications upgrading to 3.2 or later should replace the `spring-test-mvc` dependency with a -dependency on `spring-test`. - -The `spring-test` module uses a different package `org.springframework.test.web` but -otherwise is nearly identical with two exceptions. One is support for features new in -3.2 (e.g. asynchronous web requests). The other relates to the options for creating a -`MockMvc` instance. In Spring Framework 3.2 and later, this can only be done through the -TestContext framework, which provides caching benefits for the loaded configuration. -**** - -The __Spring MVC Test framework__ provides first class JUnit support for testing client -and server-side Spring MVC code through a fluent API. Typically it loads the actual -Spring configuration through the __TestContext framework__ and always uses the -`DispatcherServlet` to process requests thus approximating full integration tests -without requiring a running Servlet container. - -Client-side tests are `RestTemplate`-based and allow tests for code that relies on the -`RestTemplate` without requiring a running server to respond to the requests. - - -[[spring-mvc-test-server]] -===== Server-Side Tests -Before Spring Framework 3.2, the most likely way to test a Spring MVC controller was to -write a unit test that instantiates the controller, injects it with mock or stub -dependencies, and then calls its methods directly, using a `MockHttpServletRequest` and -`MockHttpServletResponse` where necessary. - -Although this is pretty easy to do, controllers have many annotations, and much remains -untested. Request mappings, data binding, type conversion, and validation are just a few -examples of what isn't tested. Furthermore, there are other types of annotated methods -such as `@InitBinder`, `@ModelAttribute`, and `@ExceptionHandler` that get invoked as -part of request processing. - -The idea behind Spring MVC Test is to be able to re-write those controller tests by -performing actual requests and generating responses, as they would be at runtime, along -the way invoking controllers through the Spring MVC `DispatcherServlet`. Controllers can -still be injected with mock dependencies, so tests can remain focused on the web layer. - -Spring MVC Test builds on the familiar "mock" implementations of the Servlet API -available in the `spring-test` module. This allows performing requests and generating -responses without the need for running in a Servlet container. For the most part -everything should work as it does at runtime with the exception of JSP rendering, which -is not available outside a Servlet container. Furthermore, if you are familiar with how -the `MockHttpServletResponse` works, you'll know that forwards and redirects are not -actually executed. Instead "forwarded" and "redirected" URLs are saved and can be -asserted in tests. This means if you are using JSPs, you can verify the JSP page to -which the request was forwarded. - -All other means of rendering including `@ResponseBody` methods and `View` types (besides -JSPs) such as Freemarker, Velocity, Thymeleaf, and others for rendering HTML, JSON, XML, -and so on should work as expected, and the response will contain the generated content. - -Below is an example of a test requesting account information in JSON format: - -[source,java,indent=0] ----- - import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; - import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; - - @RunWith(SpringJUnit4ClassRunner.class) - @WebAppConfiguration - @ContextConfiguration("test-servlet-context.xml") - public class ExampleTests { - - @Autowired - private WebApplicationContext wac; - - private MockMvc mockMvc; - - @Before - public void setup() { - this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build(); - } - - @Test - public void getAccount() throws Exception { - this.mockMvc.perform(get("/accounts/1").accept(MediaType.parseMediaType("application/json;charset=UTF-8"))) - .andExpect(status().isOk()) - .andExpect(content().contentType("application/json")) - .andExpect(jsonPath("$.name").value("Lee")); - } - - } ----- - -The test relies on the `WebApplicationContext` support of the __TestContext framework__. -It loads Spring configuration from an XML configuration file located in the same package -as the test class (also supports JavaConfig) and injects the created -`WebApplicationContext` into the test so a `MockMvc` instance can be created with it. - -The `MockMvc` is then used to perform a request to `"/accounts/1"` and verify the -resulting response status is 200, the response content type is `"application/json"`, and -response content has a JSON property called "name" with the value "Lee". JSON content is -inspected with the help of Jayway's https://github.com/jayway/JsonPath[JsonPath -project]. There are lots of other options for verifying the result of the performed -request and those will be discussed later. - -[[spring-mvc-test-server-static-imports]] -====== Static Imports -The fluent API in the example above requires a few static imports such as -`MockMvcRequestBuilders.*`, `MockMvcResultMatchers.*`, and `MockMvcBuilders.*`. An easy -way to find these classes is to search for types matching __"MockMvc*"__. If using -Eclipse, be sure to add them as "favorite static members" in the Eclipse preferences -under__Java -> Editor -> Content Assist -> Favorites__. That will allow use of content -assist after typing the first character of the static method name. Other IDEs (e.g. -IntelliJ) may not require any additional configuration. Just check the support for code -completion on static members. - -[[spring-mvc-test-server-setup-options]] -====== Setup Options -The goal of server-side test setup is to create an instance of `MockMvc` that can be -used to perform requests. There are two main options. - -The first option is to point to Spring MVC configuration through the __TestContext -framework__, which loads the Spring configuration and injects a `WebApplicationContext` -into the test to use to create a `MockMvc`: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @RunWith(SpringJUnit4ClassRunner.class) - @WebAppConfiguration - @ContextConfiguration("my-servlet-context.xml") - public class MyWebTests { - - @Autowired - private WebApplicationContext wac; - - private MockMvc mockMvc; - - @Before - public void setup() { - this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build(); - } - - // ... - - } ----- - -The second option is to simply register a controller instance without loading any Spring -configuration. Instead basic Spring MVC configuration suitable for testing annotated -controllers is automatically created. The created configuration is comparable to that of -the MVC JavaConfig (and the MVC namespace) and can be customized to a degree through -builder-style methods: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class MyWebTests { - - private MockMvc mockMvc; - - @Before - public void setup() { - this.mockMvc = MockMvcBuilders.standaloneSetup(new AccountController()).build(); - } - - // ... - - } ----- - -Which option should you use? - -The __"webAppContextSetup"__ loads the actual Spring MVC configuration resulting in a -more complete integration test. Since the __TestContext framework__ caches the loaded -Spring configuration, it helps to keep tests running fast even as more tests get added. -Furthermore, you can inject mock services into controllers through Spring configuration, -in order to remain focused on testing the web layer. Here is an example of declaring a -mock service with Mockito: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - ----- - -Then you can inject the mock service into the test in order set up and verify -expectations: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @RunWith(SpringJUnit4ClassRunner.class) - @WebAppConfiguration - @ContextConfiguration("test-servlet-context.xml") - public class AccountTests { - - @Autowired - private WebApplicationContext wac; - - private MockMvc mockMvc; - - @Autowired - private AccountService accountService; - - // ... - - } ----- - -The __"standaloneSetup"__ on the other hand is a little closer to a unit test. It tests -one controller at a time, the controller can be injected with mock dependencies -manually, and it doesn't involve loading Spring configuration. Such tests are more -focused in style and make it easier to see which controller is being tested, whether any -specific Spring MVC configuration is required to work, and so on. The "standaloneSetup" -is also a very convenient way to write ad-hoc tests to verify some behavior or to debug -an issue. - -Just like with integration vs unit testing, there is no right or wrong answer. Using the -"standaloneSetup" does imply the need for some additional "webAppContextSetup" tests to -verify the Spring MVC configuration. Alternatively, you can decide write all tests with -"webAppContextSetup" and always test against actual Spring MVC configuration. - -[[spring-mvc-test-server-performing-requests]] -====== Performing Requests -To perform requests, use the appropriate HTTP method and additional builder-style -methods corresponding to properties of `MockHttpServletRequest`. For example: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - mockMvc.perform(post("/hotels/{id}", 42).accept(MediaType.APPLICATION_JSON)); ----- - -In addition to all the HTTP methods, you can also perform file upload requests, which -internally creates an instance of `MockMultipartHttpServletRequest`: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - mockMvc.perform(fileUpload("/doc").file("a1", "ABC".getBytes("UTF-8"))); ----- - -Query string parameters can be specified in the URI template: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - mockMvc.perform(get("/hotels?foo={foo}", "bar")); ----- - -Or by adding Servlet request parameters: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - mockMvc.perform(get("/hotels").param("foo", "bar")); ----- - -If application code relies on Servlet request parameters, and doesn't check the query -string, as is most often the case, then it doesn't matter how parameters are added. Keep -in mind though that parameters provided in the URI template will be decoded while -parameters provided through the `param(...)` method are expected to be decoded. - -In most cases it's preferable to leave out the context path and the Servlet path from -the request URI. If you must test with the full request URI, be sure to set the -`contextPath` and `servletPath` accordingly so that request mappings will work: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - mockMvc.perform(get("/app/main/hotels/{id}").contextPath("/app").servletPath("/main")) ----- - -Looking at the above example, it would be cumbersome to set the contextPath and -servletPath with every performed request. That's why you can define default request -properties when building the `MockMvc`: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class MyWebTests { - - private MockMvc mockMvc; - - @Before - public void setup() { - mockMvc = standaloneSetup(new AccountController()) - .defaultRequest(get("/") - .contextPath("/app").servletPath("/main") - .accept(MediaType.APPLICATION_JSON).build(); - } ----- - -The above properties will apply to every request performed through the `MockMvc`. If the -same property is also specified on a given request, it will override the default value. -That is why, the HTTP method and URI don't matter, when setting default request -properties, since they must be specified on every request. - -[[spring-mvc-test-server-defining-expectations]] -====== Defining Expectations -Expectations can be defined by appending one or more `.andExpect(..)` after call to -perform the request: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - mockMvc.perform(get("/accounts/1")).andExpect(status().isOk()); ----- - -`MockMvcResultMatchers.*` defines a number of static members, some of which return types -with additional methods, for asserting the result of the performed request. The -assertions fall in two general categories. - -The first category of assertions verify properties of the response, i.e the response -status, headers, and content. Those are the most important things to test for. - -The second category of assertions go beyond the response, and allow inspecting Spring -MVC specific constructs such as which controller method processed the request, whether -an exception was raised and handled, what the content of the model is, what view was -selected, what flash attributes were added, and so on. It is also possible to verify -Servlet specific constructs such as request and session attributes. The following test -asserts that binding/validation failed: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - mockMvc.perform(post("/persons")) - .andExpect(status().isOk()) - .andExpect(model().attributeHasErrors("person")); ----- - -Many times when writing tests, it's useful to dump the result of the performed request. -This can be done as follows, where `print()` is a static import from -`MockMvcResultHandlers`: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - mockMvc.perform(post("/persons")) - .andDo(print()) - .andExpect(status().isOk()) - .andExpect(model().attributeHasErrors("person")); ----- - -As long as request processing causes an unhandled exception, the `print()` method will -print all the available result data to `System.out`. - -In some cases, you may want to get direct access to the result and verify something that -cannot be verified otherwise. This can be done by appending `.andReturn()` at the end -after all expectations: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - MvcResult mvcResult = mockMvc.perform(post("/persons")).andExpect(status().isOk()).andReturn(); - // ... ----- - -When all tests repeat the same expectations, you can define the common expectations once -when building the `MockMvc`: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - standaloneSetup(new SimpleController()) - .alwaysExpect(status().isOk()) - .alwaysExpect(content().contentType("application/json;charset=UTF-8")) - .build() ----- - -Note that the expectation is __always__ applied and cannot be overridden without -creating a separate `MockMvc` instance. - -When JSON response content contains hypermedia links created with -https://github.com/spring-projects/spring-hateoas[Spring HATEOAS], the resulting links can -be verified: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - mockMvc.perform(get("/people").accept(MediaType.APPLICATION_JSON)) - .andExpect(jsonPath("$.links[?(@.rel == 'self')].href").value("http://localhost:8080/people")); ----- - -When XML response content contains hypermedia links created with -https://github.com/spring-projects/spring-hateoas[Spring HATEOAS], the resulting links can -be verified: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - Map ns = Collections.singletonMap("ns", "http://www.w3.org/2005/Atom"); - mockMvc.perform(get("/handle").accept(MediaType.APPLICATION_XML)) - .andExpect(xpath("/person/ns:link[@rel='self']/@href", ns).string("http://localhost:8080/people")); ----- - -[[spring-mvc-test-server-filters]] -====== Filter Registrations -When setting up a `MockMvc`, you can register one or more `Filter` instances: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - mockMvc = standaloneSetup(new PersonController()).addFilters(new CharacterEncodingFilter()).build(); ----- - -Registered filters will be invoked through `MockFilterChain` from `spring-test` and the -last filter will delegates to the `DispatcherServlet`. - -[[spring-mvc-test-server-resources]] -====== Further Server-Side Test Examples -The framework's own tests include -https://github.com/spring-projects/spring-framework/tree/master/spring-test/src/test/java/org/springframework/test/web/servlet/samples[many -sample tests] intended to demonstrate how to use Spring MVC Test. Browse these examples -for further ideas. Also the -https://github.com/spring-projects/spring-mvc-showcase[spring-mvc-showcase] has full test -coverage based on Spring MVC Test. - - -[[spring-mvc-test-client]] -===== Client-Side REST Tests -Client-side tests are for code using the `RestTemplate`. The goal is to define expected -requests and provide "stub" responses: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - RestTemplate restTemplate = new RestTemplate(); - - MockRestServiceServer mockServer = MockRestServiceServer.createServer(restTemplate); - mockServer.expect(requestTo("/greeting")).andRespond(withSuccess("Hello world", MediaType.TEXT_PLAIN)); - - // use RestTemplate ... - - mockServer.verify(); ----- - -In the above example, `MockRestServiceServer` -- the central class for client-side REST -tests -- configures the `RestTemplate` with a custom `ClientHttpRequestFactory` that -asserts actual requests against expectations and returns "stub" responses. In this case -we expect a single request to "/greeting" and want to return a 200 response with -"text/plain" content. We could define as many additional requests and stub responses as -necessary. - -Once expected requests and stub responses have been defined, the `RestTemplate` can be -used in client-side code as usual. At the end of the tests `mockServer.verify()` can be -used to verify that all expected requests were performed. - -[[spring-mvc-test-client-static-imports]] -====== Static Imports -Just like with server-side tests, the fluent API for client-side tests requires a few -static imports. Those are easy to find by searching __"MockRest*"__. Eclipse users -should add `"MockRestRequestMatchers.*"` and `"MockRestResponseCreators.*"` as "favorite -static members" in the Eclipse preferences under __Java -> Editor -> Content Assist -> -Favorites__. That allows using content assist after typing the first character of the -static method name. Other IDEs (e.g. IntelliJ) may not require any additional -configuration. Just check the support for code completion on static members. - -[[spring-mvc-test-client-resources]] -====== Further Examples of Client-side REST Tests -Spring MVC Test's own tests include -https://github.com/spring-projects/spring-framework/tree/master/spring-test/src/test/java/org/springframework/test/web/client/samples[example -tests] of client-side REST tests. - - - -[[testing-examples-petclinic]] -==== PetClinic Example - -The PetClinic application, available on -https://github.com/spring-projects/spring-petclinic[GitHub], illustrates several features -of the __Spring TestContext Framework__ in a JUnit environment. Most test functionality -is included in the `AbstractClinicTests`, for which a partial listing is shown below: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - import static org.junit.Assert.assertEquals; - // import ... - - **@ContextConfiguration** - public abstract class AbstractClinicTests **extends AbstractTransactionalJUnit4SpringContextTests** { - - **@Autowired** - protected Clinic clinic; - - @Test - public void getVets() { - Collection vets = this.clinic.getVets(); - assertEquals("JDBC query must show the same number of vets", - **super.countRowsInTable("VETS")**, vets.size()); - Vet v1 = EntityUtils.getById(vets, Vet.class, 2); - assertEquals("Leary", v1.getLastName()); - assertEquals(1, v1.getNrOfSpecialties()); - assertEquals("radiology", (v1.getSpecialties().get(0)).getName()); - // ... - } - - // ... - } ----- - -Notes: - -* This test case extends the `AbstractTransactionalJUnit4SpringContextTests` class, from - which it inherits configuration for Dependency Injection (through the - `DependencyInjectionTestExecutionListener`) and transactional behavior (through the - `TransactionalTestExecutionListener`). -* The `clinic` instance variable -- the application object being tested -- is set by - Dependency Injection through `@Autowired` semantics. -* The `getVets()` method illustrates how you can use the inherited `countRowsInTable()` - method to easily verify the number of rows in a given table, thus verifying correct - behavior of the application code being tested. This allows for stronger tests and - lessens dependency on the exact test data. For example, you can add additional rows in - the database without breaking tests. -* Like many integration tests that use a database, most of the tests in - `AbstractClinicTests` depend on a minimum amount of data already in the database before - the test cases run. Alternatively, you might choose to populate the database within the - test fixture set up of your test cases -- again, within the same transaction as the - tests. - -The PetClinic application supports three data access technologies: JDBC, Hibernate, and -JPA. By declaring `@ContextConfiguration` without any specific resource locations, the -`AbstractClinicTests` class will have its application context loaded from the default -location, `AbstractClinicTests-context.xml`, which declares a common `DataSource`. -Subclasses specify additional context locations that must declare a -`PlatformTransactionManager` and a concrete implementation of `Clinic`. - -For example, the Hibernate implementation of the PetClinic tests contains the following -implementation. For this example, `HibernateClinicTests` does not contain a single line -of code: we only need to declare `@ContextConfiguration`, and the tests are inherited -from `AbstractClinicTests`. Because `@ContextConfiguration` is declared without any -specific resource locations, the __Spring TestContext Framework__ loads an application -context from all the beans defined in `AbstractClinicTests-context.xml` (i.e., the -inherited locations) and `HibernateClinicTests-context.xml`, with -`HibernateClinicTests-context.xml` possibly overriding beans defined in -`AbstractClinicTests-context.xml`. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - **@ContextConfiguration** - public class HibernateClinicTests extends AbstractClinicTests { } ----- - -In a large-scale application, the Spring configuration is often split across multiple -files. Consequently, configuration locations are typically specified in a common base -class for all application-specific integration tests. Such a base class may also add -useful instance variables -- populated by Dependency Injection, naturally -- such as a -`SessionFactory` in the case of an application using Hibernate. - -As far as possible, you should have exactly the same Spring configuration files in your -integration tests as in the deployed environment. One likely point of difference -concerns database connection pooling and transaction infrastructure. If you are -deploying to a full-blown application server, you will probably use its connection pool -(available through JNDI) and JTA implementation. Thus in production you will use a -`JndiObjectFactoryBean` or `` for the `DataSource` and -`JtaTransactionManager`. JNDI and JTA will not be available in out-of-container -integration tests, so you should use a combination like the Commons DBCP -`BasicDataSource` and `DataSourceTransactionManager` or `HibernateTransactionManager` -for them. You can factor out this variant behavior into a single XML file, having the -choice between application server and a 'local' configuration separated from all other -configuration, which will not vary between the test and production environments. In -addition, it is advisable to use properties files for connection settings. See the -PetClinic application for an example. - - - - -[[testing-resources]] -=== Further Resources -Consult the following resources for more information about testing: - -* http://www.junit.org/[JUnit]: "__A programmer-oriented testing framework for Java__". - Used by the Spring Framework in its test suite. -* http://testng.org/[TestNG]: A testing framework inspired by JUnit with added support - for annotations, test groups, data-driven testing, distributed testing, etc. -* http://www.mockobjects.com/[MockObjects.com]: Web site dedicated to mock objects, a - technique for improving the design of code within test-driven development. -* http://en.wikipedia.org/wiki/Mock_Object["Mock Objects"]: Article in Wikipedia. -* http://www.easymock.org/[EasyMock]: Java library " __that provides Mock Objects for - interfaces (and objects through the class extension) by generating them on the fly - using Java's proxy mechanism.__ " Used by the Spring Framework in its test suite. -* http://www.jmock.org/[JMock]: Library that supports test-driven development of Java - code with mock objects. -* http://mockito.org/[Mockito]: Java mock library based on the - http://xunitpatterns.com/Test%20Spy.html[test spy] pattern. -* http://dbunit.sourceforge.net/[DbUnit]: JUnit extension (also usable with Ant and - Maven) targeted for database-driven projects that, among other things, puts your - database into a known state between test runs. -* http://grinder.sourceforge.net/[The Grinder]: Java load testing framework. - - - - - - -[[spring-data-tier]] -= Data Access -[partintro] --- -This part of the reference documentation is concerned with data access and the -interaction between the data access layer and the business or service layer. - -Spring's comprehensive transaction management support is covered in some detail, -followed by thorough coverage of the various data access frameworks and technologies -that the Spring Framework integrates with. - -* <> -* <> -* <> -* <> -* <> --- - - - - -[[transaction]] -== Transaction Management - - - - -[[transaction-intro]] -=== Introduction to Spring Framework transaction management -Comprehensive transaction support is among the most compelling reasons to use the Spring -Framework. The Spring Framework provides a consistent abstraction for transaction -management that delivers the following benefits: - -* Consistent programming model across different transaction APIs such as Java - Transaction API (JTA), JDBC, Hibernate, Java Persistence API (JPA), and Java Data - Objects (JDO). -* Support for <>. -* Simpler API for <> transaction management than - complex transaction APIs such as JTA. -* Excellent integration with Spring's data access abstractions. - -The following sections describe the Spring Framework's transaction value-adds and -technologies. (The chapter also includes discussions of best practices, application -server integration, and solutions to common problems.) - -* <> describes __why__ you would use the Spring Framework's transaction abstraction - instead of EJB Container-Managed Transactions (CMT) or choosing to drive local - transactions through a proprietary API such as Hibernate. -* <> - outlines the core classes and describes how to configure and obtain `DataSource` - instances from a variety of sources. -* <>describes - how the application code ensures that resources are created, reused, and cleaned up - properly. -* <> describes support for - declarative transaction management. -* <> covers support for - programmatic (that is, explicitly coded) transaction management. - - - - -[[transaction-motivation]] -=== Advantages of the Spring Framework's transaction support model -Traditionally, Java EE developers have had two choices for transaction management: -__global__ or __local__ transactions, both of which have profound limitations. Global -and local transaction management is reviewed in the next two sections, followed by a -discussion of how the Spring Framework's transaction management support addresses the -limitations of the global and local transaction models. - - - -[[transaction-global]] -==== Global transactions -Global transactions enable you to work with multiple transactional resources, typically -relational databases and message queues. The application server manages global -transactions through the JTA, which is a cumbersome API to use (partly due to its -exception model). Furthermore, a JTA `UserTransaction` normally needs to be sourced from -JNDI, meaning that you __also__ need to use JNDI in order to use JTA. Obviously the use -of global transactions would limit any potential reuse of application code, as JTA is -normally only available in an application server environment. - -Previously, the preferred way to use global transactions was via EJB __CMT__ -(__Container Managed Transaction__): CMT is a form of __declarative transaction -management__ (as distinguished from __programmatic transaction management__). EJB CMT -removes the need for transaction-related JNDI lookups, although of course the use of EJB -itself necessitates the use of JNDI. It removes most but not all of the need to write -Java code to control transactions. The significant downside is that CMT is tied to JTA -and an application server environment. Also, it is only available if one chooses to -implement business logic in EJBs, or at least behind a transactional EJB facade. The -negatives of EJB in general are so great that this is not an attractive proposition, -especially in the face of compelling alternatives for declarative transaction management. - - - -[[transaction-local]] -==== Local transactions -Local transactions are resource-specific, such as a transaction associated with a JDBC -connection. Local transactions may be easier to use, but have significant disadvantages: -they cannot work across multiple transactional resources. For example, code that manages -transactions using a JDBC connection cannot run within a global JTA transaction. Because -the application server is not involved in transaction management, it cannot help ensure -correctness across multiple resources. (It is worth noting that most applications use a -single transaction resource.) Another downside is that local transactions are invasive -to the programming model. - - - -[[transaction-programming-model]] -==== Spring Framework's consistent programming model - -Spring resolves the disadvantages of global and local transactions. It enables -application developers to use a __consistent__ programming model __in any environment__. -You write your code once, and it can benefit from different transaction management -strategies in different environments. The Spring Framework provides both declarative and -programmatic transaction management. Most users prefer declarative transaction -management, which is recommended in most cases. - -With programmatic transaction management, developers work with the Spring Framework -transaction abstraction, which can run over any underlying transaction infrastructure. -With the preferred declarative model, developers typically write little or no code -related to transaction management, and hence do not depend on the Spring Framework -transaction API, or any other transaction API. - -.Do you need an application server for transaction management? -**** -The Spring Framework's transaction management support changes traditional rules as to -when an enterprise Java application requires an application server. - -In particular, you do not need an application server simply for declarative transactions -through EJBs. In fact, even if your application server has powerful JTA capabilities, -you may decide that the Spring Framework's declarative transactions offer more power and -a more productive programming model than EJB CMT. - -Typically you need an application server's JTA capability only if your application needs -to handle transactions across multiple resources, which is not a requirement for many -applications. Many high-end applications use a single, highly scalable database (such as -Oracle RAC) instead. Standalone transaction managers such as -http://www.atomikos.com/[Atomikos Transactions] and http://jotm.objectweb.org/[JOTM] -are other options. Of course, you may need other application server capabilities such as -Java Message Service (JMS) and Java EE Connector Architecture (JCA). - -The Spring Framework __gives you the choice of when to scale your application to a fully -loaded application server__. Gone are the days when the only alternative to using EJB -CMT or JTA was to write code with local transactions such as those on JDBC connections, -and face a hefty rework if you need that code to run within global, container-managed -transactions. With the Spring Framework, only some of the bean definitions in your -configuration file, rather than your code, need to change. -**** - - - - -[[transaction-strategies]] -=== Understanding the Spring Framework transaction abstraction -The key to the Spring transaction abstraction is the notion of a __transaction -strategy__. A transaction strategy is defined by the -`org.springframework.transaction.PlatformTransactionManager` interface: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public interface PlatformTransactionManager { - - TransactionStatus getTransaction( - TransactionDefinition definition) throws TransactionException; - - void commit(TransactionStatus status) throws TransactionException; - - void rollback(TransactionStatus status) throws TransactionException; - } ----- - -This is primarily a service provider interface (SPI), although it can be used -<> from your application code. Because -`PlatformTransactionManager` is an __interface__, it can be easily mocked or stubbed as -necessary. It is not tied to a lookup strategy such as JNDI. -`PlatformTransactionManager` implementations are defined like any other object (or bean) -in the Spring Framework IoC container. This benefit alone makes Spring Framework -transactions a worthwhile abstraction even when you work with JTA. Transactional code -can be tested much more easily than if it used JTA directly. - -Again in keeping with Spring's philosophy, the `TransactionException` that can be thrown -by any of the `PlatformTransactionManager` interface's methods is __unchecked__ (that -is, it extends the `java.lang.RuntimeException` class). Transaction infrastructure -failures are almost invariably fatal. In rare cases where application code can actually -recover from a transaction failure, the application developer can still choose to catch -and handle `TransactionException`. The salient point is that developers are not -__forced__ to do so. - -The `getTransaction(..)` method returns a `TransactionStatus` object, depending on a -`TransactionDefinition` parameter. The returned `TransactionStatus` might represent a -new transaction, or can represent an existing transaction if a matching transaction -exists in the current call stack. The implication in this latter case is that, as with -Java EE transaction contexts, a `TransactionStatus` is associated with a __thread__ of -execution. - -The `TransactionDefinition` interface specifies: - -* __Isolation__: The degree to which this transaction is isolated from the work of other - transactions. For example, can this transaction see uncommitted writes from other - transactions? -* __Propagation__: Typically, all code executed within a transaction scope will run in - that transaction. However, you have the option of specifying the behavior in the event - that a transactional method is executed when a transaction context already exists. For - example, code can continue running in the existing transaction (the common case); or - the existing transaction can be suspended and a new transaction created. __Spring - offers all of the transaction propagation options familiar from EJB CMT__. To read - about the semantics of transaction propagation in Spring, see <>. -* __Timeout__: How long this transaction runs before timing out and being rolled back - automatically by the underlying transaction infrastructure. -* __Read-only status__: A read-only transaction can be used when your code reads but - does not modify data. Read-only transactions can be a useful optimization in some - cases, such as when you are using Hibernate. - -These settings reflect standard transactional concepts. If necessary, refer to resources -that discuss transaction isolation levels and other core transaction concepts. -Understanding these concepts is essential to using the Spring Framework or any -transaction management solution. - -The `TransactionStatus` interface provides a simple way for transactional code to -control transaction execution and query transaction status. The concepts should be -familiar, as they are common to all transaction APIs: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public interface TransactionStatus extends SavepointManager { - - boolean isNewTransaction(); - - boolean hasSavepoint(); - - void setRollbackOnly(); - - boolean isRollbackOnly(); - - void flush(); - - boolean isCompleted(); - - } ----- - -Regardless of whether you opt for declarative or programmatic transaction management in -Spring, defining the correct `PlatformTransactionManager` implementation is absolutely -essential. You typically define this implementation through dependency injection. - -`PlatformTransactionManager` implementations normally require knowledge of the -environment in which they work: JDBC, JTA, Hibernate, and so on. The following examples -show how you can define a local `PlatformTransactionManager` implementation. (This -example works with plain JDBC.) - -You define a JDBC `DataSource` - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - ----- - -The related `PlatformTransactionManager` bean definition will then have a reference to -the `DataSource` definition. It will look like this: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - ----- - -If you use JTA in a Java EE container then you use a container `DataSource`, obtained -through JNDI, in conjunction with Spring's `JtaTransactionManager`. This is what the JTA -and JNDI lookup version would look like: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - - - ----- - -The `JtaTransactionManager` does not need to know about the `DataSource`, or any other -specific resources, because it uses the container's global transaction management -infrastructure. - -[NOTE] -==== -The above definition of the `dataSource` bean uses the `` tag from the -`jee` namespace. For more information on schema-based configuration, see <>, -and for more information on the `` tags see the section entitled -<>. -==== - -You can also use Hibernate local transactions easily, as shown in the following -examples. In this case, you need to define a Hibernate `LocalSessionFactoryBean`, which -your application code will use to obtain Hibernate `Session` instances. - -The `DataSource` bean definition will be similar to the local JDBC example shown -previously and thus is not shown in the following example. - -[NOTE] -==== -If the `DataSource`, used by any non-JTA transaction manager, is looked up via JNDI and -managed by a Java EE container, then it should be non-transactional because the Spring -Framework, rather than the Java EE container, will manage the transactions. -==== - -The `txManager` bean in this case is of the `HibernateTransactionManager` type. In the -same way as the `DataSourceTransactionManager` needs a reference to the `DataSource`, -the `HibernateTransactionManager` needs a reference to the `SessionFactory`. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - org/springframework/samples/petclinic/hibernate/petclinic.hbm.xml - - - - - hibernate.dialect=${hibernate.dialect} - - - - - - - ----- - -If you are using Hibernate and Java EE container-managed JTA transactions, then you -should simply use the same `JtaTransactionManager` as in the previous JTA example for -JDBC. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - ----- - -[NOTE] -==== -If you use JTA , then your transaction manager definition will look the same regardless -of what data access technology you use, be it JDBC, Hibernate JPA or any other supported -technology. This is due to the fact that JTA transactions are global transactions, which -can enlist any transactional resource. -==== - -In all these cases, application code does not need to change. You can change how -transactions are managed merely by changing configuration, even if that change means -moving from local to global transactions or vice versa. - - - - -[[tx-resource-synchronization]] -=== Synchronizing resources with transactions -It should now be clear how you create different transaction managers, and how they are -linked to related resources that need to be synchronized to transactions (for example -`DataSourceTransactionManager` to a JDBC `DataSource`, `HibernateTransactionManager` to -a Hibernate `SessionFactory`, and so forth). This section describes how the application -code, directly or indirectly using a persistence API such as JDBC, Hibernate, or JDO, -ensures that these resources are created, reused, and cleaned up properly. The section -also discusses how transaction synchronization is triggered (optionally) through the -relevant `PlatformTransactionManager`. - - - -[[tx-resource-synchronization-high]] -==== High-level synchronization approach -The preferred approach is to use Spring's highest level template based persistence -integration APIs or to use native ORM APIs with transaction- aware factory beans or -proxies for managing the native resource factories. These transaction-aware solutions -internally handle resource creation and reuse, cleanup, optional transaction -synchronization of the resources, and exception mapping. Thus user data access code does -not have to address these tasks, but can be focused purely on non-boilerplate -persistence logic. Generally, you use the native ORM API or take a __template__ approach -for JDBC access by using the `JdbcTemplate`. These solutions are detailed in subsequent -chapters of this reference documentation. - - - -[[tx-resource-synchronization-low]] -==== Low-level synchronization approach -Classes such as `DataSourceUtils` (for JDBC), `EntityManagerFactoryUtils` (for JPA), -`SessionFactoryUtils` (for Hibernate), `PersistenceManagerFactoryUtils` (for JDO), and -so on exist at a lower level. When you want the application code to deal directly with -the resource types of the native persistence APIs, you use these classes to ensure that -proper Spring Framework-managed instances are obtained, transactions are (optionally) -synchronized, and exceptions that occur in the process are properly mapped to a -consistent API. - -For example, in the case of JDBC, instead of the traditional JDBC approach of calling -the `getConnection()` method on the `DataSource`, you instead use Spring's -`org.springframework.jdbc.datasource.DataSourceUtils` class as follows: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - Connection conn = DataSourceUtils.getConnection(dataSource); ----- - -If an existing transaction already has a connection synchronized (linked) to it, that -instance is returned. Otherwise, the method call triggers the creation of a new -connection, which is (optionally) synchronized to any existing transaction, and made -available for subsequent reuse in that same transaction. As mentioned, any -`SQLException` is wrapped in a Spring Framework `CannotGetJdbcConnectionException`, one -of the Spring Framework's hierarchy of unchecked DataAccessExceptions. This approach -gives you more information than can be obtained easily from the `SQLException`, and -ensures portability across databases, even across different persistence technologies. - -This approach also works without Spring transaction management (transaction -synchronization is optional), so you can use it whether or not you are using Spring for -transaction management. - -Of course, once you have used Spring's JDBC support, JPA support or Hibernate support, -you will generally prefer not to use `DataSourceUtils` or the other helper classes, -because you will be much happier working through the Spring abstraction than directly -with the relevant APIs. For example, if you use the Spring `JdbcTemplate` or -`jdbc.object` package to simplify your use of JDBC, correct connection retrieval occurs -behind the scenes and you won't need to write any special code. - - - -[[tx-resource-synchronization-tadsp]] -==== TransactionAwareDataSourceProxy - -At the very lowest level exists the `TransactionAwareDataSourceProxy` class. This is a -proxy for a target `DataSource`, which wraps the target `DataSource` to add awareness of -Spring-managed transactions. In this respect, it is similar to a transactional JNDI -`DataSource` as provided by a Java EE server. - -It should almost never be necessary or desirable to use this class, except when existing -code must be called and passed a standard JDBC `DataSource` interface implementation. In -that case, it is possible that this code is usable, but participating in Spring managed -transactions. It is preferable to write your new code by using the higher level -abstractions mentioned above. - - - - -[[transaction-declarative]] -=== Declarative transaction management -[NOTE] -==== -Most Spring Framework users choose declarative transaction management. This option has -the least impact on application code, and hence is most consistent with the ideals of a -__non-invasive__ lightweight container. -==== - -The Spring Framework's declarative transaction management is made possible with Spring -aspect-oriented programming (AOP), although, as the transactional aspects code comes -with the Spring Framework distribution and may be used in a boilerplate fashion, AOP -concepts do not generally have to be understood to make effective use of this code. - -The Spring Framework's declarative transaction management is similar to EJB CMT in that -you can specify transaction behavior (or lack of it) down to individual method level. It -is possible to make a `setRollbackOnly()` call within a transaction context if -necessary. The differences between the two types of transaction management are: - -* Unlike EJB CMT, which is tied to JTA, the Spring Framework's declarative transaction - management works in any environment. It can work with JTA transactions or local - transactions using JDBC, JPA, Hibernate or JDO by simply adjusting the configuration - files. -* You can apply the Spring Framework declarative transaction management to any class, - not merely special classes such as EJBs. -* The Spring Framework offers declarative - <>a feature with no EJB - equivalent. Both programmatic and declarative support for rollback rules is provided. -* The Spring Framework enables you to customize transactional behavior, by using AOP. - For example, you can insert custom behavior in the case of transaction rollback. You - can also add arbitrary advice, along with the transactional advice. With EJB CMT, you - cannot influence the container's transaction management except with - `setRollbackOnly()`. -* The Spring Framework does not support propagation of transaction contexts across - remote calls, as do high-end application servers. If you need this feature, we - recommend that you use EJB. However, consider carefully before using such a feature, - because normally, one does not want transactions to span remote calls. - -.Where is TransactionProxyFactoryBean? -**** -Declarative transaction configuration in versions of Spring 2.0 and above differs -considerably from previous versions of Spring. The main difference is that there is no -longer any need to configure `TransactionProxyFactoryBean` beans. - -The pre-Spring 2.0 configuration style is still 100% valid configuration; think of the -new `` as simply defining `TransactionProxyFactoryBean` beans on your behalf. -**** - -The concept of rollback rules is important: they enable you to specify which exceptions -(and throwables) should cause automatic rollback. You specify this declaratively, in -configuration, not in Java code. So, although you can still call `setRollbackOnly()` on -the `TransactionStatus` object to roll back the current transaction back, most often you -can specify a rule that `MyApplicationException` must always result in rollback. The -significant advantage to this option is that business objects do not depend on the -transaction infrastructure. For example, they typically do not need to import Spring -transaction APIs or other Spring APIs. - -Although EJB container default behavior automatically rolls back the transaction on a -__system exception__ (usually a runtime exception), EJB CMT does not roll back the -transaction automatically on an__application exception__ (that is, a checked exception -other than `java.rmi.RemoteException`). While the Spring default behavior for -declarative transaction management follows EJB convention (roll back is automatic only -on unchecked exceptions), it is often useful to customize this behavior. - - - -[[tx-decl-explained]] -==== Understanding the Spring Framework's declarative transaction implementation -It is not sufficient to tell you simply to annotate your classes with the -`@Transactional` annotation, add `@EnableTransactionManagement` to your configuration, -and then expect you to understand how it all works. This section explains the inner -workings of the Spring Framework's declarative transaction infrastructure in the event -of transaction-related issues. - -The most important concepts to grasp with regard to the Spring Framework's declarative -transaction support are that this support is enabled -<>, and that the transactional advice -is driven by __metadata__ (currently XML- or annotation-based). The combination of AOP -with transactional metadata yields an AOP proxy that uses a `TransactionInterceptor` in -conjunction with an appropriate `PlatformTransactionManager` implementation to drive -transactions __around method invocations__. - -[NOTE] -==== -Spring AOP is covered in <>. -==== - -Conceptually, calling a method on a transactional proxy looks like this... - -image::images/tx.png[width=400] - - - -[[transaction-declarative-first-example]] -==== Example of declarative transaction implementation -Consider the following interface, and its attendant implementation. This example uses -`Foo` and `Bar` classes as placeholders so that you can concentrate on the transaction -usage without focusing on a particular domain model. For the purposes of this example, -the fact that the `DefaultFooService` class throws `UnsupportedOperationException` -instances in the body of each implemented method is good; it allows you to see -transactions created and then rolled back in response to the -`UnsupportedOperationException` instance. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - // the service interface that we want to make transactional - - package x.y.service; - - public interface FooService { - - Foo getFoo(String fooName); - - Foo getFoo(String fooName, String barName); - - void insertFoo(Foo foo); - - void updateFoo(Foo foo); - - } ----- - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - // an implementation of the above interface - - package x.y.service; - - public class DefaultFooService implements FooService { - - public Foo getFoo(String fooName) { - throw new UnsupportedOperationException(); - } - - public Foo getFoo(String fooName, String barName) { - throw new UnsupportedOperationException(); - } - - public void insertFoo(Foo foo) { - throw new UnsupportedOperationException(); - } - - public void updateFoo(Foo foo) { - throw new UnsupportedOperationException(); - } - - } ----- - -Assume that the first two methods of the `FooService` interface, `getFoo(String)` and -`getFoo(String, String)`, must execute in the context of a transaction with read-only -semantics, and that the other methods, `insertFoo(Foo)` and `updateFoo(Foo)`, must -execute in the context of a transaction with read-write semantics. The following -configuration is explained in detail in the next few paragraphs. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ----- - -Examine the preceding configuration. You want to make a service object, the `fooService` -bean, transactional. The transaction semantics to apply are encapsulated in the -`` definition. The `` definition reads as "__... all methods on -starting with `'get'` are to execute in the context of a read-only transaction, and all -other methods are to execute with the default transaction semantics__". The -`transaction-manager` attribute of the `` tag is set to the name of the -`PlatformTransactionManager` bean that is going to __drive__ the transactions, in this -case, the `txManager` bean. - -[TIP] -==== - -You can omit the `transaction-manager` attribute in the transactional advice ( -``) if the bean name of the `PlatformTransactionManager` that you want to -wire in has the name `transactionManager`. If the `PlatformTransactionManager` bean that -you want to wire in has any other name, then you must use the `transaction-manager` -attribute explicitly, as in the preceding example. -==== - -The `` definition ensures that the transactional advice defined by the -`txAdvice` bean executes at the appropriate points in the program. First you define a -pointcut that matches the execution of any operation defined in the `FooService` -interface ( `fooServiceOperation`). Then you associate the pointcut with the `txAdvice` -using an advisor. The result indicates that at the execution of a `fooServiceOperation`, -the advice defined by `txAdvice` will be run. - -The expression defined within the `` element is an AspectJ pointcut -expression; see <> for more details on pointcut expressions in Spring. - -A common requirement is to make an entire service layer transactional. The best way to -do this is simply to change the pointcut expression to match any operation in your -service layer. For example: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - ----- - -[NOTE] -==== -__In this example it is assumed that all your service interfaces are defined in the -`x.y.service` package; see <> for more details.__ -==== - -Now that we've analyzed the configuration, you may be asking yourself, "__Okay... but -what does all this configuration actually do?__". - -The above configuration will be used to create a transactional proxy around the object -that is created from the `fooService` bean definition. The proxy will be configured with -the transactional advice, so that when an appropriate method is invoked __on the -proxy__, a transaction is started, suspended, marked as read-only, and so on, depending -on the transaction configuration associated with that method. Consider the following -program that test drives the above configuration: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public final class Boot { - - public static void main(final String[] args) throws Exception { - ApplicationContext ctx = new ClassPathXmlApplicationContext("context.xml", Boot.class); - FooService fooService = (FooService) ctx.getBean("fooService"); - fooService.insertFoo (new Foo()); - } - } ----- - -The output from running the preceding program will resemble the following. (The Log4J -output and the stack trace from the UnsupportedOperationException thrown by the -insertFoo(..) method of the DefaultFooService class have been truncated for clarity.) - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - [AspectJInvocationContextExposingAdvisorAutoProxyCreator] - Creating implicit proxy for bean 'fooService' with 0 common interceptors and 1 specific interceptors - - - [JdkDynamicAopProxy] - Creating JDK dynamic proxy for [x.y.service.DefaultFooService] - - - [TransactionInterceptor] - Getting transaction for x.y.service.FooService.insertFoo - - - [DataSourceTransactionManager] - Creating new transaction with name [x.y.service.FooService.insertFoo] - [DataSourceTransactionManager] - Acquired Connection [org.apache.commons.dbcp.PoolableConnection@a53de4] for JDBC transaction - - - [RuleBasedTransactionAttribute] - Applying rules to determine whether transaction should rollback on java.lang.UnsupportedOperationException - [TransactionInterceptor] - Invoking rollback for transaction on x.y.service.FooService.insertFoo due to throwable [java.lang.UnsupportedOperationException] - - - [DataSourceTransactionManager] - Rolling back JDBC transaction on Connection [org.apache.commons.dbcp.PoolableConnection@a53de4] - [DataSourceTransactionManager] - Releasing JDBC Connection after transaction - [DataSourceUtils] - Returning JDBC Connection to DataSource - - Exception in thread "main" java.lang.UnsupportedOperationException at x.y.service.DefaultFooService.insertFoo(DefaultFooService.java:14) - - at $Proxy0.insertFoo(Unknown Source) - at Boot.main(Boot.java:11) ----- - - - -[[transaction-declarative-rolling-back]] -==== Rolling back a declarative transaction -The previous section outlined the basics of how to specify transactional settings for -classes, typically service layer classes, declaratively in your application. This -section describes how you can control the rollback of transactions in a simple -declarative fashion. - -The recommended way to indicate to the Spring Framework's transaction infrastructure -that a transaction's work is to be rolled back is to throw an `Exception` from code that -is currently executing in the context of a transaction. The Spring Framework's -transaction infrastructure code will catch any unhandled `Exception` as it bubbles up -the call stack, and make a determination whether to mark the transaction for rollback. - -In its default configuration, the Spring Framework's transaction infrastructure code -__only__ marks a transaction for rollback in the case of runtime, unchecked exceptions; -that is, when the thrown exception is an instance or subclass of `RuntimeException`. ( -++Error++s will also - by default - result in a rollback). Checked exceptions that are -thrown from a transactional method do __not__ result in rollback in the default -configuration. - -You can configure exactly which `Exception` types mark a transaction for rollback, -including checked exceptions. The following XML snippet demonstrates how you configure -rollback for a checked, application-specific `Exception` type. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - ----- - -You can also specify 'no rollback rules', if you do __not__ want a transaction rolled -back when an exception is thrown. The following example tells the Spring Framework's -transaction infrastructure to commit the attendant transaction even in the face of an -unhandled `InstrumentNotFoundException`. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - ----- - -When the Spring Framework's transaction infrastructure catches an exception and is -consults configured rollback rules to determine whether to mark the transaction for -rollback, the __strongest__ matching rule wins. So in the case of the following -configuration, any exception other than an `InstrumentNotFoundException` results in a -rollback of the attendant transaction. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - ----- - -You can also indicate a required rollback __programmatically__. Although very simple, -this process is quite invasive, and tightly couples your code to the Spring Framework's -transaction infrastructure: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public void resolvePosition() { - try { - // some business logic... - } catch (NoProductInStockException ex) { - // trigger rollback programmatically - TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); - } - } ----- - -You are strongly encouraged to use the declarative approach to rollback if at all -possible. Programmatic rollback is available should you absolutely need it, but its -usage flies in the face of achieving a clean POJO-based architecture. - - - -[[transaction-declarative-diff-tx]] -==== Configuring different transactional semantics for different beans -Consider the scenario where you have a number of service layer objects, and you want to -apply a __totally different__ transactional configuration to each of them. You do this -by defining distinct `` elements with differing `pointcut` and -`advice-ref` attribute values. - -As a point of comparison, first assume that all of your service layer classes are -defined in a root `x.y.service` package. To make all beans that are instances of classes -defined in that package (or in subpackages) and that have names ending in `Service` have -the default transactional configuration, you would write the following: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ----- - -The following example shows how to configure two distinct beans with totally different -transactional settings. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ----- - - - -[[transaction-declarative-txadvice-settings]] -==== settings - -This section summarizes the various transactional settings that can be specified using -the `` tag. The default `` settings are: - -* <> is `REQUIRED.` -* Isolation level is `DEFAULT.` -* Transaction is read/write. -* Transaction timeout defaults to the default timeout of the underlying transaction - system, or none if timeouts are not supported. -* Any `RuntimeException` triggers rollback, and any checked `Exception` does not. - -You can change these default settings; the various attributes of the `` tags -that are nested within `` and `` tags are summarized below: - -[[tx-method-settings]] -. settings -|=== -| Attribute| Required?| Default| Description - -| `name` -| Yes -| -| Method name(s) with which the transaction attributes are to be associated. The - wildcard (*) character can be used to associate the same transaction attribute - settings with a number of methods; for example, `get*`, `handle*`, `on*Event`, and so - forth. - -| `propagation` -| No -| REQUIRED -| Transaction propagation behavior. - -| `isolation` -| No -| DEFAULT -| Transaction isolation level. - -| `timeout` -| No -| -1 -| Transaction timeout value (in seconds). - -| `read-only` -| No -| false -| Is this transaction read-only? - -| `rollback-for` -| No -| -| `Exception(s)` that trigger rollback; comma-delimited. For example, - `com.foo.MyBusinessException,ServletException.` - -| `no-rollback-for` -| No -| -| `Exception(s)` that do __not__ trigger rollback; comma-delimited. For example, - `com.foo.MyBusinessException,ServletException.` -|=== - - - -[[transaction-declarative-annotations]] -==== Using @Transactional - -In addition to the XML-based declarative approach to transaction configuration, you can -use an annotation-based approach. Declaring transaction semantics directly in the Java -source code puts the declarations much closer to the affected code. There is not much -danger of undue coupling, because code that is meant to be used transactionally is -almost always deployed that way anyway. - -The ease-of-use afforded by the use of the `@Transactional` annotation is best -illustrated with an example, which is explained in the text that follows. Consider the -following class definition: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - // the service class that we want to make transactional - **@Transactional** - public class DefaultFooService implements FooService { - - Foo getFoo(String fooName); - - Foo getFoo(String fooName, String barName); - - void insertFoo(Foo foo); - - void updateFoo(Foo foo); - } ----- - -When the above POJO is defined as a bean in a Spring IoC container, the bean instance -can be made transactional by adding merely __one__ line of XML configuration: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - - ____ - - - - - - - - ----- - -[TIP] -==== -You can omit the `transaction-manager` attribute in the `` tag if -the bean name of the `PlatformTransactionManager` that you want to wire in has the name -`transactionManager`. If the `PlatformTransactionManager` bean that you want to -dependency-inject has any other name, then you have to use the `transaction-manager` -attribute explicitly, as in the preceding example. -==== - -[NOTE] -==== -The `@EnableTransactionManagement` annotation provides equivalent support if you are -using Java based configuration. Simply add the annotation to a `@Configuration` class. -See the javadocs for full details. -==== - -.Method visibility and @Transactional -**** -When using proxies, you should apply the `@Transactional` annotation only to methods -with __public__ visibility. If you do annotate protected, private or package-visible -methods with the `@Transactional` annotation, no error is raised, but the annotated -method does not exhibit the configured transactional settings. Consider the use of -AspectJ (see below) if you need to annotate non-public methods. -**** - -You can place the `@Transactional` annotation before an interface definition, a method -on an interface, a class definition, or a __public__ method on a class. However, the -mere presence of the `@Transactional` annotation is not enough to activate the -transactional behavior. The `@Transactional` annotation is simply metadata that can be -consumed by some runtime infrastructure that is `@Transactional`-aware and that can use -the metadata to configure the appropriate beans with transactional behavior. In the -preceding example, the `` element __switches on__ the -transactional behavior. - -[TIP] -==== - -Spring recommends that you only annotate concrete classes (and methods of concrete -classes) with the `@Transactional` annotation, as opposed to annotating interfaces. You -certainly can place the `@Transactional` annotation on an interface (or an interface -method), but this works only as you would expect it to if you are using interface-based -proxies. The fact that Java annotations are __not inherited from interfaces__ means that -if you are using class-based proxies ( `proxy-target-class="true"`) or the weaving-based -aspect ( `mode="aspectj"`), then the transaction settings are not recognized by the -proxying and weaving infrastructure, and the object will not be wrapped in a -transactional proxy, which would be decidedly __bad__. -==== - -[NOTE] -==== -In proxy mode (which is the default), only external method calls coming in through the -proxy are intercepted. This means that self-invocation, in effect, a method within the -target object calling another method of the target object, will not lead to an actual -transaction at runtime even if the invoked method is marked with `@Transactional`. -==== - -Consider the use of AspectJ mode (see mode attribute in table below) if you expect -self-invocations to be wrapped with transactions as well. In this case, there will not -be a proxy in the first place; instead, the target class will be weaved (that is, its -byte code will be modified) in order to turn `@Transactional` into runtime behavior on -any kind of method. - -[[tx-annotation-driven-settings]] -.Annotation driven transaction settings -|=== -| XML Attribute| Annotation Attribute| Default| Description - -| `transaction-manager` -| N/A (See `TransactionManagementConfigurer` javadocs) -| transactionManager -| Name of transaction manager to use. Only required if the name of the transaction - manager is not `transactionManager`, as in the example above. - -| `mode` -| `mode` -| proxy -| The default mode "proxy" processes annotated beans to be proxied using Spring's AOP - framework (following proxy semantics, as discussed above, applying to method calls - coming in through the proxy only). The alternative mode "aspectj" instead weaves the - affected classes with Spring's AspectJ transaction aspect, modifying the target class - byte code to apply to any kind of method call. AspectJ weaving requires - spring-aspects.jar in the classpath as well as load-time weaving (or compile-time - weaving) enabled. (See <> for details on how to set up load-time - weaving.) - -| `proxy-target-class` -| `proxyTargetClass` -| false -| Applies to proxy mode only. Controls what type of transactional proxies are created - for classes annotated with the `@Transactional` annotation. If the - `proxy-target-class` attribute is set to `true`, then class-based proxies are created. - If `proxy-target-class` is `false` or if the attribute is omitted, then standard JDK - interface-based proxies are created. (See <> for a detailed examination - of the different proxy types.) - -| `order` -| `order` -| Ordered.LOWEST_PRECEDENCE -| Defines the order of the transaction advice that is applied to beans annotated with - `@Transactional`. (For more information about the rules related to ordering of AOP - advice, see <>.) No specified ordering means that the - AOP subsystem determines the order of the advice. -|=== - -[NOTE] -==== -The `proxy-target-class` attribute controls what type of transactional proxies are -created for classes annotated with the `@Transactional` annotation. If -`proxy-target-class` is set to `true`, class-based proxies are created. If -`proxy-target-class` is `false` or if the attribute is omitted, standard JDK -interface-based proxies are created. (See <> for a discussion of the -different proxy types.) -==== - -[NOTE] -==== -`@EnableTransactionManagement` and `` only looks for -`@Transactional` on beans in the same application context they are defined in. This -means that, if you put annotation driven configuration in a `WebApplicationContext` for -a `DispatcherServlet`, it only checks for `@Transactional` beans in your controllers, -and not your services. See <> for more information. -==== - -The most derived location takes precedence when evaluating the transactional settings -for a method. In the case of the following example, the `DefaultFooService` class is -annotated at the class level with the settings for a read-only transaction, but the -`@Transactional` annotation on the `updateFoo(Foo)` method in the same class takes -precedence over the transactional settings defined at the class level. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Transactional(readOnly = true) - public class DefaultFooService implements FooService { - - public Foo getFoo(String fooName) { - // do something - } - - // these settings have precedence for this method - @Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW) - public void updateFoo(Foo foo) { - // do something - } - } ----- - - -[[transaction-declarative-attransactional-settings]] -===== @Transactional settings - -The `@Transactional` annotation is metadata that specifies that an interface, class, or -method must have transactional semantics; for example, "__start a brand new read-only -transaction when this method is invoked, suspending any existing transaction__". The -default `@Transactional` settings are as follows: - -* Propagation setting is `PROPAGATION_REQUIRED.` -* Isolation level is `ISOLATION_DEFAULT.` -* Transaction is read/write. -* Transaction timeout defaults to the default timeout of the underlying transaction - system, or to none if timeouts are not supported. -* Any `RuntimeException` triggers rollback, and any checked `Exception` does not. - -These default settings can be changed; the various properties of the `@Transactional` -annotation are summarized in the following table: - -[[tx-attransactional-properties]] -.@ -|=== -| Property| Type| Description - -| <> -| String -| Optional qualifier specifying the transaction manager to be used. - -| <> -| enum: `Propagation` -| Optional propagation setting. - -| `isolation` -| enum: `Isolation` -| Optional isolation level. - -| `readOnly` -| boolean -| Read/write vs. read-only transaction - -| `timeout` -| int (in seconds granularity) -| Transaction timeout. - -| `rollbackFor` -| Array of `Class` objects, which must be derived from `Throwable.` -| Optional array of exception classes that __must__ cause rollback. - -| `rollbackForClassName` -| Array of class names. Classes must be derived from `Throwable.` -| Optional array of names of exception classes that __must__ cause rollback. - -| `noRollbackFor` -| Array of `Class` objects, which must be derived from `Throwable.` -| Optional array of exception classes that __must not__ cause rollback. - -| `noRollbackForClassName` -| Array of `String` class names, which must be derived from `Throwable.` -| Optional array of names of exception classes that __must not__ cause rollback. -|=== - -Currently you cannot have explicit control over the name of a transaction, where 'name' -means the transaction name that will be shown in a transaction monitor, if applicable -(for example, WebLogic's transaction monitor), and in logging output. For declarative -transactions, the transaction name is always the fully-qualified class name + "." -+ method name of the transactionally-advised class. For example, if the -`handlePayment(..)` method of the `BusinessService` class started a transaction, the -name of the transaction would be: `com.foo.BusinessService.handlePayment`. - - -[[tx-multiple-tx-mgrs-with-attransactional]] -===== Multiple Transaction Managers with @Transactional -Most Spring applications only need a single transaction manager, but there may be -situations where you want multiple independent transaction managers in a single -application. The value attribute of the `@Transactional` annotation can be used to -optionally specify the identity of the `PlatformTransactionManager` to be used. This can -either be the bean name or the qualifier value of the transaction manager bean. For -example, using the qualifier notation, the following Java code - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class TransactionalService { - - @Transactional("order") - public void setSomething(String name) { ... } - - @Transactional("account") - public void doSomething() { ... } - } ----- - -could be combined with the following transaction manager bean declarations in the -application context. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - ... - - - - - ... - - ----- - -In this case, the two methods on `TransactionalService` will run under separate -transaction managers, differentiated by the "order" and "account" qualifiers. The -default `` target bean name `transactionManager` will still be -used if no specifically qualified PlatformTransactionManager bean is found. - - -[[tx-custom-attributes]] -===== Custom shortcut annotations -If you find you are repeatedly using the same attributes with `@Transactional` on many -different methods, then <> allows -you to define custom shortcut annotations for your specific use cases. For example, -defining the following annotations - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Target({ElementType.METHOD, ElementType.TYPE}) - @Retention(RetentionPolicy.RUNTIME) - @Transactional("order") - public @interface OrderTx { - } - - @Target({ElementType.METHOD, ElementType.TYPE}) - @Retention(RetentionPolicy.RUNTIME) - @Transactional("account") - public @interface AccountTx { - } ----- - -allows us to write the example from the previous section as - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class TransactionalService { - - @OrderTx - public void setSomething(String name) { ... } - - @AccountTx - public void doSomething() { ... } - } ----- - -Here we have used the syntax to define the transaction manager qualifier, but could also -have included propagation behavior, rollback rules, timeouts etc. - - - -[[tx-propagation]] -==== Transaction propagation -This section describes some semantics of transaction propagation in Spring. Please note -that this section is not an introduction to transaction propagation proper; rather it -details some of the semantics regarding transaction propagation in Spring. - -In Spring-managed transactions, be aware of the difference between __physical__ and -__logical__ transactions, and how the propagation setting applies to this difference. - - -[[tx-propagation-required]] -===== Required -image::images/tx_prop_required.png[width=400] - -PROPAGATION_REQUIRED - -When the propagation setting is `PROPAGATION_REQUIRED`, a __logical__ transaction scope -is created for each method upon which the setting is applied. Each such logical -transaction scope can determine rollback-only status individually, with an outer -transaction scope being logically independent from the inner transaction scope. Of -course, in case of standard `PROPAGATION_REQUIRED` behavior, all these scopes will be -mapped to the same physical transaction. So a rollback-only marker set in the inner -transaction scope does affect the outer transaction's chance to actually commit (as you -would expect it to). - -However, in the case where an inner transaction scope sets the rollback-only marker, the -outer transaction has not decided on the rollback itself, and so the rollback (silently -triggered by the inner transaction scope) is unexpected. A corresponding -`UnexpectedRollbackException` is thrown at that point. This is __expected behavior__ so -that the caller of a transaction can never be misled to assume that a commit was -performed when it really was not. So if an inner transaction (of which the outer caller -is not aware) silently marks a transaction as rollback-only, the outer caller still -calls commit. The outer caller needs to receive an `UnexpectedRollbackException` to -indicate clearly that a rollback was performed instead. - - -[[tx-propagation-requires_new]] -===== RequiresNew -image::images/tx_prop_requires_new.png[width=400] - -PROPAGATION_REQUIRES_NEW - -`PROPAGATION_REQUIRES_NEW`, in contrast to `PROPAGATION_REQUIRED`, uses a __completely__ -independent transaction for each affected transaction scope. In that case, the -underlying physical transactions are different and hence can commit or roll back -independently, with an outer transaction not affected by an inner transaction's rollback -status. - - -[[tx-propagation-nested]] -===== Nested -`PROPAGATION_NESTED` uses a __single__ physical transaction with multiple savepoints -that it can roll back to. Such partial rollbacks allow an inner transaction scope to -trigger a rollback __for its scope__, with the outer transaction being able to continue -the physical transaction despite some operations having been rolled back. This setting -is typically mapped onto JDBC savepoints, so will only work with JDBC resource -transactions. See Spring's `DataSourceTransactionManager`. - - - -[[transaction-declarative-applying-more-than-just-tx-advice]] -==== Advising transactional operations -Suppose you want to execute __both__ transactional __and__ some basic profiling advice. -How do you effect this in the context of ``? - -When you invoke the `updateFoo(Foo)` method, you want to see the following actions: - -* Configured profiling aspect starts up. -* Transactional advice executes. -* Method on the advised object executes. -* Transaction commits. -* Profiling aspect reports exact duration of the whole transactional method invocation. - -[NOTE] -==== -This chapter is not concerned with explaining AOP in any great detail (except as it -applies to transactions). See <> for detailed coverage of the following AOP -configuration and AOP in general. -==== - -Here is the code for a simple profiling aspect discussed above. The ordering of advice -is controlled through the `Ordered` interface. For full details on advice ordering, see -<>. -. -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - package x.y; - - import org.aspectj.lang.ProceedingJoinPoint; - import org.springframework.util.StopWatch; - import org.springframework.core.Ordered; - - public class SimpleProfiler implements Ordered { - - private int order; - - // allows us to control the ordering of advice - public int getOrder() { - return this.order; - } - - public void setOrder(int order) { - this.order = order; - } - - // this method *is* the around advice - public Object profile(ProceedingJoinPoint call) throws Throwable { - Object returnValue; - StopWatch clock = new StopWatch(getClass().getName()); - try { - clock.start(call.toShortString()); - returnValue = call.proceed(); - } finally { - clock.stop(); - System.out.println(clock.prettyPrint()); - } - return returnValue; - } - } ----- - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ----- - -The result of the above configuration is a `fooService` bean that has profiling and -transactional aspects applied to it __in the desired order__. You configure any number -of additional aspects in similar fashion. - -The following example effects the same setup as above, but uses the purely XML -declarative approach. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - - __ - - - - - - - - - - - - - - - - - - - - - - - - - - ----- - -The result of the above configuration will be a `fooService` bean that has profiling and -transactional aspects applied to it __in that order__. If you want the profiling advice -to execute __after__ the transactional advice on the way in, and __before__ the -transactional advice on the way out, then you simply swap the value of the profiling -aspect bean's `order` property so that it is higher than the transactional advice's -order value. - -You configure additional aspects in similar fashion. - - - -[[transaction-declarative-aspectj]] -==== Using @Transactional with AspectJ - -It is also possible to use the Spring Framework's `@Transactional` support outside of a -Spring container by means of an AspectJ aspect. To do so, you first annotate your -classes (and optionally your classes' methods) with the `@Transactional` annotation, and -then you link (weave) your application with the -`org.springframework.transaction.aspectj.AnnotationTransactionAspect` defined in the -`spring-aspects.jar` file. The aspect must also be configured with a transaction -manager. You can of course use the Spring Framework's IoC container to take care of -dependency-injecting the aspect. The simplest way to configure the transaction -management aspect is to use the `` element and specify the `mode` -attribute to `aspectj` as described in <>. Because -we're focusing here on applications running outside of a Spring container, we'll show -you how to do it programmatically. - -[NOTE] -==== -Prior to continuing, you may want to read <> and -<> respectively. -==== - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - // construct an appropriate transaction manager - DataSourceTransactionManager txManager = new DataSourceTransactionManager(getDataSource()); - - // configure the AnnotationTransactionAspect to use it; this must be done before executing any transactional methods - AnnotationTransactionAspect.aspectOf().setTransactionManager(txManager); ----- - -[NOTE] -==== -When using this aspect, you must annotate the __implementation__ class (and/or methods -within that class), __not__ the interface (if any) that the class implements. AspectJ -follows Java's rule that annotations on interfaces are __not inherited__. -==== - -The `@Transactional` annotation on a class specifies the default transaction semantics -for the execution of any method in the class. - -The `@Transactional` annotation on a method within the class overrides the default -transaction semantics given by the class annotation (if present). Any method may be -annotated, regardless of visibility. - -To weave your applications with the `AnnotationTransactionAspect` you must either build -your application with AspectJ (see the -http://www.eclipse.org/aspectj/doc/released/devguide/index.html[AspectJ Development -Guide]) or use load-time weaving. See <> for a discussion of load-time -weaving with AspectJ. - - - - -[[transaction-programmatic]] -=== Programmatic transaction management -The Spring Framework provides two means of programmatic transaction management: - -* Using the `TransactionTemplate`. -* Using a `PlatformTransactionManager` implementation directly. - -The Spring team generally recommends the `TransactionTemplate` for programmatic -transaction management. The second approach is similar to using the JTA -`UserTransaction` API, although exception handling is less cumbersome. - - - -[[tx-prog-template]] -==== Using the TransactionTemplate - -The `TransactionTemplate` adopts the same approach as other Spring __templates__ such as -the `JdbcTemplate`. It uses a callback approach, to free application code from having to -do the boilerplate acquisition and release of transactional resources, and results in -code that is intention driven, in that the code that is written focuses solely on what -the developer wants to do. - -[NOTE] -==== -As you will see in the examples that follow, using the `TransactionTemplate` absolutely -couples you to Spring's transaction infrastructure and APIs. Whether or not programmatic -transaction management is suitable for your development needs is a decision that you -will have to make yourself. -==== - -Application code that must execute in a transactional context, and that will use the -`TransactionTemplate` explicitly, looks like the following. You, as an application -developer, write a `TransactionCallback` implementation (typically expressed as an -anonymous inner class) that contains the code that you need to execute in the context of -a transaction. You then pass an instance of your custom `TransactionCallback` to the -`execute(..)` method exposed on the `TransactionTemplate`. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class SimpleService implements Service { - - // single TransactionTemplate shared amongst all methods in this instance - private final TransactionTemplate transactionTemplate; - - // use constructor-injection to supply the PlatformTransactionManager - public SimpleService(PlatformTransactionManager transactionManager) { - Assert.notNull(transactionManager, "The 'transactionManager' argument must not be null."); - this.transactionTemplate = new TransactionTemplate(transactionManager); - } - - public Object someServiceMethod() { - return transactionTemplate.execute(new TransactionCallback() { - // the code in this method executes in a transactional context - public Object doInTransaction(TransactionStatus status) { - updateOperation1(); - return resultOfUpdateOperation2(); - } - }); - } - } ----- - -If there is no return value, use the convenient `TransactionCallbackWithoutResult` class -with an anonymous class as follows: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - transactionTemplate.execute(new **TransactionCallbackWithoutResult**() { - protected void doInTransactionWithoutResult(TransactionStatus status) { - updateOperation1(); - updateOperation2(); - } - }); ----- - -Code within the callback can roll the transaction back by calling the -`setRollbackOnly()` method on the supplied `TransactionStatus` object: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - transactionTemplate.execute(new TransactionCallbackWithoutResult() { - - protected void doInTransactionWithoutResult(TransactionStatus status) { - try { - updateOperation1(); - updateOperation2(); - } catch (SomeBusinessExeption ex) { - **status.setRollbackOnly();** - } - } - }); ----- - - -[[tx-prog-template-settings]] -===== Specifying transaction settings -You can specify transaction settings such as the propagation mode, the isolation level, -the timeout, and so forth on the `TransactionTemplate` either programmatically or in -configuration. `TransactionTemplate` instances by default have the -<>. The -following example shows the programmatic customization of the transactional settings for -a specific `TransactionTemplate:` - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class SimpleService implements Service { - - private final TransactionTemplate transactionTemplate; - - public SimpleService(PlatformTransactionManager transactionManager) { - Assert.notNull(transactionManager, "The 'transactionManager' argument must not be null."); - this.transactionTemplate = new TransactionTemplate(transactionManager); - - // the transaction settings can be set here explicitly if so desired - this.transactionTemplate.setIsolationLevel(TransactionDefinition.ISOLATION_READ_UNCOMMITTED); - this.transactionTemplate.setTimeout(30); // 30 seconds - // and so forth... - } - } ----- - -The following example defines a `TransactionTemplate` with some custom transactional -settings, using Spring XML configuration. The `sharedTransactionTemplate` can then be -injected into as many services as are required. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - " ----- - -Finally, instances of the `TransactionTemplate` class are threadsafe, in that instances -do not maintain any conversational state. `TransactionTemplate` instances __do__ however -maintain configuration state, so while a number of classes may share a single instance -of a `TransactionTemplate`, if a class needs to use a `TransactionTemplate` with -different settings (for example, a different isolation level), then you need to create -two distinct `TransactionTemplate` instances. - - - -[[transaction-programmatic-ptm]] -==== Using the PlatformTransactionManager - -You can also use the `org.springframework.transaction.PlatformTransactionManager` -directly to manage your transaction. Simply pass the implementation of the -`PlatformTransactionManager` you are using to your bean through a bean reference. Then, -using the `TransactionDefinition` and `TransactionStatus` objects you can initiate -transactions, roll back, and commit. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - DefaultTransactionDefinition def = new DefaultTransactionDefinition(); - // explicitly setting the transaction name is something that can only be done programmatically - def.setName("SomeTxName"); - def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED); - - TransactionStatus status = txManager.getTransaction(def); - try { - // execute your business logic here - } - catch (MyException ex) { - txManager.rollback(status); - throw ex; - } - txManager.commit(status); ----- - - - - -[[tx-decl-vs-prog]] -=== Choosing between programmatic and declarative transaction management -Programmatic transaction management is usually a good idea only if you have a small -number of transactional operations. For example, if you have a web application that -require transactions only for certain update operations, you may not want to set up -transactional proxies using Spring or any other technology. In this case, using the -`TransactionTemplate` __may__ be a good approach. Being able to set the transaction name -explicitly is also something that can only be done using the programmatic approach to -transaction management. - -On the other hand, if your application has numerous transactional operations, -declarative transaction management is usually worthwhile. It keeps transaction -management out of business logic, and is not difficult to configure. When using the -Spring Framework, rather than EJB CMT, the configuration cost of declarative transaction -management is greatly reduced. - - - - -[[transaction-application-server-integration]] -=== Application server-specific integration -Spring's transaction abstraction generally is application server agnostic. Additionally, -Spring's `JtaTransactionManager` class, which can optionally perform a JNDI lookup for -the JTA `UserTransaction` and `TransactionManager` objects, autodetects the location for -the latter object, which varies by application server. Having access to the JTA -`TransactionManager` allows for enhanced transaction semantics, in particular supporting -transaction suspension. See the `JtaTransactionManager` javadocs for details. - -Spring's `JtaTransactionManager` is the standard choice to run on Java EE application -servers, and is known to work on all common servers. Advanced functionality such as -transaction suspension works on many servers as well -- including GlassFish, JBoss and -Geronimo -- without any special configuration required. However, for fully supported -transaction suspension and further advanced integration, Spring ships special adapters -for WebLogic Server and WebSphere. These adapters are discussed in the following -sections. - -__For standard scenarios, including WebLogic Server and WebSphere, consider using the -convenient `` configuration element.__ When configured, -this element automatically detects the underlying server and chooses the best -transaction manager available for the platform. This means that you won't have to -configure server-specific adapter classes (as discussed in the following sections) -explicitly; rather, they are chosen automatically, with the standard -`JtaTransactionManager` as default fallback. - - - -[[transaction-application-server-integration-websphere]] -==== IBM WebSphere -On WebSphere 6.1.0.9 and above, the recommended Spring JTA transaction manager to use is -`WebSphereUowTransactionManager`. This special adapter leverages IBM's `UOWManager` API, -which is available in WebSphere Application Server 6.0.2.19 and later and 6.1.0.9 and -later. With this adapter, Spring-driven transaction suspension (suspend/resume as -initiated by `PROPAGATION_REQUIRES_NEW`) is officially supported by IBM! - - - -[[transaction-application-server-integration-weblogic]] -==== Oracle WebLogic Server -On WebLogic Server 9.0 or above, you typically would use the -`WebLogicJtaTransactionManager` instead of the stock `JtaTransactionManager` class. This -special WebLogic-specific subclass of the normal `JtaTransactionManager` supports the -full power of Spring's transaction definitions in a WebLogic-managed transaction -environment, beyond standard JTA semantics: Features include transaction names, -per-transaction isolation levels, and proper resuming of transactions in all cases. - - - - -[[transaction-solutions-to-common-problems]] -=== Solutions to common problems - - - -[[transaction-solutions-to-common-problems-wrong-ptm]] -==== Use of the wrong transaction manager for a specific DataSource - -Use the __correct__ `PlatformTransactionManager` implementation based on your choice of -transactional technologies and requirements. Used properly, the Spring Framework merely -provides a straightforward and portable abstraction. If you are using global -transactions, you __must__ use the -`org.springframework.transaction.jta.JtaTransactionManager` class (or an -<> of -it) for all your transactional operations. Otherwise the transaction infrastructure -attempts to perform local transactions on resources such as container `DataSource` -instances. Such local transactions do not make sense, and a good application server -treats them as errors. - - - - -[[transaction-resources]] -=== Further Resources -For more information about the Spring Framework's transaction support: - -* http://www.javaworld.com/javaworld/jw-01-2009/jw-01-spring-transactions.html[Distributed - transactions in Spring, with and without XA] is a JavaWorld presentation in which - Spring's David Syer guides you through seven patterns for distributed - transactions in Spring applications, three of them with XA and four without. -* http://www.infoq.com/minibooks/JTDS[Java Transaction Design Strategies] is a book - available from http://www.infoq.com/[InfoQ] that provides a well-paced introduction - to transactions in Java. It also includes side-by-side examples of how to configure - and use transactions with both the Spring Framework and EJB3. - - - - - -[[dao]] -== DAO support - - - - -[[dao-introduction]] -=== Introduction -The Data Access Object (DAO) support in Spring is aimed at making it easy to work with -data access technologies like JDBC, Hibernate, JPA or JDO in a consistent way. This -allows one to switch between the aforementioned persistence technologies fairly easily -and it also allows one to code without worrying about catching exceptions that are -specific to each technology. - - - - -[[dao-exceptions]] -=== Consistent exception hierarchy -Spring provides a convenient translation from technology-specific exceptions like -`SQLException` to its own exception class hierarchy with the `DataAccessException` as -the root exception. These exceptions wrap the original exception so there is never any -risk that one might lose any information as to what might have gone wrong. - -In addition to JDBC exceptions, Spring can also wrap Hibernate-specific exceptions, -converting them from proprietary, checked exceptions (in the case of versions of -Hibernate prior to Hibernate 3.0), to a set of focused runtime exceptions (the same is -true for JDO and JPA exceptions). This allows one to handle most persistence exceptions, -which are non-recoverable, only in the appropriate layers, without having annoying -boilerplate catch-and-throw blocks and exception declarations in one's DAOs. (One can -still trap and handle exceptions anywhere one needs to though.) As mentioned above, JDBC -exceptions (including database-specific dialects) are also converted to the same -hierarchy, meaning that one can perform some operations with JDBC within a consistent -programming model. - -The above holds true for the various template classes in Springs support for various ORM -frameworks. If one uses the interceptor-based classes then the application must care -about handling `HibernateExceptions` and `JDOExceptions` itself, preferably via -delegating to `SessionFactoryUtils`' `convertHibernateAccessException(..)` or -`convertJdoAccessException()` methods respectively. These methods convert the exceptions -to ones that are compatible with the exceptions in the `org.springframework.dao` -exception hierarchy. As `JDOExceptions` are unchecked, they can simply get thrown too, -sacrificing generic DAO abstraction in terms of exceptions though. - -The exception hierarchy that Spring provides can be seen below. (Please note that the -class hierarchy detailed in the image shows only a subset of the entire -`DataAccessException` hierarchy.) - -image::images/DataAccessException.gif[width=400] - - - - -[[dao-annotations]] -=== Annotations used for configuring DAO or Repository classes -The best way to guarantee that your Data Access Objects (DAOs) or repositories provide -exception translation is to use the `@Repository` annotation. This annotation also -allows the component scanning support to find and configure your DAOs and repositories -without having to provide XML configuration entries for them. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - **@Repository** - public class SomeMovieFinder implements MovieFinder { - // ... - } ----- - -Any DAO or repository implementation will need to access to a persistence resource, -depending on the persistence technology used; for example, a JDBC-based repository will -need access to a JDBC `DataSource`; a JPA-based repository will need access to an -`EntityManager`. The easiest way to accomplish this is to have this resource dependency -injected using one of the `@Autowired,`, `@Inject`, `@Resource` or `@PersistenceContext` -annotations. Here is an example for a JPA repository: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Repository - public class JpaMovieFinder implements MovieFinder { - - @PersistenceContext - private EntityManager entityManager; - - // ... - - } ----- - -If you are using the classic Hibernate APIs than you can inject the SessionFactory: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Repository - public class HibernateMovieFinder implements MovieFinder { - - private SessionFactory sessionFactory; - - @Autowired - public void setSessionFactory(SessionFactory sessionFactory) { - this.sessionFactory = sessionFactory; - } - - // ... - - } ----- - -Last example we will show here is for typical JDBC support. You would have the -`DataSource` injected into an initialization method where you would create a -`JdbcTemplate` and other data access support classes like `SimpleJdbcCall` etc using -this `DataSource`. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Repository - public class JdbcMovieFinder implements MovieFinder { - - private JdbcTemplate jdbcTemplate; - - @Autowired - public void init(DataSource dataSource) { - this.jdbcTemplate = new JdbcTemplate(dataSource); - } - - // ... - - } ----- - -[NOTE] -==== -Please see the specific coverage of each persistence technology for details on how to -configure the application context to take advantage of these annotations. -==== - - - - - -[[jdbc]] -== Data access with JDBC - - - - -[[jdbc-introduction]] -=== Introduction to Spring Framework JDBC -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. - -[[jdbc-who-does-what]] -.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. - - - -[[jdbc-choose-style]] -==== Choosing an approach for JDBC database access -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. - - - -[[jdbc-packages]] -==== Package hierarchy -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. See <>, <>, and -<> - -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 in-memory database instances using Java database engines such as HSQL and H2. -See <> and <> - -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 of course objects returned by -queries are "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. See <>. - - - - -[[jdbc-core]] -=== Using the JDBC core classes to control basic JDBC processing and error handling - - - -[[jdbc-JdbcTemplate]] -==== JdbcTemplate - -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 ++ResultSet++s 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 `DataSource` should always be configured as a bean in the Spring IoC container. In -the first case the bean is given to the service directly; in the second case it is given -to the prepared template. -==== - -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). - - -[[jdbc-JdbcTemplate-examples]] -===== Examples of JdbcTemplate class usage -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. - -[[jdbc-JdbcTemplate-examples-query]] -====== Querying (SELECT) -Here is a simple query for getting the number of rows in a relation: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - int rowCount = this.jdbcTemplate.queryForObject("select count(*) from t_actor", Integer.class); ----- - -A simple query using a bind variable: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - int countOfActorsNamedJoe = this.jdbcTemplate.queryForObject( - "select count(*) from t_actor where first_name = ?", Integer.class, "Joe"); ----- - -Querying for a `String`: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - 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: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - Actor actor = this.jdbcTemplate.queryForObject( - "select first_name, last_name from t_actor where id = ?", - new Object[]{1212L}, - new RowMapper() { - 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: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - List actors = this.jdbcTemplate.query( - "select first_name, last_name from t_actor", - new RowMapper() { - 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` inner 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: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public List findAllActors() { - return this.jdbcTemplate.query( "select first_name, last_name from t_actor", new ActorMapper()); - } - - private static final class ActorMapper implements RowMapper { - - 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; - } - } ----- - -[[jdbc-JdbcTemplate-examples-update]] -====== Updating (INSERT/UPDATE/DELETE) with jdbcTemplate -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. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - this.jdbcTemplate.update( - "insert into t_actor (first_name, last_name) values (?, ?)", - "Leonor", "Watling"); ----- - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - this.jdbcTemplate.update( - "update t_actor set last_name = ? where id = ?", - "Banjo", 5276L); ----- - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - this.jdbcTemplate.update( - "delete from actor where id = ?", - Long.valueOf(actorId)); ----- - -[[jdbc-JdbcTemplate-examples-other]] -====== Other jdbcTemplate operations -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. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - 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 <>. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - this.jdbcTemplate.update( - "call SUPPORT.REFRESH_ACTORS_SUMMARY(?)", - Long.valueOf(unionId)); ----- - - -[[jdbc-JdbcTemplate-idioms]] -===== JdbcTemplate best practices - -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 -<> 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: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - 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. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - - - - - - - - - - ----- - -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`. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - **@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: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - - - - - - - - - ----- - -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`. - - - -[[jdbc-NamedParameterJdbcTemplate]] -==== NamedParameterJdbcTemplate - -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. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - // 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. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - // 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 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 http://www.oracle.com/technetwork/java/javase/documentation/spec-136004.html[the -JavaBean conventions]), and uses the properties of the wrapped JavaBean as the source -of named parameter values. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - 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... - - } ----- - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - // 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. - -See also <> for guidelines on using the -`NamedParameterJdbcTemplate` class in the context of an application. - - - -[[jdbc-SQLExceptionTranslator]] -==== SQLExceptionTranslator - -`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 `SQLErrorCodesFactory` is used by default to define Error codes and custom exception -translations. They are looked up in a file named `sql-error-codes.xml` from the -classpath and the matching `SQLErrorCodes` instance is located based on the database -name from the database metadata of the database in use. -==== -* 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 the `customSqlExceptionTranslator` property of the `SQLErrorCodes` class. -* The list of instances of the `CustomSQLErrorCodesTranslation` class, provided for the - `customTranslations` property of the `SQLErrorCodes` 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 - the `SQLStateSQLExceptionTranslator`. - -You can extend `SQLErrorCodeSQLExceptionTranslator:` - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - 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: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - 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`. - - - -[[jdbc-statements-executing]] -==== Executing statements -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: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - 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))"); - } - } ----- - - - -[[jdbc-statements-querying]] -==== Running queries -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`. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - 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: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - private JdbcTemplate jdbcTemplate; - - public void setDataSource(DataSource dataSource) { - this.jdbcTemplate = new JdbcTemplate(dataSource); - } - - public List> getList() { - return this.jdbcTemplate.queryForList("select * from mytable"); - } ----- - -The list returned would look something like this: - -[literal] -[subs="verbatim,quotes"] ----- -[{name=Bob, id=1}, {name=Mary, id=2}] ----- - - - -[[jdbc-updates]] -==== Updating the database -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. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - 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); - } - } ----- - - - -[[jdbc-auto-genereted-keys]] -==== Retrieving auto-generated keys -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: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - 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 ----- - - - - -[[jdbc-connections]] -=== Controlling database connections - - - -[[jdbc-datasource]] -==== DataSource - -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 `DriverManagerDataSource` class should only be used for testing purposes -since it does not provide pooling and will perform poorly when multiple requests for a -connection are made. -==== -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: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - 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: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - ----- - -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: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - ----- - -C3P0 configuration: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - ----- - - - -[[jdbc-DataSourceUtils]] -==== DataSourceUtils - -The `DataSourceUtils` class is a convenient and powerful helper class that provides -`static` methods to obtain connections from JNDI and close connections if necessary. It -supports thread-bound connections with, for example, `DataSourceTransactionManager`. - - - -[[jdbc-SmartDataSource]] -==== SmartDataSource - -The `SmartDataSource` interface should be implemented by classes that can provide a -connection to a relational database. It extends the `DataSource` interface to allow -classes using it to query whether the connection should be closed after a given -operation. This usage is efficient when you know that you will reuse a connection. - - - -[[jdbc-AbstractDataSource]] -==== AbstractDataSource - -`AbstractDataSource` is an `abstract` base class for Spring's `DataSource` -implementations that implements code that is common to all `DataSource` implementations. -You extend the `AbstractDataSource` class if you are writing your own `DataSource` -implementation. - - - -[[jdbc-SingleConnectionDataSource]] -==== SingleConnectionDataSource - -The `SingleConnectionDataSource` class is an implementation of the `SmartDataSource` -interface that wraps a __single__ `Connection` that is __not__ closed after each use. -Obviously, this is not multi-threading capable. - -If any client code calls `close` in the assumption of a pooled connection, as when using -persistence tools, set the `suppressClose` property to `true`. This setting returns a -close-suppressing proxy wrapping the physical connection. Be aware that you will not be -able to cast this to a native Oracle `Connection` or the like anymore. - -This is primarily a test class. For example, it enables easy testing of code outside an -application server, in conjunction with a simple JNDI environment. In contrast to -`DriverManagerDataSource`, it reuses the same connection all the time, avoiding -excessive creation of physical connections. - - - -[[jdbc-DriverManagerDataSource]] -==== DriverManagerDataSource - -The `DriverManagerDataSource` class is an implementation of the standard `DataSource` -interface that configures a plain JDBC driver through bean properties, and returns a new -`Connection` every time. - -This implementation is useful for test and stand-alone environments outside of a Java EE -container, either as a `DataSource` bean in a Spring IoC container, or in conjunction -with a simple JNDI environment. Pool-assuming `Connection.close()` calls will simply -close the connection, so any `DataSource`-aware persistence code should work. However, -using JavaBean-style connection pools such as `commons-dbcp` is so easy, even in a test -environment, that it is almost always preferable to use such a connection pool over -`DriverManagerDataSource`. - - - -[[jdbc-TransactionAwareDataSourceProxy]] -==== TransactionAwareDataSourceProxy - -`TransactionAwareDataSourceProxy` is a proxy for a target `DataSource`, which wraps that -target `DataSource` to add awareness of Spring-managed transactions. In this respect, it -is similar to a transactional JNDI `DataSource` as provided by a Java EE server. - -[NOTE] -==== -It is rarely desirable to use this class, except when already existing code that must be -called and passed a standard JDBC `DataSource` interface implementation. In this case, -it's possible to still have this code be usable, and at the same time have this code -participating in Spring managed transactions. It is generally preferable to write your -own new code using the higher level abstractions for resource management, such as -`JdbcTemplate` or `DataSourceUtils`. -==== - -__(See the `TransactionAwareDataSourceProxy` javadocs for more details.)__ - - - -[[jdbc-DataSourceTransactionManager]] -==== DataSourceTransactionManager - -The `DataSourceTransactionManager` class is a `PlatformTransactionManager` -implementation for single JDBC datasources. It binds a JDBC connection from the -specified data source to the currently executing thread, potentially allowing for one -thread connection per data source. - -Application code is required to retrieve the JDBC connection through -`DataSourceUtils.getConnection(DataSource)` instead of Java EE's standard -`DataSource.getConnection`. It throws unchecked `org.springframework.dao` exceptions -instead of checked `SQLExceptions`. All framework classes like `JdbcTemplate` use this -strategy implicitly. If not used with this transaction manager, the lookup strategy -behaves exactly like the common one - it can thus be used in any case. - -The `DataSourceTransactionManager` class supports custom isolation levels, and timeouts -that get applied as appropriate JDBC statement query timeouts. To support the latter, -application code must either use `JdbcTemplate` or call the -`DataSourceUtils.applyTransactionTimeout(..)` method for each created statement. - -This implementation can be used instead of `JtaTransactionManager` in the single -resource case, as it does not require the container to support JTA. Switching between -both is just a matter of configuration, if you stick to the required connection lookup -pattern. JTA does not support custom isolation levels! - - - -[[jdbc-NativeJdbcExtractor]] -==== NativeJdbcExtractor -Sometimes you need to access vendor specific JDBC methods that differ from the standard -JDBC API. This can be problematic if you are running in an application server or with a -`DataSource` that wraps the `Connection`, `Statement` and `ResultSet` objects with its -own wrapper objects. To gain access to the native objects you can configure your -`JdbcTemplate` or `OracleLobHandler` with a `NativeJdbcExtractor`. - -The `NativeJdbcExtractor` comes in a variety of flavors to match your execution -environment: - -* SimpleNativeJdbcExtractor -* C3P0NativeJdbcExtractor -* CommonsDbcpNativeJdbcExtractor -* JBossNativeJdbcExtractor -* WebLogicNativeJdbcExtractor -* WebSphereNativeJdbcExtractor -* XAPoolNativeJdbcExtractor - -Usually the `SimpleNativeJdbcExtractor` is sufficient for unwrapping a `Connection` -object in most environments. See the javadocs for more details. - - - - -[[jdbc-advanced-jdbc]] -=== JDBC batch operations -Most JDBC drivers provide improved performance if you batch multiple calls to the same -prepared statement. By grouping updates into batches you limit the number of round trips -to the database. - - - -[[jdbc-batch-classic]] -==== Basic batch operations with the JdbcTemplate -You accomplish `JdbcTemplate` batch processing by implementing two methods of a special -interface, `BatchPreparedStatementSetter`, and passing that in as the second parameter -in your `batchUpdate` method call. Use the `getBatchSize` method to provide the size of -the current batch. Use the `setValues` method to set the values for the parameters of -the prepared statement. This method will be called the number of times that you -specified in the `getBatchSize` call. The following example updates the actor table -based on entries in a list. The entire list is used as the batch in this example: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class JdbcActorDao implements ActorDao { - private JdbcTemplate jdbcTemplate; - - public void setDataSource(DataSource dataSource) { - this.jdbcTemplate = new JdbcTemplate(dataSource); - } - - public int[] batchUpdate(final List actors) { - int[] updateCounts = jdbcTemplate.batchUpdate("update t_actor set first_name = ?, " + - "last_name = ? where id = ?", - new BatchPreparedStatementSetter() { - public void setValues(PreparedStatement ps, int i) throws SQLException { - ps.setString(1, actors.get(i).getFirstName()); - ps.setString(2, actors.get(i).getLastName()); - ps.setLong(3, actors.get(i).getId().longValue()); - } - - public int getBatchSize() { - return actors.size(); - } - }); - return updateCounts; - } - - // ... additional methods - } ----- - -If you are processing a stream of updates or reading from a file, then you might have a -preferred batch size, but the last batch might not have that number of entries. In this -case you can use the `InterruptibleBatchPreparedStatementSetter` interface, which allows -you to interrupt a batch once the input source is exhausted. The `isBatchExhausted` method -allows you to signal the end of the batch. - - - -[[jdbc-batch-list]] -==== Batch operations with a List of objects -Both the `JdbcTemplate` and the `NamedParameterJdbcTemplate` provides an alternate way -of providing the batch update. Instead of implementing a special batch interface, you -provide all parameter values in the call as a list. The framework loops over these -values and uses an internal prepared statement setter. The API varies depending on -whether you use named parameters. For the named parameters you provide an array of -`SqlParameterSource`, one entry for each member of the batch. You can use the -`SqlParameterSource.createBatch` method to create this array, passing in either an array -of JavaBeans or an array of Maps containing the parameter values. - -This example shows a batch update using named parameters: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class JdbcActorDao implements ActorDao { - private NamedParameterTemplate namedParameterJdbcTemplate; - - public void setDataSource(DataSource dataSource) { - this.namedParameterJdbcTemplate = new NamedParameterJdbcTemplate(dataSource); - } - - public int[] batchUpdate(final List actors) { - SqlParameterSource[] batch = SqlParameterSourceUtils.createBatch(actors.toArray()); - int[] updateCounts = namedParameterJdbcTemplate.batchUpdate( - "update t_actor set first_name = :firstName, last_name = :lastName where id = :id", - batch); - return updateCounts; - } - - // ... additional methods - } ----- - -For an SQL statement using the classic "?" placeholders, you pass in a list containing an -object array with the update values. This object array must have one entry for each -placeholder in the SQL statement, and they must be in the same order as they are defined -in the SQL statement. - -The same example using classic JDBC "?" placeholders: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class JdbcActorDao implements ActorDao { - - private JdbcTemplate jdbcTemplate; - - public void setDataSource(DataSource dataSource) { - this.jdbcTemplate = new JdbcTemplate(dataSource); - } - - public int[] batchUpdate(final List actors) { - List batch = new ArrayList(); - for (Actor actor : actors) { - Object[] values = new Object[] { - actor.getFirstName(), - actor.getLastName(), - actor.getId()}; - batch.add(values); - } - int[] updateCounts = jdbcTemplate.batchUpdate( - "update t_actor set first_name = ?, last_name = ? where id = ?", - batch); - return updateCounts; - } - - // ... additional methods - - } ----- - -All of the above batch update methods return an int array containing the number of -affected rows for each batch entry. This count is reported by the JDBC driver. If the -count is not available, the JDBC driver returns a -2 value. - - - -[[jdbc-batch-multi]] -==== Batch operations with multiple batches -The last example of a batch update deals with batches that are so large that you want to -break them up into several smaller batches. You can of course do this with the methods -mentioned above by making multiple calls to the `batchUpdate` method, but there is now a -more convenient method. This method takes, in addition to the SQL statement, a -Collection of objects containing the parameters, the number of updates to make for each -batch and a `ParameterizedPreparedStatementSetter` to set the values for the parameters -of the prepared statement. The framework loops over the provided values and breaks the -update calls into batches of the size specified. - -This example shows a batch update using a batch size of 100: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class JdbcActorDao implements ActorDao { - - private JdbcTemplate jdbcTemplate; - - public void setDataSource(DataSource dataSource) { - this.jdbcTemplate = new JdbcTemplate(dataSource); - } - - public int[][] batchUpdate(final Collection actors) { - int[][] updateCounts = jdbcTemplate.batchUpdate( - "update t_actor set first_name = ?, last_name = ? where id = ?", - actors, - 100, - new ParameterizedPreparedStatementSetter() { - public void setValues(PreparedStatement ps, Actor argument) throws SQLException { - ps.setString(1, argument.getFirstName()); - ps.setString(2, argument.getLastName()); - ps.setLong(3, argument.getId().longValue()); - } - }); - return updateCounts; - } - - // ... additional methods - - } ----- - -The batch update methods for this call returns an array of int arrays containing an array -entry for each batch with an array of the number of affected rows for each update. The top -level array's length indicates the number of batches executed and the second level array's -length indicates the number of updates in that batch. The number of updates in each batch -should be the the batch size provided for all batches except for the last one that might -be less, depending on the total number of update objects provided. The update count for -each update statement is the one reported by the JDBC driver. If the count is not -available, the JDBC driver returns a -2 value. - - - - -[[jdbc-simple-jdbc]] -=== Simplifying JDBC operations with the SimpleJdbc classes -The `SimpleJdbcInsert` and `SimpleJdbcCall` classes provide a simplified configuration -by taking advantage of database metadata that can be retrieved through the JDBC driver. -This means there is less to configure up front, although you can override or turn off -the metadata processing if you prefer to provide all the details in your code. - - - -[[jdbc-simple-jdbc-insert-1]] -==== Inserting data using SimpleJdbcInsert -Let's start by looking at the `SimpleJdbcInsert` class with the minimal amount of -configuration options. You should instantiate the `SimpleJdbcInsert` in the data access -layer's initialization method. For this example, the initializing method is the -`setDataSource` method. You do not need to subclass the `SimpleJdbcInsert` class; simply -create a new instance and set the table name using the `withTableName` method. -Configuration methods for this class follow the "fluid" style that returns the instance -of the `SimpleJdbcInsert`, which allows you to chain all configuration methods. This -example uses only one configuration method; you will see examples of multiple ones later. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class JdbcActorDao implements ActorDao { - - private JdbcTemplate jdbcTemplate; - private SimpleJdbcInsert insertActor; - - public void setDataSource(DataSource dataSource) { - this.jdbcTemplate = new JdbcTemplate(dataSource); - this.insertActor = new SimpleJdbcInsert(dataSource).withTableName("t_actor"); - } - - public void add(Actor actor) { - Map parameters = new HashMap(3); - parameters.put("id", actor.getId()); - parameters.put("first_name", actor.getFirstName()); - parameters.put("last_name", actor.getLastName()); - insertActor.execute(parameters); - } - - // ... additional methods - } ----- - -The execute method used here takes a plain `java.utils.Map` as its only parameter. The -important thing to note here is that the keys used for the Map must match the column -names of the table as defined in the database. This is because we read the metadata in -order to construct the actual insert statement. - - - -[[jdbc-simple-jdbc-insert-2]] -==== Retrieving auto-generated keys using SimpleJdbcInsert -This example uses the same insert as the preceding, but instead of passing in the id it -retrieves the auto-generated key and sets it on the new Actor object. When you create -the `SimpleJdbcInsert`, in addition to specifying the table name, you specify the name -of the generated key column with the `usingGeneratedKeyColumns` method. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class JdbcActorDao implements ActorDao { - - private JdbcTemplate jdbcTemplate; - private SimpleJdbcInsert insertActor; - - public void setDataSource(DataSource dataSource) { - this.jdbcTemplate = new JdbcTemplate(dataSource); - this.insertActor = new SimpleJdbcInsert(dataSource) - .withTableName("t_actor") - .usingGeneratedKeyColumns("id"); - } - - public void add(Actor actor) { - Map parameters = new HashMap(2); - parameters.put("first_name", actor.getFirstName()); - parameters.put("last_name", actor.getLastName()); - Number newId = insertActor.executeAndReturnKey(parameters); - actor.setId(newId.longValue()); - } - - // ... additional methods - } ----- - -The main difference when executing the insert by this second approach is that you do not -add the id to the Map and you call the `executeReturningKey` method. This returns a -`java.lang.Number` object with which you can create an instance of the numerical type that -is used in our domain class. You cannot rely on all databases to return a specific Java -class here; `java.lang.Number` is the base class that you can rely on. If you have -multiple auto-generated columns, or the generated values are non-numeric, then you can -use a `KeyHolder` that is returned from the `executeReturningKeyHolder` method. - - - -[[jdbc-simple-jdbc-insert-3]] -==== Specifying columns for a SimpleJdbcInsert -You can limit the columns for an insert by specifying a list of column names with the -`usingColumns` method: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class JdbcActorDao implements ActorDao { - - private JdbcTemplate jdbcTemplate; - private SimpleJdbcInsert insertActor; - - public void setDataSource(DataSource dataSource) { - this.jdbcTemplate = new JdbcTemplate(dataSource); - this.insertActor = new SimpleJdbcInsert(dataSource) - .withTableName("t_actor") - .usingColumns("first_name", "last_name") - .usingGeneratedKeyColumns("id"); - } - - public void add(Actor actor) { - Map parameters = new HashMap(2); - parameters.put("first_name", actor.getFirstName()); - parameters.put("last_name", actor.getLastName()); - Number newId = insertActor.executeAndReturnKey(parameters); - actor.setId(newId.longValue()); - } - - // ... additional methods - - } ----- - -The execution of the insert is the same as if you had relied on the metadata to determine -which columns to use. - - - -[[jdbc-simple-jdbc-parameters]] -==== Using SqlParameterSource to provide parameter values -Using a `Map` to provide parameter values works fine, but it's not the most convenient -class to use. Spring provides a couple of implementations of the `SqlParameterSource` -interface that can be used instead.The first one is `BeanPropertySqlParameterSource`, -which is a very convenient class if you have a JavaBean-compliant class that contains -your values. It will use the corresponding getter method to extract the parameter -values. Here is an example: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class JdbcActorDao implements ActorDao { - - private JdbcTemplate jdbcTemplate; - private SimpleJdbcInsert insertActor; - - public void setDataSource(DataSource dataSource) { - this.jdbcTemplate = new JdbcTemplate(dataSource); - this.insertActor = new SimpleJdbcInsert(dataSource) - .withTableName("t_actor") - .usingGeneratedKeyColumns("id"); - } - - public void add(Actor actor) { - SqlParameterSource parameters = new BeanPropertySqlParameterSource(actor); - Number newId = insertActor.executeAndReturnKey(parameters); - actor.setId(newId.longValue()); - } - - // ... additional methods - - } ----- - -Another option is the `MapSqlParameterSource` that resembles a Map but provides a more -convenient `addValue` method that can be chained. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class JdbcActorDao implements ActorDao { - - private JdbcTemplate jdbcTemplate; - private SimpleJdbcInsert insertActor; - - public void setDataSource(DataSource dataSource) { - this.jdbcTemplate = new JdbcTemplate(dataSource); - this.insertActor = new SimpleJdbcInsert(dataSource) - .withTableName("t_actor") - .usingGeneratedKeyColumns("id"); - } - - public void add(Actor actor) { - SqlParameterSource parameters = new MapSqlParameterSource() - .addValue("first_name", actor.getFirstName()) - .addValue("last_name", actor.getLastName()); - Number newId = insertActor.executeAndReturnKey(parameters); - actor.setId(newId.longValue()); - } - - // ... additional methods - - } ----- - -As you can see, the configuration is the same; only the executing code has to change to -use these alternative input classes. - - - -[[jdbc-simple-jdbc-call-1]] -==== Calling a stored procedure with SimpleJdbcCall -The `SimpleJdbcCall` class leverages metadata in the database to look up names of `in` -and `out` parameters, so that you do not have to declare them explicitly. You can -declare parameters if you prefer to do that, or if you have parameters such as `ARRAY` -or `STRUCT` that do not have an automatic mapping to a Java class. The first example -shows a simple procedure that returns only scalar values in `VARCHAR` and `DATE` format -from a MySQL database. The example procedure reads a specified actor entry and returns -`first_name`, `last_name`, and `birth_date` columns in the form of `out` parameters. - -[source,sql,indent=0] -[subs="verbatim,quotes"] ----- - CREATE PROCEDURE read_actor ( - IN in_id INTEGER, - OUT out_first_name VARCHAR(100), - OUT out_last_name VARCHAR(100), - OUT out_birth_date DATE) - BEGIN - SELECT first_name, last_name, birth_date - INTO out_first_name, out_last_name, out_birth_date - FROM t_actor where id = in_id; - END; ----- - -The `in_id` parameter contains the `id` of the actor you are looking up. The `out` -parameters return the data read from the table. - -The `SimpleJdbcCall` is declared in a similar manner to the `SimpleJdbcInsert`. You -should instantiate and configure the class in the initialization method of your data -access layer. Compared to the StoredProcedure class, you don't have to create a subclass -and you don't have to declare parameters that can be looked up in the database metadata. -Following is an example of a SimpleJdbcCall configuration using the above stored -procedure. The only configuration option, in addition to the `DataSource`, is the name -of the stored procedure. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class JdbcActorDao implements ActorDao { - - private JdbcTemplate jdbcTemplate; - private SimpleJdbcCall procReadActor; - - public void setDataSource(DataSource dataSource) { - this.jdbcTemplate = new JdbcTemplate(dataSource); - this.procReadActor = new SimpleJdbcCall(dataSource) - .withProcedureName("read_actor"); - } - - public Actor readActor(Long id) { - SqlParameterSource in = new MapSqlParameterSource() - .addValue("in_id", id); - Map out = procReadActor.execute(in); - Actor actor = new Actor(); - actor.setId(id); - actor.setFirstName((String) out.get("out_first_name")); - actor.setLastName((String) out.get("out_last_name")); - actor.setBirthDate((Date) out.get("out_birth_date")); - return actor; - } - - // ... additional methods - - } ----- - -The code you write for the execution of the call involves creating an `SqlParameterSource` -containing the IN parameter. It's important to match the name provided for the input value -with that of the parameter name declared in the stored procedure. The case does not have -to match because you use metadata to determine how database objects should be referred to -in a stored procedure. What is specified in the source for the stored procedure is not -necessarily the way it is stored in the database. Some databases transform names to all -upper case while others use lower case or use the case as specified. - -The `execute` method takes the IN parameters and returns a Map containing any `out` -parameters keyed by the name as specified in the stored procedure. In this case they are -`out_first_name, out_last_name` and `out_birth_date`. - -The last part of the `execute` method creates an Actor instance to use to return the -data retrieved. Again, it is important to use the names of the `out` parameters as they -are declared in the stored procedure. Also, the case in the names of the `out` -parameters stored in the results map matches that of the `out` parameter names in the -database, which could vary between databases. To make your code more portable you should -do a case-insensitive lookup or instruct Spring to use a `CaseInsensitiveMap` from the -Jakarta Commons project. To do the latter, you create your own `JdbcTemplate` and set -the `setResultsMapCaseInsensitive` property to `true`. Then you pass this customized -`JdbcTemplate` instance into the constructor of your `SimpleJdbcCall`. You must include -the `commons-collections.jar` in your classpath for this to work. Here is an example of -this configuration: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class JdbcActorDao implements ActorDao { - - private SimpleJdbcCall procReadActor; - - public void setDataSource(DataSource dataSource) { - JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource); - jdbcTemplate.setResultsMapCaseInsensitive(true); - this.procReadActor = new SimpleJdbcCall(jdbcTemplate) - .withProcedureName("read_actor"); - } - - // ... additional methods - - } ----- - -By taking this action, you avoid conflicts in the case used for the names of your -returned `out` parameters. - - - -[[jdbc-simple-jdbc-call-2]] -==== Explicitly declaring parameters to use for a SimpleJdbcCall -You have seen how the parameters are deduced based on metadata, but you can declare then -explicitly if you wish. You do this by creating and configuring `SimpleJdbcCall` with -the `declareParameters` method, which takes a variable number of `SqlParameter` objects -as input. See the next section for details on how to define an `SqlParameter`. - -[NOTE] -==== -Explicit declarations are necessary if the database you use is not a Spring-supported -database. Currently Spring supports metadata lookup of stored procedure calls for the -following databases: Apache Derby, DB2, MySQL, Microsoft SQL Server, Oracle, and Sybase. -We also support metadata lookup of stored functions for: MySQL, Microsoft SQL Server, -and Oracle. -==== - -You can opt to declare one, some, or all the parameters explicitly. The parameter -metadata is still used where you do not declare parameters explicitly. To bypass all -processing of metadata lookups for potential parameters and only use the declared -parameters, you call the method `withoutProcedureColumnMetaDataAccess` as part of the -declaration. Suppose that you have two or more different call signatures declared for a -database function. In this case you call the `useInParameterNames` to specify the list -of IN parameter names to include for a given signature. - -The following example shows a fully declared procedure call, using the information from -the preceding example. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class JdbcActorDao implements ActorDao { - - private SimpleJdbcCall procReadActor; - - public void setDataSource(DataSource dataSource) { - JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource); - jdbcTemplate.setResultsMapCaseInsensitive(true); - this.procReadActor = new SimpleJdbcCall(jdbcTemplate) - .withProcedureName("read_actor") - .withoutProcedureColumnMetaDataAccess() - .useInParameterNames("in_id") - .declareParameters( - new SqlParameter("in_id", Types.NUMERIC), - new SqlOutParameter("out_first_name", Types.VARCHAR), - new SqlOutParameter("out_last_name", Types.VARCHAR), - new SqlOutParameter("out_birth_date", Types.DATE) - ); - } - - // ... additional methods - } ----- - -The execution and end results of the two examples are the same; this one specifies all -details explicitly rather than relying on metadata. - - - -[[jdbc-params]] -==== How to define SqlParameters -To define a parameter for the SimpleJdbc classes and also for the RDBMS operations -classes, covered in <>, you use an `SqlParameter` or one of its subclasses. -You typically specify the parameter name and SQL type in the constructor. The SQL type -is specified using the `java.sql.Types` constants. We have already seen declarations -like: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - new SqlParameter("in_id", Types.NUMERIC), - new SqlOutParameter("out_first_name", Types.VARCHAR), ----- - -The first line with the `SqlParameter` declares an IN parameter. IN parameters can be -used for both stored procedure calls and for queries using the `SqlQuery` and its -subclasses covered in the following section. - -The second line with the `SqlOutParameter` declares an `out` parameter to be used in a -stored procedure call. There is also an `SqlInOutParameter` for `InOut` parameters, -parameters that provide an `IN` value to the procedure and that also return a value. - -[NOTE] -==== -Only parameters declared as `SqlParameter` and `SqlInOutParameter` will be used to -provide input values. This is different from the `StoredProcedure` class, which for -backwards compatibility reasons allows input values to be provided for parameters -declared as `SqlOutParameter`. -==== - -For IN parameters, in addition to the name and the SQL type, you can specify a scale for -numeric data or a type name for custom database types. For `out` parameters, you can -provide a `RowMapper` to handle mapping of rows returned from a `REF` cursor. Another -option is to specify an `SqlReturnType` that provides an opportunity to define -customized handling of the return values. - - - -[[jdbc-simple-jdbc-call-3]] -==== Calling a stored function using SimpleJdbcCall -You call a stored function in almost the same way as you call a stored procedure, except -that you provide a function name rather than a procedure name. You use the -`withFunctionName` method as part of the configuration to indicate that we want to make -a call to a function, and the corresponding string for a function call is generated. A -specialized execute call, `executeFunction,` is used to execute the function and it -returns the function return value as an object of a specified type, which means you do -not have to retrieve the return value from the results map. A similar convenience method -named `executeObject` is also available for stored procedures that only have one `out` -parameter. The following example is based on a stored function named `get_actor_name` -that returns an actor's full name. Here is the MySQL source for this function: - -[source,sql,indent=0] -[subs="verbatim,quotes"] ----- - CREATE FUNCTION get_actor_name (in_id INTEGER) - RETURNS VARCHAR(200) READS SQL DATA - BEGIN - DECLARE out_name VARCHAR(200); - SELECT concat(first_name, ' ', last_name) - INTO out_name - FROM t_actor where id = in_id; - RETURN out_name; - END; ----- - -To call this function we again create a `SimpleJdbcCall` in the initialization method. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class JdbcActorDao implements ActorDao { - - private JdbcTemplate jdbcTemplate; - private SimpleJdbcCall funcGetActorName; - - public void setDataSource(DataSource dataSource) { - this.jdbcTemplate = new JdbcTemplate(dataSource); - JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource); - jdbcTemplate.setResultsMapCaseInsensitive(true); - this.funcGetActorName = new SimpleJdbcCall(jdbcTemplate) - .withFunctionName("get_actor_name"); - } - - public String getActorName(Long id) { - SqlParameterSource in = new MapSqlParameterSource() - .addValue("in_id", id); - String name = funcGetActorName.executeFunction(String.class, in); - return name; - } - - // ... additional methods - - } ----- - -The execute method used returns a `String` containing the return value from the function -call. - - - -[[jdbc-simple-jdbc-call-4]] -==== Returning ResultSet/REF Cursor from a SimpleJdbcCall -Calling a stored procedure or function that returns a result set is a bit tricky. Some -databases return result sets during the JDBC results processing while others require an -explicitly registered `out` parameter of a specific type. Both approaches need -additional processing to loop over the result set and process the returned rows. With -the `SimpleJdbcCall` you use the `returningResultSet` method and declare a `RowMapper` -implementation to be used for a specific parameter. In the case where the result set is -returned during the results processing, there are no names defined, so the returned -results will have to match the order in which you declare the `RowMapper` -implementations. The name specified is still used to store the processed list of results -in the results map that is returned from the execute statement. - -The next example uses a stored procedure that takes no IN parameters and returns all -rows from the t_actor table. Here is the MySQL source for this procedure: - -[source,sql,indent=0] -[subs="verbatim,quotes"] ----- - CREATE PROCEDURE read_all_actors() - BEGIN - SELECT a.id, a.first_name, a.last_name, a.birth_date FROM t_actor a; - END; ----- - -To call this procedure you declare the `RowMapper`. Because the class you want to map to -follows the JavaBean rules, you can use a `ParameterizedBeanPropertyRowMapper` that is -created by passing in the required class to map to in the `newInstance` method. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class JdbcActorDao implements ActorDao { - - private SimpleJdbcCall procReadAllActors; - - public void setDataSource(DataSource dataSource) { - JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource); - jdbcTemplate.setResultsMapCaseInsensitive(true); - this.procReadAllActors = new SimpleJdbcCall(jdbcTemplate) - .withProcedureName("read_all_actors") - .returningResultSet("actors", - ParameterizedBeanPropertyRowMapper.newInstance(Actor.class)); - } - - public List getActorsList() { - Map m = procReadAllActors.execute(new HashMap(0)); - return (List) m.get("actors"); - } - - // ... additional methods - - } ----- - -The execute call passes in an empty Map because this call does not take any parameters. -The list of Actors is then retrieved from the results map and returned to the caller. - - - - -[[jdbc-object]] -=== Modeling JDBC operations as Java objects -The `org.springframework.jdbc.object` package contains classes that allow you to access -the database in a more object-oriented manner. As an example, you can execute queries -and get the results back as a list containing business objects with the relational -column data mapped to the properties of the business object. You can also execute stored -procedures and run update, delete, and insert statements. - -[NOTE] -==== -Many Spring developers believe that the various RDBMS operation classes described below -(with the exception of the <> class) can often -be replaced with straight `JdbcTemplate` calls. Often it is simpler to write a DAO -method that simply calls a method on a `JdbcTemplate` directly (as opposed to -encapsulating a query as a full-blown class). - -However, if you are getting measurable value from using the RDBMS operation classes, -continue using these classes. -==== - - - -[[jdbc-SqlQuery]] -==== SqlQuery - -`SqlQuery` is a reusable, threadsafe class that encapsulates an SQL query. Subclasses -must implement the `newRowMapper(..)` method to provide a `RowMapper` instance that can -create one object per row obtained from iterating over the `ResultSet` that is created -during the execution of the query. The `SqlQuery` class is rarely used directly because -the `MappingSqlQuery` subclass provides a much more convenient implementation for -mapping rows to Java classes. Other implementations that extend `SqlQuery` are -`MappingSqlQueryWithParameters` and `UpdatableSqlQuery`. - - - -[[jdbc-MappingSqlQuery]] -==== MappingSqlQuery - -`MappingSqlQuery` is a reusable query in which concrete subclasses must implement the -abstract `mapRow(..)` method to convert each row of the supplied `ResultSet` into an -object of the type specified. The following example shows a custom query that maps the -data from the `t_actor` relation to an instance of the `Actor` class. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class ActorMappingQuery extends MappingSqlQuery { - - public ActorMappingQuery(DataSource ds) { - super(ds, "select id, first_name, last_name from t_actor where id = ?"); - super.declareParameter(new SqlParameter("id", Types.INTEGER)); - compile(); - } - - @Override - protected Actor mapRow(ResultSet rs, int rowNumber) throws SQLException { - Actor actor = new Actor(); - actor.setId(rs.getLong("id")); - actor.setFirstName(rs.getString("first_name")); - actor.setLastName(rs.getString("last_name")); - return actor; - } - - } ----- - -The class extends `MappingSqlQuery` parameterized with the `Actor` type. The constructor -for this customer query takes the `DataSource` as the only parameter. In this -constructor you call the constructor on the superclass with the `DataSource` and the SQL -that should be executed to retrieve the rows for this query. This SQL will be used to -create a `PreparedStatement` so it may contain place holders for any parameters to be -passed in during execution.You must declare each parameter using the `declareParameter` -method passing in an `SqlParameter`. The `SqlParameter` takes a name and the JDBC type -as defined in `java.sql.Types`. After you define all parameters, you call the -`compile()` method so the statement can be prepared and later executed. This class is -thread-safe after it is compiled, so as long as these instances are created when the DAO -is initialized they can be kept as instance variables and be reused. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - private ActorMappingQuery actorMappingQuery; - - @Autowired - public void setDataSource(DataSource dataSource) { - this.actorMappingQuery = new ActorMappingQuery(dataSource); - } - - public Customer getCustomer(Long id) { - return actorMappingQuery.findObject(id); - } ----- - -The method in this example retrieves the customer with the id that is passed in as the -only parameter. Since we only want one object returned we simply call the convenience -method `findObject` with the id as parameter. If we had instead a query that returned a -list of objects and took additional parameters then we would use one of the execute -methods that takes an array of parameter values passed in as varargs. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public List searchForActors(int age, String namePattern) { - List actors = actorSearchMappingQuery.execute(age, namePattern); - return actors; - } ----- - - - -[[jdbc-SqlUpdate]] -==== SqlUpdate - -The `SqlUpdate` class encapsulates an SQL update. Like a query, an update object is -reusable, and like all `RdbmsOperation` classes, an update can have parameters and is -defined in SQL. This class provides a number of `update(..)` methods analogous to the -`execute(..)` methods of query objects. The `SQLUpdate` class is concrete. It can be -subclassed, for example, to add a custom update method, as in the following snippet -where it's simply called `execute`. However, you don't have to subclass the `SqlUpdate` -class since it can easily be parameterized by setting SQL and declaring parameters. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - import java.sql.Types; - - import javax.sql.DataSource; - - import org.springframework.jdbc.core.SqlParameter; - import org.springframework.jdbc.object.SqlUpdate; - - public class UpdateCreditRating extends SqlUpdate { - - public UpdateCreditRating(DataSource ds) { - setDataSource(ds); - setSql("update customer set credit_rating = ? where id = ?"); - declareParameter(new SqlParameter("creditRating", Types.NUMERIC)); - declareParameter(new SqlParameter("id", Types.NUMERIC)); - compile(); - } - - /** - * @param id for the Customer to be updated - * @param rating the new value for credit rating - * @return number of rows updated - */ - public int execute(int id, int rating) { - return update(rating, id); - } - } ----- - - - -[[jdbc-StoredProcedure]] -==== StoredProcedure - -The `StoredProcedure` class is a superclass for object abstractions of RDBMS stored -procedures. This class is `abstract`, and its various `execute(..)` methods have -`protected` access, preventing use other than through a subclass that offers tighter -typing. - -The inherited `sql` property will be the name of the stored procedure in the RDBMS. - -To define a parameter for the `StoredProcedure` class, you use an `SqlParameter` or one -of its subclasses. You must specify the parameter name and SQL type in the constructor -like in the following code snippet. The SQL type is specified using the `java.sql.Types` -constants. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - new SqlParameter("in_id", Types.NUMERIC), - new SqlOutParameter("out_first_name", Types.VARCHAR), ----- - -The first line with the `SqlParameter` declares an IN parameter. IN parameters can be -used for both stored procedure calls and for queries using the `SqlQuery` and its -subclasses covered in the following section. - -The second line with the `SqlOutParameter` declares an `out` parameter to be used in the -stored procedure call. There is also an `SqlInOutParameter` for `I` `nOut` parameters, -parameters that provide an `in` value to the procedure and that also return a value. - -For `i` `n` parameters, in addition to the name and the SQL type, you can specify a -scale for numeric data or a type name for custom database types. For `out` parameters -you can provide a `RowMapper` to handle mapping of rows returned from a REF cursor. -Another option is to specify an `SqlReturnType` that enables you to define customized -handling of the return values. - -Here is an example of a simple DAO that uses a `StoredProcedure` to call a function, -`sysdate()`,which comes with any Oracle database. To use the stored procedure -functionality you have to create a class that extends `StoredProcedure`. In this -example, the `StoredProcedure` class is an inner class, but if you need to reuse the -`StoredProcedure` you declare it as a top-level class. This example has no input -parameters, but an output parameter is declared as a date type using the class -`SqlOutParameter`. The `execute()` method executes the procedure and extracts the -returned date from the results `Map`. The results `Map` has an entry for each declared -output parameter, in this case only one, using the parameter name as the key. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - import java.sql.Types; - import java.util.Date; - import java.util.HashMap; - import java.util.Map; - - import javax.sql.DataSource; - - import org.springframework.beans.factory.annotation.Autowired; - import org.springframework.jdbc.core.SqlOutParameter; - import org.springframework.jdbc.object.StoredProcedure; - - public class StoredProcedureDao { - - private GetSysdateProcedure getSysdate; - - @Autowired - public void init(DataSource dataSource) { - this.getSysdate = new GetSysdateProcedure(dataSource); - } - - public Date getSysdate() { - return getSysdate.execute(); - } - - private class GetSysdateProcedure extends StoredProcedure { - - private static final String SQL = "sysdate"; - - public GetSysdateProcedure(DataSource dataSource) { - setDataSource(dataSource); - setFunction(true); - setSql(SQL); - declareParameter(new SqlOutParameter("date", Types.DATE)); - compile(); - } - - public Date execute() { - // the 'sysdate' sproc has no input parameters, so an empty Map is supplied... - Map results = execute(new HashMap()); - Date sysdate = (Date) results.get("date"); - return sysdate; - } - } - - } ----- - -The following example of a `StoredProcedure` has two output parameters (in this case, -Oracle REF cursors). - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - import oracle.jdbc.OracleTypes; - import org.springframework.jdbc.core.SqlOutParameter; - import org.springframework.jdbc.object.StoredProcedure; - - import javax.sql.DataSource; - import java.util.HashMap; - import java.util.Map; - - public class TitlesAndGenresStoredProcedure extends StoredProcedure { - - private static final String SPROC_NAME = "AllTitlesAndGenres"; - - public TitlesAndGenresStoredProcedure(DataSource dataSource) { - super(dataSource, SPROC_NAME); - declareParameter(new SqlOutParameter("titles", OracleTypes.CURSOR, new TitleMapper())); - declareParameter(new SqlOutParameter("genres", OracleTypes.CURSOR, new GenreMapper())); - compile(); - } - - public Map execute() { - // again, this sproc has no input parameters, so an empty Map is supplied - return super.execute(new HashMap()); - } - } ----- - -Notice how the overloaded variants of the `declareParameter(..)` method that have been -used in the `TitlesAndGenresStoredProcedure` constructor are passed `RowMapper` -implementation instances; this is a very convenient and powerful way to reuse existing -functionality. The code for the two `RowMapper` implementations is provided below. - -The `TitleMapper` class maps a `ResultSet` to a `Title` domain object for each row in -the supplied `ResultSet`: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - import org.springframework.jdbc.core.RowMapper; - - import java.sql.ResultSet; - import java.sql.SQLException; - - import com.foo.domain.Title; - - public final class TitleMapper implements RowMapper { - - public Title mapRow(ResultSet rs, int rowNum) throws SQLException { - Title title = new Title(); - title.setId(rs.getLong("id")); - title.setName(rs.getString("name")); - return title; - } - } ----- - -The `GenreMapper` class maps a `ResultSet` to a `Genre` domain object for each row in -the supplied `ResultSet`. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - import org.springframework.jdbc.core.RowMapper; - - import java.sql.ResultSet; - import java.sql.SQLException; - - import com.foo.domain.Genre; - - public final class GenreMapper implements RowMapper<Genre> { - - public Genre mapRow(ResultSet rs, int rowNum) throws SQLException { - return new Genre(rs.getString("name")); - } - } ----- - -To pass parameters to a stored procedure that has one or more input parameters in its -definition in the RDBMS, you can code a strongly typed `execute(..)` method that would -delegate to the superclass' untyped `execute(Map parameters)` method (which has -`protected` access); for example: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - import oracle.jdbc.OracleTypes; - import org.springframework.jdbc.core.SqlOutParameter; - import org.springframework.jdbc.core.SqlParameter; - import org.springframework.jdbc.object.StoredProcedure; - - import javax.sql.DataSource; - - import java.sql.Types; - import java.util.Date; - import java.util.HashMap; - import java.util.Map; - - public class TitlesAfterDateStoredProcedure extends StoredProcedure { - - private static final String SPROC_NAME = "TitlesAfterDate"; - private static final String CUTOFF_DATE_PARAM = "cutoffDate"; - - public TitlesAfterDateStoredProcedure(DataSource dataSource) { - super(dataSource, SPROC_NAME); - declareParameter(new SqlParameter(CUTOFF_DATE_PARAM, Types.DATE); - declareParameter(new SqlOutParameter("titles", OracleTypes.CURSOR, new TitleMapper())); - compile(); - } - - public Map<String, Object> execute(Date cutoffDate) { - Map<String, Object> inputs = new HashMap<String, Object>(); - inputs.put(CUTOFF_DATE_PARAM, cutoffDate); - return super.execute(inputs); - } - } ----- - - - - -[[jdbc-parameter-handling]] -=== Common problems with parameter and data value handling -Common problems with parameters and data values exist in the different approaches -provided by the Spring Framework JDBC. - - - -[[jdbc-type-information]] -==== Providing SQL type information for parameters -Usually Spring determines the SQL type of the parameters based on the type of parameter -passed in. It is possible to explicitly provide the SQL type to be used when setting -parameter values. This is sometimes necessary to correctly set NULL values. - -You can provide SQL type information in several ways: - -* Many update and query methods of the `JdbcTemplate` take an additional parameter in - the form of an `int` array. This array is used to indicate the SQL type of the - corresponding parameter using constant values from the `java.sql.Types` class. Provide - one entry for each parameter. -* You can use the `SqlParameterValue` class to wrap the parameter value that needs this - additional information.Create a new instance for each value and pass in the SQL type - and parameter value in the constructor. You can also provide an optional scale - parameter for numeric values. -* For methods working with named parameters, use the `SqlParameterSource` classes - `BeanPropertySqlParameterSource` or `MapSqlParameterSource`. They both have methods - for registering the SQL type for any of the named parameter values. - - - -[[jdbc-lob]] -==== Handling BLOB and CLOB objects -You can store images, other binary objects, and large chunks of text. These large object -are called BLOB for binary data and CLOB for character data. In Spring you can handle -these large objects by using the JdbcTemplate directly and also when using the higher -abstractions provided by RDBMS Objects and the `SimpleJdbc` classes. All of these -approaches use an implementation of the `LobHandler` interface for the actual management -of the LOB data. The `LobHandler` provides access to a `LobCreator` class, through the -`getLobCreator` method, used for creating new LOB objects to be inserted. - -The `LobCreator/LobHandler` provides the following support for LOB input and output: - -* BLOB -* byte[] -- getBlobAsBytes and setBlobAsBytes -* InputStream -- getBlobAsBinaryStream and setBlobAsBinaryStream -* CLOB -* String -- getClobAsString and setClobAsString -* InputStream -- getClobAsAsciiStream and setClobAsAsciiStream -* Reader -- getClobAsCharacterStream and setClobAsCharacterStream - -The next example shows how to create and insert a BLOB. Later you will see how to read -it back from the database. - -This example uses a `JdbcTemplate` and an implementation of the -`AbstractLobCreatingPreparedStatementCallbac` `k`. It implements one method, -`setValues`. This method provides a `LobCreator` that you use to set the values for the -LOB columns in your SQL insert statement. - -For this example we assume that there is a variable, `lobHandle` `r`, that already is -set to an instance of a `DefaultLobHandler`. You typically set this value through -dependency injection. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - final File blobIn = new File("spring2004.jpg"); - final InputStream blobIs = new FileInputStream(blobIn); - final File clobIn = new File("large.txt"); - final InputStream clobIs = new FileInputStream(clobIn); - final InputStreamReader clobReader = new InputStreamReader(clobIs); - jdbcTemplate.execute( - "INSERT INTO lob_table (id, a_clob, a_blob) VALUES (?, ?, ?)", - new AbstractLobCreatingPreparedStatementCallback(lobHandler) { # <1> - protected void setValues(PreparedStatement ps, LobCreator lobCreator) throws SQLException { - ps.setLong(1, 1L); - lobCreator.setClobAsCharacterStream(ps, 2, clobReader, (int)clobIn.length()); # <2> - lobCreator.setBlobAsBinaryStream(ps, 3, blobIs, (int)blobIn.length()); # <3> - } - } - ); - blobIs.close(); - clobReader.close(); ----- - -<1> Pass in the lobHandler that in this example is a plain `DefaultLobHandler` -<2> Using the method `setClobAsCharacterStream`, pass in the contents of the CLOB. -<3> Using the method `setBlobAsBinaryStream`, pass in the contents of the BLOB. - -Now it's time to read the LOB data from the database. Again, you use a `JdbcTemplate` -with the same instance variable `l` `obHandler` and a reference to a `DefaultLobHandler`. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - List<Map<String, Object>> l = jdbcTemplate.query("select id, a_clob, a_blob from lob_table", - new RowMapper<Map<String, Object>>() { - public Map<String, Object> mapRow(ResultSet rs, int i) throws SQLException { - Map<String, Object> results = new HashMap<String, Object>(); - String clobText = lobHandler.getClobAsString(rs, "a_clob"); # <1> - results.put("CLOB", clobText); byte[] blobBytes = lobHandler.getBlobAsBytes(rs, "a_blob"); # <2> - results.put("BLOB", blobBytes); return results; } }); ----- - -<1> Using the method `getClobAsString`, retrieve the contents of the CLOB. -<2> Using the method `getBlobAsBytes`, retrieve the contents of the BLOB. - - - -[[jdbc-in-clause]] -==== Passing in lists of values for IN clause -The SQL standard allows for selecting rows based on an expression that includes a -variable list of values. A typical example would be `select * from T_ACTOR where id in -(1, 2, 3)`. This variable list is not directly supported for prepared statements by the -JDBC standard; you cannot declare a variable number of placeholders. You need a number -of variations with the desired number of placeholders prepared, or you need to generate -the SQL string dynamically once you know how many placeholders are required. The named -parameter support provided in the `NamedParameterJdbcTemplate` and `JdbcTemplate` takes -the latter approach. Pass in the values as a `java.util.List` of primitive objects. This -list will be used to insert the required placeholders and pass in the values during the -statement execution. - -[NOTE] -==== -Be careful when passing in many values. The JDBC standard does not guarantee that you -can use more than 100 values for an `in` expression list. Various databases exceed this -number, but they usually have a hard limit for how many values are allowed. Oracle's -limit is 1000. -==== - -In addition to the primitive values in the value list, you can create a `java.util.List` -of object arrays. This list would support multiple expressions defined for the `in` -clause such as `select * from T_ACTOR where (id, last_name) in ((1, 'Johnson'), (2, -'Harrop'))`. This of course requires that your database supports this syntax. - - - -[[jdbc-complex-types]] -==== Handling complex types for stored procedure calls -When you call stored procedures you can sometimes use complex types specific to the -database. To accommodate these types, Spring provides a `SqlReturnType` for handling -them when they are returned from the stored procedure call and `SqlTypeValue` when they -are passed in as a parameter to the stored procedure. - -Here is an example of returning the value of an Oracle `STRUCT` object of the user -declared type `ITEM_TYPE`. The `SqlReturnType` interface has a single method named -`getTypeValue` that must be implemented. This interface is used as part of the -declaration of an `SqlOutParameter`. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - final TestItem = new TestItem(123L, "A test item", - new SimpleDateFormat("yyyy-M-d").parse("2010-12-31")); - - declareParameter(new SqlOutParameter("item", OracleTypes.STRUCT, "ITEM_TYPE", - new SqlReturnType() { - public Object getTypeValue(CallableStatement cs, int colIndx, int sqlType, String typeName) throws SQLException { - STRUCT struct = (STRUCT) cs.getObject(colIndx); - Object[] attr = struct.getAttributes(); - TestItem item = new TestItem(); - item.setId(((Number) attr[0]).longValue()); - item.setDescription((String) attr[1]); - item.setExpirationDate((java.util.Date) attr[2]); - return item; - } - })); ----- - -You use the `SqlTypeValue` to pass in the value of a Java object like `TestItem` into a -stored procedure. The `SqlTypeValue` interface has a single method named -`createTypeValue` that you must implement. The active connection is passed in, and you -can use it to create database-specific objects such as ++StructDescriptor++s, as shown in -the following example, or ++ArrayDescriptor++s. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - final TestItem = new TestItem(123L, "A test item", - new SimpleDateFormat("yyyy-M-d").parse("2010-12-31")); - - SqlTypeValue value = new AbstractSqlTypeValue() { - protected Object createTypeValue(Connection conn, int sqlType, String typeName) throws SQLException { - StructDescriptor itemDescriptor = new StructDescriptor(typeName, conn); - Struct item = new STRUCT(itemDescriptor, conn, - new Object[] { - testItem.getId(), - testItem.getDescription(), - new java.sql.Date(testItem.getExpirationDate().getTime()) - }); - return item; - } - }; ----- - -This `SqlTypeValue` can now be added to the Map containing the input parameters for the -execute call of the stored procedure. - -Another use for the `SqlTypeValue` is passing in an array of values to an Oracle stored -procedure. Oracle has its own internal `ARRAY` class that must be used in this case, and -you can use the `SqlTypeValue` to create an instance of the Oracle `ARRAY` and populate -it with values from the Java `ARRAY`. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - final Long[] ids = new Long[] {1L, 2L}; - - SqlTypeValue value = new AbstractSqlTypeValue() { - protected Object createTypeValue(Connection conn, int sqlType, String typeName) throws SQLException { - ArrayDescriptor arrayDescriptor = new ArrayDescriptor(typeName, conn); - ARRAY idArray = new ARRAY(arrayDescriptor, conn, ids); - return idArray; - } - }; ----- - - - - -[[jdbc-embedded-database-support]] -=== Embedded database support -The `org.springframework.jdbc.datasource.embedded` package provides support for embedded -Java database engines. Support for http://www.hsqldb.org[HSQL], -http://www.h2database.com[H2], and http://db.apache.org/derby[Derby] is provided -natively. You can also use an extensible API to plug in new embedded database types and -`DataSource` implementations. - - - -[[jdbc-why-embedded-database]] -==== Why use an embedded database? -An embedded database is useful during the development phase of a project because of its -lightweight nature. Benefits include ease of configuration, quick startup time, -testability, and the ability to rapidly evolve SQL during development. - - - -[[jdbc-embedded-database-xml]] -==== Creating an embedded database instance using Spring XML -If you want to expose an embedded database instance as a bean in a Spring -ApplicationContext, use the embedded-database tag in the spring-jdbc namespace: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - <jdbc:embedded-database id="dataSource"> - <jdbc:script location="classpath:schema.sql"/> - <jdbc:script location="classpath:test-data.sql"/> - </jdbc:embedded-database> ----- - -The preceding configuration creates an embedded HSQL database populated with SQL from -schema.sql and testdata.sql resources in the classpath. The database instance is made -available to the Spring container as a bean of type `javax.sql.DataSource`. This bean -can then be injected into data access objects as needed. - - - -[[jdbc-embedded-database-java]] -==== Creating an embedded database instance programmatically -The `EmbeddedDatabaseBuilder` class provides a fluent API for constructing an embedded -database programmatically. Use this when you need to create an embedded database -instance in a standalone environment, such as a data access object unit test: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder(); - EmbeddedDatabase db = builder.setType(H2).addScript("my-schema.sql").addScript("my-test-data.sql").build(); - // do stuff against the db (EmbeddedDatabase extends javax.sql.DataSource) - db.shutdown() ----- - - - -[[jdbc-embedded-database-extension]] -==== Extending the embedded database support -Spring JDBC embedded database support can be extended in two ways: - -* Implement `EmbeddedDatabaseConfigurer` to support a new embedded database type, such - as Apache Derby. -* Implement `DataSourceFactory` to support a new DataSource implementation, such as a - connection pool, to manage embedded database connections. - -You are encouraged to contribute back extensions to the Spring community at -https://jira.spring.io/browse/SPR[jira.spring.io]. - - - -[[jdbc-embedded-database-using-HSQL]] -==== Using HSQL -Spring supports HSQL 1.8.0 and above. HSQL is the default embedded database if no type -is specified explicitly. To specify HSQL explicitly, set the `type` attribute of the -`embedded-database` tag to `HSQL`. If you are using the builder API, call the -`setType(EmbeddedDatabaseType)` method with `EmbeddedDatabaseType.HSQL`. - - - -[[jdbc-embedded-database-using-H2]] -==== Using H2 -Spring supports the H2 database as well. To enable H2, set the `type` attribute of the -`embedded-database` tag to `H2`. If you are using the builder API, call the -`setType(EmbeddedDatabaseType)` method with `EmbeddedDatabaseType.H2`. - - - -[[jdbc-embedded-database-using-Derby]] -==== Using Derby -Spring also supports Apache Derby 10.5 and above. To enable Derby, set the `type` -attribute of the `embedded-database` tag to `Derby`. If using the builder API, call the -`setType(EmbeddedDatabaseType)` method with `EmbeddedDatabaseType.Derby`. - - - -[[jdbc-embedded-database-dao-testing]] -==== Testing data access logic with an embedded database -Embedded databases provide a lightweight way to test data access code. The following is -a data access unit test template that uses an embedded database: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class DataAccessUnitTestTemplate { - - private EmbeddedDatabase db; - - @Before - public void setUp() { - // creates an HSQL in-memory database populated from default scripts - // classpath:schema.sql and classpath:data.sql - db = new EmbeddedDatabaseBuilder().addDefaultScripts().build(); - } - - @Test - public void testDataAccess() { - JdbcTemplate template = new JdbcTemplate(db); - template.query(...); - } - - @After - public void tearDown() { - db.shutdown(); - } - - } ----- - - - - -[[jdbc-intializing-datasource]] -=== Initializing a DataSource -The `org.springframework.jdbc.datasource.init` package provides support for initializing -an existing `DataSource`. The embedded database support provides one option for creating -and initializing a `DataSource` for an application, but sometimes you need to initialize -an instance running on a server somewhere. - - - -[[jdbc-initializing-datasource-xml]] -==== Initializing a database instance using Spring XML -If you want to initialize a database and you can provide a reference to a DataSource -bean, use the `initialize-database` tag in the `spring-jdbc` namespace: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - <jdbc:initialize-database data-source="dataSource"> - <jdbc:script location="classpath:com/foo/sql/db-schema.sql"/> - <jdbc:script location="classpath:com/foo/sql/db-test-data.sql"/> - </jdbc:initialize-database> ----- - -The example above runs the two scripts specified against the database: the first script -is a schema creation, and the second is a test data set insert. The script locations can -also be patterns with wildcards in the usual ant style used for resources in Spring -(e.g. `classpath*:/com/foo/**/sql/*-data.sql`). If a pattern is used the scripts are -executed in lexical order of their URL or filename. - -The default behavior of the database initializer is to unconditionally execute the -scripts provided. This will not always be what you want, for instance if running against -an existing database that already has test data in it. The likelihood of accidentally -deleting data is reduced by the commonest pattern (as shown above) that creates the -tables first and then inserts the data - the first step will fail if the tables already -exist. - -However, to get more control over the creation and deletion of existing data, the XML -namespace provides a couple more options. The first is flag to switch the initialization -on and off. This can be set according to the environment (e.g. to pull a boolean value -from system properties or an environment bean), e.g. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - <jdbc:initialize-database data-source="dataSource" - **enabled="#{systemProperties.INITIALIZE_DATABASE}"**> - <jdbc:script location="..."/> - </jdbc:initialize-database> ----- - -The second option to control what happens with existing data is to be more tolerant of -failures. To this end you can control the ability of the initializer to ignore certain -errors in the SQL it executes from the scripts, e.g. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - <jdbc:initialize-database data-source="dataSource" **ignore-failures="DROPS"**> - <jdbc:script location="..."/> - </jdbc:initialize-database> ----- - -In this example we are saying we expect that sometimes the scripts will be run against -an empty database and there are some DROP statements in the scripts which would -therefore fail. So failed SQL `DROP` statements will be ignored, but other failures will -cause an exception. This is useful if your SQL dialect doesn't support `DROP ... IF -EXISTS` (or similar) but you want to unconditionally remove all test data before -re-creating it. In that case the first script is usually a set of drops, followed by a -set of `CREATE` statements. - -The `ignore-failures` option can be set to `NONE` (the default), `DROPS` (ignore failed -drops) or `ALL` (ignore all failures). - -If you need more control than you get from the XML namespace, you can simply use the -`DataSourceInitializer` directly, and define it as a component in your application. - - -[[jdbc-client-component-initialization]] -===== Initialization of Other Components that Depend on the Database -A large class of applications can just use the database initializer with no further -complications: those that do not use the database until after the Spring context has -started. If your application is __not__ one of those then you might need to read the -rest of this section. - -The database initializer depends on a data source instance and runs the scripts provided -in its initialization callback (c.f. `init-method` in an XML bean definition or -`InitializingBean`). If other beans depend on the same data source and also use the data -source in an initialization callback then there might be a problem because the data has -not yet been initialized. A common example of this is a cache that initializes eagerly -and loads up data from the database on application startup. - -To get round this issue you two options: change your cache initialization strategy to a -later phase, or ensure that the database initializer is initialized first. - -The first option might be easy if the application is in your control, and not otherwise. -Some suggestions for how to implement this are - -* Make the cache initialize lazily on first usage, which improves application startup time -* Have your cache or a separate component that initializes the cache implement - `Lifecycle` or `SmartLifecycle`. When the application context starts up a - `SmartLifecycle` can be automatically started if its `autoStartup` flag is set, and a - `Lifecycle` can be started manually by calling - `ConfigurableApplicationContext.start()` on the enclosing context. -* Use a Spring `ApplicationEvent` or similar custom observer mechanism to trigger the - cache initialization. `ContextRefreshedEvent` is always published by the context when - it is ready for use (after all beans have been initialized), so that is often a useful - hook (this is how the `SmartLifecycle` works by default). - -The second option can also be easy. Some suggestions on how to implement this are - -* Rely on Spring BeanFactory default behavior, which is that beans are initialized in - registration order. You can easily arrange that by adopting the common practice of a - set of <import/> elements that order your application modules, and ensure that the - database and database initialization are listed first -* Separate the datasource and the business components that use it and control their - startup order by putting them in separate ApplicationContext instances (e.g. parent - has the datasource and child has the business components). This structure is common in - Spring web applications, but can be more generally applied. - - - - - -[[orm]] -== Object Relational Mapping (ORM) Data Access - - - - -[[orm-introduction]] -=== Introduction to ORM with Spring -The Spring Framework supports integration with Hibernate, Java Persistence API (JPA) -and Java Data Objects (JDO) for resource management, data access object -(DAO) implementations, and transaction strategies. For example, for Hibernate there is -first-class support with several convenient IoC features that address many typical -Hibernate integration issues. You can configure all of the supported features for O/R -(object relational) mapping tools through Dependency Injection. They can participate in -Spring's resource and transaction management, and they comply with Spring's generic -transaction and DAO exception hierarchies. The recommended integration style is to code -DAOs against plain Hibernate, JPA, and JDO APIs. The older style of using Spring's DAO -templates is no longer recommended; however, coverage of this style can be found in the -<<classic-spring-orm>> in the appendices. - -Spring adds significant enhancements to the ORM layer of your choice when you create -data access applications. You can leverage as much of the integration support as you -wish, and you should compare this integration effort with the cost and risk of building -a similar infrastructure in-house. You can use much of the ORM support as you would a -library, regardless of technology, because everything is designed as a set of reusable -JavaBeans. ORM in a Spring IoC container facilitates configuration and deployment. Thus -most examples in this section show configuration inside a Spring container. - -Benefits of using the Spring Framework to create your ORM DAOs include: - -* __Easier testing.__ Spring's IoC approach makes it easy to swap the implementations - and configuration locations of Hibernate `SessionFactory` instances, JDBC `DataSource` - instances, transaction managers, and mapped object implementations (if needed). This - in turn makes it much easier to test each piece of persistence-related code in - isolation. -* __Common data access exceptions.__ Spring can wrap exceptions from your ORM tool, - converting them from proprietary (potentially checked) exceptions to a common runtime - DataAccessException hierarchy. This feature allows you to handle most persistence - exceptions, which are non-recoverable, only in the appropriate layers, without - annoying boilerplate catches, throws, and exception declarations. You can still trap - and handle exceptions as necessary. Remember that JDBC exceptions (including - DB-specific dialects) are also converted to the same hierarchy, meaning that you can - perform some operations with JDBC within a consistent programming model. -* __General resource management.__ Spring application contexts can handle the location - and configuration of Hibernate `SessionFactory` instances, JPA `EntityManagerFactory` - instances, JDBC `DataSource` instances, and other related resources. This makes these - values easy to manage and change. Spring offers efficient, easy, and safe handling of - persistence resources. For example, related code that uses Hibernate generally needs to - use the same Hibernate `Session` to ensure efficiency and proper transaction handling. - Spring makes it easy to create and bind a `Session` to the current thread transparently, - by exposing a current `Session` through the Hibernate `SessionFactory`. Thus Spring - solves many chronic problems of typical Hibernate usage, for any local or JTA - transaction environment. -* __Integrated transaction management.__ You can wrap your ORM code with a declarative, - aspect-oriented programming (AOP) style method interceptor either through the - `@Transactional` annotation or by explicitly configuring the transaction AOP advice in - an XML configuration file. In both cases, transaction semantics and exception handling - (rollback, and so on) are handled for you. As discussed below, in - <<orm-resource-mngmnt,Resource and transaction management>>, you can also swap various - transaction managers, without affecting your ORM-related code. For example, you can - swap between local transactions and JTA, with the same full services (such as - declarative transactions) available in both scenarios. Additionally, JDBC-related code - can fully integrate transactionally with the code you use to do ORM. This is useful - for data access that is not suitable for ORM, such as batch processing and BLOB - streaming, which still need to share common transactions with ORM operations. - -[TIP] -==== -For more comprehensive ORM support, including support for alternative database -technologies such as MongoDB, you might want to check out the -http://projects.spring.io/spring-data/[Spring Data] suite of projects. If you are -a JPA user, the https://spring.io/guides/gs/accessing-data-jpa/[Getting Started Accessing -Data with JPA] guide from https://spring.io provides a great introduction. -==== - - - -[[orm-general]] -=== General ORM integration considerations -This section highlights considerations that apply to all ORM technologies. The -<<orm-hibernate>> section provides more details and also show these features and -configurations in a concrete context. - -The major goal of Spring's ORM integration is clear application layering, with any data -access and transaction technology, and for loose coupling of application objects. No -more business service dependencies on the data access or transaction strategy, no more -hard-coded resource lookups, no more hard-to-replace singletons, no more custom service -registries. One simple and consistent approach to wiring up application objects, keeping -them as reusable and free from container dependencies as possible. All the individual -data access features are usable on their own but integrate nicely with Spring's -application context concept, providing XML-based configuration and cross-referencing of -plain JavaBean instances that need not be Spring-aware. In a typical Spring application, -many important objects are JavaBeans: data access templates, data access objects, -transaction managers, business services that use the data access objects and transaction -managers, web view resolvers, web controllers that use the business services,and so on. - - - -[[orm-resource-mngmnt]] -==== Resource and transaction management -Typical business applications are cluttered with repetitive resource management code. -Many projects try to invent their own solutions, sometimes sacrificing proper handling -of failures for programming convenience. Spring advocates simple solutions for proper -resource handling, namely IoC through templating in the case of JDBC and applying AOP -interceptors for the ORM technologies. - -The infrastructure provides proper resource handling and appropriate conversion of -specific API exceptions to an unchecked infrastructure exception hierarchy. Spring -introduces a DAO exception hierarchy, applicable to any data access strategy. For direct -JDBC, the `JdbcTemplate` class mentioned in a previous section provides connection -handling and proper conversion of `SQLException` to the `DataAccessException` hierarchy, -including translation of database-specific SQL error codes to meaningful exception -classes. For ORM technologies, see the next section for how to get the same exception -translation benefits. - -When it comes to transaction management, the `JdbcTemplate` class hooks in to the Spring -transaction support and supports both JTA and JDBC transactions, through respective -Spring transaction managers. For the supported ORM technologies Spring offers Hibernate, -JPA and JDO support through the Hibernate, JPA, and JDO transaction managers as well as -JTA support. For details on transaction support, see the <<transaction>> chapter. - - - -[[orm-exception-translation]] -==== Exception translation -When you use Hibernate, JPA, or JDO in a DAO, you must decide how to handle the -persistence technology's native exception classes. The DAO throws a subclass of a -`HibernateException`, `PersistenceException` or `JDOException` depending on the -technology. These exceptions are all run-time exceptions and do not have to be declared -or caught. You may also have to deal with `IllegalArgumentException` and -`IllegalStateException`. This means that callers can only treat exceptions as generally -fatal, unless they want to depend on the persistence technology's own exception -structure. Catching specific causes such as an optimistic locking failure is not -possible without tying the caller to the implementation strategy. This trade off might -be acceptable to applications that are strongly ORM-based and/or do not need any special -exception treatment. However, Spring enables exception translation to be applied -transparently through the `@Repository` annotation: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Repository - public class ProductDaoImpl implements ProductDao { - - // class body here... - - } ----- - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - <beans> - - <!-- Exception translation bean post processor --> - <bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"/> - - <bean id="myProductDao" class="product.ProductDaoImpl"/> - - </beans> ----- - -The postprocessor automatically looks for all exception translators (implementations of -the `PersistenceExceptionTranslator` interface) and advises all beans marked with the -`@Repository` annotation so that the discovered translators can intercept and apply the -appropriate translation on the thrown exceptions. - -In summary: you can implement DAOs based on the plain persistence technology's API and -annotations, while still benefiting from Spring-managed transactions, dependency -injection, and transparent exception conversion (if desired) to Spring's custom -exception hierarchies. - - - - -[[orm-hibernate]] -=== Hibernate -We will start with a coverage of http://www.hibernate.org/[Hibernate 3] in a Spring -environment, using it to demonstrate the approach that Spring takes towards integrating -O/R mappers. This section will cover many issues in detail and show different variations -of DAO implementations and transaction demarcation. Most of these patterns can be -directly translated to all other supported ORM tools. The following sections in this -chapter will then cover the other ORM technologies, showing briefer examples there. - -[NOTE] -==== -As of Spring 4.0, Spring requires Hibernate 3.6 or later. -==== - - - -[[orm-session-factory-setup]] -==== SessionFactory setup in a Spring container - -To avoid tying application objects to hard-coded resource lookups, you can define -resources such as a JDBC `DataSource` or a Hibernate `SessionFactory` as beans in the -Spring container. Application objects that need to access resources receive references -to such predefined instances through bean references, as illustrated in the DAO -definition in the next section. - -The following excerpt from an XML application context definition shows how to set up a -JDBC `DataSource` and a Hibernate `SessionFactory` on top of it: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - <beans> - - <bean id="myDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> - <property name="driverClassName" value="org.hsqldb.jdbcDriver"/> - <property name="url" value="jdbc:hsqldb:hsql://localhost:9001"/> - <property name="username" value="sa"/> - <property name="password" value=""/> - </bean> - - <bean id="mySessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"> - <property name="dataSource" ref="myDataSource"/> - <property name="mappingResources"> - <list> - <value>product.hbm.xml</value> - </list> - </property> - <property name="hibernateProperties"> - <value> - hibernate.dialect=org.hibernate.dialect.HSQLDialect - </value> - </property> - </bean> - - </beans> ----- - -Switching from a local Jakarta Commons DBCP `BasicDataSource` to a JNDI-located -`DataSource` (usually managed by an application server) is just a matter of -configuration: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - <beans> - <jee:jndi-lookup id="myDataSource" jndi-name="java:comp/env/jdbc/myds"/> - </beans> ----- - -You can also access a JNDI-located `SessionFactory`, using Spring's -`JndiObjectFactoryBean` / `<jee:jndi-lookup>` to retrieve and expose it. However, that -is typically not common outside of an EJB context. - - - -[[orm-hibernate-straight]] -==== Implementing DAOs based on plain Hibernate 3 API -Hibernate 3 has a feature called contextual sessions, wherein Hibernate itself manages -one current `Session` per transaction. This is roughly equivalent to Spring's -synchronization of one Hibernate `Session` per transaction. A corresponding DAO -implementation resembles the following example, based on the plain Hibernate API: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class ProductDaoImpl implements ProductDao { - - private SessionFactory sessionFactory; - - public void setSessionFactory(SessionFactory sessionFactory) { - this.sessionFactory = sessionFactory; - } - - public Collection loadProductsByCategory(String category) { - return this.sessionFactory.getCurrentSession() - .createQuery("from test.Product product where product.category=?") - .setParameter(0, category) - .list(); - } - } ----- - -This style is similar to that of the Hibernate reference documentation and examples, -except for holding the `SessionFactory` in an instance variable. We strongly recommend -such an instance-based setup over the old-school `static` `HibernateUtil` class from -Hibernate's CaveatEmptor sample application. (In general, do not keep any resources in -`static` variables unless __absolutely__ necessary.) - -The above DAO follows the dependency injection pattern: it fits nicely into a Spring IoC -container, just as it would if coded against Spring's `HibernateTemplate`. Of course, -such a DAO can also be set up in plain Java (for example, in unit tests). Simply -instantiate it and call `setSessionFactory(..)` with the desired factory reference. As a -Spring bean definition, the DAO would resemble the following: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - <beans> - - <bean id="myProductDao" class="product.ProductDaoImpl"> - <property name="sessionFactory" ref="mySessionFactory"/> - </bean> - - </beans> ----- - -The main advantage of this DAO style is that it depends on Hibernate API only; no import -of any Spring class is required. This is of course appealing from a non-invasiveness -perspective, and will no doubt feel more natural to Hibernate developers. - -However, the DAO throws plain `HibernateException` (which is unchecked, so does not have -to be declared or caught), which means that callers can only treat exceptions as -generally fatal - unless they want to depend on Hibernate's own exception hierarchy. -Catching specific causes such as an optimistic locking failure is not possible without -tying the caller to the implementation strategy. This trade off might be acceptable to -applications that are strongly Hibernate-based and/or do not need any special exception -treatment. - -Fortunately, Spring's `LocalSessionFactoryBean` supports Hibernate's -`SessionFactory.getCurrentSession()` method for any Spring transaction strategy, -returning the current Spring-managed transactional `Session` even with -`HibernateTransactionManager`. Of course, the standard behavior of that method remains -the return of the current `Session` associated with the ongoing JTA transaction, if any. -This behavior applies regardless of whether you are using Spring's -`JtaTransactionManager`, EJB container managed transactions (CMTs), or JTA. - -In summary: you can implement DAOs based on the plain Hibernate 3 API, while still being -able to participate in Spring-managed transactions. - - - -[[orm-hibernate-tx-declarative]] -==== Declarative transaction demarcation -We recommend that you use Spring's declarative transaction support, which enables you to -replace explicit transaction demarcation API calls in your Java code with an AOP -transaction interceptor. This transaction interceptor can be configured in a Spring -container using either Java annotations or XML.This declarative transaction capability -allows you to keep business services free of repetitive transaction demarcation code and -to focus on adding business logic, which is the real value of your application. - -[NOTE] -==== -Prior to continuing, you are __strongly__ encouraged to read <<transaction-declarative>> -if you have not done so. -==== - -Furthermore, transaction semantics like propagation behavior and isolation level can be -changed in a configuration file and do not affect the business service implementations. - -The following example shows how you can configure an AOP transaction interceptor, using -XML, for a simple service class: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - <?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:aop="http://www.springframework.org/schema/aop" - xmlns:tx="http://www.springframework.org/schema/tx" - xsi:schemaLocation=" - http://www.springframework.org/schema/beans - http://www.springframework.org/schema/beans/spring-beans.xsd - http://www.springframework.org/schema/tx - http://www.springframework.org/schema/tx/spring-tx.xsd - http://www.springframework.org/schema/aop - http://www.springframework.org/schema/aop/spring-aop.xsd"> - - <!-- SessionFactory, DataSource, etc. omitted --> - - <bean id="transactionManager" - class="org.springframework.orm.hibernate3.HibernateTransactionManager"> - <property name="sessionFactory" ref="sessionFactory"/> - </bean> - - <aop:config> - <aop:pointcut id="productServiceMethods" - expression="execution(* product.ProductService.*(..))"/> - <aop:advisor advice-ref="txAdvice" pointcut-ref="productServiceMethods"/> - </aop:config> - - <tx:advice id="txAdvice" transaction-manager="myTxManager"> - <tx:attributes> - <tx:method name="increasePrice*" propagation="REQUIRED"/> - <tx:method name="someOtherBusinessMethod" propagation="REQUIRES_NEW"/> - <tx:method name="*" propagation="SUPPORTS" read-only="true"/> - </tx:attributes> - </tx:advice> - - <bean id="myProductService" class="product.SimpleProductService"> - <property name="productDao" ref="myProductDao"/> - </bean> - - </beans> ----- - -This is the service class that is advised: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class ProductServiceImpl implements ProductService { - - private ProductDao productDao; - - public void setProductDao(ProductDao productDao) { - this.productDao = productDao; - } - - // notice the absence of transaction demarcation code in this method - // Spring's declarative transaction infrastructure will be demarcating - // transactions on your behalf - public void increasePriceOfAllProductsInCategory(final String category) { - List productsToChange = this.productDao.loadProductsByCategory(category); - // ... - } - } ----- - -We also show an attribute-support based configuration, in the following example. You -annotate the service layer with @Transactional annotations and instruct the Spring -container to find these annotations and provide transactional semantics for these -annotated methods. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class ProductServiceImpl implements ProductService { - - private ProductDao productDao; - - public void setProductDao(ProductDao productDao) { - this.productDao = productDao; - } - - @Transactional - public void increasePriceOfAllProductsInCategory(final String category) { - List productsToChange = this.productDao.loadProductsByCategory(category); - // ... - } - - @Transactional(readOnly = true) - public List<Product> findAllProducts() { - return this.productDao.findAllProducts(); - } - - } ----- - -As you can see from the following configuration example, the configuration is much -simplified, compared to the XML example above, while still providing the same -functionality driven by the annotations in the service layer code. All you need to -provide is the TransactionManager implementation and a "<tx:annotation-driven/>" entry. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - <?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:aop="http://www.springframework.org/schema/aop" - xmlns:tx="http://www.springframework.org/schema/tx" - xsi:schemaLocation=" - http://www.springframework.org/schema/beans - http://www.springframework.org/schema/beans/spring-beans.xsd - http://www.springframework.org/schema/tx - http://www.springframework.org/schema/tx/spring-tx.xsd - http://www.springframework.org/schema/aop - http://www.springframework.org/schema/aop/spring-aop.xsd"> - - <!-- SessionFactory, DataSource, etc. omitted --> - - <bean id="transactionManager" - class="org.springframework.orm.hibernate3.HibernateTransactionManager"> - <property name="sessionFactory" ref="sessionFactory"/> - </bean> - - <tx:annotation-driven/> - - <bean id="myProductService" class="product.SimpleProductService"> - <property name="productDao" ref="myProductDao"/> - </bean> - - </beans> ----- - - - -[[orm-hibernate-tx-programmatic]] -==== Programmatic transaction demarcation -You can demarcate transactions in a higher level of the application, on top of such -lower-level data access services spanning any number of operations. Nor do restrictions -exist on the implementation of the surrounding business service; it just needs a Spring -`PlatformTransactionManager`. Again, the latter can come from anywhere, but preferably -as a bean reference through a `setTransactionManager(..)` method, just as the -`productDAO` should be set by a `setProductDao(..)` method. The following snippets show -a transaction manager and a business service definition in a Spring application context, -and an example for a business method implementation: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - <beans> - - <bean id="myTxManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"> - <property name="sessionFactory" ref="mySessionFactory"/> - </bean> - - <bean id="myProductService" class="product.ProductServiceImpl"> - <property name="transactionManager" ref="myTxManager"/> - <property name="productDao" ref="myProductDao"/> - </bean> - - </beans> ----- - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class ProductServiceImpl implements ProductService { - - private TransactionTemplate transactionTemplate; - private ProductDao productDao; - - public void setTransactionManager(PlatformTransactionManager transactionManager) { - this.transactionTemplate = new TransactionTemplate(transactionManager); - } - - public void setProductDao(ProductDao productDao) { - this.productDao = productDao; - } - - public void increasePriceOfAllProductsInCategory(final String category) { - this.transactionTemplate.execute(new TransactionCallbackWithoutResult() { - public void doInTransactionWithoutResult(TransactionStatus status) { - List productsToChange = this.productDao.loadProductsByCategory(category); - // do the price increase... - } - }); - } - } ----- - -Spring's `TransactionInterceptor` allows any checked application exception to be thrown -with the callback code, while `TransactionTemplate` is restricted to unchecked -exceptions within the callback. `TransactionTemplate` triggers a rollback in case of an -unchecked application exception, or if the transaction is marked rollback-only by the -application (via `TransactionStatus`). `TransactionInterceptor` behaves the same way by -default but allows configurable rollback policies per method. - - - -[[orm-hibernate-tx-strategies]] -==== Transaction management strategies -Both `TransactionTemplate` and `TransactionInterceptor` delegate the actual transaction -handling to a `PlatformTransactionManager` instance, which can be a -`HibernateTransactionManager` (for a single Hibernate `SessionFactory`, using a -`ThreadLocal` `Session` under the hood) or a `JtaTransactionManager` (delegating to the -JTA subsystem of the container) for Hibernate applications. You can even use a custom -`PlatformTransactionManager` implementation. Switching from native Hibernate transaction -management to JTA, such as when facing distributed transaction requirements for certain -deployments of your application, is just a matter of configuration. Simply replace -the Hibernate transaction manager with Spring's JTA transaction implementation. Both -transaction demarcation and data access code will work without changes, because they -just use the generic transaction management APIs. - -For distributed transactions across multiple Hibernate session factories, simply combine -`JtaTransactionManager` as a transaction strategy with multiple -`LocalSessionFactoryBean` definitions. Each DAO then gets one specific `SessionFactory` -reference passed into its corresponding bean property. If all underlying JDBC data -sources are transactional container ones, a business service can demarcate transactions -across any number of DAOs and any number of session factories without special regard, as -long as it is using `JtaTransactionManager` as the strategy. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - <beans> - - <jee:jndi-lookup id="dataSource1" jndi-name="java:comp/env/jdbc/myds1"/> - - <jee:jndi-lookup id="dataSource2" jndi-name="java:comp/env/jdbc/myds2"/> - - <bean id="mySessionFactory1" - class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"> - <property name="dataSource" ref="myDataSource1"/> - <property name="mappingResources"> - <list> - <value>product.hbm.xml</value> - </list> - </property> - <property name="hibernateProperties"> - <value> - hibernate.dialect=org.hibernate.dialect.MySQLDialect - hibernate.show_sql=true - </value> - </property> - </bean> - - <bean id="mySessionFactory2" - class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"> - <property name="dataSource" ref="myDataSource2"/> - <property name="mappingResources"> - <list> - <value>inventory.hbm.xml</value> - </list> - </property> - <property name="hibernateProperties"> - <value> - hibernate.dialect=org.hibernate.dialect.OracleDialect - </value> - </property> - </bean> - - <bean id="myTxManager" class="org.springframework.transaction.jta.JtaTransactionManager"/> - - <bean id="myProductDao" class="product.ProductDaoImpl"> - <property name="sessionFactory" ref="mySessionFactory1"/> - </bean> - - <bean id="myInventoryDao" class="product.InventoryDaoImpl"> - <property name="sessionFactory" ref="mySessionFactory2"/> - </bean> - - <bean id="myProductService" class="product.ProductServiceImpl"> - <property name="productDao" ref="myProductDao"/> - <property name="inventoryDao" ref="myInventoryDao"/> - </bean> - - <aop:config> - <aop:pointcut id="productServiceMethods" - expression="execution(* product.ProductService.*(..))"/> - <aop:advisor advice-ref="txAdvice" pointcut-ref="productServiceMethods"/> - </aop:config> - - <tx:advice id="txAdvice" transaction-manager="myTxManager"> - <tx:attributes> - <tx:method name="increasePrice*" propagation="REQUIRED"/> - <tx:method name="someOtherBusinessMethod" propagation="REQUIRES_NEW"/> - <tx:method name="*" propagation="SUPPORTS" read-only="true"/> - </tx:attributes> - </tx:advice> - - </beans> ----- - -Both `HibernateTransactionManager` and `JtaTransactionManager` allow for proper -JVM-level cache handling with Hibernate, without container-specific transaction manager -lookup or a JCA connector (if you are not using EJB to initiate transactions). - -`HibernateTransactionManager` can export the Hibernate JDBC `Connection` to plain JDBC -access code, for a specific `DataSource`. This capability allows for high-level -transaction demarcation with mixed Hibernate and JDBC data access completely without -JTA, if you are accessing only one database. `HibernateTransactionManager` automatically -exposes the Hibernate transaction as a JDBC transaction if you have set up the passed-in -`SessionFactory` with a `DataSource` through the `dataSource` property of the -`LocalSessionFactoryBean` class. Alternatively, you can specify explicitly the -`DataSource` for which the transactions are supposed to be exposed through the -`dataSource` property of the `HibernateTransactionManager` class. - - - -[[orm-hibernate-resources]] -==== Comparing container-managed and locally defined resources -You can switch between a container-managed JNDI `SessionFactory` and a locally defined -one, without having to change a single line of application code. Whether to keep -resource definitions in the container or locally within the application is mainly a -matter of the transaction strategy that you use. Compared to a Spring-defined local -`SessionFactory`, a manually registered JNDI `SessionFactory` does not provide any -benefits. Deploying a `SessionFactory` through Hibernate's JCA connector provides the -added value of participating in the Java EE server's management infrastructure, but does -not add actual value beyond that. - -Spring's transaction support is not bound to a container. Configured with any strategy -other than JTA, transaction support also works in a stand-alone or test environment. -Especially in the typical case of single-database transactions, Spring's single-resource -local transaction support is a lightweight and powerful alternative to JTA. When you use -local EJB stateless session beans to drive transactions, you depend both on an EJB -container and JTA, even if you access only a single database, and only use stateless -session beans to provide declarative transactions through container-managed -transactions. Also, direct use of JTA programmatically requires a Java EE environment as -well. JTA does not involve only container dependencies in terms of JTA itself and of -JNDI `DataSource` instances. For non-Spring, JTA-driven Hibernate transactions, you have -to use the Hibernate JCA connector, or extra Hibernate transaction code with the -`TransactionManagerLookup` configured for proper JVM-level caching. - -Spring-driven transactions can work as well with a locally defined Hibernate -`SessionFactory` as they do with a local JDBC `DataSource` if they are accessing a -single database. Thus you only have to use Spring's JTA transaction strategy when you -have distributed transaction requirements. A JCA connector requires container-specific -deployment steps, and obviously JCA support in the first place. This configuration -requires more work than deploying a simple web application with local resource -definitions and Spring-driven transactions. Also, you often need the Enterprise Edition -of your container if you are using, for example, WebLogic Express, which does not -provide JCA. A Spring application with local resources and transactions spanning one -single database works in any Java EE web container (without JTA, JCA, or EJB) such as -Tomcat, Resin, or even plain Jetty. Additionally, you can easily reuse such a middle -tier in desktop applications or test suites. - -All things considered, if you do not use EJBs, stick with local `SessionFactory` setup -and Spring's `HibernateTransactionManager` or `JtaTransactionManager`. You get all of -the benefits, including proper transactional JVM-level caching and distributed -transactions, without the inconvenience of container deployment. JNDI registration of a -Hibernate `SessionFactory` through the JCA connector only adds value when used in -conjunction with EJBs. - - - -[[orm-hibernate-invalid-jdbc-access-error]] -==== Spurious application server warnings with Hibernate -In some JTA environments with very strict `XADataSource` implementations -- currently -only some WebLogic Server and WebSphere versions -- when Hibernate is configured without -regard to the JTA `PlatformTransactionManager` object for that environment, it is -possible for spurious warning or exceptions to show up in the application server log. -These warnings or exceptions indicate that the connection being accessed is no longer -valid, or JDBC access is no longer valid, possibly because the transaction is no longer -active. As an example, here is an actual exception from WebLogic: - -[literal] -[subs="verbatim,quotes"] ----- -java.sql.SQLException: The transaction is no longer active - status: 'Committed'. No -further JDBC access is allowed within this transaction. ----- - -You resolve this warning by simply making Hibernate aware of the JTA -`PlatformTransactionManager` instance, to which it will synchronize (along with Spring). -You have two options for doing this: - -* If in your application context you are already directly obtaining the JTA - `PlatformTransactionManager` object (presumably from JNDI through - `JndiObjectFactoryBean` or `<jee:jndi-lookup>`) and feeding it, for example, to - Spring's `JtaTransactionManager`, then the easiest way is to specify a reference to - the bean defining this JTA `PlatformTransactionManager` instance as the value of the - `jtaTransactionManager` property for `LocalSessionFactoryBean.` Spring then makes the - object available to Hibernate. -* More likely you do not already have the JTA `PlatformTransactionManager` instance, - because Spring's `JtaTransactionManager` can find it itself. Thus you need to - configure Hibernate to look up JTA `PlatformTransactionManager` directly. You do this - by configuring an application server- specific `TransactionManagerLookup` class in the - Hibernate configuration, as described in the Hibernate manual. - -The remainder of this section describes the sequence of events that occur with and -without Hibernate's awareness of the JTA `PlatformTransactionManager`. - -When Hibernate is not configured with any awareness of the JTA -`PlatformTransactionManager`, the following events occur when a JTA transaction commits: - -* The JTA transaction commits. -* Spring's `JtaTransactionManager` is synchronized to the JTA transaction, so it is - called back through an __afterCompletion__ callback by the JTA transaction manager. -* Among other activities, this synchronization can trigger a callback by Spring to - Hibernate, through Hibernate's `afterTransactionCompletion` callback (used to clear - the Hibernate cache), followed by an explicit `close()` call on the Hibernate Session, - which causes Hibernate to attempt to `close()` the JDBC Connection. -* In some environments, this `Connection.close()` call then triggers the warning or - error, as the application server no longer considers the `Connection` usable at all, - because the transaction has already been committed. - -When Hibernate is configured with awareness of the JTA `PlatformTransactionManager`, the -following events occur when a JTA transaction commits: - -* the JTA transaction is ready to commit. -* Spring's `JtaTransactionManager` is synchronized to the JTA transaction, so the - transaction is called back through a __beforeCompletion__ callback by the JTA - transaction manager. -* Spring is aware that Hibernate itself is synchronized to the JTA transaction, and - behaves differently than in the previous scenario. Assuming the Hibernate `Session` - needs to be closed at all, Spring will close it now. -* The JTA transaction commits. -* Hibernate is synchronized to the JTA transaction, so the transaction is called back - through an __afterCompletion__ callback by the JTA transaction manager, and can - properly clear its cache. - - - - -[[orm-jdo]] -=== JDO -Spring supports the standard JDO 2.0 and 2.1 APIs as data access strategy, following the -same style as the Hibernate support. The corresponding integration classes reside in the -`org.springframework.orm.jdo` package. - - - -[[orm-jdo-setup]] -==== PersistenceManagerFactory setup - -Spring provides a `LocalPersistenceManagerFactoryBean` class that allows you to define a -local JDO `PersistenceManagerFactory` within a Spring application context: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - <beans> - - <bean id="myPmf" class="org.springframework.orm.jdo.LocalPersistenceManagerFactoryBean"> - <property name="configLocation" value="classpath:kodo.properties"/> - </bean> - - </beans> ----- - -Alternatively, you can set up a `PersistenceManagerFactory` through direct instantiation -of a `PersistenceManagerFactory` implementation class. A JDO `PersistenceManagerFactory` -implementation class follows the JavaBeans pattern, just like a JDBC `DataSource` -implementation class, which is a natural fit for a configuration that uses Spring. This -setup style usually supports a Spring-defined JDBC `DataSource`, passed into the -`connectionFactory` property. For example, for the open source JDO implementation -DataNucleus (formerly JPOX) ( http://www.datanucleus.org/[http://www.datanucleus.org/]), -this is the XML configuration of the `PersistenceManagerFactory` implementation: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - <beans> - - <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> - - <bean id="myPmf" class="org.datanucleus.jdo.JDOPersistenceManagerFactory" destroy-method="close"> - <property name="connectionFactory" ref="dataSource"/> - <property name="nontransactionalRead" value="true"/> - </bean> - - </beans> ----- - -You can also set up JDO `PersistenceManagerFactory` in the JNDI environment of a Java EE -application server, usually through the JCA connector provided by the particular JDO -implementation. Spring's standard `JndiObjectFactoryBean` or `<jee:jndi-lookup>` can be -used to retrieve and expose such a `PersistenceManagerFactory`. However, outside an EJB -context, no real benefit exists in holding the `PersistenceManagerFactory` in JNDI: only -choose such a setup for a good reason. See <<orm-hibernate-resources>> for a discussion; -the arguments there apply to JDO as well. - - - -[[orm-jdo-daos-straight]] -==== Implementing DAOs based on the plain JDO API -DAOs can also be written directly against plain JDO API, without any Spring -dependencies, by using an injected `PersistenceManagerFactory`. The following is an -example of a corresponding DAO implementation: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class ProductDaoImpl implements ProductDao { - - private PersistenceManagerFactory persistenceManagerFactory; - - public void setPersistenceManagerFactory(PersistenceManagerFactory pmf) { - this.persistenceManagerFactory = pmf; - } - - public Collection loadProductsByCategory(String category) { - PersistenceManager pm = this.persistenceManagerFactory.getPersistenceManager(); - try { - Query query = pm.newQuery(Product.class, "category = pCategory"); - query.declareParameters("String pCategory"); - return query.execute(category); - } - finally { - pm.close(); - } - } - } ----- - -Because the above DAO follows the dependency injection pattern, it fits nicely into a -Spring container, just as it would if coded against Spring's `JdoTemplate`: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - <beans> - - <bean id="myProductDao" class="product.ProductDaoImpl"> - <property name="persistenceManagerFactory" ref="myPmf"/> - </bean> - - </beans> ----- - -The main problem with such DAOs is that they always get a new `PersistenceManager` from -the factory. To access a Spring-managed transactional `PersistenceManager`, define a -`TransactionAwarePersistenceManagerFactoryProxy` (as included in Spring) in front of -your target `PersistenceManagerFactory`, then passing a reference to that proxy into -your DAOs as in the following example: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - <beans> - - <bean id="myPmfProxy" - class="org.springframework.orm.jdo.TransactionAwarePersistenceManagerFactoryProxy"> - <property name="targetPersistenceManagerFactory" ref="myPmf"/> - </bean> - - <bean id="myProductDao" class="product.ProductDaoImpl"> - <property name="persistenceManagerFactory" ref="myPmfProxy"/> - </bean> - - </beans> ----- - -Your data access code will receive a transactional `PersistenceManager` (if any) from -the `PersistenceManagerFactory.getPersistenceManager()` method that it calls. The latter -method call goes through the proxy, which first checks for a current transactional -`PersistenceManager` before getting a new one from the factory. Any `close()` calls on -the `PersistenceManager` are ignored in case of a transactional `PersistenceManager`. - -If your data access code always runs within an active transaction (or at least within -active transaction synchronization), it is safe to omit the `PersistenceManager.close()` -call and thus the entire `finally` block, which you might do to keep your DAO -implementations concise: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class ProductDaoImpl implements ProductDao { - - private PersistenceManagerFactory persistenceManagerFactory; - - public void setPersistenceManagerFactory(PersistenceManagerFactory pmf) { - this.persistenceManagerFactory = pmf; - } - - public Collection loadProductsByCategory(String category) { - PersistenceManager pm = this.persistenceManagerFactory.getPersistenceManager(); - Query query = pm.newQuery(Product.class, "category = pCategory"); - query.declareParameters("String pCategory"); - return query.execute(category); - } - } ----- - -With such DAOs that rely on active transactions, it is recommended that you enforce -active transactions through turning off -`TransactionAwarePersistenceManagerFactoryProxy`'s `allowCreate` flag: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - <beans> - - <bean id="myPmfProxy" - class="org.springframework.orm.jdo.TransactionAwarePersistenceManagerFactoryProxy"> - <property name="targetPersistenceManagerFactory" ref="myPmf"/> - <property name="allowCreate" value="false"/> - </bean> - - <bean id="myProductDao" class="product.ProductDaoImpl"> - <property name="persistenceManagerFactory" ref="myPmfProxy"/> - </bean> - - </beans> ----- - -The main advantage of this DAO style is that it depends on JDO API only; no import of -any Spring class is required. This is of course appealing from a non-invasiveness -perspective, and might feel more natural to JDO developers. - -However, the DAO throws plain `JDOException` (which is unchecked, so does not have to be -declared or caught), which means that callers can only treat exceptions as fatal, unless -you want to depend on JDO's own exception structure. Catching specific causes such as an -optimistic locking failure is not possible without tying the caller to the -implementation strategy. This trade off might be acceptable to applications that are -strongly JDO-based and/or do not need any special exception treatment. - -In summary, you can DAOs based on the plain JDO API, and they can still participate in -Spring-managed transactions. This strategy might appeal to you if you are already -familiar with JDO. However, such DAOs throw plain `JDOException`, and you would have to -convert explicitly to Spring's `DataAccessException` (if desired). - - - -[[orm-jdo-tx]] -==== Transaction management -[NOTE] -==== -You are __strongly__ encouraged to read <<transaction-declarative>> if you have not done -so, to get a more detailed coverage of Spring's declarative transaction support. -==== - -To execute service operations within transactions, you can use Spring's common -declarative transaction facilities. For example: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - <?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:aop="http://www.springframework.org/schema/aop" - xmlns:tx="http://www.springframework.org/schema/tx" - xsi:schemaLocation=" - http://www.springframework.org/schema/beans - http://www.springframework.org/schema/beans/spring-beans.xsd - http://www.springframework.org/schema/tx - http://www.springframework.org/schema/tx/spring-tx.xsd - http://www.springframework.org/schema/aop - http://www.springframework.org/schema/aop/spring-aop.xsd"> - - <bean id="myTxManager" class="org.springframework.orm.jdo.JdoTransactionManager"> - <property name="persistenceManagerFactory" ref="myPmf"/> - </bean> - - <bean id="myProductService" class="product.ProductServiceImpl"> - <property name="productDao" ref="myProductDao"/> - </bean> - - <tx:advice id="txAdvice" transaction-manager="txManager"> - <tx:attributes> - <tx:method name="increasePrice*" propagation="REQUIRED"/> - <tx:method name="someOtherBusinessMethod" propagation="REQUIRES_NEW"/> - <tx:method name="*" propagation="SUPPORTS" read-only="true"/> - </tx:attributes> - </tx:advice> - - <aop:config> - <aop:pointcut id="productServiceMethods" - expression="execution(* product.ProductService.*(..))"/> - <aop:advisor advice-ref="txAdvice" pointcut-ref="productServiceMethods"/> - </aop:config> - - </beans> ----- - -JDO requires an active transaction to modify a persistent object. The non-transactional -flush concept does not exist in JDO, in contrast to Hibernate. For this reason, you need -to set up the chosen JDO implementation for a specific environment. Specifically, you -need to set it up explicitly for JTA synchronization, to detect an active JTA -transaction itself. This is not necessary for local transactions as performed by -Spring's `JdoTransactionManager`, but it is necessary to participate in JTA -transactions, whether driven by Spring's `JtaTransactionManager` or by EJB CMT and plain -JTA. - -`JdoTransactionManager` is capable of exposing a JDO transaction to JDBC access code -that accesses the same JDBC `DataSource`, provided that the registered `JdoDialect` -supports retrieval of the underlying JDBC `Connection`. This is the case for JDBC-based -JDO 2.0 implementations by default. - - - -[[orm-jdo-dialect]] -==== JdoDialect - -As an advanced feature, both `JdoTemplate` and `JdoTransactionManager` support a custom -`JdoDialect` that can be passed into the `jdoDialect` bean property. In this scenario, -the DAOs will not receive a `PersistenceManagerFactory` reference but rather a full -`JdoTemplate` instance (for example, passed into the `jdoTemplate` property of -`JdoDaoSupport`). Using a `JdoDialect` implementation, you can enable advanced features -supported by Spring, usually in a vendor-specific manner: - -* Applying specific transaction semantics such as custom isolation level or transaction - timeout -* Retrieving the transactional JDBC `Connection` for exposure to JDBC-based DAOs -* Applying query timeouts, which are automatically calculated from Spring-managed - transaction timeouts -* Eagerly flushing a `PersistenceManager,` to make transactional changes visible to - JDBC-based data access code -* Advanced translation of `JDOExceptions` to Spring `DataAccessExceptions` - -See the `JdoDialect` javadocs for more details on its operations and how to use them -within Spring's JDO support. - - - - -[[orm-jpa]] -=== JPA -The Spring JPA, available under the `org.springframework.orm.jpa` package, offers -comprehensive support for the -http://www.oracle.com/technetwork/articles/javaee/jpa-137156.html[Java Persistence -API] in a similar manner to the integration with Hibernate or JDO, while being aware of -the underlying implementation in order to provide additional features. - - - -[[orm-jpa-setup]] -==== Three options for JPA setup in a Spring environment -The Spring JPA support offers three ways of setting up the JPA `EntityManagerFactory` -that will be used by the application to obtain an entity manager. - - -[[orm-jpa-setup-lemfb]] -===== LocalEntityManagerFactoryBean - -[NOTE] -==== -Only use this option in simple deployment environments such as stand-alone applications -and integration tests. -==== - -The `LocalEntityManagerFactoryBean` creates an `EntityManagerFactory` suitable for -simple deployment environments where the application uses only JPA for data access. The -factory bean uses the JPA `PersistenceProvider` autodetection mechanism (according to -JPA's Java SE bootstrapping) and, in most cases, requires you to specify only the -persistence unit name: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - <beans> - <bean id="myEmf" class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean"> - <property name="persistenceUnitName" value="myPersistenceUnit"/> - </bean> - </beans> ----- - -This form of JPA deployment is the simplest and the most limited. You cannot refer to an -existing JDBC `DataSource` bean definition and no support for global transactions -exists. Furthermore, weaving (byte-code transformation) of persistent classes is -provider-specific, often requiring a specific JVM agent to specified on startup. This -option is sufficient only for stand-alone applications and test environments, for which -the JPA specification is designed. - - -[[orm-jpa-setup-jndi]] -===== Obtaining an EntityManagerFactory from JNDI - -[NOTE] -==== -Use this option when deploying to a Java EE 5 server. Check your server's documentation -on how to deploy a custom JPA provider into your server, allowing for a different -provider than the server's default. -==== - -Obtaining an `EntityManagerFactory` from JNDI (for example in a Java EE 5 environment), -is simply a matter of changing the XML configuration: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - <beans> - <jee:jndi-lookup id="myEmf" jndi-name="persistence/myPersistenceUnit"/> - </beans> ----- - -This action assumes standard Java EE 5 bootstrapping: the Java EE server autodetects -persistence units (in effect, `META-INF/persistence.xml` files in application jars) and -`persistence-unit-ref` entries in the Java EE deployment descriptor (for example, -`web.xml`) and defines environment naming context locations for those persistence units. - -In such a scenario, the entire persistence unit deployment, including the weaving -(byte-code transformation) of persistent classes, is up to the Java EE server. The JDBC -`DataSource` is defined through a JNDI location in the `META-INF/persistence.xml` file; -EntityManager transactions are integrated with the server's JTA subsystem. Spring merely -uses the obtained `EntityManagerFactory`, passing it on to application objects through -dependency injection, and managing transactions for the persistence unit, typically -through `JtaTransactionManager`. - -If multiple persistence units are used in the same application, the bean names of such -JNDI-retrieved persistence units should match the persistence unit names that the -application uses to refer to them, for example, in `@PersistenceUnit` and -`@PersistenceContext` annotations. - - -[[orm-jpa-setup-lcemfb]] -===== LocalContainerEntityManagerFactoryBean - -[NOTE] -==== -Use this option for full JPA capabilities in a Spring-based application environment. -This includes web containers such as Tomcat as well as stand-alone applications and -integration tests with sophisticated persistence requirements. -==== - -The `LocalContainerEntityManagerFactoryBean` gives full control over -`EntityManagerFactory` configuration and is appropriate for environments where -fine-grained customization is required. The `LocalContainerEntityManagerFactoryBean` -creates a `PersistenceUnitInfo` instance based on the `persistence.xml` file, the -supplied `dataSourceLookup` strategy, and the specified `loadTimeWeaver`. It is thus -possible to work with custom data sources outside of JNDI and to control the weaving -process. The following example shows a typical bean definition for a -`LocalContainerEntityManagerFactoryBean`: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - <beans> - <bean id="myEmf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> - <property name="dataSource" ref="someDataSource"/> - <property name="loadTimeWeaver"> - <bean class="org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver"/> - </property> - </bean> - </beans> ----- - -The following example shows a typical `persistence.xml` file: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - <persistence xmlns="http://java.sun.com/xml/ns/persistence" version="1.0"> - <persistence-unit name="myUnit" transaction-type="RESOURCE_LOCAL"> - <mapping-file>META-INF/orm.xml</mapping-file> - <exclude-unlisted-classes/> - </persistence-unit> - </persistence> ----- - -[NOTE] -==== -The `exclude-unlisted-classes` element always indicates that __no__ scanning for -annotated entity classes is supposed to occur, in order to support the -`<exclude-unlisted-classes/>` shortcut. This is in line with the JPA specification, -which suggests that shortcut, but unfortunately is in conflict with the JPA XSD, which -implies `false` for that shortcut. Consequently, `<exclude-unlisted-classes> false -</exclude-unlisted-classes/>` is not supported. Simply omit the -`exclude-unlisted-classes` element if you want entity class scanning to occur. -==== - -Using the `LocalContainerEntityManagerFactoryBean` is the most powerful JPA setup -option, allowing for flexible local configuration within the application. It supports -links to an existing JDBC `DataSource`, supports both local and global transactions, and -so on. However, it also imposes requirements on the runtime environment, such as the -availability of a weaving-capable class loader if the persistence provider demands -byte-code transformation. - -This option may conflict with the built-in JPA capabilities of a Java EE 5 server. In a -full Java EE 5 environment, consider obtaining your `EntityManagerFactory` from JNDI. -Alternatively, specify a custom `persistenceXmlLocation` on your -`LocalContainerEntityManagerFactoryBean` definition, for example, -META-INF/my-persistence.xml, and only include a descriptor with that name in your -application jar files. Because the Java EE 5 server only looks for default -`META-INF/persistence.xml` files, it ignores such custom persistence units and hence -avoid conflicts with a Spring-driven JPA setup upfront. (This applies to Resin 3.1, for -example.) - -.When is load-time weaving required? -**** -Not all JPA providers require a JVM agent ; Hibernate is an example of one that does -not. If your provider does not require an agent or you have other alternatives, such as -applying enhancements at build time through a custom compiler or an ant task, the -load-time weaver __should not__ be used. -**** - -The `LoadTimeWeaver` interface is a Spring-provided class that allows JPA -`ClassTransformer` instances to be plugged in a specific manner, depending whether the -environment is a web container or application server. Hooking `ClassTransformers` -through an -http://docs.oracle.com/javase/6/docs/api/java/lang/instrument/package-summary.html[agent] -typically is not efficient. The agents work against the __entire virtual machine__ and -inspect __every__ class that is loaded, which is usually undesirable in a production -server environment. - -Spring provides a number of `LoadTimeWeaver` implementations for various environments, -allowing `ClassTransformer` instances to be applied only __per class loader__ and not -per VM. - -Refer to <<aop-aj-ltw-spring>> in the AOP chapter for more insight regarding the -`LoadTimeWeaver` implementations and their setup, either generic or customized to -various platforms (such as Tomcat, WebLogic, GlassFish, Resin and JBoss). - -As described in the aforementioned section, you can configure a context-wide -`LoadTimeWeaver` using the `@EnableLoadTimeWeaving` annotation of -`context:load-time-weaver` XML element. Such a global weaver is picked up by all JPA -`LocalContainerEntityManagerFactoryBeans` automatically. This is the preferred way of -setting up a load-time weaver, delivering autodetection of the platform (WebLogic, -GlassFish, Tomcat, Resin, JBoss or VM agent) and automatic propagation of the weaver to -all weaver-aware beans: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - <context:load-time-weaver/> - <bean id="emf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> - ... - </bean> ----- - -However, if needed, one can manually specify a dedicated weaver through the -`loadTimeWeaver` property: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - <bean id="emf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> - <property name="loadTimeWeaver"> - <bean class="org.springframework.instrument.classloading.ReflectiveLoadTimeWeaver"/> - </property> - </bean> ----- - -No matter how the LTW is configured, using this technique, JPA applications relying on -instrumentation can run in the target platform (ex: Tomcat) without needing an agent. -This is important especially when the hosting applications rely on different JPA -implementations because the JPA transformers are applied only at class loader level and -thus are isolated from each other. - - -[[orm-jpa-multiple-pu]] -===== Dealing with multiple persistence units -For applications that rely on multiple persistence units locations, stored in various -JARS in the classpath, for example, Spring offers the `PersistenceUnitManager` to act as -a central repository and to avoid the persistence units discovery process, which can be -expensive. The default implementation allows multiple locations to be specified that are -parsed and later retrieved through the persistence unit name. (By default, the classpath -is searched for `META-INF/persistence.xml` files.) - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - <bean id="pum" class="org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager"> - <property name="persistenceXmlLocations"> - <list> - <value>org/springframework/orm/jpa/domain/persistence-multi.xml</value> - <value>classpath:/my/package/**/custom-persistence.xml</value> - <value>classpath*:META-INF/persistence.xml</value> - </list> - </property> - <property name="dataSources"> - <map> - <entry key="localDataSource" value-ref="local-db"/> - <entry key="remoteDataSource" value-ref="remote-db"/> - </map> - </property> - <!-- if no datasource is specified, use this one --> - <property name="defaultDataSource" ref="remoteDataSource"/> - </bean> - - <bean id="emf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> - <property name="persistenceUnitManager" ref="pum"/> - <property name="persistenceUnitName" value="myCustomUnit"/> - </bean> ----- - -The default implementation allows customization of the `PersistenceUnitInfo` instances, -before they are fed to the JPA provider, declaratively through its properties, which -affect __all__ hosted units, or programmatically, through the -`PersistenceUnitPostProcessor`, which allows persistence unit selection. If no -`PersistenceUnitManager` is specified, one is created and used internally by -`LocalContainerEntityManagerFactoryBean`. - - - -[[orm-jpa-straight]] -==== Implementing DAOs based on plain JPA -[NOTE] -==== -Although `EntityManagerFactory` instances are thread-safe, `EntityManager` instances are -not. The injected JPA `EntityManager` behaves like an `EntityManager` fetched from an -application server's JNDI environment, as defined by the JPA specification. It delegates -all calls to the current transactional `EntityManager`, if any; otherwise, it falls back -to a newly created `EntityManager` per operation, in effect making its usage thread-safe. -==== - -It is possible to write code against the plain JPA without any Spring dependencies, by -using an injected `EntityManagerFactory` or `EntityManager`. Spring can understand -`@PersistenceUnit` and `@PersistenceContext` annotations both at field and method level -if a `PersistenceAnnotationBeanPostProcessor` is enabled. A plain JPA DAO implementation -using the `@PersistenceUnit` annotation might look like this: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class ProductDaoImpl implements ProductDao { - - private EntityManagerFactory emf; - - @PersistenceUnit - public void setEntityManagerFactory(EntityManagerFactory emf) { - this.emf = emf; - } - - public Collection loadProductsByCategory(String category) { - EntityManager em = this.emf.createEntityManager(); - try { - Query query = em.createQuery("from Product as p where p.category = ?1"); - query.setParameter(1, category); - return query.getResultList(); - } - finally { - if (em != null) { - em.close(); - } - } - } - } ----- - -The DAO above has no dependency on Spring and still fits nicely into a Spring -application context. Moreover, the DAO takes advantage of annotations to require the -injection of the default `EntityManagerFactory`: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - <beans> - - <!-- bean post-processor for JPA annotations --> - <bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"/> - - <bean id="myProductDao" class="product.ProductDaoImpl"/> - - </beans> ----- - -As an alternative to defining a `PersistenceAnnotationBeanPostProcessor` explicitly, -consider using the Spring `context:annotation-config` XML element in your application -context configuration. Doing so automatically registers all Spring standard -post-processors for annotation-based configuration, including -`CommonAnnotationBeanPostProcessor` and so on. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - <beans> - - <!-- post-processors for all standard config annotations --> - <context:annotation-config/> - - <bean id="myProductDao" class="product.ProductDaoImpl"/> - - </beans> ----- - -The main problem with such a DAO is that it always creates a new `EntityManager` through -the factory. You can avoid this by requesting a transactional `EntityManager` (also -called "shared EntityManager" because it is a shared, thread-safe proxy for the actual -transactional EntityManager) to be injected instead of the factory: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class ProductDaoImpl implements ProductDao { - - @PersistenceContext - private EntityManager em; - - public Collection loadProductsByCategory(String category) { - Query query = em.createQuery("from Product as p where p.category = :category"); - query.setParameter("category", category); - return query.getResultList(); - } - } ----- - -The `@PersistenceContext` annotation has an optional attribute `type`, which defaults to -`PersistenceContextType.TRANSACTION`. This default is what you need to receive a shared -EntityManager proxy. The alternative, `PersistenceContextType.EXTENDED`, is a completely -different affair: This results in a so-called extended EntityManager, which is __not -thread-safe__ and hence must not be used in a concurrently accessed component such as a -Spring-managed singleton bean. Extended EntityManagers are only supposed to be used in -stateful components that, for example, reside in a session, with the lifecycle of the -EntityManager not tied to a current transaction but rather being completely up to the -application. - -.Method- and field-level Injection -**** -Annotations that indicate dependency injections (such as `@PersistenceUnit` and -`@PersistenceContext`) can be applied on field or methods inside a class, hence the -expressions __method-level injection__ and __field-level injection__. Field-level -annotations are concise and easier to use while method-level allows for further -processing of the injected dependency. In both cases the member visibility (public, -protected, private) does not matter. - -What about class-level annotations? - -On the Java EE 5 platform, they are used for dependency declaration and not for resource -injection. -**** - -The injected `EntityManager` is Spring-managed (aware of the ongoing transaction). It is -important to note that even though the new DAO implementation uses method level -injection of an `EntityManager` instead of an `EntityManagerFactory`, no change is -required in the application context XML due to annotation usage. - -The main advantage of this DAO style is that it only depends on Java Persistence API; no -import of any Spring class is required. Moreover, as the JPA annotations are understood, -the injections are applied automatically by the Spring container. This is appealing from -a non-invasiveness perspective, and might feel more natural to JPA developers. - - - -[[orm-jpa-tx]] -==== Transaction Management -[NOTE] -==== -You are __strongly__ encouraged to read <<transaction-declarative>> if you have not done -so, to get a more detailed coverage of Spring's declarative transaction support. -==== - -To execute service operations within transactions, you can use Spring's common -declarative transaction facilities. For example: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - <?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:aop="http://www.springframework.org/schema/aop" - xmlns:tx="http://www.springframework.org/schema/tx" - xsi:schemaLocation=" - http://www.springframework.org/schema/beans - http://www.springframework.org/schema/beans/spring-beans.xsd - http://www.springframework.org/schema/tx - http://www.springframework.org/schema/tx/spring-tx.xsd - http://www.springframework.org/schema/aop - http://www.springframework.org/schema/aop/spring-aop.xsd"> - - <bean id="myTxManager" class="org.springframework.orm.jpa.JpaTransactionManager"> - <property name="entityManagerFactory" ref="myEmf"/> - </bean> - - <bean id="myProductService" class="product.ProductServiceImpl"> - <property name="productDao" ref="myProductDao"/> - </bean> - - <aop:config> - <aop:pointcut id="productServiceMethods" expression="execution(* product.ProductService.*(..))"/> - <aop:advisor advice-ref="txAdvice" pointcut-ref="productServiceMethods"/> - </aop:config> - - <tx:advice id="txAdvice" transaction-manager="myTxManager"> - <tx:attributes> - <tx:method name="increasePrice*" propagation="REQUIRED"/> - <tx:method name="someOtherBusinessMethod" propagation="REQUIRES_NEW"/> - <tx:method name="*" propagation="SUPPORTS" read-only="true"/> - </tx:attributes> - </tx:advice> - - </beans> ----- - -Spring JPA allows a configured `JpaTransactionManager` to expose a JPA transaction to -JDBC access code that accesses the same JDBC `DataSource`, provided that the registered -`JpaDialect` supports retrieval of the underlying JDBC `Connection`. Out of the box, -Spring provides dialects for the Toplink, Hibernate and OpenJPA JPA implementations. See -the next section for details on the `JpaDialect` mechanism. - - - -[[orm-jpa-dialect]] -==== JpaDialect - -As an advanced feature `JpaTemplate`, `JpaTransactionManager` and subclasses of -`AbstractEntityManagerFactoryBean` support a custom `JpaDialect`, to be passed into the -`jpaDialect` bean property. In such a scenario, the DAOs do not receive an -`EntityManagerFactory` reference but rather a full `JpaTemplate` instance (for example, -passed into the `jpaTemplate` property of `JpaDaoSupport`). A `JpaDialect` -implementation can enable some advanced features supported by Spring, usually in a -vendor-specific manner: - -* Applying specific transaction semantics such as custom isolation level or transaction - timeout) -* Retrieving the transactional JDBC `Connection` for exposure to JDBC-based DAOs) -* Advanced translation of `PersistenceExceptions` to Spring `DataAccessExceptions` - -This is particularly valuable for special transaction semantics and for advanced -translation of exception. The default implementation used ( `DefaultJpaDialect`) does -not provide any special capabilities and if the above features are required, you have to -specify the appropriate dialect. - -See the `JpaDialect` javadocs for more details of its operations and how they are used -within Spring's JPA support. - - - - - -[[oxm]] -== Marshalling XML using O/X Mappers - - - - -[[oxm-introduction]] -=== Introduction -In this chapter, we will describe Spring's Object/XML Mapping support. Object/XML -Mapping, or O/X mapping for short, is the act of converting an XML document to and from -an object. This conversion process is also known as XML Marshalling, or XML -Serialization. This chapter uses these terms interchangeably. - -Within the field of O/X mapping, a __marshaller__ is responsible for serializing an -object (graph) to XML. In similar fashion, an __unmarshaller__ deserializes the XML to -an object graph. This XML can take the form of a DOM document, an input or output -stream, or a SAX handler. - -Some of the benefits of using Spring for your O/X mapping needs are: - - - -==== Ease of configuration -Spring's bean factory makes it easy to configure marshallers, without needing to -construct JAXB context, JiBX binding factories, etc. The marshallers can be configured -as any other bean in your application context. Additionally, XML Schema-based -configuration is available for a number of marshallers, making the configuration even -simpler. - - - -==== Consistent Interfaces -Spring's O/X mapping operates through two global interfaces: the `Marshaller` and -`Unmarshaller` interface. These abstractions allow you to switch O/X mapping frameworks -with relative ease, with little or no changes required on the classes that do the -marshalling. This approach has the additional benefit of making it possible to do XML -marshalling with a mix-and-match approach (e.g. some marshalling performed using JAXB, -other using XMLBeans) in a non-intrusive fashion, leveraging the strength of each -technology. - - - -==== Consistent Exception Hierarchy -Spring provides a conversion from exceptions from the underlying O/X mapping tool to its -own exception hierarchy with the `XmlMappingException` as the root exception. As can be -expected, these runtime exceptions wrap the original exception so no information is lost. - - - - -[[oxm-marshaller-unmarshaller]] -=== Marshaller and Unmarshaller -As stated in the introduction, a __marshaller__ serializes an object to XML, and an -__unmarshaller__ deserializes XML stream to an object. In this section, we will describe -the two Spring interfaces used for this purpose. - - - -[[oxm-marshaller]] -==== Marshaller -Spring abstracts all marshalling operations behind the -`org.springframework.oxm.Marshaller` interface, the main methods of which is listed -below. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public interface Marshaller { - - /** - * Marshals the object graph with the given root into the provided Result. - */ - void marshal(Object graph, Result result) throws XmlMappingException, IOException; - - } ----- - -The `Marshaller` interface has one main method, which marshals the given object to a -given `javax.xml.transform.Result`. Result is a tagging interface that basically -represents an XML output abstraction: concrete implementations wrap various XML -representations, as indicated in the table below. - -[[oxm-marshller-tbl]] -|=== -| Result implementation| Wraps XML representation - -| `DOMResult` -| `org.w3c.dom.Node` - -| `SAXResult` -| `org.xml.sax.ContentHandler` - -| `StreamResult` -| `java.io.File`, `java.io.OutputStream`, or `java.io.Writer` -|=== - -[NOTE] -==== -Although the `marshal()` method accepts a plain object as its first parameter, most -`Marshaller` implementations cannot handle arbitrary objects. Instead, an object class -must be mapped in a mapping file, marked with an annotation, registered with the -marshaller, or have a common base class. Refer to the further sections in this chapter -to determine how your O/X technology of choice manages this. -==== - - - -[[oxm-unmarshaller]] -==== Unmarshaller -Similar to the `Marshaller`, there is the `org.springframework.oxm.Unmarshaller` -interface. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public interface Unmarshaller { - - /** - * Unmarshals the given provided Source into an object graph. - */ - Object unmarshal(Source source) throws XmlMappingException, IOException; - } ----- - -This interface also has one method, which reads from the given -`javax.xml.transform.Source` (an XML input abstraction), and returns the object read. As -with Result, Source is a tagging interface that has three concrete implementations. Each -wraps a different XML representation, as indicated in the table below. - -[[oxm-unmarshller-tbl]] -|=== -| Source implementation| Wraps XML representation - -| `DOMSource` -| `org.w3c.dom.Node` - -| `SAXSource` -| `org.xml.sax.InputSource`, and `org.xml.sax.XMLReader` - -| `StreamSource` -| `java.io.File`, `java.io.InputStream`, or `java.io.Reader` -|=== - -Even though there are two separate marshalling interfaces ( `Marshaller` and -`Unmarshaller`), all implementations found in Spring-WS implement both in one class. -This means that you can wire up one marshaller class and refer to it both as a -marshaller and an unmarshaller in your `applicationContext.xml`. - - - -[[oxm-xmlmappingexception]] -==== XmlMappingException -Spring converts exceptions from the underlying O/X mapping tool to its own exception -hierarchy with the `XmlMappingException` as the root exception. As can be expected, -these runtime exceptions wrap the original exception so no information will be lost. - -Additionally, the `MarshallingFailureException` and `UnmarshallingFailureException` -provide a distinction between marshalling and unmarshalling operations, even though the -underlying O/X mapping tool does not do so. - -The O/X Mapping exception hierarchy is shown in the following figure: -image::images/oxm-exceptions.png[width=400] - -O/X Mapping exception hierarchy - - - - -[[oxm-usage]] -=== Using Marshaller and Unmarshaller -Spring's OXM can be used for a wide variety of situations. In the following example, we -will use it to marshal the settings of a Spring-managed application as an XML file. We -will use a simple JavaBean to represent the settings: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class Settings { - - private boolean fooEnabled; - - public boolean isFooEnabled() { - return fooEnabled; - } - - public void setFooEnabled(boolean fooEnabled) { - this.fooEnabled = fooEnabled; - } - } ----- - -The application class uses this bean to store its settings. Besides a main method, the -class has two methods: `saveSettings()` saves the settings bean to a file named -`settings.xml`, and `loadSettings()` loads these settings again. A `main()` method -constructs a Spring application context, and calls these two methods. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - import java.io.FileInputStream; - import java.io.FileOutputStream; - import java.io.IOException; - import javax.xml.transform.stream.StreamResult; - import javax.xml.transform.stream.StreamSource; - - import org.springframework.context.ApplicationContext; - import org.springframework.context.support.ClassPathXmlApplicationContext; - import org.springframework.oxm.Marshaller; - import org.springframework.oxm.Unmarshaller; - - public class Application { - - private static final String FILE_NAME = "settings.xml"; - private Settings settings = new Settings(); - private Marshaller marshaller; - private Unmarshaller unmarshaller; - - public void setMarshaller(Marshaller marshaller) { - this.marshaller = marshaller; - } - - public void setUnmarshaller(Unmarshaller unmarshaller) { - this.unmarshaller = unmarshaller; - } - - public void saveSettings() throws IOException { - FileOutputStream os = null; - try { - os = new FileOutputStream(FILE_NAME); - this.marshaller.marshal(settings, new StreamResult(os)); - } finally { - if (os != null) { - os.close(); - } - } - } - - public void loadSettings() throws IOException { - FileInputStream is = null; - try { - is = new FileInputStream(FILE_NAME); - this.settings = (Settings) this.unmarshaller.unmarshal(new StreamSource(is)); - } finally { - if (is != null) { - is.close(); - } - } - } - - public static void main(String[] args) throws IOException { - ApplicationContext appContext = - new ClassPathXmlApplicationContext("applicationContext.xml"); - Application application = (Application) appContext.getBean("application"); - application.saveSettings(); - application.loadSettings(); - } - } ----- - -The `Application` requires both a `marshaller` and `unmarshaller` property to be set. We -can do so using the following `applicationContext.xml`: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - <beans> - <bean id="application" class="Application"> - <property name="marshaller" ref="castorMarshaller" /> - <property name="unmarshaller" ref="castorMarshaller" /> - </bean> - <bean id="castorMarshaller" class="org.springframework.oxm.castor.CastorMarshaller"/> - </beans> ----- - -This application context uses Castor, but we could have used any of the other marshaller -instances described later in this chapter. Note that Castor does not require any further -configuration by default, so the bean definition is rather simple. Also note that the -`CastorMarshaller` implements both `Marshaller` and `Unmarshaller`, so we can refer to the -`castorMarshaller` bean in both the `marshaller` and `unmarshaller` property of the -application. - -This sample application produces the following `settings.xml` file: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - <?xml version="1.0" encoding="UTF-8"?> - <settings foo-enabled="false"/> ----- - - - - -[[oxm-schema-based-config]] -=== XML Schema-based Configuration -Marshallers could be configured more concisely using tags from the OXM namespace. To -make these tags available, the appropriate schema has to be referenced first in the -preamble of the XML configuration file. Note the 'oxm' related text below: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - <?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:oxm="http://www.springframework.org/schema/oxm"** xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd **http://www.springframework.org/schema/oxm http://www.springframework.org/schema/oxm/spring-oxm.xsd"**> ----- - -Currently, the following tags are available: - -* <<oxm-jaxb2-xsd, `jaxb2-marshaller`>> -* <<oxm-xmlbeans-xsd, `xmlbeans-marshaller`>> -* <<oxm-castor-xsd, `castor-marshaller`>> -* <<oxm-jibx-xsd, `jibx-marshaller`>> - -Each tag will be explained in its respective marshaller's section. As an example though, -here is how the configuration of a JAXB2 marshaller might look like: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - <oxm:jaxb2-marshaller id="marshaller" contextPath="org.springframework.ws.samples.airline.schema"/> ----- - - - - -[[oxm-jaxb]] -=== JAXB -The JAXB binding compiler translates a W3C XML Schema into one or more Java classes, a -`jaxb.properties` file, and possibly some resource files. JAXB also offers a way to -generate a schema from annotated Java classes. - -Spring supports the JAXB 2.0 API as XML marshalling strategies, following the -`Marshaller` and `Unmarshaller` interfaces described in <<oxm-marshaller-unmarshaller>>. -The corresponding integration classes reside in the `org.springframework.oxm.jaxb` -package. - - - -[[oxm-jaxb2]] -==== Jaxb2Marshaller -The `Jaxb2Marshaller` class implements both the Spring `Marshaller` and `Unmarshaller` -interface. It requires a context path to operate, which you can set using the -`contextPath` property. The context path is a list of colon (:) separated Java package -names that contain schema derived classes. It also offers a `classesToBeBound` property, -which allows you to set an array of classes to be supported by the marshaller. Schema -validation is performed by specifying one or more schema resource to the bean, like so: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - <beans> - <bean id="jaxb2Marshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller"> - <property name="classesToBeBound"> - <list> - <value>org.springframework.oxm.jaxb.Flight</value> - <value>org.springframework.oxm.jaxb.Flights</value> - </list> - </property> - <property name="schema" value="classpath:org/springframework/oxm/schema.xsd"/> - </bean> - - ... - - </beans> ----- - - -[[oxm-jaxb2-xsd]] -===== XML Schema-based Configuration -The `jaxb2-marshaller` tag configures a `org.springframework.oxm.jaxb.Jaxb2Marshaller`. -Here is an example: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - <oxm:jaxb2-marshaller id="marshaller" contextPath="org.springframework.ws.samples.airline.schema"/> ----- - -Alternatively, the list of classes to bind can be provided to the marshaller via the -`class-to-be-bound` child tag: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - <oxm:jaxb2-marshaller id="marshaller"> - <oxm:class-to-be-bound name="org.springframework.ws.samples.airline.schema.Airport"/> - <oxm:class-to-be-bound name="org.springframework.ws.samples.airline.schema.Flight"/> - ... - </oxm:jaxb2-marshaller> ----- - -Available attributes are: - -|=== -| Attribute| Description| Required - -| `id` -| the id of the marshaller -| no - -| `contextPath` -| the JAXB Context path -| no -|=== - - - - -[[oxm-castor]] -=== Castor -Castor XML mapping is an open source XML binding framework. It allows you to transform -the data contained in a java object model into/from an XML document. By default, it does -not require any further configuration, though a mapping file can be used to have more -control over the behavior of Castor. - -For more information on Castor, refer to the -http://castor.codehaus.org/xml-framework.html[__Castor web site__]. The Spring -integration classes reside in the `org.springframework.oxm.castor` package. - - - -[[oxm-castor-marshaller]] -==== CastorMarshaller -As with JAXB, the `CastorMarshaller` implements both the `Marshaller` and `Unmarshaller` -interface. It can be wired up as follows: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - <beans> - <bean id="castorMarshaller" class="org.springframework.oxm.castor.CastorMarshaller" /> - ... - </beans> ----- - - - -[[oxm-castor-mapping]] -==== Mapping -Although it is possible to rely on Castor's default marshalling behavior, it might be -necessary to have more control over it. This can be accomplished using a Castor mapping -file. For more information, refer to http://castor.codehaus.org/xml-mapping.html[Castor -XML Mapping]. - -The mapping can be set using the `mappingLocation` resource property, indicated below -with a classpath resource. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - <beans> - <bean id="castorMarshaller" class="org.springframework.oxm.castor.CastorMarshaller" > - <property name="mappingLocation" value="classpath:mapping.xml" /> - </bean> - </beans> ----- - - -[[oxm-castor-xsd]] -===== XML Schema-based Configuration -The `castor-marshaller` tag configures a -`org.springframework.oxm.castor.CastorMarshaller`. Here is an example: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - <oxm:castor-marshaller id="marshaller" mapping-location="classpath:org/springframework/oxm/castor/mapping.xml"/> ----- - -The marshaller instance can be configured in two ways, by specifying either the location -of a mapping file (through the `mapping-location` property), or by identifying Java -POJOs (through the `target-class` or `target-package` properties) for which there exist -corresponding XML descriptor classes. The latter way is usually used in conjunction with -XML code generation from XML schemas. - -Available attributes are: - -|=== -| Attribute| Description| Required - -| `id` -| the id of the marshaller -| no - -| `encoding` -| the encoding to use for unmarshalling from XML -| no - -| `target-class` -| a Java class name for a POJO for which an XML class descriptor is available (as - generated through code generation) -| no - -| `target-package` -| a Java package name that identifies a package that contains POJOs and their - corresponding Castor XML descriptor classes (as generated through code generation from - XML schemas) -| no - -| `mapping-location` -| location of a Castor XML mapping file -| no -|=== - - - - -[[oxm-xmlbeans]] -=== XMLBeans -XMLBeans is an XML binding tool that has full XML Schema support, and offers full XML -Infoset fidelity. It takes a different approach to that of most other O/X mapping -frameworks, in that all classes that are generated from an XML Schema are all derived -from `XmlObject`, and contain XML binding information in them. - -For more information on XMLBeans, refer to the http://xmlbeans.apache.org/[__XMLBeans -web site __]. The Spring-WS integration classes reside in the -`org.springframework.oxm.xmlbeans` package. - - - -[[oxm-xmlbeans-marshaller]] -==== XmlBeansMarshaller -The `XmlBeansMarshaller` implements both the `Marshaller` and `Unmarshaller` interfaces. -It can be configured as follows: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - <beans> - - <bean id="xmlBeansMarshaller" class="org.springframework.oxm.xmlbeans.XmlBeansMarshaller" /> - ... - - </beans> ----- - -[NOTE] -==== -Note that the `XmlBeansMarshaller` can only marshal objects of type `XmlObject`, and not -every `java.lang.Object`. -==== - - -[[oxm-xmlbeans-xsd]] -===== XML Schema-based Configuration -The `xmlbeans-marshaller` tag configures a -`org.springframework.oxm.xmlbeans.XmlBeansMarshaller`. Here is an example: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - <oxm:xmlbeans-marshaller id="marshaller"/> ----- - -Available attributes are: - -|=== -| Attribute| Description| Required - -| `id` -| the id of the marshaller -| no - -| `options` -| the bean name of the XmlOptions that is to be used for this marshaller. Typically a - `XmlOptionsFactoryBean` definition -| no -|=== - - - - -[[oxm-jibx]] -=== JiBX -The JiBX framework offers a solution similar to that which JDO provides for ORM: a -binding definition defines the rules for how your Java objects are converted to or from -XML. After preparing the binding and compiling the classes, a JiBX binding compiler -enhances the class files, and adds code to handle converting instances of the classes -from or to XML. - -For more information on JiBX, refer to the http://jibx.sourceforge.net/[__JiBX web -site__]. The Spring integration classes reside in the `org.springframework.oxm.jibx` -package. - - - -[[oxm-jibx-marshaller]] -==== JibxMarshaller -The `JibxMarshaller` class implements both the `Marshaller` and `Unmarshaller` -interface. To operate, it requires the name of the class to marshal in, which you can -set using the `targetClass` property. Optionally, you can set the binding name using the -`bindingName` property. In the next sample, we bind the `Flights` class: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - <beans> - <bean id="jibxFlightsMarshaller" class="org.springframework.oxm.jibx.JibxMarshaller"> - <property name="targetClass">org.springframework.oxm.jibx.Flights</property> - </bean> - ... - </beans> ----- - -A `JibxMarshaller` is configured for a single class. If you want to marshal multiple -classes, you have to configure multiple ++JibxMarshaller++s with different `targetClass` -property values. - - -[[oxm-jibx-xsd]] -===== XML Schema-based Configuration -The `jibx-marshaller` tag configures a `org.springframework.oxm.jibx.JibxMarshaller`. -Here is an example: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - <oxm:jibx-marshaller id="marshaller" target-class="org.springframework.ws.samples.airline.schema.Flight"/> ----- - -Available attributes are: - -|=== -| Attribute| Description| Required - -| `id` -| the id of the marshaller -| no - -| `target-class` -| the target class for this marshaller -| yes - -| `bindingName` -| the binding name used by this marshaller -| no -|=== - - - - -[[oxm-xstream]] -=== XStream -XStream is a simple library to serialize objects to XML and back again. It does not -require any mapping, and generates clean XML. - -For more information on XStream, refer to the http://xstream.codehaus.org/[__XStream -web site__]. The Spring integration classes reside in the -`org.springframework.oxm.xstream` package. - - - -[[oxm-xstream-marshaller]] -==== XStreamMarshaller -The `XStreamMarshaller` does not require any configuration, and can be configured in an -application context directly. To further customize the XML, you can set an__alias map__, -which consists of string aliases mapped to classes: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - <beans> - <bean id="xstreamMarshaller" class="org.springframework.oxm.xstream.XStreamMarshaller"> - <property name="aliases"> - <props> - <prop key="Flight">org.springframework.oxm.xstream.Flight</prop> - </props> - </property> - </bean> - ... - </beans> ----- - -[WARNING] -==== - -By default, XStream allows for arbitrary classes to be unmarshalled, which can result in -security vulnerabilities. As such, it is __not recommended to use the -`XStreamMarshaller` to unmarshal XML from external sources__ (i.e. the Web), as this can -result in __security vulnerabilities__. If you do use the `XStreamMarshaller` to -unmarshal XML from an external source, set the `supportedClasses` property on the -`XStreamMarshaller`, like so: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - <bean id="xstreamMarshaller" class="org.springframework.oxm.xstream.XStreamMarshaller"> - <property name="supportedClasses" value="org.springframework.oxm.xstream.Flight"/> - ... - </bean> ----- - -This will make sure that only the registered classes are eligible for unmarshalling. - -Additionally, you can register -{javadoc-baseurl}/org/springframework/oxm/xstream/XStreamMarshaller.html#setConverters(com.thoughtworks.xstream.converters.ConverterMatcher...)[custom -converters] to make sure that only your supported classes can be unmarshalled. You might -want to add a `CatchAllConverter` as the last converter in the list, in addition to -converters that explicitly support the domain classes that should be supported. As a -result, default XStream converters with lower priorities and possible security -vulnerabilities do not get invoked. -==== - -NOTE: Note that XStream is an XML serialization library, not a data binding library. -Therefore, it has limited namespace support. As such, it is rather unsuitable for usage -within Web services. - - - - - - -[[spring-web]] -= The Web -[partintro] --- -This part of the reference documentation covers Spring Framework's support for the -presentation tier (and specifically web-based presentation tiers) including support -for WebSocket-style messaging in web applications. - -Spring Framework's own web framework, <<mvc,Spring Web MVC>>, is covered in the -first couple of chapters. Subsequent chapters are concerned with Spring Framework's -integration with other web technologies, such as <<jsf,JSF>> and. - -Following that is coverage of Spring Framework's MVC <<portlet,portlet framework>>. - -The section then concludes with comprehensive coverage of the Spring Framework -<<websocket>> (including <<websocket-stomp>>). - -* <<mvc>> -* <<view>> -* <<web-integration>> -* <<portlet>> -* <<websocket>> --- - - - - -[[mvc]] -== Web MVC framework - - - - -[[mvc-introduction]] -=== Introduction to Spring Web MVC framework -The Spring Web model-view-controller (MVC) framework is designed around a -`DispatcherServlet` that dispatches requests to handlers, with configurable handler -mappings, view resolution, locale, time zone and theme resolution as well as support for -uploading files. The default handler is based on the `@Controller` and `@RequestMapping` -annotations, offering a wide range of flexible handling methods. With the introduction -of Spring 3.0, the `@Controller` mechanism also allows you to create RESTful Web sites -and applications, through the `@PathVariable` annotation and other features. - -**** -"Open for extension..." -A key design principle in Spring Web MVC and in Spring in general is the "__Open for -extension, closed for modification__" principle. - -Some methods in the core classes of Spring Web MVC are marked `final`. As a developer -you cannot override these methods to supply your own behavior. This has not been done -arbitrarily, but specifically with this principle in mind. - -For an explanation of this principle, refer to __Expert Spring Web MVC and Web Flow__ by -Seth Ladd and others; specifically see the section "A Look At Design," on page 117 of -the first edition. Alternatively, see - -* http://www.objectmentor.com/resources/articles/ocp.pdf[Bob Martin, The Open-Closed - Principle (PDF)] - -You cannot add advice to final methods when you use Spring MVC. For example, you cannot -add advice to the `AbstractController.setSynchronizeOnSession()` method. Refer to -<<aop-understanding-aop-proxies>> for more information on AOP proxies and why you cannot -add advice to final methods. -**** - -In Spring Web MVC you can use any object as a command or form-backing object; you do not -need to implement a framework-specific interface or base class. Spring's data binding is -highly flexible: for example, it treats type mismatches as validation errors that can be -evaluated by the application, not as system errors. Thus you need not duplicate your -business objects' properties as simple, untyped strings in your form objects simply to -handle invalid submissions, or to convert the Strings properly. Instead, it is often -preferable to bind directly to your business objects. - -Spring's view resolution is extremely flexible. A `Controller` is typically responsible -for preparing a model `Map` with data and selecting a view name but it can also write -directly to the response stream and complete the request. View name resolution is highly -configurable through file extension or Accept header content type negotiation, through -bean names, a properties file, or even a custom `ViewResolver` implementation. The model -(the M in MVC) is a `Map` interface, which allows for the complete abstraction of the -view technology. You can integrate directly with template based rendering technologies -such as JSP, Velocity and Freemarker, or directly generate XML, JSON, Atom, and many -other types of content. The model `Map` is simply transformed into an appropriate -format, such as JSP request attributes, a Velocity template model. - - - -[[mvc-features]] -==== Features of Spring Web MVC - -.Spring Web Flow -**** -Spring Web Flow (SWF) aims to be the best solution for the management of web application -page flow. - -SWF integrates with existing frameworks like Spring MVC and JSF, in both Servlet and -Portlet environments. If you have a business process (or processes) that would benefit -from a conversational model as opposed to a purely request model, then SWF may be the -solution. - -SWF allows you to capture logical page flows as self-contained modules that are reusable -in different situations, and as such is ideal for building web application modules that -guide the user through controlled navigations that drive business processes. - -For more information about SWF, consult the -http://projects.spring.io/spring-webflow/[Spring Web Flow website]. -**** - -Spring's web module includes many unique web support features: - -* __Clear separation of roles__. Each role -- controller, validator, command object, - form object, model object, `DispatcherServlet`, handler mapping, view resolver, and so - on -- can be fulfilled by a specialized object. -* __Powerful and straightforward configuration of both framework and application classes - as JavaBeans__. This configuration capability includes easy referencing across - contexts, such as from web controllers to business objects and validators. -* __Adaptability, non-intrusiveness, and flexibility.__ Define any controller method - signature you need, possibly using one of the parameter annotations (such as - @RequestParam, @RequestHeader, @PathVariable, and more) for a given scenario. -* __Reusable business code, no need for duplication__. Use existing business objects - as command or form objects instead of mirroring them to extend a particular framework - base class. -* __Customizable binding and validation__. Type mismatches as application-level - validation errors that keep the offending value, localized date and number binding, - and so on instead of String-only form objects with manual parsing and conversion to - business objects. -* __Customizable handler mapping and view resolution__. Handler mapping and view - resolution strategies range from simple URL-based configuration, to sophisticated, - purpose-built resolution strategies. Spring is more flexible than web MVC frameworks - that mandate a particular technique. -* __Flexible model transfer__. Model transfer with a name/value `Map` supports easy - integration with any view technology. -* __Customizable locale, time zone and theme resolution, support for JSPs with or without - Spring tag library, support for JSTL, support for Velocity without the need for extra - bridges, and so on.__ -* __A simple yet powerful JSP tag library known as the Spring tag library that provides - support for features such as data binding and themes__. The custom tags allow for - maximum flexibility in terms of markup code. For information on the tag library - descriptor, see the appendix entitled <<spring.tld>> -* __A JSP form tag library, introduced in Spring 2.0, that makes writing forms in JSP - pages much easier.__ For information on the tag library descriptor, see the appendix - entitled <<spring-form.tld>> -* __Beans whose lifecycle is scoped to the current HTTP request or HTTP `Session`.__ - This is not a specific feature of Spring MVC itself, but rather of the - `WebApplicationContext` container(s) that Spring MVC uses. These bean scopes are - described in <<beans-factory-scopes-other>> - - - -[[mvc-introduction-pluggability]] -==== Pluggability of other MVC implementations -Non-Spring MVC implementations are preferable for some projects. Many teams expect to -leverage their existing investment in skills and tools, for example with JSF. - -If you do not want to use Spring's Web MVC, but intend to leverage other solutions that -Spring offers, you can integrate the web MVC framework of your choice with Spring -easily. Simply start up a Spring root application context through its -`ContextLoaderListener`, and access it through its `ServletContext` attribute (or -Spring's respective helper method) from within any action object. No "plug-ins" -are involved, so no dedicated integration is necessary. From the web layer's point of -view, you simply use Spring as a library, with the root application context instance as -the entry point. - -Your registered beans and Spring's services can be at your fingertips even without -Spring's Web MVC. Spring does not compete with other web frameworks in this scenario. -It simply addresses the many areas that the pure web MVC frameworks do not, from bean -configuration to data access and transaction handling. So you can enrich your -application with a Spring middle tier and/or data access tier, even if you just want -to use, for example, the transaction abstraction with JDBC or Hibernate. - - - - -[[mvc-servlet]] -=== The DispatcherServlet - -Spring's web MVC framework is, like many other web MVC frameworks, request-driven, -designed around a central Servlet that dispatches requests to controllers and offers -other functionality that facilitates the development of web applications. Spring's -`DispatcherServlet` however, does more than just that. It is completely integrated with -the Spring IoC container and as such allows you to use every other feature that Spring -has. - -The request processing workflow of the Spring Web MVC `DispatcherServlet` is illustrated -in the following diagram. The pattern-savvy reader will recognize that the -`DispatcherServlet` is an expression of the "Front Controller" design pattern (this is a -pattern that Spring Web MVC shares with many other leading web frameworks). - -image::images/mvc.png[width=400] - -The request processing workflow in Spring Web MVC (high level) - -The `DispatcherServlet` is an actual `Servlet` (it inherits from the `HttpServlet` base -class), and as such is declared in the `web.xml` of your web application. You need to -map requests that you want the `DispatcherServlet` to handle, by using a URL mapping in -the same `web.xml` file. This is standard Java EE Servlet configuration; the following -example shows such a `DispatcherServlet` declaration and mapping: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - <web-app> - <servlet> - <servlet-name>example</servlet-name> - <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> - <load-on-startup>1</load-on-startup> - </servlet> - - <servlet-mapping> - <servlet-name>example</servlet-name> - <url-pattern>/example/*</url-pattern> - </servlet-mapping> - - </web-app> ----- - -In the preceding example, all requests starting with `/example` will be handled by the -`DispatcherServlet` instance named `example`. In a Servlet 3.0+ environment, you also -have the option of configuring the Servlet container programmatically. Below is the code -based equivalent of the above `web.xml` example: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class MyWebApplicationInitializer implements WebApplicationInitializer { - - @Override - public void onStartup(ServletContext container) { - ServletRegistration.Dynamic registration = container.addServlet("dispatcher", new DispatcherServlet()); - registration.setLoadOnStartup(1); - registration.addMapping("/example/*"); - } - - } ----- - -`WebApplicationInitializer` is an interface provided by Spring MVC that ensures your -code-based configuration is detected and automatically used to initialize any Servlet 3 -container. An abstract base class implementation of this interace named -`AbstractDispatcherServletInitializer` makes it even easier to register the -`DispatcherServlet` by simply specifying its servlet mapping. -See <<mvc-container-config,Code-based Servlet container initialization>> for more details. - -The above is only the first step in setting up Spring Web MVC. You now need to configure -the various beans used by the Spring Web MVC framework (over and above the -`DispatcherServlet` itself). - -As detailed in <<context-introduction>>, `ApplicationContext` instances in Spring can be -scoped. In the Web MVC framework, each `DispatcherServlet` has its own -`WebApplicationContext`, which inherits all the beans already defined in the root -`WebApplicationContext`. These inherited beans can be overridden in the servlet-specific -scope, and you can define new scope-specific beans local to a given Servlet instance. - -.Context hierarchy in Spring Web MVC -image::images/mvc-contexts.gif[width=400] - -Upon initialization of a `DispatcherServlet`, Spring MVC looks for a file named -__[servlet-name]-servlet.xml__ in the `WEB-INF` directory of your web application and -creates the beans defined there, overriding the definitions of any beans defined with -the same name in the global scope. - -Consider the following `DispatcherServlet` Servlet configuration (in the `web.xml` file): - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - <web-app> - <servlet> - <servlet-name>**golfing**</servlet-name> - <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> - <load-on-startup>1</load-on-startup> - </servlet> - <servlet-mapping> - <servlet-name>**golfing**</servlet-name> - <url-pattern>/golfing/*</url-pattern> - </servlet-mapping> - </web-app> ----- - -With the above Servlet configuration in place, you will need to have a file called -`/WEB-INF/golfing-servlet.xml` in your application; this file will contain all of your -Spring Web MVC-specific components (beans). You can change the exact location of this -configuration file through a Servlet initialization parameter (see below for details). - -It is also possible to have just one root context for single DispatcherServlet scenarios -by setting an empty contextConfigLocation servlet init parameter, as shown below: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - <web-app> - <context-param> - <param-name>contextConfigLocation</param-name> - <param-value>/WEB-INF/root-context.xml</param-value> - </context-param> - <servlet> - <servlet-name>dispatcher</servlet-name> - <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> - <init-param> - <param-name>contextConfigLocation</param-name> - <param-value></param-value> - </init-param> - <load-on-startup>1</load-on-startup> - </servlet> - <servlet-mapping> - <servlet-name>dispatcher</servlet-name> - <url-pattern>/*</url-pattern> - </servlet-mapping> - <listener> - <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> - </listener> - </web-app> ----- - - -The `WebApplicationContext` is an extension of the plain `ApplicationContext` that has -some extra features necessary for web applications. It differs from a normal -`ApplicationContext` in that it is capable of resolving themes (see -<<mvc-themeresolver>>), and that it knows which Servlet it is associated with (by having -a link to the `ServletContext`). The `WebApplicationContext` is bound in the -`ServletContext`, and by using static methods on the `RequestContextUtils` class you can -always look up the `WebApplicationContext` if you need access to it. - - - -[[mvc-servlet-special-bean-types]] -==== Special Bean Types In the WebApplicationContext - -The Spring `DispatcherServlet` uses special beans to process requests and render the -appropriate views. These beans are part of Spring MVC. You can choose which special -beans to use by simply configuring one or more of them in the `WebApplicationContext`. -However, you don't need to do that initially since Spring MVC maintains a list of -default beans to use if you don't configure any. More on that in the next section. First -see the table below listing the special bean types the `DispatcherServlet` relies on. - -[[mvc-webappctx-special-beans-tbl]] -.Special bean types in the WebApplicationContext -|=== -| Bean type| Explanation - -| <<mvc-handlermapping,HandlerMapping>> -| Maps incoming requests to handlers and a list of pre- and post-processors (handler - interceptors) based on some criteria the details of which vary by `HandlerMapping` - implementation. The most popular implementation supports annotated controllers but - other implementations exists as well. - -| HandlerAdapter -| Helps the `DispatcherServlet` to invoke a handler mapped to a request regardless of - the handler is actually invoked. For example, invoking an annotated controller - requires resolving various annotations. Thus the main purpose of a `HandlerAdapter` is - to shield the `DispatcherServlet` from such details. - -| <<mvc-exceptionhandlers,HandlerExceptionResolver>> -| Maps exceptions to views also allowing for more complex exception handling code. - -| <<mvc-viewresolver,ViewResolver>> -| Resolves logical String-based view names to actual `View` types. - -| <<mvc-localeresolver,LocaleResolver>> & <<mvc-timezone,LocaleContextResolver>> -| Resolves the locale a client is using and possibly their time zone, in order to be able - to offer internationalized views - -| <<mvc-themeresolver,ThemeResolver>> -| Resolves themes your web application can use, for example, to offer personalized layouts - -| <<mvc-multipart,MultipartResolver>> -| Parses multi-part requests for example to support processing file uploads from HTML - forms. - -| <<mvc-flash-attributes,FlashMapManager>> -| Stores and retrieves the "input" and the "output" `FlashMap` that can be used to pass - attributes from one request to another, usually across a redirect. -|=== - - - -[[mvc-servlet-config]] -==== Default DispatcherServlet Configuration -As mentioned in the previous section for each special bean the `DispatcherServlet` -maintains a list of implementations to use by default. This information is kept in the -file `DispatcherServlet.properties` in the package `org.springframework.web.servlet`. - -All special beans have some reasonable defaults of their own. Sooner or later though -you'll need to customize one or more of the properties these beans provide. For example -it's quite common to configure an `InternalResourceViewResolver` settings its `prefix` -property to the parent location of view files. - -Regardless of the details, the important concept to understand here is that once -you configure a special bean such as an `InternalResourceViewResolver` in your -`WebApplicationContext`, you effectively override the list of default implementations -that would have been used otherwise for that special bean type. For example if you -configure an `InternalResourceViewResolver`, the default list of `ViewResolver` -implementations is ignored. - -In <<mvc-config>> you'll learn about other options for configuring Spring MVC including -MVC Java config and the MVC XML namespace both of which provide a simple starting point -and assume little knowledge of how Spring MVC works. Regardless of how you choose to -configure your application, the concepts explained in this section are fundamental -should be of help to you. - - - -[[mvc-servlet-sequence]] -==== DispatcherServlet Processing Sequence -After you set up a `DispatcherServlet`, and a request comes in for that specific -`DispatcherServlet`, the `DispatcherServlet` starts processing the request as follows: - -* The `WebApplicationContext` is searched for and bound in the request as an attribute - that the controller and other elements in the process can use. It is bound by default - under the key `DispatcherServlet.WEB_APPLICATION_CONTEXT_ATTRIBUTE`. -* The locale resolver is bound to the request to enable elements in the process to - resolve the locale to use when processing the request (rendering the view, preparing - data, and so on). If you do not need locale resolving, you do not need it. -* The theme resolver is bound to the request to let elements such as views determine - which theme to use. If you do not use themes, you can ignore it. -* If you specify a multipart file resolver, the request is inspected for multiparts; if - multiparts are found, the request is wrapped in a `MultipartHttpServletRequest` for - further processing by other elements in the process. See <<mvc-multipart>> for further - information about multipart handling. -* An appropriate handler is searched for. If a handler is found, the execution chain - associated with the handler (preprocessors, postprocessors, and controllers) is - executed in order to prepare a model or rendering. -* If a model is returned, the view is rendered. If no model is returned, (may be due to - a preprocessor or postprocessor intercepting the request, perhaps for security - reasons), no view is rendered, because the request could already have been fulfilled. - -Handler exception resolvers that are declared in the `WebApplicationContext` pick up -exceptions that are thrown during processing of the request. Using these exception -resolvers allows you to define custom behaviors to address exceptions. - -The Spring `DispatcherServlet` also supports the return of the -__last-modification-date__, as specified by the Servlet API. The process of determining -the last modification date for a specific request is straightforward: the -`DispatcherServlet` looks up an appropriate handler mapping and tests whether the -handler that is found implements the __LastModified__ interface. If so, the value of the -`long getLastModified(request)` method of the `LastModified` interface is returned to -the client. - -You can customize individual `DispatcherServlet` instances by adding Servlet -initialization parameters ( `init-param` elements) to the Servlet declaration in the -`web.xml` file. See the following table for the list of supported parameters. - -[[mvc-disp-servlet-init-params-tbl]] -.DispatcherServlet initialization parameters -|=== -| Parameter| Explanation - -| `contextClass` -| Class that implements `WebApplicationContext`, which instantiates the context used by - this Servlet. By default, the `XmlWebApplicationContext` is used. - -| `contextConfigLocation` -| String that is passed to the context instance (specified by `contextClass`) to - indicate where context(s) can be found. The string consists potentially of multiple - strings (using a comma as a delimiter) to support multiple contexts. In case of - multiple context locations with beans that are defined twice, the latest location - takes precedence. - -| `namespace` -| Namespace of the `WebApplicationContext`. Defaults to `[servlet-name]-servlet`. -|=== - - - - -[[mvc-controller]] -=== Implementing Controllers -Controllers provide access to the application behavior that you typically define through -a service interface. Controllers interpret user input and transform it into a model that -is represented to the user by the view. Spring implements a controller in a very -abstract way, which enables you to create a wide variety of controllers. - -Spring 2.5 introduced an annotation-based programming model for MVC controllers that -uses annotations such as `@RequestMapping`, `@RequestParam`, `@ModelAttribute`, and so -on. This annotation support is available for both Servlet MVC and Portlet MVC. -Controllers implemented in this style do not have to extend specific base classes or -implement specific interfaces. Furthermore, they do not usually have direct dependencies -on Servlet or Portlet APIs, although you can easily configure access to Servlet or -Portlet facilities. - -[TIP] -==== - -Available in the https://github.com/spring-projects/[spring-projects Org on Github], -a number of web applications leverage the annotation support described in this section -including __MvcShowcase__, __MvcAjax__, __MvcBasic__, __PetClinic__, __PetCare__, -and others. -==== - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Controller - public class HelloWorldController { - - @RequestMapping("/helloWorld") - public String helloWorld(Model model) { - model.addAttribute("message", "Hello World!"); - return "helloWorld"; - } - } ----- - -As you can see, the `@Controller` and `@RequestMapping` annotations allow flexible -method names and signatures. In this particular example the method accepts a `Model` and -returns a view name as a `String`, but various other method parameters and return values -can be used as explained later in this section. `@Controller` and `@RequestMapping` and -a number of other annotations form the basis for the Spring MVC implementation. This -section documents these annotations and how they are most commonly used in a Servlet -environment. - - - -[[mvc-ann-controller]] -==== Defining a controller with @Controller - -The `@Controller` annotation indicates that a particular class serves the role of -a __controller__. Spring does not require you to extend any controller base class or -reference the Servlet API. However, you can still reference Servlet-specific features if -you need to. - -The `@Controller` annotation acts as a stereotype for the annotated class, indicating -its role. The dispatcher scans such annotated classes for mapped methods and detects -`@RequestMapping` annotations (see the next section). - -You can define annotated controller beans explicitly, using a standard Spring bean -definition in the dispatcher's context. However, the `@Controller` stereotype also -allows for autodetection, aligned with Spring general support for detecting component -classes in the classpath and auto-registering bean definitions for them. - -To enable autodetection of such annotated controllers, you add component scanning to -your configuration. Use the __spring-context__ schema as shown in the following XML -snippet: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - <?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:p="http://www.springframework.org/schema/p" - 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"> - - <context:component-scan base-package="org.springframework.samples.petclinic.web"/> - - <!-- ... --> - - </beans> ----- - - - -[[mvc-ann-requestmapping]] -==== Mapping Requests With @RequestMapping - -You use the `@RequestMapping` annotation to map URLs such as `/appointments` onto an -entire class or a particular handler method. Typically the class-level annotation maps a -specific request path (or path pattern) onto a form controller, with additional -method-level annotations narrowing the primary mapping for a specific HTTP method -request method ("GET", "POST", etc.) or an HTTP request parameter condition. - -The following example from the __Petcare__ sample shows a controller in a Spring MVC -application that uses this annotation: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Controller - **@RequestMapping("/appointments")** - public class AppointmentsController { - - private final AppointmentBook appointmentBook; - - @Autowired - public AppointmentsController(AppointmentBook appointmentBook) { - this.appointmentBook = appointmentBook; - } - - **@RequestMapping(method = RequestMethod.GET)** - public Map<String, Appointment> get() { - return appointmentBook.getAppointmentsForToday(); - } - - **@RequestMapping(value="/{day}", method = RequestMethod.GET)** - public Map<String, Appointment> getForDay(@PathVariable @DateTimeFormat(iso=ISO.DATE) Date day, Model model) { - return appointmentBook.getAppointmentsForDay(day); - } - - **@RequestMapping(value="/new", method = RequestMethod.GET)** - public AppointmentForm getNewForm() { - return new AppointmentForm(); - } - - **@RequestMapping(method = RequestMethod.POST)** - public String add(@Valid AppointmentForm appointment, BindingResult result) { - if (result.hasErrors()) { - return "appointments/new"; - } - appointmentBook.addAppointment(appointment); - return "redirect:/appointments"; - } - } ----- - -In the example, the `@RequestMapping` is used in a number of places. The first usage is -on the type (class) level, which indicates that all handling methods on this controller -are relative to the `/appointments` path. The `get()` method has a further -`@RequestMapping` refinement: it only accepts GET requests, meaning that an HTTP GET for -`/appointments` invokes this method. The `post()` has a similar refinement, and the -`getNewForm()` combines the definition of HTTP method and path into one, so that GET -requests for `appointments/new` are handled by that method. - -The `getForDay()` method shows another usage of `@RequestMapping`: URI templates. (See -<<mvc-ann-requestmapping-uri-templates,the next section >>). - -A `@RequestMapping` on the class level is not required. Without it, all paths are simply -absolute, and not relative. The following example from the __PetClinic__ sample -application shows a multi-action controller using `@RequestMapping`: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Controller - public class ClinicController { - - private final Clinic clinic; - - @Autowired - public ClinicController(Clinic clinic) { - this.clinic = clinic; - } - - **@RequestMapping("/")** - public void welcomeHandler() { - } - - **@RequestMapping("/vets")** - public ModelMap vetsHandler() { - return new ModelMap(this.clinic.getVets()); - } - - } ----- - -[[mvc-ann-requestmapping-proxying]] -===== ++@Controller++'s and AOP Proxying - -In some cases a controller may need to be decorated with an AOP proxy at runtime. -One example is if you choose to have `@Transactional` annotations directly on the -controller. When this is the case, for controllers specifically, we recommend -using class-based proxying. This is typically the default choice with controllers. -However if a controller must implement an interface that is not a Spring Context -callback (e.g. `InitializingBean`, `*Aware`, etc), you may need to explicitly -configure class-based proxying. For example with `<tx:annotation-driven />`, -change to `<tx:annotation-driven proxy-target-class="true" />`. - -[[mvc-ann-requestmapping-31-vs-30]] -===== New Support Classes for @RequestMapping methods in Spring MVC 3.1 -Spring 3.1 introduced a new set of support classes for `@RequestMapping` methods called -`RequestMappingHandlerMapping` and `RequestMappingHandlerAdapter` respectively. They are -recommended for use and even required to take advantage of new features in Spring MVC -3.1 and going forward. The new support classes are enabled by default by the MVC -namespace and the MVC Java config but must be configured explicitly if using neither. -This section describes a few important differences between the old and the new support -classes. - -Prior to Spring 3.1, type and method-level request mappings were examined in two -separate stages -- a controller was selected first by the -`DefaultAnnotationHandlerMapping` and the actual method to invoke was narrowed down -second by the `AnnotationMethodHandlerAdapter`. - -With the new support classes in Spring 3.1, the `RequestMappingHandlerMapping` is the -only place where a decision is made about which method should process the request. Think -of controller methods as a collection of unique endpoints with mappings for each method -derived from type and method-level `@RequestMapping` information. - -This enables some new possibilities. For once a `HandlerInterceptor` or a -`HandlerExceptionResolver` can now expect the Object-based handler to be a -`HandlerMethod`, which allows them to examine the exact method, its parameters and -associated annotations. The processing for a URL no longer needs to be split across -different controllers. - -There are also several things no longer possible: - -* Select a controller first with a `SimpleUrlHandlerMapping` or - `BeanNameUrlHandlerMapping` and then narrow the method based on `@RequestMapping` - annotations. -* Rely on method names as a fall-back mechanism to disambiguate between two - `@RequestMapping` methods that don't have an explicit path mapping URL path but - otherwise match equally, e.g. by HTTP method. In the new support classes - `@RequestMapping` methods have to be mapped uniquely. -* Have a single default method (without an explicit path mapping) with which requests - are processed if no other controller method matches more concretely. In the new - support classes if a matching method is not found a 404 error is raised. - -The above features are still supported with the existing support classes. However to -take advantage of new Spring MVC 3.1 features you'll need to use the new support classes. - - -[[mvc-ann-requestmapping-uri-templates]] -===== URI Template Patterns -__URI templates__ can be used for convenient access to selected parts of a URL in a -`@RequestMapping` method. - -A URI Template is a URI-like string, containing one or more variable names. When you -substitute values for these variables, the template becomes a URI. The -http://bitworking.org/projects/URI-Templates/[proposed RFC] for URI Templates defines -how a URI is parameterized. For example, the URI Template -`http://www.example.com/users/{userId}` contains the variable __userId__. Assigning the -value __fred__ to the variable yields `http://www.example.com/users/fred`. - -In Spring MVC you can use the `@PathVariable` annotation on a method argument to bind it -to the value of a URI template variable: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @RequestMapping(value="/owners/{ownerId}", method=RequestMethod.GET) - public String findOwner(**@PathVariable** String ownerId, Model model) { - Owner owner = ownerService.findOwner(ownerId); - model.addAttribute("owner", owner); - return "displayOwner"; - } ----- - -The URI Template " `/owners/{ownerId}`" specifies the variable name `ownerId`. When the -controller handles this request, the value of `ownerId` is set to the value found in the -appropriate part of the URI. For example, when a request comes in for `/owners/fred`, -the value of `ownerId` is `fred`. - -[TIP] -==== - -To process the @PathVariable annotation, Spring MVC needs to find the matching URI -template variable by name. You can specify it in the annotation: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @RequestMapping(value="/owners/{ownerId}", method=RequestMethod.GET) - public String findOwner(**@PathVariable("ownerId")** String theOwner, Model model) { - // implementation omitted - } ----- - -Or if the URI template variable name matches the method argument name you can omit that -detail. As long as your code is not compiled without debugging information, Spring MVC -will match the method argument name to the URI template variable name: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @RequestMapping(value="/owners/{ownerId}", method=RequestMethod.GET) - public String findOwner(**@PathVariable** String ownerId, Model model) { - // implementation omitted - } ----- -==== - -A method can have any number of `@PathVariable` annotations: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @RequestMapping(value="/owners/{ownerId}/pets/{petId}", method=RequestMethod.GET) - public String findPet(**@PathVariable** String ownerId, **@PathVariable** String petId, Model model) { - Owner owner = ownerService.findOwner(ownerId); - Pet pet = owner.getPet(petId); - model.addAttribute("pet", pet); - return "displayPet"; - } ----- - -When a `@PathVariable` annotation is used on a `Map<String, String>` argument, the map -is populated with all URI template variables. - -A URI template can be assembled from type and path level __@RequestMapping__ -annotations. As a result the `findPet()` method can be invoked with a URL such as -`/owners/42/pets/21`. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Controller - @RequestMapping(**"/owners/{ownerId}"**) - public class RelativePathUriTemplateController { - - @RequestMapping(**"/pets/{petId}"**) - public void findPet(@PathVariable String ownerId, @PathVariable String petId, Model model) { - // implementation omitted - } - - } ----- - -A `@PathVariable` argument can be of __any simple type__ such as int, long, Date, etc. -Spring automatically converts to the appropriate type or throws a -`TypeMismatchException` if it fails to do so. You can also register support for parsing -additional data types. See <<mvc-ann-typeconversion>> and <<mvc-ann-webdatabinder>>. - - -[[mvc-ann-requestmapping-uri-templates-regex]] -===== URI Template Patterns with Regular Expressions -Sometimes you need more precision in defining URI template variables. Consider the URL -`"/spring-web/spring-web-3.0.5.jar"`. How do you break it down into multiple parts? - -The `@RequestMapping` annotation supports the use of regular expressions in URI template -variables. The syntax is `{varName:regex}` where the first part defines the variable -name and the second - the regular expression.For example: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @RequestMapping("/spring-web/{symbolicName:[a-z-]+}-{version:\\d\\.\\d\\.\\d}{extension:\\.[a-z]+}") - public void handle(@PathVariable String version, @PathVariable String extension) { - // ... - } - } ----- - - -[[mvc-ann-requestmapping-patterns]] -===== Path Patterns -In addition to URI templates, the `@RequestMapping` annotation also supports Ant-style -path patterns (for example, `/myPath/*.do`). A combination of URI template variables and -Ant-style globs is also supported (e.g. `/owners/*/pets/{petId}`). - - -[[mvc-ann-requestmapping-pattern-comparison]] -===== Path Pattern Comparison -When a URL matches multiple patterns, a sort is used to find the most specific match. - -A pattern with a lower count of URI variables and wild cards is considered more specific. -For example `/hotels/{hotel}/*` has 1 URI variable and 1 wild card and is considered -more specific than `/hotels/{hotel}/**` which as 1 URI variable and 2 wild cards. - -If two patterns have the same count, the one that is longer is considered more specific. -For example `/foo/bar*` is longer and considered more specific than `/foo/*`. - -When two patterns have the same count and length, the pattern with fewer wild cards is considered more specific. -For example `/hotels/{hotel}` is more specific than `/hotels/*`. - -There are also some additional special rules: - -* The *default mapping pattern* `/**` is less specific than any other pattern. -For example `/api/{a}/{b}/{c}` is more specific. -* A *prefix pattern* such as `/public/**` is less specific than any other pattern that doesn't contain double wildcards. -For example `/public/path3/{a}/{b}/{c}` is more specific. - -For the full details see `AntPatternComparator` in `AntPathMatcher`. Note that the PathMatcher -can be customized (see <<mvc-config-path-matching>> in the section on configuring Spring MVC). - - -[[mvc-ann-requestmapping-placeholders]] -===== Path Patterns with Placeholders -Patterns in `@RequestMapping` annotations support ${...} placeholders against local -properties and/or system properties and environment variables. This may be useful in -cases where the path a controller is mapped to may need to be customized through -configuration. For more information on placeholders, see the javadocs of the -`PropertyPlaceholderConfigurer` class. - - - -[[mvc-ann-requestmapping-suffix-pattern-match]] -===== Path Pattern Matching By Suffix -By default Spring MVC automatically performs `".*"` suffix pattern matching so -that a controller mapped to `/person` is also implicitly mapped to `/person.*`. -This allows indicating content types via file extensions, e.g. `/person.pdf`, -`/person.xml`, etc. A common pitfall however is when the last path segment of the -mapping is a URI variable, e.g. `/person/{id}`. While a request for `/person/1.json` -would correctly result in path variable id=1 and extension ".json", when the id -naturally contains a dot, e.g. `/person/joe@email.com` the result does not match -expectations. Clearly here ".com" is not a file extension. - -The proper way to address this is to configure Spring MVC to only do suffix pattern -matching against file extensions registered for content negotiation purposes. -For more on this, first see <<mvc-config-content-negotiation>> and then -<<mvc-config-path-matching>> showing how to enable suffix pattern matching -along with how to use registered suffix patterns only. - - - -[[mvc-ann-matrix-variables]] -===== Matrix Variables -The URI specification http://tools.ietf.org/html/rfc3986#section-3.3[RFC 3986] defines -the possibility of including name-value pairs within path segments. There is no specific -term used in the spec. The general "URI path parameters" could be applied although the -more unique http://www.w3.org/DesignIssues/MatrixURIs.html["Matrix URIs"], originating -from an old post by Tim Berners-Lee, is also frequently used and fairly well known. -Within Spring MVC these are referred to as matrix variables. - -Matrix variables can appear in any path segment, each matrix variable separated with a -";" (semicolon). For example: `"/cars;color=red;year=2012"`. Multiple values may be -either "," (comma) separated `"color=red,green,blue"` or the variable name may be -repeated `"color=red;color=green;color=blue"`. - -If a URL is expected to contain matrix variables, the request mapping pattern must -represent them with a URI template. This ensures the request can be matched correctly -regardless of whether matrix variables are present or not and in what order they are -provided. - -Below is an example of extracting the matrix variable "q": - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - // GET /pets/42;q=11;r=22 - - @RequestMapping(value = "/pets/{petId}", method = RequestMethod.GET) - public void findPet(@PathVariable String petId, @MatrixVariable int q) { - - // petId == 42 - // q == 11 - - } ----- - -Since all path segments may contain matrix variables, in some cases you need to be more -specific to identify where the variable is expected to be: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - // GET /owners/42;q=11/pets/21;q=22 - - @RequestMapping(value = "/owners/{ownerId}/pets/{petId}", method = RequestMethod.GET) - public void findPet( - @MatrixVariable(value="q", pathVar="ownerId") int q1, - @MatrixVariable(value="q", pathVar="petId") int q2) { - - // q1 == 11 - // q2 == 22 - - } ----- - -A matrix variable may be defined as optional and a default value specified: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - // GET /pets/42 - - @RequestMapping(value = "/pets/{petId}", method = RequestMethod.GET) - public void findPet(@MatrixVariable(required=false, defaultValue="1") int q) { - - // q == 1 - - } ----- - -All matrix variables may be obtained in a Map: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - // GET /owners/42;q=11;r=12/pets/21;q=22;s=23 - - @RequestMapping(value = "/owners/{ownerId}/pets/{petId}", method = RequestMethod.GET) - public void findPet( - @MatrixVariable Map<String, String> matrixVars, - @MatrixVariable(pathVar="petId"") Map<String, String> petMatrixVars) { - - // matrixVars: ["q" : [11,22], "r" : 12, "s" : 23] - // petMatrixVars: ["q" : 11, "s" : 23] - - } ----- - -Note that to enable the use of matrix variables, you must set the -`removeSemicolonContent` property of `RequestMappingHandlerMapping` to `false`. By -default it is set to `true`. - -[TIP] -==== - -The MVC Java config and the MVC namespace both provide options for enabling the use of -matrix variables. - -If you are using Java config, The <<mvc-config-advanced-java, Advanced Customizations -with MVC Java Config>> section describes how the `RequestMappingHandlerMapping` can -be customized. - -In the MVC namespace, the `<mvc:annotation-driven>` element has an -`enable-matrix-variables` attribute that should be set to `true`. By default it is set -to `false`. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - <?xml version="1.0" encoding="UTF-8"?> - <beans xmlns="http://www.springframework.org/schema/beans" - xmlns:mvc="http://www.springframework.org/schema/mvc" - 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.xsd - http://www.springframework.org/schema/mvc - http://www.springframework.org/schema/mvc/spring-mvc.xsd"> - - <mvc:annotation-driven enable-matrix-variables="true"/> - - </beans> ----- -==== - -[[mvc-ann-requestmapping-consumes]] -===== Consumable Media Types -You can narrow the primary mapping by specifying a list of consumable media types. The -request will be matched only if the __Content-Type__ request header matches the specified -media type. For example: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Controller - @RequestMapping(value = "/pets", method = RequestMethod.POST, **consumes="application/json"**) - public void addPet(@RequestBody Pet pet, Model model) { - // implementation omitted - } ----- - -Consumable media type expressions can also be negated as in __!text/plain__ to match to -all requests other than those with __Content-Type__ of __text/plain__. - -[TIP] -==== - -The __consumes__ condition is supported on the type and on the method level. Unlike most -other conditions, when used at the type level, method-level consumable types override -rather than extend type-level consumable types. -==== - - -[[mvc-ann-requestmapping-produces]] -===== Producible Media Types -You can narrow the primary mapping by specifying a list of producible media types. The -request will be matched only if the __Accept__ request header matches one of these -values. Furthermore, use of the __produces__ condition ensures the actual content type -used to generate the response respects the media types specified in the __produces__ -condition. For example: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Controller - @RequestMapping(value = "/pets/{petId}", method = RequestMethod.GET, **produces="application/json"**) - @ResponseBody - public Pet getPet(@PathVariable String petId, Model model) { - // implementation omitted - } ----- - -Just like with __consumes__, producible media type expressions can be negated as in -__!text/plain__ to match to all requests other than those with an __Accept__ header -value of __text/plain__. - -[TIP] -==== -The __produces__ condition is supported on the type and on the method level. Unlike most -other conditions, when used at the type level, method-level producible types override -rather than extend type-level producible types. -==== - - -[[mvc-ann-requestmapping-params-and-headers]] -===== Request Parameters and Header Values -You can narrow request matching through request parameter conditions such as -`"myParam"`, `"!myParam"`, or `"myParam=myValue"`. The first two test for request -parameter presence/absence and the third for a specific parameter value. Here is an -example with a request parameter value condition: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Controller - @RequestMapping("/owners/{ownerId}") - public class RelativePathUriTemplateController { - - @RequestMapping(value = "/pets/{petId}", method = RequestMethod.GET, **params="myParam=myValue"**) - public void findPet(@PathVariable String ownerId, @PathVariable String petId, Model model) { - // implementation omitted - } - - } ----- - -The same can be done to test for request header presence/absence or to match based on a -specific request header value: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Controller - @RequestMapping("/owners/{ownerId}") - public class RelativePathUriTemplateController { - - @RequestMapping(value = "/pets", method = RequestMethod.GET, **headers="myHeader=myValue"**) - public void findPet(@PathVariable String ownerId, @PathVariable String petId, Model model) { - // implementation omitted - } - - } ----- - -[TIP] -==== - -Although you can match to __Content-Type__ and __Accept__ header values using media type -wild cards (for example __"content-type=text/*"__ will match to __"text/plain"__ and -__"text/html"__), it is recommended to use the __consumes__ and __produces__ conditions -respectively instead. They are intended specifically for that purpose. -==== - - - -[[mvc-ann-methods]] -==== Defining @RequestMapping handler methods - -An `@RequestMapping` handler method can have a very flexible signatures. The supported -method arguments and return values are described in the following section. Most -arguments can be used in arbitrary order with the only exception of `BindingResult` -arguments. This is described in the next section. - -[NOTE] -==== -Spring 3.1 introduced a new set of support classes for `@RequestMapping` methods called -`RequestMappingHandlerMapping` and `RequestMappingHandlerAdapter` respectively. They are -recommended for use and even required to take advantage of new features in Spring MVC -3.1 and going forward. The new support classes are enabled by default from the MVC -namespace and with use of the MVC Java config but must be configured explicitly if using -neither. -==== - - -[[mvc-ann-arguments]] -===== Supported method argument types -The following are the supported method arguments: - -* Request or response objects (Servlet API). Choose any specific request or response - type, for example `ServletRequest` or `HttpServletRequest`. -* Session object (Servlet API): of type `HttpSession`. An argument of this type enforces - the presence of a corresponding session. As a consequence, such an argument is never - `null`. - -[NOTE] -==== -Session access may not be thread-safe, in particular in a Servlet environment. Consider -setting the ++RequestMappingHandlerAdapter++'s "synchronizeOnSession" flag to "true" if -multiple requests are allowed to access a session concurrently. -==== - -* `org.springframework.web.context.request.WebRequest` or - `org.springframework.web.context.request.NativeWebRequest`. Allows for generic request - parameter access as well as request/session attribute access, without ties to the - native Servlet/Portlet API. -* `java.util.Locale` for the current request locale, determined by the most specific - locale resolver available, in effect, the configured `LocaleResolver` in a Servlet - environment. -* `java.io.InputStream` / `java.io.Reader` for access to the request's content. This - value is the raw InputStream/Reader as exposed by the Servlet API. -* `java.io.OutputStream` / `java.io.Writer` for generating the response's content. This - value is the raw OutputStream/Writer as exposed by the Servlet API. -* `org.springframework.http.HttpMethod` for the HTTP request method. -* `java.security.Principal` containing the currently authenticated user. -* `@PathVariable` annotated parameters for access to URI template variables. See - <<mvc-ann-requestmapping-uri-templates>>. -* `@MatrixVariable` annotated parameters for access to name-value pairs located in URI - path segments. See <<mvc-ann-matrix-variables>>. -* `@RequestParam` annotated parameters for access to specific Servlet request - parameters. Parameter values are converted to the declared method argument type. See - <<mvc-ann-requestparam>>. -* `@RequestHeader` annotated parameters for access to specific Servlet request HTTP - headers. Parameter values are converted to the declared method argument type. -* `@RequestBody` annotated parameters for access to the HTTP request body. Parameter - values are converted to the declared method argument type using - ++HttpMessageConverter++s. See <<mvc-ann-requestbody>>. -* `@RequestPart` annotated parameters for access to the content of a - "multipart/form-data" request part. See <<mvc-multipart-forms-non-browsers>> and - <<mvc-multipart>>. -* `HttpEntity<?>` parameters for access to the Servlet request HTTP headers and - contents. The request stream will be converted to the entity body using - ++HttpMessageConverter++s. See <<mvc-ann-httpentity>>. -* `java.util.Map` / `org.springframework.ui.Model` / `org.springframework.ui.ModelMap` - for enriching the implicit model that is exposed to the web view. -* `org.springframework.web.servlet.mvc.support.RedirectAttributes` to specify the exact - set of attributes to use in case of a redirect and also to add flash attributes - (attributes stored temporarily on the server-side to make them available to the - request after the redirect). `RedirectAttributes` is used instead of the implicit - model if the method returns a "redirect:" prefixed view name or `RedirectView`. -* Command or form objects to bind request parameters to bean properties (via setters) or - directly to fields, with customizable type conversion, depending on `@InitBinder` - methods and/or the HandlerAdapter configuration. See the `webBindingInitializer` - property on `RequestMappingHandlerAdapter`. Such command objects along with their - validation results will be exposed as model attributes by default, using the command - class class name - e.g. model attribute "orderAddress" for a command object of type - "some.package.OrderAddress". The `ModelAttribute` annotation can be used on a method - argument to customize the model attribute name used. -* `org.springframework.validation.Errors` / - `org.springframework.validation.BindingResult` validation results for a preceding - command or form object (the immediately preceding method argument). -* `org.springframework.web.bind.support.SessionStatus` status handle for marking form - processing as complete, which triggers the cleanup of session attributes that have - been indicated by the `@SessionAttributes` annotation at the handler type level. -* `org.springframework.web.util.UriComponentsBuilder` a builder for preparing a URL - relative to the current request's host, port, scheme, context path, and the literal - part of the servlet mapping. - -The `Errors` or `BindingResult` parameters have to follow the model object that is being -bound immediately as the method signature might have more that one model object and -Spring will create a separate `BindingResult` instance for each of them so the following -sample won't work: - -.Invalid ordering of BindingResult and @ModelAttribute -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @RequestMapping(method = RequestMethod.POST) - public String processSubmit(**@ModelAttribute("pet") Pet pet**, Model model, **BindingResult result**) { ... } ----- - -Note, that there is a `Model` parameter in between `Pet` and `BindingResult`. To get -this working you have to reorder the parameters as follows: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @RequestMapping(method = RequestMethod.POST) - public String processSubmit(**@ModelAttribute("pet") Pet pet**, **BindingResult result**, Model model) { ... } ----- - - -[[mvc-ann-return-types]] -===== Supported method return types -The following are the supported return types: - -* A `ModelAndView` object, with the model implicitly enriched with command objects and - the results of `@ModelAttribute` annotated reference data accessor methods. -* A `Model` object, with the view name implicitly determined through a - `RequestToViewNameTranslator` and the model implicitly enriched with command objects - and the results of `@ModelAttribute` annotated reference data accessor methods. -* A `Map` object for exposing a model, with the view name implicitly determined through - a `RequestToViewNameTranslator` and the model implicitly enriched with command objects - and the results of `@ModelAttribute` annotated reference data accessor methods. -* A `View` object, with the model implicitly determined through command objects and - `@ModelAttribute` annotated reference data accessor methods. The handler method may - also programmatically enrich the model by declaring a `Model` argument (see above). -* A `String` value that is interpreted as the logical view name, with the model - implicitly determined through command objects and `@ModelAttribute` annotated - reference data accessor methods. The handler method may also programmatically enrich - the model by declaring a `Model` argument (see above). -* `void` if the method handles the response itself (by writing the response content - directly, declaring an argument of type `ServletResponse` / `HttpServletResponse` for - that purpose) or if the view name is supposed to be implicitly determined through a - `RequestToViewNameTranslator` (not declaring a response argument in the handler method - signature). -* If the method is annotated with `@ResponseBody`, the return type is written to the - response HTTP body. The return value will be converted to the declared method argument - type using ++HttpMessageConverter++s. See <<mvc-ann-responsebody>>. -* An `HttpEntity<?>` or `ResponseEntity<?>` object to provide access to the Servlet - response HTTP headers and contents. The entity body will be converted to the response - stream using ++HttpMessageConverter++s. See <<mvc-ann-httpentity>>. -* An `HttpHeaders` object to return a response with no body. -* A `Callable<?>` can be returned when the application wants to produce the return value - asynchronously in a thread managed by Spring MVC. -* A `DeferredResult<?>` can be returned when the application wants to produce the return - value from a thread of its own choosing. -* A `ListenableFuture<?>` can be returned when the application wants to produce the return - value from a thread of its own choosing. -* Any other return type is considered to be a single model attribute to be exposed to - the view, using the attribute name specified through `@ModelAttribute` at the method - level (or the default attribute name based on the return type class name). The model - is implicitly enriched with command objects and the results of `@ModelAttribute` - annotated reference data accessor methods. - - -[[mvc-ann-requestparam]] -===== Binding request parameters to method parameters with @RequestParam - -Use the `@RequestParam` annotation to bind request parameters to a method parameter in -your controller. - -The following code snippet shows the usage: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Controller - @RequestMapping("/pets") - @SessionAttributes("pet") - public class EditPetForm { - - // ... - - @RequestMapping(method = RequestMethod.GET) - public String setupForm(**@RequestParam("petId") int petId**, ModelMap model) { - Pet pet = this.clinic.loadPet(petId); - model.addAttribute("pet", pet); - return "petForm"; - } - - // ... - - } ----- - -Parameters using this annotation are required by default, but you can specify that a -parameter is optional by setting ++@RequestParam++'s `required` attribute to `false` -(e.g., `@RequestParam(value="id", required=false)`). - -Type conversion is applied automatically if the target method parameter type is not -`String`. See <<mvc-ann-typeconversion>>. - - -[[mvc-ann-requestbody]] -===== Mapping the request body with the @RequestBody annotation -The `@RequestBody` method parameter annotation indicates that a method parameter should -be bound to the value of the HTTP request body. For example: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @RequestMapping(value = "/something", method = RequestMethod.PUT) - public void handle(@RequestBody String body, Writer writer) throws IOException { - writer.write(body); - } ----- - -You convert the request body to the method argument by using an `HttpMessageConverter`. -`HttpMessageConverter` is responsible for converting from the HTTP request message to an -object and converting from an object to the HTTP response body. The -`RequestMappingHandlerAdapter` supports the `@RequestBody` annotation with the following -default `HttpMessageConverters`: - -* `ByteArrayHttpMessageConverter` converts byte arrays. -* `StringHttpMessageConverter` converts strings. -* `FormHttpMessageConverter` converts form data to/from a MultiValueMap<String, String>. -* `SourceHttpMessageConverter` converts to/from a javax.xml.transform.Source. - -For more information on these converters, see <<rest-message-conversion,Message -Converters>>. Also note that if using the MVC namespace or the MVC Java config, a wider -range of message converters are registered by default. See <<mvc-config-enable>> for more information. - -If you intend to read and write XML, you will need to configure the -`MarshallingHttpMessageConverter` with a specific `Marshaller` and an `Unmarshaller` -implementation from the `org.springframework.oxm` package. The example below shows how -to do that directly in your configuration but if your application is configured through -the MVC namespace or the MVC Java config see <<mvc-config-enable>> instead. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"> - <property name="messageConverters"> - <util:list id="beanList"> - <ref bean="stringHttpMessageConverter"/> - <ref bean="marshallingHttpMessageConverter"/> - </util:list> - </property - </bean> - - <bean id="stringHttpMessageConverter" - class="org.springframework.http.converter.StringHttpMessageConverter"/> - - <bean id="marshallingHttpMessageConverter" - class="org.springframework.http.converter.xml.MarshallingHttpMessageConverter"> - <property name="marshaller" ref="castorMarshaller" /> - <property name="unmarshaller" ref="castorMarshaller" /> - </bean> - - <bean id="castorMarshaller" class="org.springframework.oxm.castor.CastorMarshaller"/> ----- - -An `@RequestBody` method parameter can be annotated with `@Valid`, in which case it will -be validated using the configured `Validator` instance. When using the MVC namespace or -the MVC Java config, a JSR-303 validator is configured automatically assuming a JSR-303 -implementation is available on the classpath. - -Just like with `@ModelAttribute` parameters, an `Errors` argument can be used to examine -the errors. If such an argument is not declared, a `MethodArgumentNotValidException` -will be raised. The exception is handled in the `DefaultHandlerExceptionResolver`, which -sends a `400` error back to the client. - -[NOTE] -==== -Also see <<mvc-config-enable>> for -information on configuring message converters and a validator through the MVC namespace -or the MVC Java config. -==== - - -[[mvc-ann-responsebody]] -===== Mapping the response body with the @ResponseBody annotation - -The `@ResponseBody` annotation is similar to `@RequestBody`. This annotation can be put -on a method and indicates that the return type should be written straight to the HTTP -response body (and not placed in a Model, or interpreted as a view name). For example: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @RequestMapping(value = "/something", method = RequestMethod.PUT) - @ResponseBody - public String helloWorld() { - return "Hello World"; - } ----- - -The above example will result in the text `Hello World` being written to the HTTP -response stream. - -As with `@RequestBody`, Spring converts the returned object to a response body by using -an `HttpMessageConverter`. For more information on these converters, see the previous -section and <<rest-message-conversion,Message Converters>>. - -[[mvc-ann-restcontroller]] -===== Creating REST Controllers with the @RestController annotation - -It's a very common use case to have Controllers implement a REST API, thus serving only -JSON, XML or custom MediaType content. For convenience, instead of annotating all your -`@RequestMapping` methods with `@ResponseBody`, you can annotate your Controller Class -with `@RestController`. - -{javadoc-baseurl}/org/springframework/web/bind/annotation/RestController.html[`@RestController`] -is a stereotype annotation that combines `@ResponseBody` and `@Controller`. More than -that, it gives more meaning to your Controller and also may carry additional semantics -in future releases of the framework. - -As with regular ++@Controller++s, a `@RestController` may be assisted by a -`@ControllerAdvice` Bean. See the <<mvc-ann-controller-advice>> section for more details. - -[[mvc-ann-httpentity]] -===== Using HttpEntity - -The `HttpEntity` is similar to `@RequestBody` and `@ResponseBody`. Besides getting -access to the request and response body, `HttpEntity` (and the response-specific -subclass `ResponseEntity`) also allows access to the request and response headers, like -so: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @RequestMapping("/something") - public ResponseEntity<String> handle(HttpEntity<byte[]> requestEntity) throws UnsupportedEncodingException { - String requestHeader = requestEntity.getHeaders().getFirst("MyRequestHeader")); - byte[] requestBody = requestEntity.getBody(); - - // do something with request header and body - - HttpHeaders responseHeaders = new HttpHeaders(); - responseHeaders.set("MyResponseHeader", "MyValue"); - return new ResponseEntity<String>("Hello World", responseHeaders, HttpStatus.CREATED); - } ----- - -The above example gets the value of the `MyRequestHeader` request header, and reads the -body as a byte array. It adds the `MyResponseHeader` to the response, writes `Hello -World` to the response stream, and sets the response status code to 201 (Created). - -As with `@RequestBody` and `@ResponseBody`, Spring uses `HttpMessageConverter` to -convert from and to the request and response streams. For more information on these -converters, see the previous section and <<rest-message-conversion,Message Converters>>. - - -[[mvc-ann-modelattrib-methods]] -===== Using @ModelAttribute on a method - -The `@ModelAttribute` annotation can be used on methods or on method arguments. This -section explains its usage on methods while the next section explains its usage on -method arguments. - -An `@ModelAttribute` on a method indicates the purpose of that method is to add one or -more model attributes. Such methods support the same argument types as `@RequestMapping` -methods but cannot be mapped directly to requests. Instead `@ModelAttribute` methods in -a controller are invoked before `@RequestMapping` methods, within the same controller. A -couple of examples: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - // Add one attribute - // The return value of the method is added to the model under the name "account" - // You can customize the name via @ModelAttribute("myAccount") - - @ModelAttribute - public Account addAccount(@RequestParam String number) { - return accountManager.findAccount(number); - } - - // Add multiple attributes - - @ModelAttribute - public void populateModel(@RequestParam String number, Model model) { - model.addAttribute(accountManager.findAccount(number)); - // add more ... - } ----- - -`@ModelAttribute` methods are used to populate the model with commonly needed attributes -for example to fill a drop-down with states or with pet types, or to retrieve a command -object like Account in order to use it to represent the data on an HTML form. The latter -case is further discussed in the next section. - -Note the two styles of `@ModelAttribute` methods. In the first, the method adds an -attribute implicitly by returning it. In the second, the method accepts a `Model` and -adds any number of model attributes to it. You can choose between the two styles -depending on your needs. - -A controller can have any number of `@ModelAttribute` methods. All such methods are -invoked before `@RequestMapping` methods of the same controller. - -`@ModelAttribute` methods can also be defined in an ++@ControllerAdvice++-annotated class -and such methods apply to many controllers. See the <<mvc-ann-controller-advice>> section -for more details. - -[TIP] -==== - -What happens when a model attribute name is not explicitly specified? In such cases a -default name is assigned to the model attribute based on its type. For example if the -method returns an object of type `Account`, the default name used is "account". You can -change that through the value of the `@ModelAttribute` annotation. If adding attributes -directly to the `Model`, use the appropriate overloaded `addAttribute(..)` method - -i.e., with or without an attribute name. -==== - -The `@ModelAttribute` annotation can be used on `@RequestMapping` methods as well. In -that case the return value of the `@RequestMapping` method is interpreted as a model -attribute rather than as a view name. The view name is derived from view name -conventions instead much like for methods returning void -- see <<mvc-coc-r2vnt>>. - - -[[mvc-ann-modelattrib-method-args]] -===== Using @ModelAttribute on a method argument - -As explained in the previous section `@ModelAttribute` can be used on methods or on -method arguments. This section explains its usage on method arguments. - -An `@ModelAttribute` on a method argument indicates the argument should be retrieved -from the model. If not present in the model, the argument should be instantiated first -and then added to the model. Once present in the model, the argument's fields should be -populated from all request parameters that have matching names. This is known as data -binding in Spring MVC, a very useful mechanism that saves you from having to parse each -form field individually. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @RequestMapping(value="/owners/{ownerId}/pets/{petId}/edit", method = RequestMethod.POST) - public String processSubmit(**@ModelAttribute Pet pet**) { } ----- - -Given the above example where can the Pet instance come from? There are several options: - -* It may already be in the model due to use of `@SessionAttributes` -- see - <<mvc-ann-sessionattrib>>. -* It may already be in the model due to an `@ModelAttribute` method in the same - controller -- as explained in the previous section. -* It may be retrieved based on a URI template variable and type converter (explained in - more detail below). -* It may be instantiated using its default constructor. - -An `@ModelAttribute` method is a common way to to retrieve an attribute from the -database, which may optionally be stored between requests through the use of -`@SessionAttributes`. In some cases it may be convenient to retrieve the attribute by -using an URI template variable and a type converter. Here is an example: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @RequestMapping(value="/accounts/{account}", method = RequestMethod.PUT) - public String save(@ModelAttribute("account") Account account) { - - } ----- - -In this example the name of the model attribute (i.e. "account") matches the name of a -URI template variable. If you register `Converter<String, Account>` that can turn the -`String` account value into an `Account` instance, then the above example will work -without the need for an `@ModelAttribute` method. - -The next step is data binding. The `WebDataBinder` class matches request parameter names --- including query string parameters and form fields -- to model attribute fields by -name. Matching fields are populated after type conversion (from String to the target -field type) has been applied where necessary. Data binding and validation are covered in -<<validation>>. Customizing the data binding process for a controller level is covered -in <<mvc-ann-webdatabinder>>. - -As a result of data binding there may be errors such as missing required fields or type -conversion errors. To check for such errors add a `BindingResult` argument immediately -following the `@ModelAttribute` argument: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @RequestMapping(value="/owners/{ownerId}/pets/{petId}/edit", method = RequestMethod.POST) - public String processSubmit(**@ModelAttribute("pet") Pet pet**, BindingResult result) { - - if (result.hasErrors()) { - return "petForm"; - } - - // ... - - } ----- - -With a `BindingResult` you can check if errors were found in which case it's common to -render the same form where the errors can be shown with the help of Spring's `<errors>` -form tag. - -In addition to data binding you can also invoke validation using your own custom -validator passing the same `BindingResult` that was used to record data binding errors. -That allows for data binding and validation errors to be accumulated in one place and -subsequently reported back to the user: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @RequestMapping(value="/owners/{ownerId}/pets/{petId}/edit", method = RequestMethod.POST) - public String processSubmit(**@ModelAttribute("pet") Pet pet**, BindingResult result) { - - new PetValidator().validate(pet, result); - if (result.hasErrors()) { - return "petForm"; - } - - // ... - - } ----- - -Or you can have validation invoked automatically by adding the JSR-303 `@Valid` -annotation: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @RequestMapping(value="/owners/{ownerId}/pets/{petId}/edit", method = RequestMethod.POST) - public String processSubmit(**@Valid @ModelAttribute("pet") Pet pet**, BindingResult result) { - - if (result.hasErrors()) { - return "petForm"; - } - - // ... - - } ----- - -See <<validation-beanvalidation>> and <<validation>> for details on how to configure and -use validation. - - -[[mvc-ann-sessionattrib]] -===== Using @SessionAttributes to store model attributes in the HTTP session between requests - -The type-level `@SessionAttributes` annotation declares session attributes used by a -specific handler. This will typically list the names of model attributes or types of -model attributes which should be transparently stored in the session or some -conversational storage, serving as form-backing beans between subsequent requests. - -The following code snippet shows the usage of this annotation, specifying the model -attribute name: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Controller - @RequestMapping("/editPet.do") - **@SessionAttributes("pet")** - public class EditPetForm { - // ... - } ----- - -[[mvc-ann-redirect-attributes]] -===== Specifying redirect and flash attributes -By default all model attributes are considered to be exposed as URI template variables -in the redirect URL. Of the remaining attributes those that are primitive types or -collections/arrays of primitive types are automatically appended as query parameters. - -In annotated controllers however the model may contain additional attributes originally -added for rendering purposes (e.g. drop-down field values). To gain precise control over -the attributes used in a redirect scenario, an `@RequestMapping` method can declare an -argument of type `RedirectAttributes` and use it to add attributes for use in -`RedirectView`. If the controller method does redirect, the content of -`RedirectAttributes` is used. Otherwise the content of the default `Model` is used. - -The `RequestMappingHandlerAdapter` provides a flag called -`"ignoreDefaultModelOnRedirect"` that can be used to indicate the content of the default -`Model` should never be used if a controller method redirects. Instead the controller -method should declare an attribute of type `RedirectAttributes` or if it doesn't do so -no attributes should be passed on to `RedirectView`. Both the MVC namespace and the MVC -Java config keep this flag set to `false` in order to maintain backwards compatibility. -However, for new applications we recommend setting it to `true` - -The `RedirectAttributes` interface can also be used to add flash attributes. Unlike -other redirect attributes, which end up in the target redirect URL, flash attributes are -saved in the HTTP session (and hence do not appear in the URL). The model of the -controller serving the target redirect URL automatically receives these flash attributes -after which they are removed from the session. See <<mvc-flash-attributes>> for an -overview of the general support for flash attributes in Spring MVC. - - -[[mvc-ann-form-urlencoded-data]] -===== Working with "application/x-www-form-urlencoded" data - -The previous sections covered use of `@ModelAttribute` to support form submission -requests from browser clients. The same annotation is recommended for use with requests -from non-browser clients as well. However there is one notable difference when it comes -to working with HTTP PUT requests. Browsers can submit form data via HTTP GET or HTTP -POST. Non-browser clients can also submit forms via HTTP PUT. This presents a challenge -because the Servlet specification requires the `ServletRequest.getParameter*()` family -of methods to support form field access only for HTTP POST, not for HTTP PUT. - -To support HTTP PUT and PATCH requests, the `spring-web` module provides the filter -`HttpPutFormContentFilter`, which can be configured in `web.xml`: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - <filter> - <filter-name>httpPutFormFilter</filter-name> - <filter-class>org.springframework.web.filter.HttpPutFormContentFilter</filter-class> - </filter> - - <filter-mapping> - <filter-name>httpPutFormFilter</filter-name> - <servlet-name>dispatcherServlet</servlet-name> - </filter-mapping> - - <servlet> - <servlet-name>dispatcherServlet</servlet-name> - <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> - </servlet> ----- - -The above filter intercepts HTTP PUT and PATCH requests with content type -`application/x-www-form-urlencoded`, reads the form data from the body of the request, -and wraps the `ServletRequest` in order to make the form data available through the -`ServletRequest.getParameter*()` family of methods. - -[NOTE] -==== -As `HttpPutFormContentFilter` consumes the body of the request, it should not be -configured for PUT or PATCH URLs that rely on other converters for -`application/x-www-form-urlencoded`. This includes `@RequestBody MultiValueMap<String, -String>` and `HttpEntity<MultiValueMap<String, String>>`. -==== - - -[[mvc-ann-cookievalue]] -===== Mapping cookie values with the @CookieValue annotation -The `@CookieValue` annotation allows a method parameter to be bound to the value of an -HTTP cookie. - -Let us consider that the following cookie has been received with an http request: - -[literal] -[subs="verbatim,quotes"] ----- -JSESSIONID=415A4AC178C59DACE0B2C9CA727CDD84 ----- - -The following code sample demonstrates how to get the value of the `JSESSIONID` cookie: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @RequestMapping("/displayHeaderInfo.do") - public void displayHeaderInfo(**@CookieValue("JSESSIONID")** String cookie) { - //... - } ----- - -Type conversion is applied automatically if the target method parameter type is not -`String`. See <<mvc-ann-typeconversion>>. - -This annotation is supported for annotated handler methods in Servlet and Portlet -environments. - - -[[mvc-ann-requestheader]] -===== Mapping request header attributes with the @RequestHeader annotation -The `@RequestHeader` annotation allows a method parameter to be bound to a request header. - -Here is a sample request header: - -[literal] -[subs="verbatim,quotes"] ----- -Host localhost:8080 -Accept text/html,application/xhtml+xml,application/xml;q=0.9 -Accept-Language fr,en-gb;q=0.7,en;q=0.3 -Accept-Encoding gzip,deflate -Accept-Charset ISO-8859-1,utf-8;q=0.7,*;q=0.7 -Keep-Alive 300 ----- - -The following code sample demonstrates how to get the value of the `Accept-Encoding` and -`Keep-Alive` headers: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @RequestMapping("/displayHeaderInfo.do") - public void displayHeaderInfo(**@RequestHeader("Accept-Encoding")** String encoding, - **@RequestHeader("Keep-Alive")** long keepAlive) { - //... - } ----- - -Type conversion is applied automatically if the method parameter is not `String`. See -<<mvc-ann-typeconversion>>. - -[TIP] -==== -Built-in support is available for converting a comma-separated string into an -array/collection of strings or other types known to the type conversion system. For -example a method parameter annotated with `@RequestHeader("Accept")` may be of type -`String` but also `String[]` or `List<String>`. -==== - -This annotation is supported for annotated handler methods in Servlet and Portlet -environments. - - -[[mvc-ann-typeconversion]] -===== Method Parameters And Type Conversion -String-based values extracted from the request including request parameters, path -variables, request headers, and cookie values may need to be converted to the target -type of the method parameter or field (e.g., binding a request parameter to a field in -an `@ModelAttribute` parameter) they're bound to. If the target type is not `String`, -Spring automatically converts to the appropriate type. All simple types such as int, -long, Date, etc. are supported. You can further customize the conversion process through -a `WebDataBinder` (see <<mvc-ann-webdatabinder>>) or by registering `Formatters` with -the `FormattingConversionService` (see <<format>>). - - -[[mvc-ann-webdatabinder]] -===== Customizing WebDataBinder initialization -To customize request parameter binding with PropertyEditors through Spring's -`WebDataBinder`, you can use `@InitBinder`-annotated methods within your controller, -`@InitBinder` methods within an `@ControllerAdvice` class, or provide a custom -`WebBindingInitializer`. See the <<mvc-ann-controller-advice>> section for more details. - -[[mvc-ann-initbinder]] -====== Customizing data binding with @InitBinder -Annotating controller methods with `@InitBinder` allows you to configure web data -binding directly within your controller class. `@InitBinder` identifies methods that -initialize the `WebDataBinder` that will be used to populate command and form object -arguments of annotated handler methods. - -Such init-binder methods support all arguments that `@RequestMapping` supports, except -for command/form objects and corresponding validation result objects. Init-binder -methods must not have a return value. Thus, they are usually declared as `void`. Typical -arguments include `WebDataBinder` in combination with `WebRequest` or -`java.util.Locale`, allowing code to register context-specific editors. - -The following example demonstrates the use of `@InitBinder` to configure a -`CustomDateEditor` for all `java.util.Date` form properties. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Controller - public class MyFormController { - - **@InitBinder** - public void initBinder(WebDataBinder binder) { - SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd"); - dateFormat.setLenient(false); - binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, false)); - } - - // ... - - } ----- - -[[mvc-ann-webbindinginitializer]] -====== Configuring a custom WebBindingInitializer - -To externalize data binding initialization, you can provide a custom implementation of -the `WebBindingInitializer` interface, which you then enable by supplying a custom bean -configuration for an `AnnotationMethodHandlerAdapter`, thus overriding the default -configuration. - -The following example from the PetClinic application shows a configuration using a -custom implementation of the `WebBindingInitializer` interface, -`org.springframework.samples.petclinic.web.ClinicBindingInitializer`, which configures -PropertyEditors required by several of the PetClinic controllers. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"> - <property name="cacheSeconds" value="0" /> - <property name="webBindingInitializer"> - <bean class="org.springframework.samples.petclinic.web.ClinicBindingInitializer" /> - </property> - </bean> ----- - -`@InitBinder` methods can also be defined in an ++@ControllerAdvice++-annotated class in -which case they apply to matching controllers. This provides an alternative to using a -`WebBindingInitializer`. See the <<mvc-ann-controller-advice>> section for more details. - - -[[mvc-ann-lastmodified]] -===== Support for the Last-Modified Response Header To Facilitate Content Caching -An `@RequestMapping` method may wish to support `'Last-Modified'` HTTP requests, as -defined in the contract for the Servlet API's `getLastModified` method, to facilitate -content caching. This involves calculating a lastModified `long` value for a given -request, comparing it against the `'If-Modified-Since'` request header value, and -potentially returning a response with status code 304 (Not Modified). An annotated -controller method can achieve that as follows: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @RequestMapping - public String myHandleMethod(WebRequest webRequest, Model model) { - - long lastModified = // 1. application-specific calculation - - if (request.checkNotModified(lastModified)) { - // 2. shortcut exit - no further processing necessary - return null; - } - - // 3. or otherwise further request processing, actually preparing content - model.addAttribute(...); - return "myViewName"; - } ----- - -There are two key elements to note: calling `request.checkNotModified(lastModified)` and -returning `null`. The former sets the response status to 304 before it returns `true`. -The latter, in combination with the former, causes Spring MVC to do no further -processing of the request. - -[[mvc-ann-controller-advice]] -===== Advising controllers with the `@ControllerAdvice` annotation -The `@ControllerAdvice` annotation is a component annotation allowing implementation -classes to be auto-detected through classpath scanning. It is automatically enabled when -using the MVC namespace or the MVC Java config. - -Classes annotated with `@ControllerAdvice` can contain `@ExceptionHandler`, -`@InitBinder`, and `@ModelAttribute` annotated methods, and these methods will apply to -`@RequestMapping` methods across all controller hierarchies as opposed to the controller -hierarchy within which they are declared. - -The `@ControllerAdvice` annotation can also target a subset of controllers with its -attributes: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - // Target all Controllers annotated with @RestController - @ControllerAdvice(annotations = RestController.class) - public class AnnotationAdvice {} - - // Target all Controllers within specific packages - @ControllerAdvice("org.example.controllers") - public class BasePackageAdvice {} - - // Target all Controllers assignable to specific classes - @ControllerAdvice(assignableTypes = {ControllerInterface.class, AbstractController.class}) - public class AssignableTypesAdvice {} ----- - -Check out the -{javadoc-baseurl}/org/springframework/web/bind/annotation/ControllerAdvice.html[`@ControllerAdvice` -documentation] for more details. - -[[mvc-ann-jsonview]] -===== Jackson Serialization View Support - -It can sometimes be useful to filter contextually the object that will be serialized to the -HTTP response body. In order to provide such capability, Spring MVC has built-in support for -rendering with http://wiki.fasterxml.com/JacksonJsonViews[Jackson's Serialization Views]. - -To use it with `@ResponseBody` controller method or methods return `ResponseEntity`, simply -add the `@JsonView` annotation: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @RestController - public class UserController { - - @RequestMapping(value = "/user", method = RequestMethod.GET) - @JsonView(User.WithoutPasswordView.class) - public User getUser() { - return new User("eric", "7!jd#h23"); - } - } - - public class User { - - public interface WithoutPasswordView {}; - public interface WithPasswordView extends WithoutPasswordView {}; - - private String username; - private String password; - - public User() { - } - - public User(String username, String password) { - this.username = username; - this.password = password; - } - - @JsonView(WithoutPasswordView.class) - public String getUsername() { - return this.username; - } - - @JsonView(WithPasswordView.class) - public String getPassword() { - return this.password; - } - } ----- - -For controllers relying on view resolution, simply add the serialization view class -to the model: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Controller - public class UserController extends AbstractController { - - @RequestMapping(value = "/user", method = RequestMethod.GET) - public String getUser(Model model) { - model.addAttribute("user", new User("eric", "7!jd#h23")); - model.addAttribute(JsonView.class.getName(), User.WithoutPasswordView.class); - return "userView"; - } - } - ----- - -[[mvc-ann-async]] -==== Asynchronous Request Processing -Spring MVC 3.2 introduced Servlet 3 based asynchronous request processing. Instead of -returning a value, as usual, a controller method can now return a -`java.util.concurrent.Callable` and produce the return value from a separate thread. -Meanwhile the main Servlet container thread is released and allowed to process other -requests. Spring MVC invokes the `Callable` in a separate thread with the help of a -`TaskExecutor` and when the `Callable` returns, the request is dispatched back to the -Servlet container to resume processing with the value returned by the `Callable`. Here -is an example controller method: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @RequestMapping(method=RequestMethod.POST) - public Callable<String> processUpload(final MultipartFile file) { - - return new Callable<String>() { - public String call() throws Exception { - // ... - return "someView"; - } - }; - - } ----- - -A second option is for the controller to return an instance of `DeferredResult`. In this -case the return value will also be produced from a separate thread. However, that thread -is not known to Spring MVC. For example the result may be produced in response to some -external event such as a JMS message, a scheduled task, etc. Here is an example -controller method: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @RequestMapping("/quotes") - @ResponseBody - public DeferredResult<String> quotes() { - DeferredResult<String> deferredResult = new DeferredResult<String>(); - // Save the deferredResult in in-memory queue ... - return deferredResult; - } - - // In some other thread... - deferredResult.setResult(data); ----- - -This may be difficult to understand without any knowledge of the Servlet 3 async -processing feature. It would certainly help to read up on it. At a very minimum consider -the following basic facts: - -* A `ServletRequest` can be put in asynchronous mode by calling `request.startAsync()`. - The main effect of doing so is that the Servlet, as well as any Filters, can exit but - the response will remain open allowing some other thread to complete processing. -* The call to `request.startAsync()` returns an `AsyncContext`, which can be used for - further control over async processing. For example it provides the method `dispatch`, - which can be called from an application thread in order to "dispatch" the request back - to the Servlet container. An async dispatch is similar to a forward except it is made - from one (application) thread to another (Servlet container) thread whereas a forward - occurs synchronously in the same (Servlet container) thread. -* `ServletRequest` provides access to the current `DispatcherType`, which can be used to - distinguish if a `Servlet` or a `Filter` is processing on the initial request - processing thread and when it is processing in an async dispatch. - -With the above in mind, the following is the sequence of events for async request -processing with a `Callable`: (1) Controller returns a `Callable`, (2) Spring MVC starts -async processing and submits the `Callable` to a `TaskExecutor` for processing in a -separate thread, (3) the `DispatcherServlet` and all Filter's exit the request -processing thread but the response remains open, (4) the `Callable` produces a result -and Spring MVC dispatches the request back to the Servlet container, (5) the -`DispatcherServlet` is invoked again and processing resumes with the asynchronously -produced result from the `Callable`. The exact sequencing of (2), (3), and (4) may vary -depending on the speed of execution of the concurrent threads. - -The sequence of events for async request processing with a `DeferredResult` is the same -in principal except it's up to the application to produce the asynchronous result from -some thread: (1) Controller returns a `DeferredResult` and saves it in some in-memory -queue or list where it can be accessed, (2) Spring MVC starts async processing, (3) the -`DispatcherServlet` and all configured Filter's exit the request processing thread but -the response remains open, (4) the application sets the `DeferredResult` from some -thread and Spring MVC dispatches the request back to the Servlet container, (5) the -`DispatcherServlet` is invoked again and processing resumes with the asynchronously -produced result. - -Explaining the motivation for async request processing and when or why to use it are -beyond the scope of this document. For further information you may wish to read -https://spring.io/blog/2012/05/07/spring-mvc-3-2-preview-introducing-servlet-3-async-support[this -blog post series]. - - -[[mvc-ann-async-exceptions]] -===== Exception Handling for Async Requests -What happens if a `Callable` returned from a controller method raises an Exception while -being executed? The effect is similar to what happens when any controller method raises -an exception. It is handled by a matching `@ExceptionHandler` method in the same -controller or by one of the configured `HandlerExceptionResolver` instances. - -[NOTE] -==== -Under the covers, when a `Callable` raises an Exception, Spring MVC still dispatches to -the Servlet container to resume processing. The only difference is that the result of -executing the `Callable` is an `Exception` that must be processed with the configured -`HandlerExceptionResolver` instances. -==== - -When using a `DeferredResult`, you have a choice of calling its `setErrorResult(Object)` -method and provide an `Exception` or any other Object you'd like to use as the result. -If the result is an `Exception`, it will be processed with a matching -`@ExceptionHandler` method in the same controller or with any configured -`HandlerExceptionResolver` instance. - - -[[mvc-ann-async-interception]] -===== Intercepting Async Requests -An existing `HandlerInterceptor` can implement `AsyncHandlerInterceptor`, which provides -one additional method `afterConcurrentHandlingStarted`. It is invoked after async -processing starts and when the initial request processing thread is being exited. See -the `AsyncHandlerInterceptor` javadocs for more details on that. - -Further options for async request lifecycle callbacks are provided directly on -`DeferredResult`, which has the methods `onTimeout(Runnable)` and -`onCompletion(Runnable)`. Those are called when the async request is about to time out -or has completed respectively. The timeout event can be handled by setting the -`DeferredResult` to some value. The completion callback however is final and the result -can no longer be set. - -Similar callbacks are also available with a `Callable`. However, you will need to wrap -the `Callable` in an instance of `WebAsyncTask` and then use that to register the -timeout and completion callbacks. Just like with `DeferredResult`, the timeout event can -be handled and a value can be returned while the completion event is final. - -You can also register a `CallableProcessingInterceptor` or a -`DeferredResultProcessingInterceptor` globally through the MVC Java config or the MVC -namespace. Those interceptors provide a full set of callbacks and apply every time a -`Callable` or a `DeferredResult` is used. - - -[[mvc-ann-async-configuration]] -===== Configuration for Async Request Processing - -[[mvc-ann-async-configuration-servlet3]] -====== Servlet 3 Async Config -To use Servlet 3 async request processing, you need to update `web.xml` to version 3.0: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - <web-app xmlns="http://java.sun.com/xml/ns/javaee" - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - http://java.sun.com/xml/ns/javaee - http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" - version="3.0"> - - ... - - </web-app> ----- - -The `DispatcherServlet` and any `Filter` configuration need to have the -`<async-supported>true</async-supported>` sub-element. Additionally, any `Filter` that -also needs to get involved in async dispatches should also be configured to support the -ASYNC dispatcher type. Note that it is safe to enable the ASYNC dispatcher type for all -filters provided with the Spring Framework since they will not get involved in async -dispatches unless needed. - -[WARNING] -==== -Note that for some Filters it is absolutely critical to ensure they are mapped to -be invoked during asynchronous dispatches. For example if a filter such as the -`OpenEntityManagerInViewFilter` is responsible for releasing database connection -resources and must be invoked at the end of an async request. - -Below is an example of a propertly configured filter: -==== - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - <web-app xmlns="http://java.sun.com/xml/ns/javaee" - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:schemaLocation=" - http://java.sun.com/xml/ns/javaee - http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" - version="3.0"> - - <filter> - <filter-name>Spring OpenEntityManagerInViewFilter</filter-name> - <filter-class>org.springframework.~.OpenEntityManagerInViewFilter</filter-class> - <async-supported>true</async-supported> - </filter> - - <filter-mapping> - <filter-name>Spring OpenEntityManagerInViewFilter</filter-name> - <url-pattern>/*</url-pattern> - <dispatcher>REQUEST</dispatcher> - <dispatcher>ASYNC</dispatcher> - </filter-mapping> - - </web-app> - ----- - -If using Servlet 3, Java based configuration, e.g. via `WebApplicationInitializer`, -you'll also need to set the "asyncSupported" flag as well as the ASYNC dispatcher type -just like with `web.xml`. To simplify all this configuration, consider extending -`AbstractDispatcherServletInitializer` or -`AbstractAnnotationConfigDispatcherServletInitializer`, which automatically set those -options and make it very easy to register `Filter` instances. - -[[mvc-ann-async-configuration-spring-mvc]] -====== Spring MVC Async Config -The MVC Java config and the MVC namespace both provide options for configuring async -request processing. `WebMvcConfigurer` has the method `configureAsyncSupport` while -<mvc:annotation-driven> has an <async-support> sub-element. - -Those allow you to configure the default timeout value to use for async requests, which -if not set depends on the underlying Servlet container (e.g. 10 seconds on Tomcat). You -can also configure an `AsyncTaskExecutor` to use for executing `Callable` instances -returned from controller methods. It is highly recommended to configure this property -since by default Spring MVC uses `SimpleAsyncTaskExecutor`. The MVC Java config and the -MVC namespace also allow you to register `CallableProcessingInterceptor` and -`DeferredResultProcessingInterceptor` instances. - -If you need to override the default timeout value for a specific `DeferredResult`, you -can do so by using the appropriate class constructor. Similarly, for a `Callable`, you -can wrap it in a `WebAsyncTask` and use the appropriate class constructor to customize -the timeout value. The class constructor of `WebAsyncTask` also allows providing an -`AsyncTaskExecutor`. - - - -[[mvc-ann-tests]] -==== Testing Controllers -The `spring-test` module offers first class support for testing annotated controllers. -See <<spring-mvc-test-framework>>. - - - - -[[mvc-handlermapping]] -=== Handler mappings -In previous versions of Spring, users were required to define one or more -`HandlerMapping` beans in the web application context to map incoming web requests to -appropriate handlers. With the introduction of annotated controllers, you generally -don't need to do that because the `RequestMappingHandlerMapping` automatically looks for -`@RequestMapping` annotations on all `@Controller` beans. However, do keep in mind that -all `HandlerMapping` classes extending from `AbstractHandlerMapping` have the following -properties that you can use to customize their behavior: - -* `interceptors` List of interceptors to use. ++HandlerInterceptor++s are discussed in - <<mvc-handlermapping-interceptor>>. -* `defaultHandler` Default handler to use, when this handler mapping does not result in - a matching handler. -* `order` Based on the value of the order property (see the - `org.springframework.core.Ordered` interface), Spring sorts all handler mappings - available in the context and applies the first matching handler. -* `alwaysUseFullPath` If `true` , Spring uses the full path within the current Servlet - context to find an appropriate handler. If `false` (the default), the path within the - current Servlet mapping is used. For example, if a Servlet is mapped using - `/testing/*` and the `alwaysUseFullPath` property is set to true, - `/testing/viewPage.html` is used, whereas if the property is set to false, - `/viewPage.html` is used. -* `urlDecode` Defaults to `true`, as of Spring 2.5. If you prefer to compare encoded - paths, set this flag to `false`. However, the `HttpServletRequest` always exposes the - Servlet path in decoded form. Be aware that the Servlet path will not match when - compared with encoded paths. - -The following example shows how to configure an interceptor: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - <beans> - <bean id="handlerMapping" class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"> - <property name="interceptors"> - <bean class="example.MyInterceptor"/> - </property> - </bean> - <beans> ----- - - - -[[mvc-handlermapping-interceptor]] -==== Intercepting requests with a HandlerInterceptor - -Spring's handler mapping mechanism includes handler interceptors, which are useful when -you want to apply specific functionality to certain requests, for example, checking for -a principal. - -Interceptors located in the handler mapping must implement `HandlerInterceptor` from the -`org.springframework.web.servlet` package. This interface defines three methods: -`preHandle(..)` is called __before__ the actual handler is executed; `postHandle(..)` is -called __after__ the handler is executed; and `afterCompletion(..)` is called __after -the complete request has finished__. These three methods should provide enough -flexibility to do all kinds of preprocessing and postprocessing. - -The `preHandle(..)` method returns a boolean value. You can use this method to break or -continue the processing of the execution chain. When this method returns `true`, the -handler execution chain will continue; when it returns false, the `DispatcherServlet` -assumes the interceptor itself has taken care of requests (and, for example, rendered an -appropriate view) and does not continue executing the other interceptors and the actual -handler in the execution chain. - -Interceptors can be configured using the `interceptors` property, which is present on -all `HandlerMapping` classes extending from `AbstractHandlerMapping`. This is shown in -the example below: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - <beans> - <bean id="handlerMapping" - class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"> - <property name="interceptors"> - <list> - <ref bean="officeHoursInterceptor"/> - </list> - </property> - </bean> - - <bean id="officeHoursInterceptor" - class="samples.TimeBasedAccessInterceptor"> - <property name="openingTime" value="9"/> - <property name="closingTime" value="18"/> - </bean> - <beans> ----- - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - package samples; - - public class TimeBasedAccessInterceptor extends HandlerInterceptorAdapter { - - private int openingTime; - private int closingTime; - - public void setOpeningTime(int openingTime) { - this.openingTime = openingTime; - } - - public void setClosingTime(int closingTime) { - this.closingTime = closingTime; - } - - public boolean preHandle(HttpServletRequest request, HttpServletResponse response, - Object handler) throws Exception { - Calendar cal = Calendar.getInstance(); - int hour = cal.get(HOUR_OF_DAY); - if (openingTime <= hour && hour < closingTime) { - return true; - } - response.sendRedirect("http://host.com/outsideOfficeHours.html"); - return false; - } - } ----- - -Any request handled by this mapping is intercepted by the `TimeBasedAccessInterceptor`. -If the current time is outside office hours, the user is redirected to a static HTML -file that says, for example, you can only access the website during office hours. - -[NOTE] -==== -When using the `RequestMappingHandlerMapping` the actual handler is an instance of -`HandlerMethod` which identifies the specific controller method that will be invoked. -==== - -As you can see, the Spring adapter class `HandlerInterceptorAdapter` makes it easier to -extend the `HandlerInterceptor` interface. - -[TIP] -==== - -In the example above, the configured interceptor will apply to all requests handled with -annotated controller methods. If you want to narrow down the URL paths to which an -interceptor applies, you can use the MVC namespace or the MVC Java config, or declare -bean instances of type `MappedInterceptor` to do that. See <<mvc-config-enable>>. -==== - - - - -[[mvc-viewresolver]] -=== Resolving views -All MVC frameworks for web applications provide a way to address views. Spring provides -view resolvers, which enable you to render models in a browser without tying you to a -specific view technology. Out of the box, Spring enables you to use JSPs, Velocity -templates and XSLT views, for example. See <<view>> for a discussion of how to integrate -and use a number of disparate view technologies. - -The two interfaces that are important to the way Spring handles views are `ViewResolver` -and `View`. The `ViewResolver` provides a mapping between view names and actual views. -The `View` interface addresses the preparation of the request and hands the request over -to one of the view technologies. - - - -[[mvc-viewresolver-resolver]] -==== Resolving views with the ViewResolver interface - -As discussed in <<mvc-controller>>, all handler methods in the Spring Web MVC -controllers must resolve to a logical view name, either explicitly (e.g., by returning a -`String`, `View`, or `ModelAndView`) or implicitly (i.e., based on conventions). Views -in Spring are addressed by a logical view name and are resolved by a view resolver. -Spring comes with quite a few view resolvers. This table lists most of them; a couple of -examples follow. - -[[mvc-view-resolvers-tbl]] -.View resolvers -|=== -| ViewResolver| Description - -| `AbstractCachingViewResolver` -| Abstract view resolver that caches views. Often views need preparation before they can - be used; extending this view resolver provides caching. - -| `XmlViewResolver` -| Implementation of `ViewResolver` that accepts a configuration file written in XML with - the same DTD as Spring's XML bean factories. The default configuration file is - `/WEB-INF/views.xml`. - -| `ResourceBundleViewResolver` -| Implementation of `ViewResolver` that uses bean definitions in a `ResourceBundle`, - specified by the bundle base name. Typically you define the bundle in a properties - file, located in the classpath. The default file name is `views.properties`. - -| `UrlBasedViewResolver` -| Simple implementation of the `ViewResolver` interface that effects the direct - resolution of logical view names to URLs, without an explicit mapping definition. This - is appropriate if your logical names match the names of your view resources in a - straightforward manner, without the need for arbitrary mappings. - -| `InternalResourceViewResolver` -| Convenient subclass of `UrlBasedViewResolver` that supports `InternalResourceView` (in - effect, Servlets and JSPs) and subclasses such as `JstlView` and `TilesView`. You can - specify the view class for all views generated by this resolver by using - `setViewClass(..)`. See the `UrlBasedViewResolver` javadocs for details. - -| `VelocityViewResolver` / `FreeMarkerViewResolver` -| Convenient subclass of `UrlBasedViewResolver` that supports `VelocityView` (in effect, - Velocity templates) or `FreeMarkerView` ,respectively, and custom subclasses of them. - -| `ContentNegotiatingViewResolver` -| Implementation of the `ViewResolver` interface that resolves a view based on the - request file name or `Accept` header. See <<mvc-multiple-representations>>. -|=== - -As an example, with JSP as a view technology, you can use the `UrlBasedViewResolver`. -This view resolver translates a view name to a URL and hands the request over to the -RequestDispatcher to render the view. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - <bean id="viewResolver" - class="org.springframework.web.servlet.view.UrlBasedViewResolver"> - <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/> - <property name="prefix" value="/WEB-INF/jsp/"/> - <property name="suffix" value=".jsp"/> - </bean> ----- - -When returning `test` as a logical view name, this view resolver forwards the request to -the `RequestDispatcher` that will send the request to `/WEB-INF/jsp/test.jsp`. - -When you combine different view technologies in a web application, you can use the -`ResourceBundleViewResolver`: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - <bean id="viewResolver" - class="org.springframework.web.servlet.view.ResourceBundleViewResolver"> - <property name="basename" value="views"/> - <property name="defaultParentView" value="parentView"/> - </bean> ----- - -The `ResourceBundleViewResolver` inspects the `ResourceBundle` identified by the -basename, and for each view it is supposed to resolve, it uses the value of the property -`[viewname].(class)` as the view class and the value of the property `[viewname].url` as -the view url. Examples can be found in the next chapter which covers view technologies. -As you can see, you can identify a parent view, from which all views in the properties -file "extend". This way you can specify a default view class, for example. - -[NOTE] -==== -Subclasses of `AbstractCachingViewResolver` cache view instances that they resolve. -Caching improves performance of certain view technologies. It's possible to turn off the -cache by setting the `cache` property to `false`. Furthermore, if you must refresh a -certain view at runtime (for example when a Velocity template is modified), you can use -the `removeFromCache(String viewName, Locale loc)` method. -==== - - - -[[mvc-viewresolver-chaining]] -==== Chaining ViewResolvers -Spring supports multiple view resolvers. Thus you can chain resolvers and, for example, -override specific views in certain circumstances. You chain view resolvers by adding -more than one resolver to your application context and, if necessary, by setting the -`order` property to specify ordering. Remember, the higher the order property, the later -the view resolver is positioned in the chain. - -In the following example, the chain of view resolvers consists of two resolvers, an -`InternalResourceViewResolver`, which is always automatically positioned as the last -resolver in the chain, and an `XmlViewResolver` for specifying Excel views. Excel views -are not supported by the `InternalResourceViewResolver`. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - <bean id="jspViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> - <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/> - <property name="prefix" value="/WEB-INF/jsp/"/> - <property name="suffix" value=".jsp"/> - </bean> - - <bean id="excelViewResolver" class="org.springframework.web.servlet.view.XmlViewResolver"> - <property name="order" value="1"/> - <property name="location" value="/WEB-INF/views.xml"/> - </bean> - - <!-- in views.xml --> - - <beans> - <bean name="report" class="org.springframework.example.ReportExcelView"/> - </beans> ----- - -If a specific view resolver does not result in a view, Spring examines the context for -other view resolvers. If additional view resolvers exist, Spring continues to inspect -them until a view is resolved. If no view resolver returns a view, Spring throws a -`ServletException`. - -The contract of a view resolver specifies that a view resolver __can__ return null to -indicate the view could not be found. Not all view resolvers do this, however, because -in some cases, the resolver simply cannot detect whether or not the view exists. For -example, the `InternalResourceViewResolver` uses the `RequestDispatcher` internally, and -dispatching is the only way to figure out if a JSP exists, but this action can only -execute once. The same holds for the `VelocityViewResolver` and some others. Check the -javadocs of the specific view resolver to see whether it reports non-existing views. -Thus, putting an `InternalResourceViewResolver` in the chain in a place other than -the last results in the chain not being fully inspected, because the -`InternalResourceViewResolver` will __always__ return a view! - - - -[[mvc-redirecting]] -==== Redirecting to views -As mentioned previously, a controller typically returns a logical view name, which a -view resolver resolves to a particular view technology. For view technologies such as -JSPs that are processed through the Servlet or JSP engine, this resolution is usually -handled through the combination of `InternalResourceViewResolver` and -`InternalResourceView`, which issues an internal forward or include via the Servlet -API's `RequestDispatcher.forward(..)` method or `RequestDispatcher.include()` method. -For other view technologies, such as Velocity, XSLT, and so on, the view itself writes -the content directly to the response stream. - -It is sometimes desirable to issue an HTTP redirect back to the client, before the view -is rendered. This is desirable, for example, when one controller has been called with -`POST` data, and the response is actually a delegation to another controller (for -example on a successful form submission). In this case, a normal internal forward will -mean that the other controller will also see the same `POST` data, which is potentially -problematic if it can confuse it with other expected data. Another reason to perform a -redirect before displaying the result is to eliminate the possibility of the user -submitting the form data multiple times. In this scenario, the browser will first send -an initial `POST`; it will then receive a response to redirect to a different URL; and -finally the browser will perform a subsequent `GET` for the URL named in the redirect -response. Thus, from the perspective of the browser, the current page does not reflect -the result of a `POST` but rather of a `GET`. The end effect is that there is no way the -user can accidentally re- `POST` the same data by performing a refresh. The refresh -forces a `GET` of the result page, not a resend of the initial `POST` data. - - -[[mvc-redirecting-redirect-view]] -===== RedirectView - -One way to force a redirect as the result of a controller response is for the controller -to create and return an instance of Spring's `RedirectView`. In this case, -`DispatcherServlet` does not use the normal view resolution mechanism. Rather because it -has been given the (redirect) view already, the `DispatcherServlet` simply instructs the -view to do its work. - -The `RedirectView` issues an `HttpServletResponse.sendRedirect()` call that returns to -the client browser as an HTTP redirect. By default all model attributes are considered -to be exposed as URI template variables in the redirect URL. Of the remaining attributes -those that are primitive types or collections/arrays of primitive types are -automatically appended as query parameters. - -Appending primitive type attributes as query parameters may be the desired result if a -model instance was prepared specifically for the redirect. However, in annotated -controllers the model may contain additional attributes added for rendering purposes -(e.g. drop-down field values). To avoid the possibility of having such attributes appear -in the URL an annotated controller can declare an argument of type `RedirectAttributes` -and use it to specify the exact attributes to make available to `RedirectView`. If the -controller method decides to redirect, the content of `RedirectAttributes` is used. -Otherwise the content of the model is used. - -Note that URI template variables from the present request are automatically made -available when expanding a redirect URL and do not need to be added explicitly neither -through `Model` nor `RedirectAttributes`. For example: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @RequestMapping(value = "/files/{path}", method = RequestMethod.POST) - public String upload(...) { - // ... - return "redirect:files/{path}"; - } ----- - -If you use `RedirectView` and the view is created by the controller itself, it is -recommended that you configure the redirect URL to be injected into the controller so -that it is not baked into the controller but configured in the context along with the -view names. The next section discusses this process. - - -[[mvc-redirecting-redirect-prefix]] -===== The redirect: prefix - -While the use of `RedirectView` works fine, if the controller itself creates the -`RedirectView`, there is no avoiding the fact that the controller is aware that a -redirection is happening. This is really suboptimal and couples things too tightly. The -controller should not really care about how the response gets handled. In general it -should operate only in terms of view names that have been injected into it. - -The special `redirect:` prefix allows you to accomplish this. If a view name is returned -that has the prefix `redirect:`, the `UrlBasedViewResolver` (and all subclasses) will -recognize this as a special indication that a redirect is needed. The rest of the view -name will be treated as the redirect URL. - -The net effect is the same as if the controller had returned a `RedirectView`, but now -the controller itself can simply operate in terms of logical view names. A logical view -name such as `redirect:/myapp/some/resource` will redirect relative to the current -Servlet context, while a name such as `redirect:http://myhost.com/some/arbitrary/path` -will redirect to an absolute URL. - - -[[mvc-redirecting-forward-prefix]] -===== The forward: prefix - -It is also possible to use a special `forward:` prefix for view names that are -ultimately resolved by `UrlBasedViewResolver` and subclasses. This creates an -`InternalResourceView` (which ultimately does a `RequestDispatcher.forward()`) around -the rest of the view name, which is considered a URL. Therefore, this prefix is not -useful with `InternalResourceViewResolver` and `InternalResourceView` (for JSPs for -example). But the prefix can be helpful when you are primarily using another view -technology, but still want to force a forward of a resource to be handled by the -Servlet/JSP engine. (Note that you may also chain multiple view resolvers, instead.) - -As with the `redirect:` prefix, if the view name with the `forward:` prefix is injected -into the controller, the controller does not detect that anything special is happening -in terms of handling the response. - - - -[[mvc-multiple-representations]] -==== ContentNegotiatingViewResolver - -The `ContentNegotiatingViewResolver` does not resolve views itself but rather delegates -to other view resolvers, selecting the view that resembles the representation requested -by the client. Two strategies exist for a client to request a representation from the -server: - -* Use a distinct URI for each resource, typically by using a different file extension in - the URI. For example, the URI `http://www.example.com/users/fred.pdf` requests a PDF - representation of the user fred, and `http://www.example.com/users/fred.xml` requests - an XML representation. -* Use the same URI for the client to locate the resource, but set the `Accept` HTTP - request header to list the http://en.wikipedia.org/wiki/Internet_media_type[media - types] that it understands. For example, an HTTP request for - `http://www.example.com/users/fred` with an `Accept` header set to `application/pdf` - requests a PDF representation of the user fred, while - `http://www.example.com/users/fred` with an `Accept` header set to `text/xml` requests - an XML representation. This strategy is known as - http://en.wikipedia.org/wiki/Content_negotiation[content negotiation]. - -[NOTE] -==== -One issue with the `Accept` header is that it is impossible to set it in a web browser -within HTML. For example, in Firefox, it is fixed to: - -[literal] -[subs="verbatim,quotes"] ----- -Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 ----- - -For this reason it is common to see the use of a distinct URI for each representation -when developing browser based web applications. -==== - -To support multiple representations of a resource, Spring provides the -`ContentNegotiatingViewResolver` to resolve a view based on the file extension or -`Accept` header of the HTTP request. `ContentNegotiatingViewResolver` does not perform -the view resolution itself but instead delegates to a list of view resolvers that you -specify through the bean property `ViewResolvers`. - -The `ContentNegotiatingViewResolver` selects an appropriate `View` to handle the request -by comparing the request media type(s) with the media type (also known as -`Content-Type`) supported by the `View` associated with each of its `ViewResolvers`. The -first `View` in the list that has a compatible `Content-Type` returns the representation -to the client. If a compatible view cannot be supplied by the `ViewResolver` chain, then -the list of views specified through the `DefaultViews` property will be consulted. This -latter option is appropriate for singleton `Views` that can render an appropriate -representation of the current resource regardless of the logical view name. The `Accept` -header may include wild cards, for example `text/*`, in which case a `View` whose -Content-Type was `text/xml` is a compatible match. - -To support the resolution of a view based on a file extension, use the -`ContentNegotiatingViewResolver` bean property `mediaTypes` to specify a mapping of file -extensions to media types. For more information on the algorithm used to determine the -request media type, refer to the API documentation for `ContentNegotiatingViewResolver`. - -Here is an example configuration of a `ContentNegotiatingViewResolver:` - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - <bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver"> - <property name="mediaTypes"> - <map> - <entry key="atom" value="application/atom+xml"/> - <entry key="html" value="text/html"/> - <entry key="json" value="application/json"/> - </map> - </property> - <property name="viewResolvers"> - <list> - <bean class="org.springframework.web.servlet.view.BeanNameViewResolver"/> - <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> - <property name="prefix" value="/WEB-INF/jsp/"/> - <property name="suffix" value=".jsp"/> - </bean> - </list> - </property> - <property name="defaultViews"> - <list> - <bean class="org.springframework.web.servlet.view.json.MappingJackson2JsonView" /> - </list> - </property> - </bean> - - <bean id="content" class="com.foo.samples.rest.SampleContentAtomView"/> ----- - -The `InternalResourceViewResolver` handles the translation of view names and JSP pages, -while the `BeanNameViewResolver` returns a view based on the name of a bean. (See -"<<mvc-viewresolver-resolver,Resolving views with the ViewResolver interface>>" for more -details on how Spring looks up and instantiates a view.) In this example, the `content` -bean is a class that inherits from `AbstractAtomFeedView`, which returns an Atom RSS -feed. For more information on creating an Atom Feed representation, see the section Atom -Views. - -In the above configuration, if a request is made with an `.html` extension, the view -resolver looks for a view that matches the `text/html` media type. The -`InternalResourceViewResolver` provides the matching view for `text/html`. If the -request is made with the file extension `.atom`, the view resolver looks for a view that -matches the `application/atom+xml` media type. This view is provided by the -`BeanNameViewResolver` that maps to the `SampleContentAtomView` if the view name -returned is `content`. If the request is made with the file extension `.json`, the -`MappingJackson2JsonView` instance from the `DefaultViews` list will be selected -regardless of the view name. Alternatively, client requests can be made without a file -extension but with the `Accept` header set to the preferred media-type, and the same -resolution of request to views would occur. - -[NOTE] -==== -If `ContentNegotiatingViewResolver`'s list of ViewResolvers is not configured -explicitly, it automatically uses any ViewResolvers defined in the application context. -==== - -The corresponding controller code that returns an Atom RSS feed for a URI of the form -`http://localhost/content.atom` or `http://localhost/content` with an `Accept` header of -application/atom+xml is shown below. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Controller - public class ContentController { - - private List<SampleContent> contentList = new ArrayList<SampleContent>(); - - @RequestMapping(value="/content", method=RequestMethod.GET) - public ModelAndView getContent() { - ModelAndView mav = new ModelAndView(); - mav.setViewName("content"); - mav.addObject("sampleContentList", contentList); - return mav; - } - - } ----- - - - - -[[mvc-flash-attributes]] -=== Using flash attributes -Flash attributes provide a way for one request to store attributes intended for use in -another. This is most commonly needed when redirecting -- for example, the -__Post/Redirect/Get__ pattern. Flash attributes are saved temporarily before the -redirect (typically in the session) to be made available to the request after the -redirect and removed immediately. - -Spring MVC has two main abstractions in support of flash attributes. `FlashMap` is used -to hold flash attributes while `FlashMapManager` is used to store, retrieve, and manage -`FlashMap` instances. - -Flash attribute support is always "on" and does not need to enabled explicitly although -if not used, it never causes HTTP session creation. On each request there is an "input" -`FlashMap` with attributes passed from a previous request (if any) and an "output" -`FlashMap` with attributes to save for a subsequent request. Both `FlashMap` instances -are accessible from anywhere in Spring MVC through static methods in -`RequestContextUtils`. - -Annotated controllers typically do not need to work with `FlashMap` directly. Instead an -`@RequestMapping` method can accept an argument of type `RedirectAttributes` and use it -to add flash attributes for a redirect scenario. Flash attributes added via -`RedirectAttributes` are automatically propagated to the "output" FlashMap. Similarly -after the redirect attributes from the "input" `FlashMap` are automatically added to the -`Model` of the controller serving the target URL. - -.Matching requests to flash attributes -**** -The concept of flash attributes exists in many other Web frameworks and has proven to be -exposed sometimes to concurrency issues. This is because by definition flash attributes -are to be stored until the next request. However the very "next" request may not be the -intended recipient but another asynchronous request (e.g. polling or resource requests) -in which case the flash attributes are removed too early. - -To reduce the possibility of such issues, `RedirectView` automatically "stamps" -`FlashMap` instances with the path and query parameters of the target redirect URL. In -turn the default `FlashMapManager` matches that information to incoming requests when -looking up the "input" `FlashMap`. - -This does not eliminate the possibility of a concurrency issue entirely but nevertheless -reduces it greatly with information that is already available in the redirect URL. -Therefore the use of flash attributes is recommended mainly for redirect scenarios . -**** - - - - -[[mvc-construct-encode-uri]] -=== Building URIs - -Spring MVC provides a mechanism for building and encoding a URI using -`UriComponentsBuilder` and `UriComponents`. - -For example you can expand and encode a URI template string: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - UriComponents uriComponents = UriComponentsBuilder.fromUriString( - "http://example.com/hotels/{hotel}/bookings/{booking}").build(); - - URI uri = uriComponents.expand("42", "21").encode().toUri(); ----- - -Note that `UriComponents` is immutable and the `expand()` and `encode()` operations -return new instances if necessary. - -You can also expand and encode using individual URI components: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - UriComponents uriComponents = UriComponentsBuilder.newInstance() - .scheme("http").host("example.com").path("/hotels/{hotel}/bookings/{booking}").build() - .expand("42", "21") - .encode(); ----- - -In a Servlet environment the `ServletUriComponentsBuilder` sub-class provides static -factory methods to copy available URL information from a Servlet requests: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - HttpServletRequest request = ... - - // Re-use host, scheme, port, path and query string - // Replace the "accountId" query param - - ServletUriComponentsBuilder ucb = ServletUriComponentsBuilder.fromRequest(request) - .replaceQueryParam("accountId", "{id}").build() - .expand("123") - .encode(); ----- - -Alternatively, you may choose to copy a subset of the available information up to and -including the context path: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - // Re-use host, port and context path - // Append "/accounts" to the path - - ServletUriComponentsBuilder ucb = ServletUriComponentsBuilder.fromContextPath(request) - .path("/accounts").build() ----- - -Or in cases where the `DispatcherServlet` is mapped by name (e.g. `/main/*`), you can -also have the literal part of the servlet mapping included: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - // Re-use host, port, context path - // Append the literal part of the servlet mapping to the path - // Append "/accounts" to the path - - ServletUriComponentsBuilder ucb = ServletUriComponentsBuilder.fromServletMapping(request) - .path("/accounts").build() ----- - -[[mvc-construct-uri-controllers]] -=== Building URIs to Controllers and methods - -Spring MVC provides another mechanism for building and encoding URIs that link to -Controllers and methods defined within an application. -{javadoc-baseurl}/org/springframework/web/servlet/mvc/method/annotation/MvcUriComponentsBuilder.html[`MvcUriComponentsBuilder`] -extends `UriComponentsBuilder` and provides such possibilities. - -Given this Controller: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Controller - @RequestMapping("/hotels/{hotel}") - public class BookingController { - - @RequestMapping("/bookings/{booking}") - public String getBooking(@PathVariable Long booking) { - - // ... - - } ----- - -and using the `MvcUriComponentsBuilder`, the previous example is now: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - UriComponents uriComponents = MvcUriComponentsBuilder - .fromMethodName(BookingController.class, "getBooking",21).buildAndExpand(42); - - URI uri = uriComponents.encode().toUri(); ----- - -The `MvcUriComponentsBuilder` can also create "mock Controllers", thus enabling to create -URIs by coding against the actual Controller's API: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - UriComponents uriComponents = MvcUriComponentsBuilder - .fromMethodCall(on(BookingController.class).getBooking(21)).buildAndExpand(42); - - URI uri = uriComponents.encode().toUri(); ----- - - -[[mvc-localeresolver]] -=== Using locales -Most parts of Spring's architecture support internationalization, just as the Spring web -MVC framework does. `DispatcherServlet` enables you to automatically resolve messages -using the client's locale. This is done with `LocaleResolver` objects. - -When a request comes in, the `DispatcherServlet` looks for a locale resolver, and if it -finds one it tries to use it to set the locale. Using the `RequestContext.getLocale()` -method, you can always retrieve the locale that was resolved by the locale resolver. - -In addition to automatic locale resolution, you can also attach an interceptor to the -handler mapping (see <<mvc-handlermapping-interceptor>> for more information on handler -mapping interceptors) to change the locale under specific circumstances, for example, -based on a parameter in the request. - -Locale resolvers and interceptors are defined in the -`org.springframework.web.servlet.i18n` package and are configured in your application -context in the normal way. Here is a selection of the locale resolvers included in -Spring. - - - -[[mvc-timezone]] -==== Obtaining Time Zone Information -In addition to obtaining the client's locale, it is often useful to know their time zone. -The `LocaleContextResolver` interface offers an extension to `LocaleResolver` that allows -resolvers to provide a richer `LocaleContext`, which may include time zone information. - -When available, the user's `TimeZone` can be obtained using the -`RequestContext.getTimeZone()` method. Time zone information will automatically be used -by Date/Time `Converter` and `Formatter` objects registered with Spring's -`ConversionService`. - - - -[[mvc-localeresolver-acceptheader]] -==== AcceptHeaderLocaleResolver -This locale resolver inspects the `accept-language` header in the request that was sent -by the client (e.g., a web browser). Usually this header field contains the locale of -the client's operating system. __Note that this resolver does not support time zone -information.__ - - - -[[mvc-localeresolver-cookie]] -==== CookieLocaleResolver - -This locale resolver inspects a `Cookie` that might exist on the client to see if a -`Locale` or `TimeZone` is specified. If so, it uses the specified details. Using the -properties of this locale resolver, you can specify the name of the cookie as well as the -maximum age. Find below an example of defining a `CookieLocaleResolver`. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - <bean id="localeResolver" class="org.springframework.web.servlet.i18n.CookieLocaleResolver"> - - <property name="cookieName" value="clientlanguage"/> - - <!-- in seconds. If set to -1, the cookie is not persisted (deleted when browser shuts down) --> - <property name="cookieMaxAge" value="100000"> - - </bean> ----- - -[[mvc-cookie-locale-resolver-props-tbl]] -.CookieLocaleResolver properties -[cols="1,1,4"] -|=== -| Property| Default| Description - -| cookieName -| classname + LOCALE -| The name of the cookie - -| cookieMaxAge -| Integer.MAX_INT -| The maximum time a cookie will stay persistent on the client. If -1 is specified, the - cookie will not be persisted; it will only be available until the client shuts down - their browser. - -| cookiePath -| / -| Limits the visibility of the cookie to a certain part of your site. When cookiePath is - specified, the cookie will only be visible to that path and the paths below it. -|=== - - - -[[mvc-localeresolver-session]] -==== SessionLocaleResolver - -The `SessionLocaleResolver` allows you to retrieve `Locale` and `TimeZone` from the -session that might be associated with the user's request. - - - -[[mvc-localeresolver-interceptor]] -==== LocaleChangeInterceptor - -You can enable changing of locales by adding the `LocaleChangeInterceptor` to one of the -handler mappings (see <<mvc-handlermapping>>). It will detect a parameter in the request -and change the locale. It calls `setLocale()` on the `LocaleResolver` that also exists -in the context. The following example shows that calls to all `*.view` resources -containing a parameter named `siteLanguage` will now change the locale. So, for example, -a request for the following URL, `http://www.sf.net/home.view?siteLanguage=nl` will -change the site language to Dutch. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - <bean id="localeChangeInterceptor" - class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor"> - <property name="paramName" value="siteLanguage"/> - </bean> - - <bean id="localeResolver" - class="org.springframework.web.servlet.i18n.CookieLocaleResolver"/> - - <bean id="urlMapping" - class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping"> - <property name="interceptors"> - <list> - <ref bean="localeChangeInterceptor"/> - </list> - </property> - <property name="mappings"> - <value>/**/*.view=someController</value> - </property> - </bean> ----- - - - - -[[mvc-themeresolver]] -=== Using themes - - - -[[mvc-themeresolver-introduction]] -==== Overview of themes -You can apply Spring Web MVC framework themes to set the overall look-and-feel of your -application, thereby enhancing user experience. A theme is a collection of static -resources, typically style sheets and images, that affect the visual style of the -application. - - - -[[mvc-themeresolver-defining]] -==== Defining themes -To use themes in your web application, you must set up an implementation of the -`org.springframework.ui.context.ThemeSource` interface. The `WebApplicationContext` -interface extends `ThemeSource` but delegates its responsibilities to a dedicated -implementation. By default the delegate will be an -`org.springframework.ui.context.support.ResourceBundleThemeSource` implementation that -loads properties files from the root of the classpath. To use a custom `ThemeSource` -implementation or to configure the base name prefix of the `ResourceBundleThemeSource`, -you can register a bean in the application context with the reserved name `themeSource`. -The web application context automatically detects a bean with that name and uses it. - -When using the `ResourceBundleThemeSource`, a theme is defined in a simple properties -file. The properties file lists the resources that make up the theme. Here is an example: - -[literal] -[subs="verbatim,quotes"] ----- -styleSheet=/themes/cool/style.css -background=/themes/cool/img/coolBg.jpg ----- - -The keys of the properties are the names that refer to the themed elements from view -code. For a JSP, you typically do this using the `spring:theme` custom tag, which is -very similar to the `spring:message` tag. The following JSP fragment uses the theme -defined in the previous example to customize the look and feel: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - <%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%> - <html> - <head> - <link rel="stylesheet" href="<spring:theme code='styleSheet'/>" type="text/css"/> - </head> - <body style="background=<spring:theme code='background'/>"> - ... - </body> - </html> ----- - -By default, the `ResourceBundleThemeSource` uses an empty base name prefix. As a result, -the properties files are loaded from the root of the classpath. Thus you would put the -`cool.properties` theme definition in a directory at the root of the classpath, for -example, in `/WEB-INF/classes`. The `ResourceBundleThemeSource` uses the standard Java -resource bundle loading mechanism, allowing for full internationalization of themes. For -example, we could have a `/WEB-INF/classes/cool_nl.properties` that references a special -background image with Dutch text on it. - - - -[[mvc-themeresolver-resolving]] -==== Theme resolvers -After you define themes, as in the preceding section, you decide which theme to use. The -`DispatcherServlet` will look for a bean named `themeResolver` to find out which -`ThemeResolver` implementation to use. A theme resolver works in much the same way as a -`LocaleResolver`. It detects the theme to use for a particular request and can also -alter the request's theme. The following theme resolvers are provided by Spring: - -[[mvc-theme-resolver-impls-tbl]] -.ThemeResolver implementations -[cols="1,4"] -|=== -| Class| Description - -| `FixedThemeResolver` -| Selects a fixed theme, set using the `defaultThemeName` property. - -| `SessionThemeResolver` -| The theme is maintained in the user's HTTP session. It only needs to be set once for - each session, but is not persisted between sessions. - -| `CookieThemeResolver` -| The selected theme is stored in a cookie on the client. -|=== - -Spring also provides a `ThemeChangeInterceptor` that allows theme changes on every -request with a simple request parameter. - - - - -[[mvc-multipart]] -=== Spring's multipart (file upload) support - - - -[[mvc-multipart-introduction]] -==== Introduction -Spring's built-in multipart support handles file uploads in web applications. You enable -this multipart support with pluggable `MultipartResolver` objects, defined in the -`org.springframework.web.multipart` package. Spring provides one `MultipartResolver` -implementation for use with http://jakarta.apache.org/commons/fileupload[__Commons -FileUpload__] and another for use with Servlet 3.0 multipart request parsing. - -By default, Spring does no multipart handling, because some developers want to handle -multiparts themselves. You enable Spring multipart handling by adding a multipart -resolver to the web application's context. Each request is inspected to see if it -contains a multipart. If no multipart is found, the request continues as expected. If a -multipart is found in the request, the `MultipartResolver` that has been declared in -your context is used. After that, the multipart attribute in your request is treated -like any other attribute. - - - -[[mvc-multipart-resolver-commons]] -==== Using a MultipartResolver with __Commons FileUpload__ - -The following example shows how to use the `CommonsMultipartResolver`: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - <bean id="multipartResolver" - class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> - - <!-- one of the properties available; the maximum file size in bytes --> - <property name="maxUploadSize" value="100000"/> - - </bean> ----- - -Of course you also need to put the appropriate jars in your classpath for the multipart -resolver to work. In the case of the `CommonsMultipartResolver`, you need to use -`commons-fileupload.jar`. - -When the Spring `DispatcherServlet` detects a multi-part request, it activates the -resolver that has been declared in your context and hands over the request. The resolver -then wraps the current `HttpServletRequest` into a `MultipartHttpServletRequest` that -supports multipart file uploads. Using the `MultipartHttpServletRequest`, you can get -information about the multiparts contained by this request and actually get access to -the multipart files themselves in your controllers. - - - -[[mvc-multipart-resolver-standard]] -==== Using a MultipartResolver with __Servlet 3.0__ - -In order to use Servlet 3.0 based multipart parsing, you need to mark the -`DispatcherServlet` with a `"multipart-config"` section in `web.xml`, or with a -`javax.servlet.MultipartConfigElement` in programmatic Servlet registration, or in case -of a custom Servlet class possibly with a `javax.servlet.annotation.MultipartConfig` -annotation on your Servlet class. Configuration settings such as maximum sizes or -storage locations need to be applied at that Servlet registration level as Servlet 3.0 -does not allow for those settings to be done from the MultipartResolver. - -Once Servlet 3.0 multipart parsing has been enabled in one of the above mentioned ways -you can add the `StandardServletMultipartResolver` to your Spring configuration: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - <bean id="multipartResolver" - class="org.springframework.web.multipart.support.StandardServletMultipartResolver"> - </bean> ----- - - - -[[mvc-multipart-forms]] -==== Handling a file upload in a form -After the `MultipartResolver` completes its job, the request is processed like any -other. First, create a form with a file input that will allow the user to upload a form. -The encoding attribute ( `enctype="multipart/form-data"`) lets the browser know how to -encode the form as multipart request: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - <html> - <head> - <title>Upload a file please - - -

Please upload a file

-
- - - -
- - ----- - -The next step is to create a controller that handles the file upload. This controller is -very similar to a <>, except that we -use `MultipartHttpServletRequest` or `MultipartFile` in the method parameters: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Controller - public class FileUploadController { - - @RequestMapping(value = "/form", method = RequestMethod.POST) - public String handleFormUpload(@RequestParam("name") String name, - @RequestParam("file") MultipartFile file) { - - if (!file.isEmpty()) { - byte[] bytes = file.getBytes(); - // store the bytes somewhere - return "redirect:uploadSuccess"; - } - - return "redirect:uploadFailure"; - } - - } ----- - -Note how the `@RequestParam` method parameters map to the input elements declared in the -form. In this example, nothing is done with the `byte[]`, but in practice you can save -it in a database, store it on the file system, and so on. - -When using Servlet 3.0 multipart parsing you can also use `javax.servlet.http.Part` for -the method parameter: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Controller - public class FileUploadController { - - @RequestMapping(value = "/form", method = RequestMethod.POST) - public String handleFormUpload(@RequestParam("name") String name, - @RequestParam("file") Part file) { - - InputStream inputStream = file.getInputStream(); - // store bytes from uploaded file somewhere - - return "redirect:uploadSuccess"; - } - - } ----- - - - -[[mvc-multipart-forms-non-browsers]] -==== Handling a file upload request from programmatic clients -Multipart requests can also be submitted from non-browser clients in a RESTful service -scenario. All of the above examples and configuration apply here as well. However, -unlike browsers that typically submit files and simple form fields, a programmatic -client can also send more complex data of a specific content type -- for example a -multipart request with a file and second part with JSON formatted data: - -[literal] -[subs="verbatim,quotes"] ----- -POST /someUrl -Content-Type: multipart/mixed - ---edt7Tfrdusa7r3lNQc79vXuhIIMlatb7PQg7Vp -Content-Disposition: form-data; name="meta-data" -Content-Type: application/json; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -{ - "name": "value" -} ---edt7Tfrdusa7r3lNQc79vXuhIIMlatb7PQg7Vp -Content-Disposition: form-data; name="file-data"; filename="file.properties" -Content-Type: text/xml -Content-Transfer-Encoding: 8bit -... File Data ... ----- - -You could access the part named "meta-data" with a `@RequestParam("meta-data") String -metadata` controller method argument. However, you would probably prefer to accept a -strongly typed object initialized from the JSON formatted data in the body of the -request part, very similar to the way `@RequestBody` converts the body of a -non-multipart request to a target object with the help of an `HttpMessageConverter`. - -You can use the `@RequestPart` annotation instead of the `@RequestParam` annotation for -this purpose. It allows you to have the content of a specific multipart passed through -an `HttpMessageConverter` taking into consideration the `'Content-Type'` header of the -multipart: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @RequestMapping(value="/someUrl", method = RequestMethod.POST) - public String onSubmit(**@RequestPart("meta-data") MetaData metadata, - @RequestPart("file-data") MultipartFile file**) { - - // ... - - } ----- - -Notice how `MultipartFile` method arguments can be accessed with `@RequestParam` or with -`@RequestPart` interchangeably. However, the `@RequestPart("meta-data") MetaData` method -argument in this case is read as JSON content based on its `'Content-Type'` header and -converted with the help of the `MappingJackson2HttpMessageConverter`. - - - - -[[mvc-exceptionhandlers]] -=== Handling exceptions - - - -[[mvc-exceptionhandlers-resolver]] -==== HandlerExceptionResolver - -Spring `HandlerExceptionResolver` implementations deal with unexpected exceptions that -occur during controller execution. A `HandlerExceptionResolver` somewhat resembles the -exception mappings you can define in the web application descriptor `web.xml`. However, -they provide a more flexible way to do so. For example they provide information about -which handler was executing when the exception was thrown. Furthermore, a programmatic -way of handling exceptions gives you more options for responding appropriately before -the request is forwarded to another URL (the same end result as when you use the Servlet -specific exception mappings). - -Besides implementing the `HandlerExceptionResolver` interface, which is only a matter of -implementing the `resolveException(Exception, Handler)` method and returning a -`ModelAndView`, you may also use the provided `SimpleMappingExceptionResolver` or create -`@ExceptionHandler` methods. The `SimpleMappingExceptionResolver` enables you to take -the class name of any exception that might be thrown and map it to a view name. This is -functionally equivalent to the exception mapping feature from the Servlet API, but it is -also possible to implement more finely grained mappings of exceptions from different -handlers. The `@ExceptionHandler` annotation on the other hand can be used on methods -that should be invoked to handle an exception. Such methods may be defined locally -within an `@Controller` or may apply to many `@Controller` classes when defined within an -`@ControllerAdvice` class. The following sections explain this in more detail. - - - -[[mvc-ann-exceptionhandler]] -==== @ExceptionHandler - -The `HandlerExceptionResolver` interface and the `SimpleMappingExceptionResolver` -implementations allow you to map Exceptions to specific views declaratively along with -some optional Java logic before forwarding to those views. However, in some cases, -especially when relying on `@ResponseBody` methods rather than on view resolution, it -may be more convenient to directly set the status of the response and optionally write -error content to the body of the response. - -You can do that with `@ExceptionHandler` methods. When declared within a controller such -methods apply to exceptions raised by `@RequestMapping` methods of that contoroller (or -any of its sub-classes). You can also declare an `@ExceptionHandler` method within an -`@ControllerAdvice` class in which case it handles exceptions from `@RequestMapping` -methods from many controllers. Below is an example of a controller-local -`@ExceptionHandler` method: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Controller - public class SimpleController { - - // @RequestMapping methods omitted ... - - @ExceptionHandler(IOException.class) - public ResponseEntity handleIOException(IOException ex) { - // prepare responseEntity - return responseEntity; - } - - } ----- - -The `@ExceptionHandler` value can be set to an array of Exception types. If an exception -is thrown that matches one of the types in the list, then the method annotated with the -matching `@ExceptionHandler` will be invoked. If the annotation value is not set then -the exception types listed as method arguments are used. - -Much like standard controller methods annotated with a `@RequestMapping` annotation, the -method arguments and return values of `@ExceptionHandler` methods can be flexible. For -example, the `HttpServletRequest` can be accessed in Servlet environments and the -`PortletRequest` in Portlet environments. The return type can be a `String`, which is -interpreted as a view name, a `ModelAndView` object, a `ResponseEntity`, or you can also -add the `@ResponseBody` to have the method return value converted with message -converters and written to the response stream. - - - -[[mvc-ann-rest-spring-mvc-exceptions]] -==== Handling Standard Spring MVC Exceptions -Spring MVC may raise a number of exceptions while processing a request. The -`SimpleMappingExceptionResolver` can easily map any exception to a default error view as -needed. However, when working with clients that interpret responses in an automated way -you will want to set specific status code on the response. Depending on the exception -raised the status code may indicate a client error (4xx) or a server error (5xx). - -The `DefaultHandlerExceptionResolver` translates Spring MVC exceptions to specific error -status codes. It is registered by default with the MVC namespace, the MVC Java config, -and also by the the `DispatcherServlet` (i.e. when not using the MVC namespace or Java -config). Listed below are some of the exceptions handled by this resolver and the -corresponding status codes: - -|=== -| Exception| HTTP Status Code - -| `BindException` -| 400 (Bad Request) - -| `ConversionNotSupportedException` -| 500 (Internal Server Error) - -| `HttpMediaTypeNotAcceptableException` -| 406 (Not Acceptable) - -| `HttpMediaTypeNotSupportedException` -| 415 (Unsupported Media Type) - -| `HttpMessageNotReadableException` -| 400 (Bad Request) - -| `HttpMessageNotWritableException` -| 500 (Internal Server Error) - -| `HttpRequestMethodNotSupportedException` -| 405 (Method Not Allowed) - -| `MethodArgumentNotValidException` -| 400 (Bad Request) - -| `MissingServletRequestParameterException` -| 400 (Bad Request) - -| `MissingServletRequestPartException` -| 400 (Bad Request) - -| `NoHandlerFoundException` -| 404 (Not Found) - -| `NoSuchRequestHandlingMethodException` -| 404 (Not Found) - -| `TypeMismatchException` -| 400 (Bad Request) -|=== - -The `DefaultHandlerExceptionResolver` works transparently by setting the status of the -response. However, it stops short of writing any error content to the body of the -response while your application may need to add developer-friendly content to every -error response for example when providing a REST API. You can prepare a `ModelAndView` -and render error content through view resolution -- i.e. by configuring a -`ContentNegotiatingViewResolver`, `MappingJackson2JsonView`, and so on. However, you may -prefer to use `@ExceptionHandler` methods instead. - -If you prefer to write error content via `@ExceptionHandler` methods you can extend -`ResponseEntityExceptionHandler` instead. This is a convenient base for -`@ControllerAdvice` classes providing an `@ExceptionHandler` method to handle standard -Spring MVC exceptions and return `ResponseEntity`. That allows you to customize the -response and write error content with message converters. See the -`ResponseEntityExceptionHandler` javadocs for more details. - - - -[[mvc-ann-annotated-exceptions]] -==== Annotating Business Exceptions With @ResponseStatus - -A business exception can be annotated with `@ResponseStatus`. When the exception is -raised, the `ResponseStatusExceptionResolver` handles it by setting the status of the -response accordingly. By default the `DispatcherServlet` registers the -`ResponseStatusExceptionResolver` and it is available for use. - - - -[[mvc-ann-customer-servlet-container-error-page]] -==== Customizing the Default Servlet Container Error Page -When the status of the response is set to an error status code and the body of the -response is empty, Servlet containers commonly render an HTML formatted error page. To -customize the default error page of the container, you can declare an `` -element in `web.xml`. Up until Servlet 3, that element had to be mapped to a specific -status code or exception type. Starting with Servlet 3 an error page does not need to be -mapped, which effectively means the specified location customizes the default Servlet -container error page. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - /error - ----- - -Note that the actual location for the error page can be a JSP page or some other URL -within the container including one handled through an `@Controller` method: - -When writing error information, the status code and the error message set on the -`HttpServletResponse` can be accessed through request attributes in a controller: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Controller - public class ErrorController { - - @RequestMapping(value="/error", produces="application/json") - @ResponseBody - public Map handle(HttpServletRequest request) { - - Map map = new HashMap(); - map.put("status", request.getAttribute("javax.servlet.error.status_code")); - map.put("reason", request.getAttribute("javax.servlet.error.message")); - - return map; - } - - } ----- - -or in a JSP: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - <%@ page contentType="application/json" pageEncoding="UTF-8"%> - { - status:<%=request.getAttribute("javax.servlet.error.status_code") %>, - reason:<%=request.getAttribute("javax.servlet.error.message") %> - } ----- - - -[[mvc-web-security]] -=== Web Security - -The http://projects.spring.io/spring-security/[Spring Security] project provides features -to protect web applications from malicious exploits. Check out the reference documentation in the sections on -http://docs.spring.io/spring-security/site/docs/current/reference/htmlsingle/#csrf["CSRF protection"], -http://docs.spring.io/spring-security/site/docs/current/reference/htmlsingle/#headers["Security Response Headers"], and also -http://docs.spring.io/spring-security/site/docs/current/reference/htmlsingle/#mvc["Spring MVC Integration"]. -Note that using Spring Security to secure the application is not necessarily required for all features. -For example CSRF protection can be added simply by adding the `CsrfFilter` and -`CsrfRequestDataValueProcessor` to your configuration. See the -https://github.com/spring-projects/spring-mvc-showcase/commit/361adc124c05a8187b84f25e8a57550bb7d9f8e4[Spring MVC Showcase] -for an example. - -Another option is to use a framework dedicated to Web Security. -http://hdiv.org/[HDIV] is one such framework and integrates with Spring MVC. - - - - -[[mvc-coc]] -=== Convention over configuration support -For a lot of projects, sticking to established conventions and having reasonable -defaults is just what they (the projects) need, and Spring Web MVC now has explicit -support for __convention over configuration__. What this means is that if you establish -a set of naming conventions and suchlike, you can __substantially__ cut down on the -amount of configuration that is required to set up handler mappings, view resolvers, -`ModelAndView` instances, etc. This is a great boon with regards to rapid prototyping, -and can also lend a degree of (always good-to-have) consistency across a codebase should -you choose to move forward with it into production. - -Convention-over-configuration support addresses the three core areas of MVC: models, -views, and controllers. - - - -[[mvc-coc-ccnhm]] -==== The Controller ControllerClassNameHandlerMapping - -The `ControllerClassNameHandlerMapping` class is a `HandlerMapping` implementation that -uses a convention to determine the mapping between request URLs and the `Controller` -instances that are to handle those requests. - -Consider the following simple `Controller` implementation. Take special notice of the -__name__ of the class. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class **ViewShoppingCartController** implements Controller { - - public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) { - // the implementation is not hugely important for this example... - } - - } ----- - -Here is a snippet from the corresponding Spring Web MVC configuration file: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - ----- - -The `ControllerClassNameHandlerMapping` finds all of the various handler (or -`Controller`) beans defined in its application context and strips `Controller` off the -name to define its handler mappings. Thus, `ViewShoppingCartController` maps to the -`/viewshoppingcart*` request URL. - -Let's look at some more examples so that the central idea becomes immediately familiar. -(Notice all lowercase in the URLs, in contrast to camel-cased `Controller` class names.) - -* `WelcomeController` maps to the `/welcome*` request URL -* `HomeController` maps to the `/home*` request URL -* `IndexController` maps to the `/index*` request URL -* `RegisterController` maps to the `/register*` request URL - -In the case of `MultiActionController` handler classes, the mappings generated are -slightly more complex. The `Controller` names in the following examples are assumed to -be `MultiActionController` implementations: - -* `AdminController` maps to the `/admin/*` request URL -* `CatalogController` maps to the `/catalog/*` request URL - -If you follow the convention of naming your `Controller` implementations as -`xxxController`, the `ControllerClassNameHandlerMapping` saves you the tedium of -defining and maintaining a potentially __looooong__ `SimpleUrlHandlerMapping` (or -suchlike). - -The `ControllerClassNameHandlerMapping` class extends the `AbstractHandlerMapping` base -class so you can define `HandlerInterceptor` instances and everything else just as you -would with many other `HandlerMapping` implementations. - - - -[[mvc-coc-modelmap]] -==== The Model ModelMap (ModelAndView) - -The `ModelMap` class is essentially a glorified `Map` that can make adding objects that -are to be displayed in (or on) a `View` adhere to a common naming convention. Consider -the following `Controller` implementation; notice that objects are added to the -`ModelAndView` without any associated name specified. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class DisplayShoppingCartController implements Controller { - - public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) { - - List cartItems = // get a List of CartItem objects - User user = // get the User doing the shopping - - ModelAndView mav = new ModelAndView("displayShoppingCart"); <-- the logical view name - - mav.addObject(cartItems); <-- look ma, no name, just the object - mav.addObject(user); <-- and again ma! - - return mav; - } - } ----- - -The `ModelAndView` class uses a `ModelMap` class that is a custom `Map` implementation -that automatically generates a key for an object when an object is added to it. The -strategy for determining the name for an added object is, in the case of a scalar object -such as `User`, to use the short class name of the object's class. The following -examples are names that are generated for scalar objects put into a `ModelMap` instance. - -* An `x.y.User` instance added will have the name `user` generated. -* An `x.y.Registration` instance added will have the name `registration` generated. -* An `x.y.Foo` instance added will have the name `foo` generated. -* A `java.util.HashMap` instance added will have the name `hashMap` generated. You - probably want to be explicit about the name in this case because `hashMap` is less - than intuitive. -* Adding `null` will result in an `IllegalArgumentException` being thrown. If the object - (or objects) that you are adding could be `null`, then you will also want to be - explicit about the name. - -.What, no automatic pluralization? -**** -Spring Web MVC's convention-over-configuration support does not support automatic -pluralization. That is, you cannot add a `List` of `Person` objects to a `ModelAndView` -and have the generated name be `people`. - -This decision was made after some debate, with the "Principle of Least Surprise" winning -out in the end. -**** - -The strategy for generating a name after adding a `Set` or a `List` is to peek into the -collection, take the short class name of the first object in the collection, and use -that with `List` appended to the name. The same applies to arrays although with arrays -it is not necessary to peek into the array contents. A few examples will make the -semantics of name generation for collections clearer: - -* An `x.y.User[]` array with zero or more `x.y.User` elements added will have the name - `userList` generated. -* An `x.y.Foo[]` array with zero or more `x.y.User` elements added will have the name - `fooList` generated. -* A `java.util.ArrayList` with one or more `x.y.User` elements added will have the name - `userList` generated. -* A `java.util.HashSet` with one or more `x.y.Foo` elements added will have the name - `fooList` generated. -* An __empty__ `java.util.ArrayList` will not be added at all (in effect, the - `addObject(..)` call will essentially be a no-op). - - - -[[mvc-coc-r2vnt]] -==== The View - RequestToViewNameTranslator - -The `RequestToViewNameTranslator` interface determines a logical `View` name when no -such logical view name is explicitly supplied. It has just one implementation, the -`DefaultRequestToViewNameTranslator` class. - -The `DefaultRequestToViewNameTranslator` maps request URLs to logical view names, as -with this example: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class RegistrationController implements Controller { - - public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) { - // process the request... - ModelAndView mav = new ModelAndView(); - // add data as necessary to the model... - return mav; - // notice that no View or logical view name has been set - } - - } ----- - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - - - - - - - - - - - - ----- - -Notice how in the implementation of the `handleRequest(..)` method no `View` or logical -view name is ever set on the `ModelAndView` that is returned. The -`DefaultRequestToViewNameTranslator` is tasked with generating a __logical view name__ -from the URL of the request. In the case of the above `RegistrationController`, which is -used in conjunction with the `ControllerClassNameHandlerMapping`, a request URL of -`http://localhost/registration.html` results in a logical view name of `registration` -being generated by the `DefaultRequestToViewNameTranslator`. This logical view name is -then resolved into the `/WEB-INF/jsp/registration.jsp` view by the -`InternalResourceViewResolver` bean. - -[TIP] -==== - -You do not need to define a `DefaultRequestToViewNameTranslator` bean explicitly. If you -like the default settings of the `DefaultRequestToViewNameTranslator`, you can rely on -the Spring Web MVC `DispatcherServlet` to instantiate an instance of this class if one -is not explicitly configured. -==== - -Of course, if you need to change the default settings, then you do need to configure -your own `DefaultRequestToViewNameTranslator` bean explicitly. Consult the comprehensive -`DefaultRequestToViewNameTranslator` javadocs for details on the various properties -that can be configured. - - - - -[[mvc-etag]] -=== ETag support -An http://en.wikipedia.org/wiki/HTTP_ETag[ETag] (entity tag) is an HTTP response header -returned by an HTTP/1.1 compliant web server used to determine change in content at a -given URL. It can be considered to be the more sophisticated successor to the -`Last-Modified` header. When a server returns a representation with an ETag header, the -client can use this header in subsequent GETs, in an `If-None-Match` header. If the -content has not changed, the server returns `304: Not Modified`. - -Support for ETags is provided by the Servlet filter `ShallowEtagHeaderFilter`. It is a -plain Servlet Filter, and thus can be used in combination with any web framework. The -`ShallowEtagHeaderFilter` filter creates so-called shallow ETags (as opposed to deep -ETags, more about that later).The filter caches the content of the rendered JSP (or -other content), generates an MD5 hash over that, and returns that as an ETag header in -the response. The next time a client sends a request for the same resource, it uses that -hash as the `If-None-Match` value. The filter detects this, renders the view again, and -compares the two hashes. If they are equal, a `304` is returned. This filter will not -save processing power, as the view is still rendered. The only thing it saves is -bandwidth, as the rendered response is not sent back over the wire. - -You configure the `ShallowEtagHeaderFilter` in `web.xml`: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - etagFilter - org.springframework.web.filter.ShallowEtagHeaderFilter - - - - etagFilter - petclinic - ----- - - - - -[[mvc-container-config]] -=== Code-based Servlet container initialization -In a Servlet 3.0+ environment, you have the option of configuring the Servlet container -programmatically as an alternative or in combination with a `web.xml` file. Below is an -example of registering a `DispatcherServlet`: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - import org.springframework.web.WebApplicationInitializer; - - public class MyWebApplicationInitializer implements WebApplicationInitializer { - - @Override - public void onStartup(ServletContext container) { - XmlWebApplicationContext appContext = new XmlWebApplicationContext(); - appContext.setConfigLocation("/WEB-INF/spring/dispatcher-config.xml"); - - ServletRegistration.Dynamic registration = container.addServlet("dispatcher", new DispatcherServlet(appContext)); - registration.setLoadOnStartup(1); - registration.addMapping("/"); - } - - } ----- - -`WebApplicationInitializer` is an interface provided by Spring MVC that ensures your -implementation is detected and automatically used to initialize any Servlet 3 container. -An abstract base class implementation of `WebApplicationInitializer` named -`AbstractDispatcherServletInitializer` makes it even easier to register the -`DispatcherServlet` by simply overriding methods to specify the servlet mapping and the -location of the `DispatcherServlet` configuration: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class MyWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer { - - @Override - protected Class[] getRootConfigClasses() { - return null; - } - - @Override - protected Class[] getServletConfigClasses() { - return new Class[] { MyWebConfig.class }; - } - - @Override - protected String[] getServletMappings() { - return new String[] { "/" }; - } - - } ----- - -The above example is for an application that uses Java-based Spring configuration. If -using XML-based Spring configuration, extend directly from -`AbstractDispatcherServletInitializer`: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class MyWebAppInitializer extends AbstractDispatcherServletInitializer { - - @Override - protected WebApplicationContext createRootApplicationContext() { - return null; - } - - @Override - protected WebApplicationContext createServletApplicationContext() { - XmlWebApplicationContext cxt = new XmlWebApplicationContext(); - cxt.setConfigLocation("/WEB-INF/spring/dispatcher-config.xml"); - return cxt; - } - - @Override - protected String[] getServletMappings() { - return new String[] { "/" }; - } - - } ----- - -`AbstractDispatcherServletInitializer` also provides a convenient way to add `Filter` -instances and have them automatically mapped to the `DispatcherServlet`: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class MyWebAppInitializer extends AbstractDispatcherServletInitializer { - - // ... - - @Override - protected Filter[] getServletFilters() { - return new Filter[] { new HiddenHttpMethodFilter(), new CharacterEncodingFilter() }; - } - - } ----- - -Each filter is added with a default name based on its concrete type and automatically -mapped to the `DispatcherServlet`. - -The `isAsyncSupported` protected method of `AbstractDispatcherServletInitializer` -provides a single place to enable async support on the `DispatcherServlet` and all -filters mapped to it. By default this flag is set to `true`. - - - - -[[mvc-config]] -=== Configuring Spring MVC -<> and <> explained about Spring -MVC's special beans and the default implementations used by the `DispatcherServlet`. In -this section you'll learn about two additional ways of configuring Spring MVC. Namely -the MVC Java config and the MVC XML namespace. - -The MVC Java config and the MVC namespace provide similar default configuration that -overrides the `DispatcherServlet` defaults. The goal is to spare most applications from -having to having to create the same configuration and also to provide higher-level -constructs for configuring Spring MVC that serve as a simple starting point and require -little or no prior knowledge of the underlying configuration. - -You can choose either the MVC Java config or the MVC namespace depending on your -preference. Also as you will see further below, with the MVC Java config it is easier to -see the underlying configuration as well as to make fine-grained customizations directly -to the created Spring MVC beans. But let's start from the beginning. - - - -[[mvc-config-enable]] -==== Enabling the MVC Java Config or the MVC XML Namespace -To enable MVC Java config add the annotation `@EnableWebMvc` to one of your -`@Configuration` classes: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Configuration - @EnableWebMvc - public class WebConfig { - - } ----- - -To achieve the same in XML use the `mvc:annotation-driven` element in your -DispatcherServlet context (or in your root context if you have no DispatcherServlet -context defined): - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - ----- - -The above registers a `RequestMappingHandlerMapping`, a `RequestMappingHandlerAdapter`, -and an `ExceptionHandlerExceptionResolver` (among others) in support of processing -requests with annotated controller methods using annotations such as `@RequestMapping`, -`@ExceptionHandler`, and others. - -It also enables the following: - -. Spring 3 style type conversion through a <> instance -in addition to the JavaBeans PropertyEditors used for Data Binding. -. Support for <> Number fields using the `@NumberFormat` annotation -through the `ConversionService`. -. Support for <> Date, Calendar, Long, and Joda Time fields using the -`@DateTimeFormat` annotation. -. Support for <> `@Controller` inputs with `@Valid`, if -a JSR-303 Provider is present on the classpath. -. HttpMessageConverter support for `@RequestBody` method parameters and `@ResponseBody` -method return values from `@RequestMapping` or `@ExceptionHandler` methods. - -+ - -This is the complete list of HttpMessageConverters set up by mvc:annotation-driven: - -+ - -.. `ByteArrayHttpMessageConverter` converts byte arrays. -.. `StringHttpMessageConverter` converts strings. -.. `ResourceHttpMessageConverter` converts to/from -`org.springframework.core.io.Resource` for all media types. -.. `SourceHttpMessageConverter` converts to/from a `javax.xml.transform.Source`. -.. `FormHttpMessageConverter` converts form data to/from a `MultiValueMap`. -.. `Jaxb2RootElementHttpMessageConverter` converts Java objects to/from XML -- added if -JAXB2 is present and Jackson 2 XML extension is not present on the classpath. -.. `MappingJackson2HttpMessageConverter` converts to/from JSON -- added if Jackson 2 -is present on the classpath. -.. `MappingJackson2XmlHttpMessageConverter` converts to/from XML -- added if -https://github.com/FasterXML/jackson-dataformat-xml[Jackson 2 XML extension] is present -on the classpath. -.. `AtomFeedHttpMessageConverter` converts Atom feeds -- added if Rome is present on the -classpath. -.. `RssChannelHttpMessageConverter` converts RSS feeds -- added if Rome is present on -the classpath. - - - -[[mvc-config-customize]] -==== Customizing the Provided Configuration -To customize the default configuration in Java you simply implement the -`WebMvcConfigurer` interface or more likely extend the class `WebMvcConfigurerAdapter` -and override the methods you need. Below is an example of some of the available methods -to override. See -{javadoc-baseurl}/org/springframework/web/servlet/config/annotation/WebMvcConfigurer.html[`WebMvcConfigurer`] -for a list of all methods and the javadocs for further details: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Configuration - @EnableWebMvc - public class WebConfig extends WebMvcConfigurerAdapter { - - @Override - protected void addFormatters(FormatterRegistry registry) { - // Add formatters and/or converters - } - - @Override - public void configureMessageConverters(List> converters) { - // Configure the list of HttpMessageConverters to use - } - - } ----- - -To customize the default configuration of `` check what -attributes and sub-elements it supports. You can view the -http://schema.spring.io/mvc/spring-mvc.xsd[Spring MVC XML schema] or use the code -completion feature of your IDE to discover what attributes and sub-elements are -available. The sample below shows a subset of what is available: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - - - - - - - - ----- - - - -[[mvc-config-interceptors]] -==== Interceptors -You can configure `HandlerInterceptors` or `WebRequestInterceptors` to be applied to all -incoming requests or restricted to specific URL path patterns. - -An example of registering interceptors in Java: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Configuration - @EnableWebMvc - public class WebConfig extends WebMvcConfigurerAdapter { - - @Override - public void addInterceptors(InterceptorRegistry registry) { - registry.addInterceptor(new LocaleInterceptor()); - registry.addInterceptor(new ThemeInterceptor()).addPathPatterns("/**").excludePathPatterns("/admin/**"); - registry.addInterceptor(new SecurityInterceptor()).addPathPatterns("/secure/*"); - } - - } ----- - -And in XML use the `` element: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - - - - - ----- - - - -[[mvc-config-content-negotiation]] -==== Content Negotiation -You can configure how Spring MVC determines the requested media types from the client -for request mapping as well as for content negotiation purposes. The available options -are to check the file extension in the request URI, the "Accept" header, a request -parameter, as well as to fall back on a default content type. By default, file extension -in the request URI is checked first and the "Accept" header is checked next. - -For file extensions in the request URI, the MVC Java config and the MVC namespace, -automatically register extensions such as `.json`, `.xml`, `.rss`, and `.atom` if the -corresponding dependencies such as Jackson, JAXB2, or Rome are present on the classpath. -Additional extensions may be not need to be registered explicitly if they can be -discovered via `ServletContext.getMimeType(String)` or the __Java Activation Framework__ -(see `javax.activation.MimetypesFileTypeMap`). You can register more extensions with the -{javadoc-baseurl}/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerMapping.html#setUseRegisteredSuffixPatternMatch(boolean)[setUseRegisteredSuffixPatternMatch -method]. - -The introduction of `ContentNegotiationManager` also enables selective suffix pattern -matching for incoming requests. For more details, see its javadocs. - -Below is an example of customizing content negotiation options through the MVC Java -config: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Configuration - @EnableWebMvc - public class WebConfig extends WebMvcConfigurerAdapter { - - @Override - public void configureContentNegotiation(ContentNegotiationConfigurer configurer) { - configurer.favorPathExtension(false).favorParameter(true); - } - } ----- - -In the MVC namespace, the `` element has a -`content-negotiation-manager` attribute, which expects a `ContentNegotiationManager` -that in turn can be created with a `ContentNegotiationManagerFactoryBean`: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - json=application/json - xml=application/xml - - - ----- - -If not using the MVC Java config or the MVC namespace, you'll need to create an instance -of `ContentNegotiationManager` and use it to configure `RequestMappingHandlerMapping` -for request mapping purposes, and `RequestMappingHandlerAdapter` and -`ExceptionHandlerExceptionResolver` for content negotiation purposes. - -Note that `ContentNegotiatingViewResolver` now can also be configured with a -`ContentNegotiatingViewResolver`, so you can use one instance throughout Spring MVC. - -In more advanced cases, it may be useful to configure multiple -`ContentNegotiationManager` instances that in turn may contain custom -`ContentNegotiationStrategy` implementations. For example you could configure -`ExceptionHandlerExceptionResolver` with a `ContentNegotiationManager` that always -resolves the requested media type to `"application/json"`. Or you may want to plug a -custom strategy that has some logic to select a default content type (e.g. either XML or -JSON) if no content types were requested. - - - -[[mvc-config-view-controller]] -==== View Controllers -This is a shortcut for defining a `ParameterizableViewController` that immediately -forwards to a view when invoked. Use it in static cases when there is no Java controller -logic to execute before the view generates the response. - -An example of forwarding a request for `"/"` to a view called `"home"` in Java: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Configuration - @EnableWebMvc - public class WebConfig extends WebMvcConfigurerAdapter { - - @Override - public void addViewControllers(ViewControllerRegistry registry) { - registry.addViewController("/").setViewName("home"); - } - - } ----- - -And the same in XML use the `` element: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - ----- - - -[[mvc-config-view-resolvers]] -==== View Resolvers -The MVC config simplifies the registration of view resolvers. - -The following is a Java config example that configures content negotiation view -resolution using FreeMarker HTML templates and Jackson as a default `View` for -JSON rendering: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Configuration - @EnableWebMvc - public class WebConfig extends WebMvcConfigurerAdapter { - - @Override - public void configureViewResolvers(ViewResolverRegistry registry) { - registry.enableContentNegotiation(new MappingJackson2JsonView()); - registry.jsp(); - } - - } ----- - -And the same in XML: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - ----- - -Note however that FreeMarker, Velocity, Tiles, and Groovy Markup also require -configuration of the underlying view technology. - -The MVC namespace provides dedicated elements. For example with FreeMarker: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - - - - - - - ----- - -In Java config simply add the respective "Configurer" bean: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Configuration - @EnableWebMvc - public class WebConfig extends WebMvcConfigurerAdapter { - - @Override - public void configureViewResolvers(ViewResolverRegistry registry) { - registry.enableContentNegotiation(new MappingJackson2JsonView()); - registry.freeMarker().cache(false); - } - - @Bean - public FreeMarkerConfigurer freeMarkerConfigurer() { - FreeMarkerConfigurer configurer = new FreeMarkerConfigurer(); - configurer.setTemplateLoaderPath("/WEB-INF/"); - return configurer; - } - - } ----- - - - -[[mvc-config-static-resources]] -==== Serving of Resources -This option allows static resource requests following a particular URL pattern to be -served by a `ResourceHttpRequestHandler` from any of a list of `Resource` locations. -This provides a convenient way to serve static resources from locations other than the -web application root, including locations on the classpath. The `cache-period` property -may be used to set far future expiration headers (1 year is the recommendation of -optimization tools such as Page Speed and YSlow) so that they will be more efficiently -utilized by the client. The handler also properly evaluates the `Last-Modified` header -(if present) so that a `304` status code will be returned as appropriate, avoiding -unnecessary overhead for resources that are already cached by the client. For example, -to serve resource requests with a URL pattern of `/resources/**` from a -`public-resources` directory within the web application root you would use: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Configuration - @EnableWebMvc - public class WebConfig extends WebMvcConfigurerAdapter { - - @Override - public void addResourceHandlers(ResourceHandlerRegistry registry) { - registry.addResourceHandler("/resources/**").addResourceLocations("/public-resources/"); - } - - } ----- - -And the same in XML: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - ----- - -To serve these resources with a 1-year future expiration to ensure maximum use of the -browser cache and a reduction in HTTP requests made by the browser: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Configuration - @EnableWebMvc - public class WebConfig extends WebMvcConfigurerAdapter { - - @Override - public void addResourceHandlers(ResourceHandlerRegistry registry) { - registry.addResourceHandler("/resources/**").addResourceLocations("/public-resources/").setCachePeriod(31556926); - } - - } ----- - -And in XML: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - ----- - -The `mapping` attribute must be an Ant pattern that can be used by -`SimpleUrlHandlerMapping`, and the `location` attribute must specify one or more valid -resource directory locations. Multiple resource locations may be specified using a -comma-separated list of values. The locations specified will be checked in the specified -order for the presence of the resource for any given request. For example, to enable the -serving of resources from both the web application root and from a known path of -`/META-INF/public-web-resources/` in any jar on the classpath use: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @EnableWebMvc - @Configuration - public class WebConfig extends WebMvcConfigurerAdapter { - - @Override - public void addResourceHandlers(ResourceHandlerRegistry registry) { - registry.addResourceHandler("/resources/**") - .addResourceLocations("/", "classpath:/META-INF/public-web-resources/"); - } - - } ----- - -And in XML: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - ----- - -When serving resources that may change when a new version of the application is -deployed, it is recommended that you incorporate a version string into the mapping -pattern used to request the resources, so that you may force clients to request the -newly deployed version of your application's resources. Such a version string can be -parameterized and accessed using SpEL so that it may be easily managed in a single place -when deploying new versions. - -As an example, let's consider an application that uses a performance-optimized custom -build (as recommended) of the Dojo JavaScript library in production, and that the build -is generally deployed within the web application at a path of -`/public-resources/dojo/dojo.js`. Since different parts of Dojo may be incorporated into -the custom build for each new version of the application, the client web browsers need -to be forced to re-download that custom-built `dojo.js` resource any time a new version -of the application is deployed. A simple way to achieve this would be to manage the -version of the application in a properties file, such as: - -[literal] -[subs="verbatim,quotes"] ----- -application.version=1.0.0 ----- - -and then to make the properties file's values accessible to SpEL as a bean using the -`util:properties` tag: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - ----- - -With the application version now accessible via SpEL, we can incorporate this into the -use of the `resources` tag: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - ----- - -In Java, you can use the `@PropertySouce` annotation and then inject the `Environment` -abstraction for access to all defined properties: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Configuration - @EnableWebMvc - @PropertySource("/WEB-INF/spring/application.properties") - public class WebConfig extends WebMvcConfigurerAdapter { - - @Inject Environment env; - - @Override - public void addResourceHandlers(ResourceHandlerRegistry registry) { - registry.addResourceHandler( - "/resources-" + env.getProperty("application.version") + "/**") - .addResourceLocations("/public-resources/"); - } - - } ----- - -and finally, to request the resource with the proper URL, we can take advantage of the -Spring JSP tags: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - ----- - - -[[mvc-default-servlet-handler]] -==== Falling Back On the "Default" Servlet To Serve Resources -This allows for mapping the `DispatcherServlet` to "/" (thus overriding the mapping -of the container's default Servlet), while still allowing static resource requests to be -handled by the container's default Servlet. It configures a -`DefaultServletHttpRequestHandler` with a URL mapping of "/**" and the lowest priority -relative to other URL mappings. - -This handler will forward all requests to the default Servlet. Therefore it is important -that it remains last in the order of all other URL `HandlerMappings`. That will be the -case if you use `` or alternatively if you are setting up your -own customized `HandlerMapping` instance be sure to set its `order` property to a value -lower than that of the `DefaultServletHttpRequestHandler`, which is `Integer.MAX_VALUE`. - -To enable the feature using the default setup use: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Configuration - @EnableWebMvc - public class WebConfig extends WebMvcConfigurerAdapter { - - @Override - public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) { - configurer.enable(); - } - - } ----- - -Or in XML: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - ----- - -The caveat to overriding the "/" Servlet mapping is that the `RequestDispatcher` for the -default Servlet must be retrieved by name rather than by path. The -`DefaultServletHttpRequestHandler` will attempt to auto-detect the default Servlet for -the container at startup time, using a list of known names for most of the major Servlet -containers (including Tomcat, Jetty, GlassFish, JBoss, Resin, WebLogic, and WebSphere). -If the default Servlet has been custom configured with a different name, or if a -different Servlet container is being used where the default Servlet name is unknown, -then the default Servlet's name must be explicitly provided as in the following example: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Configuration - @EnableWebMvc - public class WebConfig extends WebMvcConfigurerAdapter { - - @Override - public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) { - configurer.enable("myCustomDefaultServlet"); - } - - } ----- - -Or in XML: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - ----- - - - -[[mvc-config-path-matching]] -==== Path Matching -This allows customizing various settings related to URL mapping and path matching. -For details on the individual options check out the -{javadoc-baseurl}/org/springframework/web/servlet/config/annotation/PathMatchConfigurer.html[PathMatchConfigurer] API. - -Below is an example in Java config: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Configuration - @EnableWebMvc - public class WebConfig extends WebMvcConfigurerAdapter { - - @Override - public void configurePathMatch(PathMatchConfigurer configurer) { - configurer - .setUseSuffixPatternMatch(true) - .setUseTrailingSlashMatch(false) - .setUseRegisteredSuffixPatternMatch(true) - .setPathMatcher(antPathMatcher()) - .setUrlPathHelper(urlPathHelper()); - } - - @Bean - public UrlPathHelper urlPathHelper() { - //... - } - - @Bean - public PathMatcher antPathMatcher() { - //... - } - - } ----- - -And the same in XML, use the `` element: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - ----- - - - -[[mvc-config-advanced-java]] -==== Advanced Customizations with MVC Java Config -As you can see from the above examples, MVC Java config and the MVC namespace provide -higher level constructs that do not require deep knowledge of the underlying beans -created for you. Instead it helps you to focus on your application needs. However, at -some point you may need more fine-grained control or you may simply wish to understand -the underlying configuration. - -The first step towards more fine-grained control is to see the underlying beans created -for you. In MVC Java config you can see the javadocs and the `@Bean` methods in -`WebMvcConfigurationSupport`. The configuration in this class is automatically imported -through the `@EnableWebMvc` annotation. In fact if you open `@EnableWebMvc` you can see -the `@Import` statement. - -The next step towards more fine-grained control is to customize a property on one of the -beans created in `WebMvcConfigurationSupport` or perhaps to provide your own instance. -This requires two things -- remove the `@EnableWebMvc` annotation in order to prevent -the import and then extend from `DelegatingWebMvcConfiguration`, a subclass of -`WebMvcConfigurationSupport`. -Here is an example: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Configuration - public class WebConfig extends DelegatingWebMvcConfiguration { - - @Override - public void addInterceptors(InterceptorRegistry registry){ - // ... - } - - @Override - @Bean - public RequestMappingHandlerAdapter requestMappingHandlerAdapter() { - // Create or let "super" create the adapter - // Then customize one of its properties - } - - } ----- - -[NOTE] -==== -An application should have only one configuration extending `DelegatingWebMvcConfiguration` -or a single `@EnableWebMvc` annotated class, since they both register the same underlying -beans. - -Modifying beans in this way does not prevent you from using any of the higher-level -constructs shown earlier in this section. `WebMvcConfigurerAdapter` subclasses and -`WebMvcConfigurer` implementations are still being used. -==== - - - -[[mvc-config-advanced-xml]] -==== Advanced Customizations with the MVC Namespace -Fine-grained control over the configuration created for you is a bit harder with the MVC -namespace. - -If you do need to do that, rather than replicating the configuration it provides, -consider configuring a `BeanPostProcessor` that detects the bean you want to customize -by type and then modifying its properties as necessary. For example: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Component - public class MyPostProcessor implements BeanPostProcessor { - - public Object postProcessBeforeInitialization(Object bean, String name) throws BeansException { - if (bean instanceof RequestMappingHandlerAdapter) { - // Modify properties of the adapter - } - } - - } ----- - -Note that `MyPostProcessor` needs to be included in an `` in order for -it to be detected or if you prefer you can declare it explicitly with an XML bean -declaration. - - - -[[view]] -== View technologies - - - - -[[view-introduction]] -=== Introduction -One of the areas in which Spring excels is in the separation of view technologies from -the rest of the MVC framework. For example, deciding to use Velocity or XSLT in place of -an existing JSP is primarily a matter of configuration. This chapter covers the major -view technologies that work with Spring and touches briefly on how to add new ones. This -chapter assumes you are already familiar with <> which covers the -basics of how views in general are coupled to the MVC framework. - - - - -[[view-jsp]] -=== JSP & JSTL -Spring provides a couple of out-of-the-box solutions for JSP and JSTL views. Using JSP -or JSTL is done using a normal view resolver defined in the `WebApplicationContext`. -Furthermore, of course you need to write some JSPs that will actually render the view. - -[NOTE] -==== -Setting up your application to use JSTL is a common source of error, mainly caused by -confusion over the different servlet spec., JSP and JSTL version numbers, what they mean -and how to declare the taglibs correctly. The article -http://www.mularien.com/blog/2008/04/24/how-to-reference-and-use-jstl-in-your-web-application/[How -to Reference and Use JSTL in your Web Application] provides a useful guide to the common -pitfalls and how to avoid them. Note that as of Spring 3.0, the minimum supported -servlet version is 2.4 (JSP 2.0 and JSTL 1.1), which reduces the scope for confusion -somewhat. -==== - - - -[[view-jsp-resolver]] -==== View resolvers -Just as with any other view technology you're integrating with Spring, for JSPs you'll -need a view resolver that will resolve your views. The most commonly used view resolvers -when developing with JSPs are the `InternalResourceViewResolver` and the -`ResourceBundleViewResolver`. Both are declared in the `WebApplicationContext`: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - # And a sample properties file is uses (views.properties in WEB-INF/classes): - welcome.(class)=org.springframework.web.servlet.view.JstlView - welcome.url=/WEB-INF/jsp/welcome.jsp - - productList.(class)=org.springframework.web.servlet.view.JstlView - productList.url=/WEB-INF/jsp/productlist.jsp ----- - -As you can see, the `ResourceBundleViewResolver` needs a properties file defining the -view names mapped to 1) a class and 2) a URL. With a `ResourceBundleViewResolver` you -can mix different types of views using only one resolver. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - ----- - -The `InternalResourceBundleViewResolver` can be configured for using JSPs as described -above. As a best practice, we strongly encourage placing your JSP files in a directory -under the `'WEB-INF'` directory, so there can be no direct access by clients. - - - -[[view-jsp-jstl]] -==== 'Plain-old' JSPs versus JSTL -When using the Java Standard Tag Library you must use a special view class, the -`JstlView`, as JSTL needs some preparation before things such as the I18N features will -work. - - - -[[view-jsp-tags]] -==== Additional tags facilitating development -Spring provides data binding of request parameters to command objects as described in -earlier chapters. To facilitate the development of JSP pages in combination with those -data binding features, Spring provides a few tags that make things even easier. All -Spring tags have__HTML escaping__ features to enable or disable escaping of characters. - -The tag library descriptor (TLD) is included in the `spring-webmvc.jar`. Further -information about the individual tags can be found in the appendix entitled -<>. - - - -[[view-jsp-formtaglib]] -==== Using Spring's form tag library -As of version 2.0, Spring provides a comprehensive set of data binding-aware tags for -handling form elements when using JSP and Spring Web MVC. Each tag provides support for -the set of attributes of its corresponding HTML tag counterpart, making the tags -familiar and intuitive to use. The tag-generated HTML is HTML 4.01/XHTML 1.0 compliant. - -Unlike other form/input tag libraries, Spring's form tag library is integrated with -Spring Web MVC, giving the tags access to the command object and reference data your -controller deals with. As you will see in the following examples, the form tags make -JSPs easier to develop, read and maintain. - -Let's go through the form tags and look at an example of how each tag is used. We have -included generated HTML snippets where certain tags require further commentary. - - -[[view-jsp-formtaglib-configuration]] -===== Configuration -The form tag library comes bundled in `spring-webmvc.jar`. The library descriptor is -called `spring-form.tld`. - -To use the tags from this library, add the following directive to the top of your JSP -page: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - <%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %> ----- - -where `form` is the tag name prefix you want to use for the tags from this library. - - -[[view-jsp-formtaglib-formtag]] -===== The form tag - -This tag renders an HTML 'form' tag and exposes a binding path to inner tags for -binding. It puts the command object in the `PageContext` so that the command object can -be accessed by inner tags. __All the other tags in this library are nested tags of the -`form` tag__. - -Let's assume we have a domain object called `User`. It is a JavaBean with properties -such as `firstName` and `lastName`. We will use it as the form backing object of our -form controller which returns `form.jsp`. Below is an example of what `form.jsp` would -look like: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - - - - - - -
First Name:
Last Name:
- -
-
----- - -The `firstName` and `lastName` values are retrieved from the command object placed in -the `PageContext` by the page controller. Keep reading to see more complex examples of -how inner tags are used with the `form` tag. - -The generated HTML looks like a standard form: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- -
- - - - - - - - - - - - -
First Name:
Last Name:
- -
-
----- - -The preceding JSP assumes that the variable name of the form backing object is -`'command'`. If you have put the form backing object into the model under another name -(definitely a best practice), then you can bind the form to the named variable like so: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - - - - - - -
First Name:
Last Name:
- -
-
----- - - -[[view-jsp-formtaglib-inputtag]] -===== The input tag - -This tag renders an HTML 'input' tag using the bound value and type='text' by default. -For an example of this tag, see <>. Starting with Spring -3.1 you can use other types such HTML5-specific types like 'email', 'tel', 'date', and -others. - - -[[view-jsp-formtaglib-checkboxtag]] -===== The checkbox tag - -This tag renders an HTML 'input' tag with type 'checkbox'. - -Let's assume our `User` has preferences such as newsletter subscription and a list of -hobbies. Below is an example of the `Preferences` class: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class Preferences { - - private boolean receiveNewsletter; - private String[] interests; - private String favouriteWord; - - public boolean isReceiveNewsletter() { - return receiveNewsletter; - } - - public void setReceiveNewsletter(boolean receiveNewsletter) { - this.receiveNewsletter = receiveNewsletter; - } - - public String[] getInterests() { - return interests; - } - - public void setInterests(String[] interests) { - this.interests = interests; - } - - public String getFavouriteWord() { - return favouriteWord; - } - - public void setFavouriteWord(String favouriteWord) { - this.favouriteWord = favouriteWord; - } - } ----- - -The `form.jsp` would look like: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - <%-- Approach 1: Property is of type java.lang.Boolean --%> - - - - - - <%-- Approach 2: Property is of an array or of type java.util.Collection --%> - - - - - - <%-- Approach 3: Property is of type java.lang.Object --%> - - -
Subscribe to newsletter?:
Interests: - Quidditch: - Herbology: - Defence Against the Dark Arts: -
Favourite Word: - Magic: -
-
----- - -There are 3 approaches to the `checkbox` tag which should meet all your checkbox needs. - -* Approach One - When the bound value is of type `java.lang.Boolean`, the - `input(checkbox)` is marked as 'checked' if the bound value is `true`. The `value` - attribute corresponds to the resolved value of the `setValue(Object)` value property. -* Approach Two - When the bound value is of type `array` or `java.util.Collection`, the - `input(checkbox)` is marked as 'checked' if the configured `setValue(Object)` value is - present in the bound `Collection`. -* Approach Three - For any other bound value type, the `input(checkbox)` is marked as - 'checked' if the configured `setValue(Object)` is equal to the bound value. - -Note that regardless of the approach, the same HTML structure is generated. Below is an -HTML snippet of some checkboxes: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - Interests: - - Quidditch: - - Herbology: - - Defence Against the Dark Arts: - - - ----- - -What you might not expect to see is the additional hidden field after each checkbox. -When a checkbox in an HTML page is __not__ checked, its value will not be sent to the -server as part of the HTTP request parameters once the form is submitted, so we need a -workaround for this quirk in HTML in order for Spring form data binding to work. The -`checkbox` tag follows the existing Spring convention of including a hidden parameter -prefixed by an underscore ("_") for each checkbox. By doing this, you are effectively -telling Spring that "__the checkbox was visible in the form and I want my object to -which the form data will be bound to reflect the state of the checkbox no matter what__". - - -[[view-jsp-formtaglib-checkboxestag]] -===== The checkboxes tag - -This tag renders multiple HTML 'input' tags with type 'checkbox'. - -Building on the example from the previous `checkbox` tag section. Sometimes you prefer -not to have to list all the possible hobbies in your JSP page. You would rather provide -a list at runtime of the available options and pass that in to the tag. That is the -purpose of the `checkboxes` tag. You pass in an `Array`, a `List` or a `Map` containing -the available options in the "items" property. Typically the bound property is a -collection so it can hold multiple values selected by the user. Below is an example of -the JSP using this tag: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - -
Interests: - <%-- Property is of an array or of type java.util.Collection --%> - -
-
----- - -This example assumes that the "interestList" is a `List` available as a model attribute -containing strings of the values to be selected from. In the case where you use a Map, -the map entry key will be used as the value and the map entry's value will be used as -the label to be displayed. You can also use a custom object where you can provide the -property names for the value using "itemValue" and the label using "itemLabel". - - -[[view-jsp-formtaglib-radiobuttontag]] -===== The radiobutton tag - -This tag renders an HTML 'input' tag with type 'radio'. - -A typical usage pattern will involve multiple tag instances bound to the same property -but with different values. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - Sex: - - Male:
- Female: - - ----- - - -[[view-jsp-formtaglib-radiobuttonstag]] -===== The radiobuttons tag - -This tag renders multiple HTML 'input' tags with type 'radio'. - -Just like the `checkboxes` tag above, you might want to pass in the available options as -a runtime variable. For this usage you would use the `radiobuttons` tag. You pass in an -`Array`, a `List` or a `Map` containing the available options in the "items" property. -In the case where you use a Map, the map entry key will be used as the value and the map -entry's value will be used as the label to be displayed. You can also use a custom -object where you can provide the property names for the value using "itemValue" and the -label using "itemLabel". - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - Sex: - - ----- - - -[[view-jsp-formtaglib-passwordtag]] -===== The password tag - -This tag renders an HTML 'input' tag with type 'password' using the bound value. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - Password: - - - - ----- - -Please note that by default, the password value is __not__ shown. If you do want the -password value to be shown, then set the value of the `'showPassword'` attribute to -true, like so. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - Password: - - - - ----- - - -[[view-jsp-formtaglib-selecttag]] -===== The select tag - -This tag renders an HTML 'select' element. It supports data binding to the selected -option as well as the use of nested `option` and `options` tags. - -Let's assume a `User` has a list of skills. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - Skills: - - ----- - -If the `User's` skill were in Herbology, the HTML source of the 'Skills' row would look -like: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - Skills: - - - - ----- - - -[[view-jsp-formtaglib-optiontag]] -===== The option tag - -This tag renders an HTML 'option'. It sets 'selected' as appropriate based on the bound -value. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - House: - - - - - - - - - ----- - -If the `User's` house was in Gryffindor, the HTML source of the 'House' row would look -like: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - House: - - - - ----- - - -[[view-jsp-formtaglib-optionstag]] -===== The options tag - -This tag renders a list of HTML 'option' tags. It sets the 'selected' attribute as -appropriate based on the bound value. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - Country: - - - - - - - ----- - -If the `User` lived in the UK, the HTML source of the 'Country' row would look like: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - Country: - - - - ----- - -As the example shows, the combined usage of an `option` tag with the `options` tag -generates the same standard HTML, but allows you to explicitly specify a value in the -JSP that is for display only (where it belongs) such as the default string in the -example: "-- Please Select". - -The `items` attribute is typically populated with a collection or array of item objects. -`itemValue` and `itemLabel` simply refer to bean properties of those item objects, if -specified; otherwise, the item objects themselves will be stringified. Alternatively, -you may specify a `Map` of items, in which case the map keys are interpreted as option -values and the map values correspond to option labels. If `itemValue` and/or `itemLabel` -happen to be specified as well, the item value property will apply to the map key and -the item label property will apply to the map value. - - -[[view-jsp-formtaglib-textAreatag]] -===== The textarea tag - -This tag renders an HTML 'textarea'. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - Notes: - - - ----- - - -[[view-jsp-formtaglib-hiddeninputtag]] -===== The hidden tag - -This tag renders an HTML 'input' tag with type 'hidden' using the bound value. To submit -an unbound hidden value, use the HTML `input` tag with type 'hidden'. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - ----- - -If we choose to submit the 'house' value as a hidden one, the HTML would look like: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - ----- - - -[[view-jsp-formtaglib-errorstag]] -===== The errors tag - -This tag renders field errors in an HTML 'span' tag. It provides access to the errors -created in your controller or those that were created by any validators associated with -your controller. - -Let's assume we want to display all error messages for the `firstName` and `lastName` -fields once we submit the form. We have a validator for instances of the `User` class -called `UserValidator`. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class UserValidator implements Validator { - - public boolean supports(Class candidate) { - return User.class.isAssignableFrom(candidate); - } - - public void validate(Object obj, Errors errors) { - ValidationUtils.rejectIfEmptyOrWhitespace(errors, "firstName", "required", "Field is required."); - ValidationUtils.rejectIfEmptyOrWhitespace(errors, "lastName", "required", "Field is required."); - } - } ----- - -The `form.jsp` would look like: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - <%-- Show errors for firstName field --%> - - - - - - - <%-- Show errors for lastName field --%> - - - - - -
First Name:
Last Name:
- -
-
----- - -If we submit a form with empty values in the `firstName` and `lastName` fields, this is -what the HTML would look like: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- -
- - - - - <%-- Associated errors to firstName field displayed --%> - - - - - - - <%-- Associated errors to lastName field displayed --%> - - - - - -
First Name:Field is required.
Last Name:Field is required.
- -
-
----- - -What if we want to display the entire list of errors for a given page? The example below -shows that the `errors` tag also supports some basic wildcarding functionality. - -* `path="*"` - displays all errors -* `path="lastName"` - displays all errors associated with the `lastName` field -* if `path` is omitted - object errors only are displayed - -The example below will display a list of errors at the top of the page, followed by -field-specific errors next to the fields: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - - - - - - - - - -
First Name:
Last Name:
- -
-
----- - -The HTML would look like: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- -
- Field is required.
Field is required.
- - - - - - - - - - - - - - - - ----- - - -[[rest-method-conversion]] -===== HTTP Method Conversion -A key principle of REST is the use of the Uniform Interface. This means that all -resources (URLs) can be manipulated using the same four HTTP methods: GET, PUT, POST, -and DELETE. For each method, the HTTP specification defines the exact semantics. For -instance, a GET should always be a safe operation, meaning that is has no side effects, -and a PUT or DELETE should be idempotent, meaning that you can repeat these operations -over and over again, but the end result should be the same. While HTTP defines these -four methods, HTML only supports two: GET and POST. Fortunately, there are two possible -workarounds: you can either use JavaScript to do your PUT or DELETE, or simply do a POST -with the 'real' method as an additional parameter (modeled as a hidden input field in an -HTML form). This latter trick is what Spring's `HiddenHttpMethodFilter` does. This -filter is a plain Servlet Filter and therefore it can be used in combination with any -web framework (not just Spring MVC). Simply add this filter to your web.xml, and a POST -with a hidden _method parameter will be converted into the corresponding HTTP method -request. - -To support HTTP method conversion the Spring MVC form tag was updated to support setting -the HTTP method. For example, the following snippet taken from the updated Petclinic -sample - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - -

-
----- - -This will actually perform an HTTP POST, with the 'real' DELETE method hidden behind a -request parameter, to be picked up by the `HiddenHttpMethodFilter`, as defined in -web.xml: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - - httpMethodFilter - org.springframework.web.filter.HiddenHttpMethodFilter - - - - httpMethodFilter - petclinic - ----- - -The corresponding `@Controller` method is shown below: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @RequestMapping(method = RequestMethod.DELETE) - public String deletePet(@PathVariable int ownerId, @PathVariable int petId) { - this.clinic.deletePet(petId); - return "redirect:/owners/" + ownerId; - } ----- - - -[[view-jsp-formtaglib-html5]] -===== HTML5 Tags -Starting with Spring 3, the Spring form tag library allows entering dynamic attributes, -which means you can enter any HTML5 specific attributes. - -In Spring 3.1, the form input tag supports entering a type attribute other than 'text'. -This is intended to allow rendering new HTML5 specific input types such as 'email', -'date', 'range', and others. Note that entering type='text' is not required since 'text' -is the default type. - - - - -[[view-tiles]] -=== Tiles -It is possible to integrate Tiles - just as any other view technology - in web -applications using Spring. The following describes in a broad way how to do this. - - -[NOTE] -==== -This section focuses on Spring's support for Tiles v3 in the -`org.springframework.web.servlet.view.tiles3` package. -==== - - -[[view-tiles-dependencies]] -==== Dependencies -To be able to use Tiles, you have to add a dependency on Tiles version 3.0.1 or higher -and http://tiles.apache.org/framework/dependency-management.html[its transitive dependencies] -to your project. - - -[[view-tiles-integrate]] -==== How to integrate Tiles -To be able to use Tiles, you have to configure it using files containing definitions -(for basic information on definitions and other Tiles concepts, please have a look at -http://tiles.apache.org[]). In Spring this is done using the `TilesConfigurer`. Have a -look at the following piece of example ApplicationContext configuration: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - /WEB-INF/defs/general.xml - /WEB-INF/defs/widgets.xml - /WEB-INF/defs/administrator.xml - /WEB-INF/defs/customer.xml - /WEB-INF/defs/templates.xml - - - ----- - -As you can see, there are five files containing definitions, which are all located in -the `'WEB-INF/defs'` directory. At initialization of the `WebApplicationContext`, the -files will be loaded and the definitions factory will be initialized. After that has -been done, the Tiles includes in the definition files can be used as views within your -Spring web application. To be able to use the views you have to have a `ViewResolver` -just as with any other view technology used with Spring. Below you can find two -possibilities, the `UrlBasedViewResolver` and the `ResourceBundleViewResolver`. - -You can specify locale specific Tiles definitions by adding an underscore and then -the locale. For example: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - /WEB-INF/defs/tiles.xml - /WEB-INF/defs/tiles_fr_FR.xml - - - ----- - -With this configuration, `tiles_fr_FR.xml` will be used for requests with the `fr_FR` locale, -and `tiles.xml` will be used by default. - -[NOTE] -==== -Since underscores are used to indicate locales, it is recommended to avoid using -them otherwise in the file names for Tiles definitions. -==== - - -[[view-tiles-url]] -===== UrlBasedViewResolver - -The `UrlBasedViewResolver` instantiates the given `viewClass` for each view it has to -resolve. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - ----- - - -[[view-tiles-resource]] -===== ResourceBundleViewResolver - -The `ResourceBundleViewResolver` has to be provided with a property file containing -viewnames and viewclasses the resolver can use: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - ----- - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - ... - welcomeView.(class)=org.springframework.web.servlet.view.tiles3.TilesView - welcomeView.url=welcome (this is the name of a Tiles definition) - - vetsView.(class)=org.springframework.web.servlet.view.tiles3.TilesView - vetsView.url=vetsView (again, this is the name of a Tiles definition) - - findOwnersForm.(class)=org.springframework.web.servlet.view.JstlView - findOwnersForm.url=/WEB-INF/jsp/findOwners.jsp - ... ----- - -As you can see, when using the `ResourceBundleViewResolver`, you can easily mix -different view technologies. - -Note that the `TilesView` class supports JSTL (the JSP Standard Tag Library) out of the -box. - - -[[view-tiles-preparer]] -===== SimpleSpringPreparerFactory and SpringBeanPreparerFactory - -As an advanced feature, Spring also supports two special Tiles `PreparerFactory` -implementations. Check out the Tiles documentation for details on how to use -`ViewPreparer` references in your Tiles definition files. - -Specify `SimpleSpringPreparerFactory` to autowire ViewPreparer instances based on -specified preparer classes, applying Spring's container callbacks as well as applying -configured Spring BeanPostProcessors. If Spring's context-wide annotation-config has -been activated, annotations in ViewPreparer classes will be automatically detected and -applied. Note that this expects preparer __classes__ in the Tiles definition files, just -like the default `PreparerFactory` does. - -Specify `SpringBeanPreparerFactory` to operate on specified preparer __names__ instead -of classes, obtaining the corresponding Spring bean from the DispatcherServlet's -application context. The full bean creation process will be in the control of the Spring -application context in this case, allowing for the use of explicit dependency injection -configuration, scoped beans etc. Note that you need to define one Spring bean definition -per preparer name (as used in your Tiles definitions). - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - /WEB-INF/defs/general.xml - /WEB-INF/defs/widgets.xml - /WEB-INF/defs/administrator.xml - /WEB-INF/defs/customer.xml - /WEB-INF/defs/templates.xml - - - - - - - ----- - - - - -[[view-velocity]] -=== Velocity & FreeMarker -http://velocity.apache.org[Velocity] and http://www.freemarker.org[FreeMarker] are two -templating languages that can be used as view technologies within Spring MVC -applications. The languages are quite similar and serve similar needs and so are -considered together in this section. For semantic and syntactic differences between the -two languages, see the http://www.freemarker.org[FreeMarker] web site. - - - -[[view-velocity-dependencies]] -==== Dependencies -Your web application will need to include `velocity-1.x.x.jar` or `freemarker-2.x.jar` -in order to work with Velocity or FreeMarker respectively and `commons-collections.jar` -is required for Velocity. Typically they are included in the `WEB-INF/lib` folder where -they are guaranteed to be found by a Java EE server and added to the classpath for your -application. It is of course assumed that you already have the `spring-webmvc.jar` in -your `'WEB-INF/lib'` directory too! If you make use of Spring's 'dateToolAttribute' or -'numberToolAttribute' in your Velocity views, you will also need to include the -`velocity-tools-generic-1.x.jar` - - - -[[view-velocity-contextconfig]] -==== Context configuration -A suitable configuration is initialized by adding the relevant configurer bean -definition to your `'*-servlet.xml'` as shown below: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - - - - ----- - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - - - - ----- - -[NOTE] -==== -For non web-apps add a `VelocityConfigurationFactoryBean` or a -`FreeMarkerConfigurationFactoryBean` to your application context definition file. -==== - - - -[[view-velocity-createtemplates]] -==== Creating templates -Your templates need to be stored in the directory specified by the `*Configurer` bean -shown above. This document does not cover details of creating templates for the two -languages - please see their relevant websites for information. If you use the view -resolvers highlighted, then the logical view names relate to the template file names in -similar fashion to `InternalResourceViewResolver` for JSP's. So if your controller -returns a ModelAndView object containing a view name of "welcome" then the resolvers -will look for the `/WEB-INF/freemarker/welcome.ftl` or `/WEB-INF/velocity/welcome.vm` -template as appropriate. - - - -[[view-velocity-advancedconfig]] -==== Advanced configuration -The basic configurations highlighted above will be suitable for most application -requirements, however additional configuration options are available for when unusual or -advanced requirements dictate. - - -[[view-velocity-example-velocityproperties]] -===== velocity.properties -This file is completely optional, but if specified, contains the values that are passed -to the Velocity runtime in order to configure velocity itself. Only required for -advanced configurations, if you need this file, specify its location on the -`VelocityConfigurer` bean definition above. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - ----- - -Alternatively, you can specify velocity properties directly in the bean definition for -the Velocity config bean by replacing the "configLocation" property with the following -inline properties. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - file - - org.apache.velocity.runtime.resource.loader.FileResourceLoader - - ${webapp.root}/WEB-INF/velocity - false - - - ----- - -Refer to the -{javadoc-baseurl}/org/springframework/ui/velocity/VelocityEngineFactory.html[API -documentation] for Spring configuration of Velocity, or the Velocity documentation for -examples and definitions of the `'velocity.properties'` file itself. - - -[[views-freemarker]] -===== FreeMarker -FreeMarker 'Settings' and 'SharedVariables' can be passed directly to the FreeMarker -`Configuration` object managed by Spring by setting the appropriate bean properties on -the `FreeMarkerConfigurer` bean. The `freemarkerSettings` property requires a -`java.util.Properties` object and the `freemarkerVariables` property requires a -`java.util.Map`. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - - - ----- - -See the FreeMarker documentation for details of settings and variables as they apply to -the `Configuration` object. - - - -[[view-velocity-forms]] -==== Bind support and form handling -Spring provides a tag library for use in JSP's that contains (amongst other things) a -`` tag. This tag primarily enables forms to display values from form -backing objects and to show the results of failed validations from a `Validator` in the -web or business tier. From version 1.1, Spring now has support for the same -functionality in both Velocity and FreeMarker, with additional convenience macros for -generating form input elements themselves. - - -[[view-bind-macros]] -===== The bind macros -A standard set of macros are maintained within the `spring-webmvc.jar` file for both -languages, so they are always available to a suitably configured application. - -Some of the macros defined in the Spring libraries are considered internal (private) but -no such scoping exists in the macro definitions making all macros visible to calling -code and user templates. The following sections concentrate only on the macros you need -to be directly calling from within your templates. If you wish to view the macro code -directly, the files are called spring.vm / spring.ftl and are in the packages -`org.springframework.web.servlet.view.velocity` or -`org.springframework.web.servlet.view.freemarker` respectively. - - -[[view-simple-binding]] -===== Simple binding -In your html forms (vm / ftl templates) that act as the 'formView' for a Spring form -controller, you can use code similar to the following to bind to field values and -display error messages for each input field in similar fashion to the JSP equivalent. -Note that the name of the command object is "command" by default, but can be overridden -in your MVC configuration by setting the 'commandName' bean property on your form -controller. Example code is shown below for the `personFormV` and `personFormF` views -configured earlier; - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - ... -
- Name: - #springBind( "command.name" ) -
- #foreach($error in $status.errorMessages) $error
#end -
- ... - - - ... - ----- - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - <#import "/spring.ftl" as spring /> - - ... -
- Name: - <@spring.bind "command.name" /> -
- <#list spring.status.errorMessages as error> ${error}
-
- ... - - - ... - ----- - -`#springBind` / `<@spring.bind>` requires a 'path' argument which consists of the name -of your command object (it will be 'command' unless you changed it in your -FormController properties) followed by a period and the name of the field on the command -object you wish to bind to. Nested fields can be used too such as -"command.address.street". The `bind` macro assumes the default HTML escaping behavior -specified by the ServletContext parameter `defaultHtmlEscape` in web.xml - -The optional form of the macro called `#springBindEscaped` / `<@spring.bindEscaped>` -takes a second argument and explicitly specifies whether HTML escaping should be used in -the status error messages or values. Set to true or false as required. Additional form -handling macros simplify the use of HTML escaping and these macros should be used -wherever possible. They are explained in the next section. - - -[[views-form-macros]] -===== Form input generation macros -Additional convenience macros for both languages simplify both binding and form -generation (including validation error display). It is never necessary to use these -macros to generate form input fields, and they can be mixed and matched with simple HTML -or calls direct to the spring bind macros highlighted previously. - -The following table of available macros show the VTL and FTL definitions and the -parameter list that each takes. - -[[views-macros-defs-tbl]] -.Table of macro definitions -[cols="3,1,1"] -|=== -| macro| VTL definition| FTL definition - -| **message** (output a string from a resource bundle based on the code parameter) -| #springMessage($code) -| <@spring.message code/> - -| **messageText** (output a string from a resource bundle based on the code parameter, - falling back to the value of the default parameter) -| #springMessageText($code $text) -| <@spring.messageText code, text/> - -| **url** (prefix a relative URL with the application's context root) -| #springUrl($relativeUrl) -| <@spring.url relativeUrl/> - -| **formInput** (standard input field for gathering user input) -| #springFormInput($path $attributes) -| <@spring.formInput path, attributes, fieldType/> - -| **formHiddenInput *** (hidden input field for submitting non-user input) -| #springFormHiddenInput($path $attributes) -| <@spring.formHiddenInput path, attributes/> - -| **formPasswordInput** * (standard input field for gathering passwords. Note that no - value will ever be populated in fields of this type) -| #springFormPasswordInput($path $attributes) -| <@spring.formPasswordInput path, attributes/> - -| **formTextarea** (large text field for gathering long, freeform text input) -| #springFormTextarea($path $attributes) -| <@spring.formTextarea path, attributes/> - -| **formSingleSelect** (drop down box of options allowing a single required value to be - selected) -| #springFormSingleSelect( $path $options $attributes) -| <@spring.formSingleSelect path, options, attributes/> - -| **formMultiSelect** (a list box of options allowing the user to select 0 or more values) -| #springFormMultiSelect($path $options $attributes) -| <@spring.formMultiSelect path, options, attributes/> - -| **formRadioButtons** (a set of radio buttons allowing a single selection to be made - from the available choices) -| #springFormRadioButtons($path $options $separator $attributes) -| <@spring.formRadioButtons path, options separator, attributes/> - -| **formCheckboxes** (a set of checkboxes allowing 0 or more values to be selected) -| #springFormCheckboxes($path $options $separator $attributes) -| <@spring.formCheckboxes path, options, separator, attributes/> - -| **formCheckbox** (a single checkbox) -| #springFormCheckbox($path $attributes) -| <@spring.formCheckbox path, attributes/> - -| **showErrors** (simplify display of validation errors for the bound field) -| #springShowErrors($separator $classOrStyle) -| <@spring.showErrors separator, classOrStyle/> -|=== - -* In FTL (FreeMarker), these two macros are not actually required as you can use the - normal `formInput` macro, specifying ' `hidden`' or ' `password`' as the value for the - `fieldType` parameter. - -The parameters to any of the above macros have consistent meanings: - -* path: the name of the field to bind to (ie "command.name") -* options: a Map of all the available values that can be selected from in the input - field. The keys to the map represent the values that will be POSTed back from the form - and bound to the command object. Map objects stored against the keys are the labels - displayed on the form to the user and may be different from the corresponding values - posted back by the form. Usually such a map is supplied as reference data by the - controller. Any Map implementation can be used depending on required behavior. For - strictly sorted maps, a `SortedMap` such as a `TreeMap` with a suitable Comparator may - be used and for arbitrary Maps that should return values in insertion order, use a - `LinkedHashMap` or a `LinkedMap` from commons-collections. -* separator: where multiple options are available as discreet elements (radio buttons or - checkboxes), the sequence of characters used to separate each one in the list (ie - "
"). -* attributes: an additional string of arbitrary tags or text to be included within the - HTML tag itself. This string is echoed literally by the macro. For example, in a - textarea field you may supply attributes as 'rows="5" cols="60"' or you could pass - style information such as 'style="border:1px solid silver"'. -* classOrStyle: for the showErrors macro, the name of the CSS class that the span tag - wrapping each error will use. If no information is supplied (or the value is empty) - then the errors will be wrapped in tags. - -Examples of the macros are outlined below some in FTL and some in VTL. Where usage -differences exist between the two languages, they are explained in the notes. - -[[views-form-macros-input]] -====== Input Fields -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - ... - Name: - #springFormInput("command.name" "")
- #springShowErrors("
" "")
----- - -The formInput macro takes the path parameter (command.name) and an additional attributes -parameter which is empty in the example above. The macro, along with all other form -generation macros, performs an implicit spring bind on the path parameter. The binding -remains valid until a new bind occurs so the showErrors macro doesn't need to pass the -path parameter again - it simply operates on whichever field a bind was last created for. - -The showErrors macro takes a separator parameter (the characters that will be used to -separate multiple errors on a given field) and also accepts a second parameter, this -time a class name or style attribute. Note that FreeMarker is able to specify default -values for the attributes parameter, unlike Velocity, and the two macro calls above -could be expressed as follows in FTL: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - <@spring.formInput "command.name"/> - <@spring.showErrors "
"/> ----- - -Output is shown below of the form fragment generating the name field, and displaying a -validation error after the form was submitted with no value in the field. Validation -occurs through Spring's Validation framework. - -The generated HTML looks like this: - -[source,jsp,indent=0] -[subs="verbatim,quotes"] ----- - Name: - -
- required -
-
----- - -The formTextarea macro works the same way as the formInput macro and accepts the same -parameter list. Commonly, the second parameter (attributes) will be used to pass style -information or rows and cols attributes for the textarea. - -[[views-form-macros-select]] -====== Selection Fields -Four selection field macros can be used to generate common UI value selection inputs in -your HTML forms. - -* formSingleSelect -* formMultiSelect -* formRadioButtons -* formCheckboxes - -Each of the four macros accepts a Map of options containing the value for the form -field, and the label corresponding to that value. The value and the label can be the -same. - -An example of radio buttons in FTL is below. The form backing object specifies a default -value of 'London' for this field and so no validation is necessary. When the form is -rendered, the entire list of cities to choose from is supplied as reference data in the -model under the name 'cityMap'. - -[source,jsp,indent=0] -[subs="verbatim,quotes"] ----- - ... - Town: - <@spring.formRadioButtons "command.address.town", cityMap, "" />

----- - -This renders a line of radio buttons, one for each value in `cityMap` using the -separator "". No additional attributes are supplied (the last parameter to the macro is -missing). The cityMap uses the same String for each key-value pair in the map. The map's -keys are what the form actually submits as POSTed request parameters, map values are the -labels that the user sees. In the example above, given a list of three well known cities -and a default value in the form backing object, the HTML would be - -[source,jsp,indent=0] -[subs="verbatim,quotes"] ----- - Town: - London - Paris - New York ----- - -If your application expects to handle cities by internal codes for example, the map of -codes would be created with suitable keys like the example below. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - protected Map referenceData(HttpServletRequest request) throws Exception { - Map cityMap = new LinkedHashMap(); - cityMap.put("LDN", "London"); - cityMap.put("PRS", "Paris"); - cityMap.put("NYC", "New York"); - - Map m = new HashMap(); - m.put("cityMap", cityMap); - return m; - } ----- - -The code would now produce output where the radio values are the relevant codes but the -user still sees the more user friendly city names. - -[source,jsp,indent=0] -[subs="verbatim,quotes"] ----- - Town: - London - Paris - New York ----- - - -[[views-form-macros-html-escaping]] -===== HTML escaping and XHTML compliance -Default usage of the form macros above will result in HTML tags that are HTML 4.01 -compliant and that use the default value for HTML escaping defined in your web.xml as -used by Spring's bind support. In order to make the tags XHTML compliant or to override -the default HTML escaping value, you can specify two variables in your template (or in -your model where they will be visible to your templates). The advantage of specifying -them in the templates is that they can be changed to different values later in the -template processing to provide different behavior for different fields in your form. - -To switch to XHTML compliance for your tags, specify a value of 'true' for a -model/context variable named xhtmlCompliant: - -[source,jsp,indent=0] -[subs="verbatim,quotes"] ----- - ## for Velocity.. - #set($springXhtmlCompliant = true) - - <#-- for FreeMarker --> - <#assign xhtmlCompliant = true in spring> ----- - -Any tags generated by the Spring macros will now be XHTML compliant after processing -this directive. - -In similar fashion, HTML escaping can be specified per field: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - <#-- until this point, default HTML escaping is used --> - - <#assign htmlEscape = true in spring> - <#-- next field will use HTML escaping --> - <@spring.formInput "command.name" /> - - <#assign htmlEscape = false in spring> - <#-- all future fields will be bound with HTML escaping off --> ----- - - - - -[[view-xslt]] -=== XSLT -XSLT is a transformation language for XML and is popular as a view technology within web -applications. XSLT can be a good choice as a view technology if your application -naturally deals with XML, or if your model can easily be converted to XML. The following -section shows how to produce an XML document as model data and have it transformed with -XSLT in a Spring Web MVC application. - - - -[[view-xslt-firstwords]] -==== My First Words -This example is a trivial Spring application that creates a list of words in the -`Controller` and adds them to the model map. The map is returned along with the view -name of our XSLT view. See <> for details of Spring Web MVC's -`Controller` interface. The XSLT view will turn the list of words into a simple XML -document ready for transformation. - - -[[view-xslt-beandefs]] -===== Bean definitions -Configuration is standard for a simple Spring application. The dispatcher servlet config -file contains a reference to a `ViewResolver`, URL mappings and a single controller -bean... - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - ----- - -... that encapsulates our word generation logic. - - -[[view-xslt-controllercode]] -===== Standard MVC controller code -The controller logic is encapsulated in a subclass of `AbstractController`, with the -handler method being defined like so... - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - protected ModelAndView handleRequestInternal(HttpServletRequest request, - HttpServletResponse response) throws Exception { - - Map map = new HashMap(); - List wordList = new ArrayList(); - - wordList.add("hello"); - wordList.add("world"); - - map.put("wordList", wordList); - - return new ModelAndView("home", map); - } ----- - -So far we've done nothing that's XSLT specific. The model data has been created in the -same way as you would for any other Spring MVC application. Depending on the -configuration of the application now, that list of words could be rendered by JSP/JSTL -by having them added as request attributes, or they could be handled by Velocity by -adding the object to the `VelocityContext`. In order to have XSLT render them, they of -course have to be converted into an XML document somehow. There are software packages -available that will automatically 'domify' an object graph, but within Spring, you have -complete flexibility to create the DOM from your model in any way you choose. This -prevents the transformation of XML playing too great a part in the structure of your -model data which is a danger when using tools to manage the domification process. - - -[[view-xslt-subclassing]] -===== Convert the model data to XML -In order to create a DOM document from our list of words or any other model data, we -must subclass the (provided) -`org.springframework.web.servlet.view.xslt.AbstractXsltView` class. In doing so, we must -also typically implement the abstract method `createXsltSource(..)` method. The first -parameter passed to this method is our model map. Here's the complete listing of the -`HomePage` class in our trivial word application: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - package xslt; - - // imports omitted for brevity - - public class HomePage extends AbstractXsltView { - - protected Source createXsltSource(Map model, String rootName, - HttpServletRequest request, HttpServletResponse response) throws Exception { - - Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument(); - Element root = document.createElement(rootName); - - List words = (List) model.get("wordList"); - for (Iterator it = words.iterator(); it.hasNext();) { - String nextWord = (String) it.next(); - Element wordNode = document.createElement("word"); - Text textNode = document.createTextNode(nextWord); - wordNode.appendChild(textNode); - root.appendChild(wordNode); - } - return new DOMSource(root); - } - - } ----- - -A series of parameter name/value pairs can optionally be defined by your subclass which -will be added to the transformation object. The parameter names must match those defined -in your XSLT template declared with `defaultValue`. To specify the parameters, override the -`getParameters()` method of the `AbstractXsltView` class and return a `Map` of the -name/value pairs. If your parameters need to derive information from the current -request, you can override the `getParameters(HttpServletRequest request)` method instead. - - -[[view-xslt-viewdefinitions]] -===== Defining the view properties -The views.properties file (or equivalent xml definition if you're using an XML based -view resolver as we did in the Velocity examples above) looks like this for the one-view -application that is 'My First Words': - -[literal] -[subs="verbatim,quotes"] ----- -home.(class)=xslt.HomePage -home.stylesheetLocation=/WEB-INF/xsl/home.xslt -home.root=words ----- - -Here, you can see how the view is tied in with the `HomePage` class just written which -handles the model domification in the first property `'.(class)'`. The -`'stylesheetLocation'` property points to the XSLT file which will handle the XML -transformation into HTML for us and the final property `'.root'` is the name that will -be used as the root of the XML document. This gets passed to the `HomePage` class above -in the second parameter to the `createXsltSource(..)` method(s). - - -[[view-xslt-transforming]] -===== Document transformation -Finally, we have the XSLT code used for transforming the above document. As shown in the -above `'views.properties'` file, the stylesheet is called `'home.xslt'` and it lives in -the war file in the `'WEB-INF/xsl'` directory. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - Hello! - -

My First Words

- - - -
- - -
-
- -
----- - - - -[[view-xslt-summary]] -==== Summary -A summary of the files discussed and their location in the WAR file is shown in the -simplified WAR structure below. - -[literal] -[subs="verbatim,quotes"] ----- -ProjectRoot - | - +- WebContent - | - +- WEB-INF - | - +- classes - | | - | +- xslt - | | | - | | +- HomePageController.class - | | +- HomePage.class - | | - | +- views.properties - | - +- lib - | | - | +- spring-*.jar - | - +- xsl - | | - | +- home.xslt - | - +- frontcontroller-servlet.xml ----- - -You will also need to ensure that an XML parser and an XSLT engine are available on the -classpath. JDK 1.4 provides them by default, and most Java EE containers will also make -them available by default, but it's a possible source of errors to be aware of. - - - - -[[view-document]] -=== Document views (PDF/Excel) - - - -[[view-document-intro]] -==== Introduction -Returning an HTML page isn't always the best way for the user to view the model output, -and Spring makes it simple to generate a PDF document or an Excel spreadsheet -dynamically from the model data. The document is the view and will be streamed from the -server with the correct content type to (hopefully) enable the client PC to run their -spreadsheet or PDF viewer application in response. - -In order to use Excel views, you need to add the 'poi' library to your classpath, and -for PDF generation, the iText library. - - - -[[view-document-config]] -==== Configuration and setup -Document based views are handled in an almost identical fashion to XSLT views, and the -following sections build upon the previous one by demonstrating how the same controller -used in the XSLT example is invoked to render the same model as both a PDF document and -an Excel spreadsheet (which can also be viewed or manipulated in Open Office). - - -[[view-document-configviews]] -===== Document view definitions -First, let's amend the views.properties file (or xml equivalent) and add a simple view -definition for both document types. The entire file now looks like this with the XSLT -view shown from earlier: - -[literal] -[subs="verbatim,quotes"] ----- -home.(class)=xslt.HomePage -home.stylesheetLocation=/WEB-INF/xsl/home.xslt -home.root=words - -xl.(class)=excel.HomePage - -pdf.(class)=pdf.HomePage ----- - -__If you want to start with a template spreadsheet or a fillable PDF form to add your -model data to, specify the location as the 'url' property in the view definition__ - - -[[view-document-configcontroller]] -===== Controller code -The controller code we'll use remains exactly the same from the XSLT example earlier -other than to change the name of the view to use. Of course, you could be clever and -have this selected based on a URL parameter or some other logic - proof that Spring -really is very good at decoupling the views from the controllers! - - -[[view-document-configsubclasses]] -===== Subclassing for Excel views -Exactly as we did for the XSLT example, we'll subclass suitable abstract classes in -order to implement custom behavior in generating our output documents. For Excel, this -involves writing a subclass of -`org.springframework.web.servlet.view.document.AbstractExcelView` (for Excel files -generated by POI) or `org.springframework.web.servlet.view.document.AbstractJExcelView` -(for JExcelApi-generated Excel files) and implementing the `buildExcelDocument()` method. - -Here's the complete listing for our POI Excel view which displays the word list from the -model map in consecutive rows of the first column of a new spreadsheet: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - package excel; - - // imports omitted for brevity - - public class HomePage extends AbstractExcelView { - - protected void buildExcelDocument(Map model, HSSFWorkbook wb, HttpServletRequest req, - HttpServletResponse resp) throws Exception { - - HSSFSheet sheet; - HSSFRow sheetRow; - HSSFCell cell; - - // Go to the first sheet - // getSheetAt: only if wb is created from an existing document - // sheet = wb.getSheetAt(0); - sheet = wb.createSheet("Spring"); - sheet.setDefaultColumnWidth((short) 12); - - // write a text at A1 - cell = getCell(sheet, 0, 0); - setText(cell, "Spring-Excel test"); - - List words = (List) model.get("wordList"); - for (int i=0; i < words.size(); i++) { - cell = getCell(sheet, 2+i, 0); - setText(cell, (String) words.get(i)); - } - } - - } ----- - -And the following is a view generating the same Excel file, now using JExcelApi: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - package excel; - - // imports omitted for brevity - - public class HomePage extends AbstractJExcelView { - - protected void buildExcelDocument(Map model, WritableWorkbook wb, - HttpServletRequest request, HttpServletResponse response) throws Exception { - - WritableSheet sheet = wb.createSheet("Spring", 0); - - sheet.addCell(new Label(0, 0, "Spring-Excel test")); - - List words = (List) model.get("wordList"); - for (int i = 0; i < words.size(); i++) { - sheet.addCell(new Label(2+i, 0, (String) words.get(i))); - } - } - } ----- - -Note the differences between the APIs. We've found that the JExcelApi is somewhat more -intuitive, and furthermore, JExcelApi has slightly better image-handling capabilities. -There have been memory problems with large Excel files when using JExcelApi however. - -If you now amend the controller such that it returns `xl` as the name of the view ( -`return new ModelAndView("xl", map);`) and run your application again, you should find -that the Excel spreadsheet is created and downloaded automatically when you request the -same page as before. - - -[[view-document-configsubclasspdf]] -===== Subclassing for PDF views -The PDF version of the word list is even simpler. This time, the class extends -`org.springframework.web.servlet.view.document.AbstractPdfView` and implements the -`buildPdfDocument()` method as follows: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - package pdf; - - // imports omitted for brevity - - public class PDFPage extends AbstractPdfView { - - protected void buildPdfDocument(Map model, Document doc, PdfWriter writer, - HttpServletRequest req, HttpServletResponse resp) throws Exception { - List words = (List) model.get("wordList"); - for (int i=0; i - -
----- - -Here we've configured an instance of the `ResourceBundleViewResolver` class that will -look for view mappings in the resource bundle with base name `views`. (The content of -this file is described in the next section.) - - -[[view-jasper-reports-configuration-views]] -===== Configuring the Views - -The Spring Framework contains five different `View` implementations for JasperReports, -four of which correspond to one of the four output formats supported by JasperReports, -and one that allows for the format to be determined at runtime: - -[[view-jasper-reports-configuration-views-classes]] -.JasperReports View classes -|=== -| Class Name| Render Format - -| `JasperReportsCsvView` -| CSV - -| `JasperReportsHtmlView` -| HTML - -| `JasperReportsPdfView` -| PDF - -| `JasperReportsXlsView` -| Microsoft Excel - -| `JasperReportsMultiFormatView` -| The view is <> -|=== - -Mapping one of these classes to a view name and a report file is a matter of adding the -appropriate entries in the resource bundle configured in the previous section as shown -here: - -[literal] -[subs="verbatim,quotes"] ----- -simpleReport.(class)=org.springframework.web.servlet.view.jasperreports.JasperReportsPdfView -simpleReport.url=/WEB-INF/reports/DataSourceReport.jasper ----- - -Here you can see that the view with name `simpleReport` is mapped to the -`JasperReportsPdfView` class, causing the output of this report to be rendered in PDF -format. The `url` property of the view is set to the location of the underlying report -file. - - -[[view-jasper-reports-configuration-report-files]] -===== About Report Files -JasperReports has two distinct types of report file: the design file, which has a -`.jrxml` extension, and the compiled report file, which has a `.jasper` extension. -Typically, you use the JasperReports Ant task to compile your `.jrxml` design file into -a `.jasper` file before deploying it into your application. With the Spring Framework -you can map either of these files to your report file and the framework will take care -of compiling the `.jrxml` file on the fly for you. You should note that after a `.jrxml` -file is compiled by the Spring Framework, the compiled report is cached for the lifetime -of the application. Thus, to make changes to the file you will need to restart your -application. - - -[[view-jasper-reports-configuration-multiformat-view]] -===== Using JasperReportsMultiFormatView - -The `JasperReportsMultiFormatView` allows for the report format to be specified at -runtime. The actual rendering of the report is delegated to one of the other -JasperReports view classes - the `JasperReportsMultiFormatView` class simply adds a -wrapper layer that allows for the exact implementation to be specified at runtime. - -The `JasperReportsMultiFormatView` class introduces two concepts: the format key and the -discriminator key. The `JasperReportsMultiFormatView` class uses the mapping key to look -up the actual view implementation class, and it uses the format key to lookup up the -mapping key. From a coding perspective you add an entry to your model with the format -key as the key and the mapping key as the value, for example: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public ModelAndView handleSimpleReportMulti(HttpServletRequest request, - HttpServletResponse response) throws Exception { - - String uri = request.getRequestURI(); - String format = uri.substring(uri.lastIndexOf(".") + 1); - - Map model = getModel(); - model.put("format", format); - - return new ModelAndView("simpleReportMulti", model); - - } ----- - -In this example, the mapping key is determined from the extension of the request URI and -is added to the model under the default format key: `format`. If you wish to use a -different format key then you can configure this using the `formatKey` property of the -`JasperReportsMultiFormatView` class. - -By default the following mapping key mappings are configured in -`JasperReportsMultiFormatView`: - -[[view-jasper-reports-configuration-multiformat-view-mappings]] -.JasperReportsMultiFormatView Default Mapping Key Mappings -|=== -| Mapping Key| View Class - -| csv -| `JasperReportsCsvView` - -| html -| `JasperReportsHtmlView` - -| pdf -| `JasperReportsPdfView` - -| xls -| `JasperReportsXlsView` -|=== - -So in the example above a request to URI /foo/myReport.pdf would be mapped to the -`JasperReportsPdfView` class. You can override the mapping key to view class mappings -using the `formatMappings` property of `JasperReportsMultiFormatView`. - - - -[[view-jasper-reports-model]] -==== Populating the ModelAndView - -In order to render your report correctly in the format you have chosen, you must supply -Spring with all of the data needed to populate your report. For JasperReports this means -you must pass in all report parameters along with the report datasource. Report -parameters are simple name/value pairs and can be added to the `Map` for your model as -you would add any name/value pair. - -When adding the datasource to the model you have two approaches to choose from. The -first approach is to add an instance of `JRDataSource` or a `Collection` type to the -model `Map` under any arbitrary key. Spring will then locate this object in the model -and treat it as the report datasource. For example, you may populate your model like so: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - private Map getModel() { - Map model = new HashMap(); - Collection beanData = getBeanData(); - model.put("myBeanData", beanData); - return model; - } ----- - -The second approach is to add the instance of `JRDataSource` or `Collection` under a -specific key and then configure this key using the `reportDataKey` property of the view -class. In both cases Spring will wrap instances of `Collection` in a -`JRBeanCollectionDataSource` instance. For example: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - private Map getModel() { - Map model = new HashMap(); - Collection beanData = getBeanData(); - Collection someData = getSomeData(); - model.put("myBeanData", beanData); - model.put("someData", someData); - return model; - } ----- - -Here you can see that two `Collection` instances are being added to the model. To ensure -that the correct one is used, we simply modify our view configuration as appropriate: - -[literal] -[subs="verbatim,quotes"] ----- -simpleReport.(class)=org.springframework.web.servlet.view.jasperreports.JasperReportsPdfView -simpleReport.url=/WEB-INF/reports/DataSourceReport.jasper -simpleReport.reportDataKey=myBeanData ----- - -Be aware that when using the first approach, Spring will use the first instance of -`JRDataSource` or `Collection` that it encounters. If you need to place multiple -instances of `JRDataSource` or `Collection` into the model you need to use the second -approach. - - - -[[view-jasper-reports-subreports]] -==== Working with Sub-Reports -JasperReports provides support for embedded sub-reports within your master report files. -There are a wide variety of mechanisms for including sub-reports in your report files. -The easiest way is to hard code the report path and the SQL query for the sub report -into your design files. The drawback of this approach is obvious: the values are -hard-coded into your report files reducing reusability and making it harder to modify -and update report designs. To overcome this you can configure sub-reports declaratively, -and you can include additional data for these sub-reports directly from your controllers. - - -[[view-jasper-reports-subreports-config-reports]] -===== Configuring Sub-Report Files -To control which sub-report files are included in a master report using Spring, your -report file must be configured to accept sub-reports from an external source. To do this -you declare a parameter in your report file like so: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - ----- - -Then, you define your sub-report to use this sub-report parameter: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - - ----- - -This defines a master report file that expects the sub-report to be passed in as an -instance of `net.sf.jasperreports.engine.JasperReports` under the parameter -`ProductsSubReport`. When configuring your Jasper view class, you can instruct Spring to -load a report file and pass it into the JasperReports engine as a sub-report using the -`subReportUrls` property: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - ----- - -Here, the key of the `Map` corresponds to the name of the sub-report parameter in the -report design file, and the entry is the URL of the report file. Spring will load this -report file, compiling it if necessary, and pass it into the JasperReports engine under -the given key. - - -[[view-jasper-reports-subreports-config-datasources]] -===== Configuring Sub-Report Data Sources -This step is entirely optional when using Spring to configure your sub-reports. If you -wish, you can still configure the data source for your sub-reports using static queries. -However, if you want Spring to convert data returned in your `ModelAndView` into -instances of `JRDataSource` then you need to specify which of the parameters in your -`ModelAndView` Spring should convert. To do this, configure the list of parameter names -using the `subReportDataKeys` property of your chosen view class: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - ----- - -Here, the key you supply __must__ correspond to both the key used in your `ModelAndView` -and the key used in your report design file. - - - -[[view-jasper-reports-exporter-parameters]] -==== Configuring Exporter Parameters -If you have special requirements for exporter configuration -- perhaps you want a -specific page size for your PDF report -- you can configure these exporter parameters -declaratively in your Spring configuration file using the `exporterParameters` property -of the view class. The `exporterParameters` property is typed as a `Map`. In your -configuration the key of an entry should be the fully-qualified name of a static field -that contains the exporter parameter definition, and the value of an entry should be the -value you want to assign to the parameter. An example of this is shown below: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - Footer by Spring! - </td><td width="50%">&nbsp; </td></tr> - </table></body></html> - - - - - ----- - -Here you can see that the `JasperReportsHtmlView` is configured with an exporter -parameter for `net.sf.jasperreports.engine.export.JRHtmlExporterParameter.HTML_FOOTER` -which will output a footer in the resulting HTML. - - - - -[[view-feeds]] -=== Feed Views -Both `AbstractAtomFeedView` and `AbstractRssFeedView` inherit from the base class -`AbstractFeedView` and are used to provide Atom and RSS Feed views respectfully. They -are based on java.net's https://rome.dev.java.net[ROME] project and are located in the -package `org.springframework.web.servlet.view.feed`. - -`AbstractAtomFeedView` requires you to implement the `buildFeedEntries()` method and -optionally override the `buildFeedMetadata()` method (the default implementation is -empty), as shown below. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class SampleContentAtomView extends AbstractAtomFeedView { - - @Override - protected void buildFeedMetadata(Map model, - Feed feed, HttpServletRequest request) { - // implementation omitted - } - - @Override - protected List buildFeedEntries(Map model, - HttpServletRequest request, HttpServletResponse response) throws Exception { - // implementation omitted - } - - } ----- - -Similar requirements apply for implementing `AbstractRssFeedView`, as shown below. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class SampleContentAtomView extends AbstractRssFeedView { - - @Override - protected void buildFeedMetadata(Map model, - Channel feed, HttpServletRequest request) { - // implementation omitted - } - - @Override - protected List buildFeedItems(Map model, - HttpServletRequest request, HttpServletResponse response) throws Exception { - // implementation omitted - } - - } ----- - -The `buildFeedItems()` and `buildFeedEntires()` methods pass in the HTTP request in case -you need to access the Locale. The HTTP response is passed in only for the setting of -cookies or other HTTP headers. The feed will automatically be written to the response -object after the method returns. - -For an example of creating an Atom view please refer to Alef Arendsen's Spring Team Blog -https://spring.io/blog/2009/03/16/adding-an-atom-view-to-an-application-using-spring-s-rest-support[entry]. - - - - -[[view-xml-marshalling]] -=== XML Marshalling View -The `MarshallingView` uses an XML `Marshaller` defined in the `org.springframework.oxm` -package to render the response content as XML. The object to be marshalled can be set -explicitly using `MarhsallingView`'s `modelKey` bean property. Alternatively, the view -will iterate over all model properties and marshal the first type that is supported -by the `Marshaller`. For more information on the functionality in the -`org.springframework.oxm` package refer to the chapter <>. - - - - -[[view-json-mapping]] -=== JSON Mapping View -The `MappingJackson2JsonView` uses the Jackson library's `ObjectMapper` to render the response -content as JSON. By default, the entire contents of the model map (with the exception of -framework-specific classes) will be encoded as JSON. For cases where the contents of the -map need to be filtered, users may specify a specific set of model attributes to encode -via the `RenderedAttributes` property. The `extractValueFromSingleKeyModel` property may -also be used to have the value in single-key models extracted and serialized directly -rather than as a map of model attributes. - -JSON mapping can be customized as needed through the use of Jackson's provided -annotations. When further control is needed, a custom `ObjectMapper` can be injected -through the `ObjectMapper` property for cases where custom JSON -serializers/deserializers need to be provided for specific types. - - - - -[[view-xml-mapping]] -=== XML Mapping View -The `MappingJackson2XmlView` uses the -https://github.com/FasterXML/jackson-dataformat-xml[Jackson XML extension]'s `XmlMapper` -to render the response content as XML. If the model contains multiples entries, the -object to be serialized should be set explicitly using `MappingJackson2XmlView`'s -`modelKey` bean property. If the model contains a single entry, it will be serialized -automatically. - -XML mapping can be customized as needed through the use of JAXB or Jackson's provided -annotations. When further control is needed, a custom `XmlMapper` can be injected -through the `ObjectMapper` property for cases where custom XML -serializers/deserializers need to be provided for specific types. - - - - - -[[web-integration]] -== Integrating with other web frameworks - - - - -[[intro]] -=== Introduction - -.Spring Web Flow -**** -Spring Web Flow (SWF) aims to be the best solution for the management of web application -page flow. - -SWF integrates with existing frameworks like Spring MVC and JSF, in both Servlet and -Portlet environments. If you have a business process (or processes) that would benefit -from a conversational model as opposed to a purely request model, then SWF may be the -solution. - -SWF allows you to capture logical page flows as self-contained modules that are reusable -in different situations, and as such is ideal for building web application modules that -guide the user through controlled navigations that drive business processes. - -For more information about SWF, consult the -http://projects.spring.io/spring-webflow/[Spring Web Flow website]. -**** - -This chapter details Spring's integration with third party web frameworks, such as -http://www.oracle.com/technetwork/java/javaee/javaserverfaces-139869.html[JSF]. - -One of the core value propositions of the Spring Framework is that of enabling -__choice__. In a general sense, Spring does not force one to use or buy into any -particular architecture, technology, or methodology (although it certainly recommends -some over others). This freedom to pick and choose the architecture, technology, or -methodology that is most relevant to a developer and their development team is -arguably most evident in the web area, where Spring provides its own web framework -(<>), while at the same time providing integration with a number of -popular third party web frameworks. This allows one to continue to leverage any and all -of the skills one may have acquired in a particular web framework such as JSF, while -at the same time being able to enjoy the benefits afforded by Spring in other areas such -as data access, declarative transaction management, and flexible configuration and -application assembly. - -Having dispensed with the woolly sales patter (c.f. the previous paragraph), the -remainder of this chapter will concentrate upon the meaty details of integrating your -favorite web framework with Spring. One thing that is often commented upon by developers -coming to Java from other languages is the seeming super-abundance of web frameworks -available in Java. There are indeed a great number of web frameworks in the Java space; -in fact there are far too many to cover with any semblance of detail in a single -chapter. This chapter thus picks four of the more popular web frameworks in Java, -starting with the Spring configuration that is common to all of the supported web -frameworks, and then detailing the specific integration options for each supported web -framework. - -[NOTE] -==== -Please note that this chapter does not attempt to explain how to use any of the -supported web frameworks. For example, if you want to use JSF for the presentation -layer of your web application, the assumption is that you are already familiar with -JSF itself. If you need further details about any of the supported web frameworks -themselves, please do consult <> at the end of this chapter. -==== - - - - -[[web-integration-common]] -=== Common configuration -Before diving into the integration specifics of each supported web framework, let us -first take a look at the Spring configuration that is __not__ specific to any one web -framework. (This section is equally applicable to Spring's own web framework, Spring -MVC.) - -One of the concepts (for want of a better word) espoused by (Spring's) lightweight -application model is that of a layered architecture. Remember that in a 'classic' -layered architecture, the web layer is but one of many layers; it serves as one of the -entry points into a server side application and it delegates to service objects -(facades) defined in a service layer to satisfy business specific (and -presentation-technology agnostic) use cases. In Spring, these service objects, any other -business-specific objects, data access objects, etc. exist in a distinct 'business -context', which contains __no__ web or presentation layer objects (presentation objects -such as Spring MVC controllers are typically configured in a distinct 'presentation -context'). This section details how one configures a Spring container (a -`WebApplicationContext`) that contains all of the 'business beans' in one's application. - -On to specifics: all that one need do is to declare a -{javadoc-baseurl}/org/springframework/web/context/ContextLoaderListener.html[`ContextLoaderListener`] -in the standard Java EE servlet `web.xml` file of one's web application, and add a -`contextConfigLocation` section (in the same file) that defines which -set of Spring XML configuration files to load. - -Find below the configuration: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - org.springframework.web.context.ContextLoaderListener - ----- - -Find below the configuration: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - contextConfigLocation - /WEB-INF/applicationContext*.xml - ----- - -If you don't specify the `contextConfigLocation` context parameter, the -`ContextLoaderListener` will look for a file called `/WEB-INF/applicationContext.xml` to -load. Once the context files are loaded, Spring creates a -{javadoc-baseurl}/org/springframework/web/context/WebApplicationContext.html[`WebApplicationContext`] -object based on the bean definitions and stores it in the `ServletContext` of the web -application. - -All Java web frameworks are built on top of the Servlet API, and so one can use the -following code snippet to get access to this 'business context' `ApplicationContext` -created by the `ContextLoaderListener`. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - WebApplicationContext ctx = WebApplicationContextUtils.getWebApplicationContext(servletContext); ----- - -The -{javadoc-baseurl}/org/springframework/web/context/support/WebApplicationContextUtils.html[`WebApplicationContextUtils`] -class is for convenience, so you don't have to remember the name of the `ServletContext` -attribute. Its __getWebApplicationContext()__ method will return `null` if an object -doesn't exist under the `WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE` -key. Rather than risk getting `NullPointerExceptions` in your application, it's better -to use the `getRequiredWebApplicationContext()` method. This method throws an exception -when the `ApplicationContext` is missing. - -Once you have a reference to the `WebApplicationContext`, you can retrieve beans by -their name or type. Most developers retrieve beans by name and then cast them to one of -their implemented interfaces. - -Fortunately, most of the frameworks in this section have simpler ways of looking up -beans. Not only do they make it easy to get beans from a Spring container, but they also -allow you to use dependency injection on their controllers. Each web framework section -has more detail on its specific integration strategies. - - - - -[[jsf]] -=== JavaServer Faces 1.2 -JavaServer Faces (JSF) is the JCP's standard component-based, event-driven web user -interface framework. As of Java EE 5, it is an official part of the Java EE umbrella. - -For a popular JSF runtime as well as for popular JSF component libraries, check out the -http://myfaces.apache.org/[Apache MyFaces project]. The MyFaces project also provides -common JSF extensions such as http://myfaces.apache.org/orchestra/[MyFaces Orchestra]: -a Spring-based JSF extension that provides rich conversation scope support. - -[NOTE] -==== -Spring Web Flow 2.0 provides rich JSF support through its newly established Spring Faces -module, both for JSF-centric usage (as described in this section) and for Spring-centric -usage (using JSF views within a Spring MVC dispatcher). Check out the -http://projects.spring.io/spring-webflow[Spring Web Flow website] for details! -==== - -The key element in Spring's JSF integration is the JSF `ELResolver` mechanism. - -[[jsf-springbeanfaceselresolver]] -==== SpringBeanFacesELResolver (JSF 1.2+) -`SpringBeanFacesELResolver` is a JSF 1.2 compliant `ELResolver` implementation, -integrating with the standard Unified EL as used by JSF 1.2 and JSP 2.1. Like -`SpringBeanVariableResolver`, it delegates to the Spring's 'business context' -`WebApplicationContext` __first__, then to the default resolver of the underlying JSF -implementation. - -Configuration-wise, simply define `SpringBeanFacesELResolver` in your JSF 1.2 -__faces-context.xml__ file: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - org.springframework.web.jsf.el.SpringBeanFacesELResolver - ... - - ----- - - -[[jsf-facescontextutils]] -==== FacesContextUtils -A custom `VariableResolver` works well when mapping one's properties to beans -in __faces-config.xml__, but at times one may need to grab a bean explicitly. The -{javadoc-baseurl}/org/springframework/web/jsf/FacesContextUtils.html[`FacesContextUtils`] -class makes this easy. It is similar to `WebApplicationContextUtils`, except that it -takes a `FacesContext` parameter rather than a `ServletContext` parameter. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - ApplicationContext ctx = FacesContextUtils.getWebApplicationContext(FacesContext.getCurrentInstance()); ----- - - - -[[struts]] -=== Apache Struts 2.x -Invented by Craig McClanahan, http://struts.apache.org[Struts] is an open source project -hosted by the Apache Software Foundation. At the time, it greatly simplified the -JSP/Servlet programming paradigm and won over many developers who were using proprietary -frameworks. It simplified the programming model, it was open source (and thus free as in -beer), and it had a large community, which allowed the project to grow and become popular -among Java web developers. - -Check out the Struts -https://struts.apache.org/release/2.3.x/docs/spring-plugin.html[Spring Plugin] for the -built-in Spring integration shipped with Struts. - - - -[[tapestry]] -=== Tapestry 5.x -From the http://tapestry.apache.org/[Tapestry homepage]: - -Tapestry is a "__Component oriented framework for creating dynamic, robust, -highly scalable web applications in Java.__" - -While Spring has its own <>, there are a number of unique -advantages to building an enterprise Java application using a combination of Tapestry -for the web user interface and the Spring container for the lower layers. - -For more information, check out Tapestry's dedicated -https://tapestry.apache.org/integrating-with-spring-framework.html[integration module for -Spring]. - - - -[[web-integration-resources]] -=== Further Resources -Find below links to further resources about the various web frameworks described in this -chapter. - -* The http://www.oracle.com/technetwork/java/javaee/javaserverfaces-139869.html[JSF] homepage -* The http://struts.apache.org/[Struts] homepage -* The http://tapestry.apache.org/[Tapestry] homepage - - - - - -[[portlet]] -== Portlet MVC Framework - - - - -[[portlet-introduction]] -=== Introduction - -.JSR-168 The Java Portlet Specification -**** -For more general information about portlet development, please review a whitepaper from -Oracle entitled -http://www.oracle.com/technetwork/java/index-raji-test-141933.html["Introduction -to JSR 168"], and of course the -http://jcp.org/aboutJava/communityprocess/final/jsr168/[JSR-168 Specification] itself. -**** - -In addition to supporting conventional (servlet-based) Web development, Spring also -supports JSR-168 Portlet development. As much as possible, the Portlet MVC framework is -a mirror image of the Web MVC framework, and also uses the same underlying view -abstractions and integration technology. So, be sure to review the chapters entitled -<> and <> before continuing with this chapter. - -[NOTE] -==== -Bear in mind that while the concepts of Spring MVC are the same in Spring Portlet MVC, -there are some notable differences created by the unique workflow of JSR-168 portlets. -==== - -The main way in which portlet workflow differs from servlet workflow is that the request -to the portlet can have two distinct phases: the action phase and the render phase. The -action phase is executed only once and is where any 'backend' changes or actions occur, -such as making changes in a database. The render phase then produces what is displayed -to the user each time the display is refreshed. The critical point here is that for a -single overall request, the action phase is executed only once, but the render phase may -be executed multiple times. This provides (and requires) a clean separation between the -activities that modify the persistent state of your system and the activities that -generate what is displayed to the user. - -.Spring Web Flow -**** -Spring Web Flow (SWF) aims to be the best solution for the management of web application -page flow. - -SWF integrates with existing frameworks like Spring MVC and JSF, in both Servlet and -Portlet environments. If you have a business process (or processes) that would benefit -from a conversational model as opposed to a purely request model, then SWF may be the -solution. - -SWF allows you to capture logical page flows as self-contained modules that are reusable -in different situations, and as such is ideal for building web application modules that -guide the user through controlled navigations that drive business processes. - -For more information about SWF, consult the Spring Web Flow website. -**** - -The dual phases of portlet requests are one of the real strengths of the JSR-168 -specification. For example, dynamic search results can be updated routinely on the -display without the user explicitly rerunning the search. Most other portlet MVC -frameworks attempt to completely hide the two phases from the developer and make it look -as much like traditional servlet development as possible - we think this approach -removes one of the main benefits of using portlets. So, the separation of the two phases -is preserved throughout the Spring Portlet MVC framework. The primary manifestation of -this approach is that where the servlet version of the MVC classes will have one method -that deals with the request, the portlet version of the MVC classes will have two -methods that deal with the request: one for the action phase and one for the render -phase. For example, where the servlet version of `AbstractController` has the -`handleRequestInternal(..)` method, the portlet version of `AbstractController` has -`handleActionRequestInternal(..)` and `handleRenderRequestInternal(..)` methods. - -The framework is designed around a `DispatcherPortlet` that dispatches requests to -handlers, with configurable handler mappings and view resolution, just as the -`DispatcherServlet` in the web framework does. File upload is also supported in the same -way. - -Locale resolution and theme resolution are not supported in Portlet MVC - these areas -are in the purview of the portal/portlet container and are not appropriate at the Spring -level. However, all mechanisms in Spring that depend on the locale (such as -internationalization of messages) will still function properly because -`DispatcherPortlet` exposes the current locale in the same way as `DispatcherServlet`. - - - -[[portlet-introduction-controller]] -==== Controllers - The C in MVC -The default handler is still a very simple `Controller` interface, offering just two -methods: - -* `void handleActionRequest(request,response)` -* `ModelAndView handleRenderRequest(request,response)` - -The framework also includes most of the same controller implementation hierarchy, such -as `AbstractController`, `SimpleFormController`, and so on. Data binding, command object -usage, model handling, and view resolution are all the same as in the servlet framework. - - - -[[portlet-introduction-view]] -==== Views - The V in MVC -All the view rendering capabilities of the servlet framework are used directly via a -special bridge servlet named `ViewRendererServlet`. By using this servlet, the portlet -request is converted into a servlet request and the view can be rendered using the -entire normal servlet infrastructure. This means all the existing renderers, such as -JSP, Velocity, etc., can still be used within the portlet. - - - -[[portlet-introduction-scope]] -==== Web-scoped beans -Spring Portlet MVC supports beans whose lifecycle is scoped to the current HTTP request -or HTTP `Session` (both normal and global). This is not a specific feature of Spring -Portlet MVC itself, but rather of the `WebApplicationContext` container(s) that Spring -Portlet MVC uses. These bean scopes are described in detail in -<> - - - - -[[portlet-dispatcher]] -=== The DispatcherPortlet - -Portlet MVC is a request-driven web MVC framework, designed around a portlet that -dispatches requests to controllers and offers other functionality facilitating the -development of portlet applications. Spring's `DispatcherPortlet` however, does more -than just that. It is completely integrated with the Spring `ApplicationContext` and -allows you to use every other feature Spring has. - -Like ordinary portlets, the `DispatcherPortlet` is declared in the `portlet.xml` file of -your web application: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - sample - org.springframework.web.portlet.DispatcherPortlet - - text/html - view - - - Sample Portlet - - ----- - -The `DispatcherPortlet` now needs to be configured. - -In the Portlet MVC framework, each `DispatcherPortlet` has its own -`WebApplicationContext`, which inherits all the beans already defined in the Root -`WebApplicationContext`. These inherited beans can be overridden in the portlet-specific -scope, and new scope-specific beans can be defined local to a given portlet instance. - -The framework will, on initialization of a `DispatcherPortlet`, look for a file named -`[portlet-name]-portlet.xml` in the `WEB-INF` directory of your web application and -create the beans defined there (overriding the definitions of any beans defined with the -same name in the global scope). - -The config location used by the `DispatcherPortlet` can be modified through a portlet -initialization parameter (see below for details). - -The Spring `DispatcherPortlet` has a few special beans it uses, in order to be able to -process requests and render the appropriate views. These beans are included in the -Spring framework and can be configured in the `WebApplicationContext`, just as any other -bean would be configured. Each of those beans is described in more detail below. Right -now, we'll just mention them, just to let you know they exist and to enable us to go on -talking about the `DispatcherPortlet`. For most of the beans, defaults are provided so -you don't have to worry about configuring them. - -[[portlet-webappctx-special-beans-tbl]] -.Special beans in the WebApplicationContext -[cols="1,4"] -|=== -| Expression| Explanation - -| handler mapping(s) -| (<>) a list of pre- and post-processors and controllers that - will be executed if they match certain criteria (for instance a matching portlet mode - specified with the controller) - -| controller(s) -| (<>) the beans providing the actual functionality (or at least, - access to the functionality) as part of the MVC triad - -| view resolver -| (<>) capable of resolving view names to view definitions - -| multipart resolver -| (<>) offers functionality to process file uploads from HTML forms - -| handler exception resolver -| (<>) offers functionality to map exceptions to views or - implement other more complex exception handling code -|=== - -When a `DispatcherPortlet` is setup for use and a request comes in for that specific -`DispatcherPortlet`, it starts processing the request. The list below describes the -complete process a request goes through if handled by a `DispatcherPortlet`: - -. The locale returned by `PortletRequest.getLocale()` is bound to the request to let -elements in the process resolve the locale to use when processing the request (rendering -the view, preparing data, etc.). -. If a multipart resolver is specified and this is an `ActionRequest`, the request is -inspected for multiparts and if they are found, it is wrapped in a -`MultipartActionRequest` for further processing by other elements in the process. (See -<> for further information about multipart handling). -. An appropriate handler is searched for. If a handler is found, the execution chain -associated with the handler (pre-processors, post-processors, controllers) will be -executed in order to prepare a model. -. If a model is returned, the view is rendered, using the view resolver that has been -configured with the `WebApplicationContext`. If no model is returned (which could be due -to a pre- or post-processor intercepting the request, for example, for security -reasons), no view is rendered, since the request could already have been fulfilled. - -Exceptions that are thrown during processing of the request get picked up by any of the -handler exception resolvers that are declared in the `WebApplicationContext`. Using -these exception resolvers you can define custom behavior in case such exceptions get -thrown. - -You can customize Spring's `DispatcherPortlet` by adding context parameters in the -`portlet.xml` file or portlet init-parameters. The possibilities are listed below. - -[[portlet-dpp-init-params]] -.DispatcherPortlet initialization parameters -[cols="1,4"] -|=== -| Parameter| Explanation - -| `contextClass` -| Class that implements `WebApplicationContext`, which will be used to instantiate the - context used by this portlet. If this parameter isn't specified, the - `XmlPortletApplicationContext` will be used. - -| `contextConfigLocation` -| String which is passed to the context instance (specified by `contextClass`) to - indicate where context(s) can be found. The String is potentially split up into - multiple Strings (using a comma as a delimiter) to support multiple contexts (in case - of multiple context locations, for beans that are defined twice, the latest takes - precedence). - -| `namespace` -| The namespace of the `WebApplicationContext`. Defaults to `[portlet-name]-portlet`. - -| `viewRendererUrl` -| The URL at which `DispatcherPortlet` can access an instance of `ViewRendererServlet` - (see <>). -|=== - - - - -[[portlet-viewservlet]] -=== The ViewRendererServlet - -The rendering process in Portlet MVC is a bit more complex than in Web MVC. In order to -reuse all the <> from Spring Web MVC, we must convert the -`PortletRequest` / `PortletResponse` to `HttpServletRequest` / `HttpServletResponse` and -then call the `render` method of the `View`. To do this, `DispatcherPortlet` uses a -special servlet that exists for just this purpose: the `ViewRendererServlet`. - -In order for `DispatcherPortlet` rendering to work, you must declare an instance of the -`ViewRendererServlet` in the `web.xml` file for your web application as follows: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - ViewRendererServlet - org.springframework.web.servlet.ViewRendererServlet - - - - ViewRendererServlet - /WEB-INF/servlet/view - ----- - -To perform the actual rendering, `DispatcherPortlet` does the following: - -. Binds the `WebApplicationContext` to the request as an attribute under the same -`WEB_APPLICATION_CONTEXT_ATTRIBUTE` key that `DispatcherServlet` uses. -. Binds the `Model` and `View` objects to the request to make them available to the -`ViewRendererServlet`. -. Constructs a `PortletRequestDispatcher` and performs an `include` using the `/WEB- -INF/servlet/view` URL that is mapped to the `ViewRendererServlet`. - -The `ViewRendererServlet` is then able to call the `render` method on the `View` with -the appropriate arguments. - -The actual URL for the `ViewRendererServlet` can be changed using `DispatcherPortlet`'s -`viewRendererUrl` configuration parameter. - - - - -[[portlet-controller]] -=== Controllers -The controllers in Portlet MVC are very similar to the Web MVC Controllers, and porting -code from one to the other should be simple. - -The basis for the Portlet MVC controller architecture is the -`org.springframework.web.portlet.mvc.Controller` interface, which is listed below. - -[source,java,indent=0] ----- - public interface Controller { - - /** - * Process the render request and return a ModelAndView object which the - * DispatcherPortlet will render. - */ - ModelAndView handleRenderRequest(RenderRequest request, - RenderResponse response) throws Exception; - - /** - * Process the action request. There is nothing to return. - */ - void handleActionRequest(ActionRequest request, - ActionResponse response) throws Exception; - - } ----- - -As you can see, the Portlet `Controller` interface requires two methods that handle the -two phases of a portlet request: the action request and the render request. The action -phase should be capable of handling an action request, and the render phase should be -capable of handling a render request and returning an appropriate model and view. While -the `Controller` interface is quite abstract, Spring Portlet MVC offers several -controllers that already contain a lot of the functionality you might need; most of -these are very similar to controllers from Spring Web MVC. The `Controller` interface -just defines the most common functionality required of every controller: handling an -action request, handling a render request, and returning a model and a view. - - - -[[portlet-controller-abstractcontroller]] -==== AbstractController and PortletContentGenerator - -Of course, just a `Controller` interface isn't enough. To provide a basic -infrastructure, all of Spring Portlet MVC's ++Controller++s inherit from -`AbstractController`, a class offering access to Spring's `ApplicationContext` and -control over caching. - -[[portlet-ac-features]] -.Features offered by the AbstractController -[cols="1,4"] -|=== -| Parameter| Explanation - -| `requireSession` -| Indicates whether or not this `Controller` requires a session to do its work. This - feature is offered to all controllers. If a session is not present when such a - controller receives a request, the user is informed using a `SessionRequiredException`. - -| `synchronizeSession` -| Use this if you want handling by this controller to be synchronized on the user's - session. To be more specific, the extending controller will override the - `handleRenderRequestInternal(..)` and `handleActionRequestInternal(..)` methods, which - will be synchronized on the user's session if you specify this variable. - -| `renderWhenMinimized` -| If you want your controller to actually render the view when the portlet is in a - minimized state, set this to true. By default, this is set to false so that portlets - that are in a minimized state don't display any content. - -| `cacheSeconds` -| When you want a controller to override the default cache expiration defined for the - portlet, specify a positive integer here. By default it is set to `-1`, which does not - change the default caching. Setting it to `0` will ensure the result is never cached. -|=== - -The `requireSession` and `cacheSeconds` properties are declared on the -`PortletContentGenerator` class, which is the superclass of `AbstractController`) but -are included here for completeness. - -When using the `AbstractController` as a base class for your controllers (which is not -recommended since there are a lot of other controllers that might already do the job for -you) you only have to override either the `handleActionRequestInternal(ActionRequest, -ActionResponse)` method or the `handleRenderRequestInternal(RenderRequest, -RenderResponse)` method (or both), implement your logic, and return a `ModelAndView` -object (in the case of `handleRenderRequestInternal`). - -The default implementations of both `handleActionRequestInternal(..)` and -`handleRenderRequestInternal(..)` throw a `PortletException`. This is consistent with -the behavior of `GenericPortlet` from the JSR- 168 Specification API. So you only need -to override the method that your controller is intended to handle. - -Here is short example consisting of a class and a declaration in the web application -context. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - package samples; - - import javax.portlet.RenderRequest; - import javax.portlet.RenderResponse; - - import org.springframework.web.portlet.mvc.AbstractController; - import org.springframework.web.portlet.ModelAndView; - - public class SampleController extends AbstractController { - - public ModelAndView handleRenderRequestInternal(RenderRequest request, RenderResponse response) { - ModelAndView mav = new ModelAndView("foo"); - mav.addObject("message", "Hello World!"); - return mav; - } - - } ----- - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - ----- - -The class above and the declaration in the web application context is all you need -besides setting up a handler mapping (see <>) to get this very -simple controller working. - - - -[[portlet-controller-simple]] -==== Other simple controllers -Although you can extend `AbstractController`, Spring Portlet MVC provides a number of -concrete implementations which offer functionality that is commonly used in simple MVC -applications. - -The `ParameterizableViewController` is basically the same as the example above, except -for the fact that you can specify the view name that it will return in the web -application context (no need to hard-code the view name). - -The `PortletModeNameViewController` uses the current mode of the portlet as the view -name. So, if your portlet is in View mode (i.e. `PortletMode.VIEW`) then it uses "view" -as the view name. - - - -[[portlet-controller-command]] -==== Command Controllers -Spring Portlet MVC has the exact same hierarchy of __command controllers__ as Spring Web -MVC. They provide a way to interact with data objects and dynamically bind parameters -from the `PortletRequest` to the data object specified. Your data objects don't have to -implement a framework-specific interface, so you can directly manipulate your persistent -objects if you desire. Let's examine what command controllers are available, to get an -overview of what you can do with them: - -* `AbstractCommandController` - a command controller you can use to create your own - command controller, capable of binding request parameters to a data object you - specify. This class does not offer form functionality, it does however offer - validation features and lets you specify in the controller itself what to do with the - command object that has been filled with the parameters from the request. -* `AbstractFormController` - an abstract controller offering form submission support. - Using this controller you can model forms and populate them using a command object you - retrieve in the controller. After a user has filled the form, `AbstractFormController` - binds the fields, validates, and hands the object back to the controller to take - appropriate action. Supported features are: invalid form submission (resubmission), - validation, and normal form workflow. You implement methods to determine which views - are used for form presentation and success. Use this controller if you need forms, but - don't want to specify what views you're going to show the user in the application - context. -* `SimpleFormController` - a concrete `AbstractFormController` that provides even more - support when creating a form with a corresponding command object. The - `SimpleFormController` lets you specify a command object, a viewname for the form, a - viewname for the page you want to show the user when form submission has succeeded, - and more. -* `AbstractWizardFormController` -- a concrete `AbstractFormController` that provides a - wizard-style interface for editing the contents of a command object across multiple - display pages. Supports multiple user actions: finish, cancel, or page change, all of - which are easily specified in request parameters from the view. - -These command controllers are quite powerful, but they do require a detailed -understanding of how they operate in order to use them efficiently. Carefully review the -javadocs for this entire hierarchy and then look at some sample implementations before -you start using them. - - - -[[portlet-controller-wrapping]] -==== PortletWrappingController - -Instead of developing new controllers, it is possible to use existing portlets and map -requests to them from a `DispatcherPortlet`. Using the `PortletWrappingController`, you -can instantiate an existing `Portlet` as a `Controller` as follows: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - config=/WEB-INF/my-portlet-config.xml - - ----- - -This can be very valuable since you can then use interceptors to pre-process and -post-process requests going to these portlets. Since JSR-168 does not support any kind -of filter mechanism, this is quite handy. For example, this can be used to wrap the -Hibernate `OpenSessionInViewInterceptor` around a MyFaces JSF Portlet. - - - - -[[portlet-handlermapping]] -=== Handler mappings -Using a handler mapping you can map incoming portlet requests to appropriate handlers. -There are some handler mappings you can use out of the box, for example, the -`PortletModeHandlerMapping`, but let's first examine the general concept of a -`HandlerMapping`. - -Note: We are intentionally using the term "Handler" here instead of "Controller". -`DispatcherPortlet` is designed to be used with other ways to process requests than just -Spring Portlet MVC's own Controllers. A Handler is any Object that can handle portlet -requests. Controllers are an example of Handlers, and they are of course the default. To -use some other framework with `DispatcherPortlet`, a corresponding implementation of -`HandlerAdapter` is all that is needed. - -The functionality a basic `HandlerMapping` provides is the delivering of a -`HandlerExecutionChain`, which must contain the handler that matches the incoming -request, and may also contain a list of handler interceptors that are applied to the -request. When a request comes in, the `DispatcherPortlet` will hand it over to the -handler mapping to let it inspect the request and come up with an appropriate -`HandlerExecutionChain`. Then the `DispatcherPortlet` will execute the handler and -interceptors in the chain (if any). These concepts are all exactly the same as in Spring -Web MVC. - -The concept of configurable handler mappings that can optionally contain interceptors -(executed before or after the actual handler was executed, or both) is extremely -powerful. A lot of supporting functionality can be built into a custom `HandlerMapping`. -Think of a custom handler mapping that chooses a handler not only based on the portlet -mode of the request coming in, but also on a specific state of the session associated -with the request. - -In Spring Web MVC, handler mappings are commonly based on URLs. Since there is really no -such thing as a URL within a Portlet, we must use other mechanisms to control mappings. -The two most common are the portlet mode and a request parameter, but anything available -to the portlet request can be used in a custom handler mapping. - -The rest of this section describes three of Spring Portlet MVC's most commonly used -handler mappings. They all extend `AbstractHandlerMapping` and share the following -properties: - -* `interceptors`: The list of interceptors to use. ++HandlerInterceptor++s are discussed - in <>. -* `defaultHandler`: The default handler to use, when this handler mapping does not - result in a matching handler. -* `order`: Based on the value of the order property (see the - `org.springframework.core.Ordered` interface), Spring will sort all handler mappings - available in the context and apply the first matching handler. -* `lazyInitHandlers`: Allows for lazy initialization of singleton handlers (prototype - handlers are always lazily initialized). Default value is false. This property is - directly implemented in the three concrete Handlers. - - - -[[portlet-handlermapping-portletmode]] -==== PortletModeHandlerMapping - -This is a simple handler mapping that maps incoming requests based on the current mode -of the portlet (e.g. 'view', 'edit', 'help'). An example: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - - ----- - - - -[[portlet-handlermapping-parameter]] -==== ParameterHandlerMapping - -If we need to navigate around to multiple controllers without changing portlet mode, the -simplest way to do this is with a request parameter that is used as the key to control -the mapping. - -`ParameterHandlerMapping` uses the value of a specific request parameter to control the -mapping. The default name of the parameter is `'action'`, but can be changed using the -`'parameterName'` property. - -The bean configuration for this mapping will look something like this: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - - ----- - - - -[[portlet-handlermapping-portletmodeparameter]] -==== PortletModeParameterHandlerMapping - -The most powerful built-in handler mapping, `PortletModeParameterHandlerMapping` -combines the capabilities of the two previous ones to allow different navigation within -each portlet mode. - -Again the default name of the parameter is "action", but can be changed using the -`parameterName` property. - -By default, the same parameter value may not be used in two different portlet modes. -This is so that if the portal itself changes the portlet mode, the request will no -longer be valid in the mapping. This behavior can be changed by setting the -`allowDupParameters` property to true. However, this is not recommended. - -The bean configuration for this mapping will look something like this: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - - - - - - - - - - - - ----- - -This mapping can be chained ahead of a `PortletModeHandlerMapping`, which can then -provide defaults for each mode and an overall default as well. - - - -[[portlet-handlermapping-interceptor]] -==== Adding HandlerInterceptors - -Spring's handler mapping mechanism has a notion of handler interceptors, which can be -extremely useful when you want to apply specific functionality to certain requests, for -example, checking for a principal. Again Spring Portlet MVC implements these concepts in -the same way as Web MVC. - -Interceptors located in the handler mapping must implement `HandlerInterceptor` from the -`org.springframework.web.portlet` package. Just like the servlet version, this interface -defines three methods: one that will be called before the actual handler will be -executed ( `preHandle`), one that will be called after the handler is executed ( -`postHandle`), and one that is called after the complete request has finished ( -`afterCompletion`). These three methods should provide enough flexibility to do all -kinds of pre- and post- processing. - -The `preHandle` method returns a boolean value. You can use this method to break or -continue the processing of the execution chain. When this method returns `true`, the -handler execution chain will continue. When it returns `false`, the `DispatcherPortlet` -assumes the interceptor itself has taken care of requests (and, for example, rendered an -appropriate view) and does not continue executing the other interceptors and the actual -handler in the execution chain. - -The `postHandle` method is only called on a `RenderRequest`. The `preHandle` and -`afterCompletion` methods are called on both an `ActionRequest` and a `RenderRequest`. -If you need to execute logic in these methods for just one type of request, be sure to -check what kind of request it is before processing it. - - - -[[portlet-handlermapping-interceptoradapter]] -==== HandlerInterceptorAdapter - -As with the servlet package, the portlet package has a concrete implementation of -`HandlerInterceptor` called `HandlerInterceptorAdapter`. This class has empty versions -of all the methods so that you can inherit from this class and implement just one or two -methods when that is all you need. - - - -[[portlet-handlermapping-parameterinterceptor]] -==== ParameterMappingInterceptor - -The portlet package also has a concrete interceptor named `ParameterMappingInterceptor` -that is meant to be used directly with `ParameterHandlerMapping` and -`PortletModeParameterHandlerMapping`. This interceptor will cause the parameter that is -being used to control the mapping to be forwarded from an `ActionRequest` to the -subsequent `RenderRequest`. This will help ensure that the `RenderRequest` is mapped to -the same Handler as the `ActionRequest`. This is done in the `preHandle` method of the -interceptor, so you can still modify the parameter value in your handler to change where -the `RenderRequest` will be mapped. - -Be aware that this interceptor is calling `setRenderParameter` on the `ActionResponse`, -which means that you cannot call `sendRedirect` in your handler when using this -interceptor. If you need to do external redirects then you will either need to forward -the mapping parameter manually or write a different interceptor to handle this for you. - - - - -[[portlet-viewresolver]] -=== Views and resolving them -As mentioned previously, Spring Portlet MVC directly reuses all the view technologies -from Spring Web MVC. This includes not only the various `View` implementations -themselves, but also the `ViewResolver` implementations. For more information, refer to -<> and <> respectively. - -A few items on using the existing `View` and `ViewResolver` implementations are worth -mentioning: - -* Most portals expect the result of rendering a portlet to be an HTML fragment. So, - things like JSP/JSTL, Velocity, FreeMarker, and XSLT all make sense. But it is - unlikely that views that return other document types will make any sense in a portlet - context. -* There is no such thing as an HTTP redirect from within a portlet (the - `sendRedirect(..)` method of `ActionResponse` cannot be used to stay within the - portal). So, `RedirectView` and use of the `'redirect:'` prefix will __not__ work - correctly from within Portlet MVC. -* It may be possible to use the `'forward:'` prefix from within Portlet MVC. However, - remember that since you are in a portlet, you have no idea what the current URL looks - like. This means you cannot use a relative URL to access other resources in your web - application and that you will have to use an absolute URL. - -Also, for JSP development, the new Spring Taglib and the new Spring Form Taglib both -work in portlet views in exactly the same way that they work in servlet views. - - - - -[[portlet-multipart]] -=== Multipart (file upload) support -Spring Portlet MVC has built-in multipart support to handle file uploads in portlet -applications, just like Web MVC does. The design for the multipart support is done with -pluggable `PortletMultipartResolver` objects, defined in the -`org.springframework.web.portlet.multipart` package. Spring provides a -`PortletMultipartResolver` for use with -http://jakarta.apache.org/commons/fileupload[Commons FileUpload]. How uploading files is -supported will be described in the rest of this section. - -By default, no multipart handling will be done by Spring Portlet MVC, as some developers -will want to handle multiparts themselves. You will have to enable it yourself by adding -a multipart resolver to the web application's context. After you have done that, -`DispatcherPortlet` will inspect each request to see if it contains a multipart. If no -multipart is found, the request will continue as expected. However, if a multipart is -found in the request, the `PortletMultipartResolver` that has been declared in your -context will be used. After that, the multipart attribute in your request will be -treated like any other attribute. - -[NOTE] -==== -Any configured `PortletMultipartResolver` bean __must__ have the following id (or name): -" `portletMultipartResolver`". If you have defined your `PortletMultipartResolver` with -any other name, then the `DispatcherPortlet` will __not__ find your -`PortletMultipartResolver`, and consequently no multipart support will be in effect. -==== - - - -[[portlet-multipart-resolver]] -==== Using the PortletMultipartResolver - -The following example shows how to use the `CommonsPortletMultipartResolver`: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - ----- - -Of course you also need to put the appropriate jars in your classpath for the multipart -resolver to work. In the case of the `CommonsMultipartResolver`, you need to use -`commons-fileupload.jar`. Be sure to use at least version 1.1 of Commons FileUpload as -previous versions do not support JSR-168 Portlet applications. - -Now that you have seen how to set Portlet MVC up to handle multipart requests, let's -talk about how to actually use it. When `DispatcherPortlet` detects a multipart request, -it activates the resolver that has been declared in your context and hands over the -request. What the resolver then does is wrap the current `ActionRequest` in a -`MultipartActionRequest` that has support for multipart file uploads. Using the -`MultipartActionRequest` you can get information about the multiparts contained by this -request and actually get access to the multipart files themselves in your controllers. - -Note that you can only receive multipart file uploads as part of an `ActionRequest`, not -as part of a `RenderRequest`. - - - -[[portlet-multipart-forms]] -==== Handling a file upload in a form -After the `PortletMultipartResolver` has finished doing its job, the request will be -processed like any other. To use the `PortletMultipartResolver`, create a form with an -upload field (see example below), then let Spring bind the file onto your form (backing -object). To actually let the user upload a file, we have to create a (JSP/HTML) form: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- -

Please upload a file

-
- - - ----- - -As you can see, we've created a field named "file" that matches the property of the bean -that holds the `byte[]` array. Furthermore we've added the encoding attribute ( -`enctype="multipart/form-data"`), which is necessary to let the browser know how to -encode the multipart fields (do not forget this!). - -Just as with any other property that's not automagically convertible to a string or -primitive type, to be able to put binary data in your objects you have to register a -custom editor with the `PortletRequestDataBinder`. There are a couple of editors -available for handling files and setting the results on an object. There's a -`StringMultipartFileEditor` capable of converting files to Strings (using a user-defined -character set), and there is a `ByteArrayMultipartFileEditor` which converts files to -byte arrays. They function analogous to the `CustomDateEditor`. - -So, to be able to upload files using a form, declare the resolver, a mapping to a -controller that will process the bean, and the controller itself. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - - - - - - - - ----- - -After that, create the controller and the actual class to hold the file property. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class FileUploadController extends SimpleFormController { - - public void onSubmitAction(ActionRequest request, ActionResponse response, - Object command, BindException errors) throws Exception { - - // cast the bean - FileUploadBean bean = (FileUploadBean) command; - - // let's see if there's content there - byte[] file = bean.getFile(); - if (file == null) { - // hmm, that's strange, the user did not upload anything - } - - // do something with the file here - } - - protected void initBinder(PortletRequest request, - PortletRequestDataBinder binder) throws Exception { - // to actually be able to convert Multipart instance to byte[] - // we have to register a custom editor - binder.registerCustomEditor(byte[].class, new ByteArrayMultipartFileEditor()); - // now Spring knows how to handle multipart object and convert - } - - } - - public class FileUploadBean { - - private byte[] file; - - public void setFile(byte[] file) { - this.file = file; - } - - public byte[] getFile() { - return file; - } - - } ----- - -As you can see, the `FileUploadBean` has a property of type `byte[]` that holds the -file. The controller registers a custom editor to let Spring know how to actually -convert the multipart objects the resolver has found to properties specified by the -bean. In this example, nothing is done with the `byte[]` property of the bean itself, -but in practice you can do whatever you want (save it in a database, mail it to -somebody, etc). - -An equivalent example in which a file is bound straight to a String-typed property on a -form backing object might look like this: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class FileUploadController extends SimpleFormController { - - public void onSubmitAction(ActionRequest request, ActionResponse response, - Object command, BindException errors) throws Exception { - - // cast the bean - FileUploadBean bean = (FileUploadBean) command; - - // let's see if there's content there - String file = bean.getFile(); - if (file == null) { - // hmm, that's strange, the user did not upload anything - } - - // do something with the file here - } - - protected void initBinder(PortletRequest request, - PortletRequestDataBinder binder) throws Exception { - - // to actually be able to convert Multipart instance to a String - // we have to register a custom editor - binder.registerCustomEditor(String.class, new StringMultipartFileEditor()); - // now Spring knows how to handle multipart objects and convert - } - } - - public class FileUploadBean { - - private String file; - - public void setFile(String file) { - this.file = file; - } - - public String getFile() { - return file; - } - } ----- - -Of course, this last example only makes (logical) sense in the context of uploading a -plain text file (it wouldn't work so well in the case of uploading an image file). - -The third (and final) option is where one binds directly to a `MultipartFile` property -declared on the (form backing) object's class. In this case one does not need to -register any custom property editor because there is no type conversion to be performed. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class FileUploadController extends SimpleFormController { - - public void onSubmitAction(ActionRequest request, ActionResponse response, - Object command, BindException errors) throws Exception { - - // cast the bean - FileUploadBean bean = (FileUploadBean) command; - - // let's see if there's content there - MultipartFile file = bean.getFile(); - if (file == null) { - // hmm, that's strange, the user did not upload anything - } - - // do something with the file here - } - } - - public class FileUploadBean { - - private MultipartFile file; - - public void setFile(MultipartFile file) { - this.file = file; - } - - public MultipartFile getFile() { - return file; - } - - } ----- - - - - -[[portlet-exceptionresolver]] -=== Handling exceptions -Just like Servlet MVC, Portlet MVC provides ++HandlerExceptionResolver++s to ease the -pain of unexpected exceptions that occur while your request is being processed by a -handler that matched the request. Portlet MVC also provides a portlet-specific, concrete -`SimpleMappingExceptionResolver` that enables you to take the class name of any -exception that might be thrown and map it to a view name. - - - - -[[portlet-annotation]] -=== Annotation-based controller configuration -Spring 2.5 introduced an annotation-based programming model for MVC controllers, using -annotations such as `@RequestMapping`, `@RequestParam`, `@ModelAttribute`, etc. This -annotation support is available for both Servlet MVC and Portlet MVC. Controllers -implemented in this style do not have to extend specific base classes or implement -specific interfaces. Furthermore, they do not usually have direct dependencies on -Servlet or Portlet API's, although they can easily get access to Servlet or Portlet -facilities if desired. - -The following sections document these annotations and how they are most commonly used in -a Portlet environment. - - - -[[portlet-ann-setup]] -==== Setting up the dispatcher for annotation support -__`@RequestMapping` will only be processed if a corresponding `HandlerMapping` (for -type level annotations) and/or `HandlerAdapter` (for method level annotations) is -present in the dispatcher.__ This is the case by default in both `DispatcherServlet` and -`DispatcherPortlet`. - -However, if you are defining custom `HandlerMappings` or `HandlerAdapters`, then you -need to make sure that a corresponding custom `DefaultAnnotationHandlerMapping` and/or -`AnnotationMethodHandlerAdapter` is defined as well - provided that you intend to use -`@RequestMapping`. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - // ... (controller bean definitions) ... - - ----- - -Defining a `DefaultAnnotationHandlerMapping` and/or `AnnotationMethodHandlerAdapter` -explicitly also makes sense if you would like to customize the mapping strategy, e.g. -specifying a custom `WebBindingInitializer` (see below). - - - -[[portlet-ann-controller]] -==== Defining a controller with @Controller - -The `@Controller` annotation indicates that a particular class serves the role of a -__controller__. There is no need to extend any controller base class or reference the -Portlet API. You are of course still able to reference Portlet-specific features if you -need to. - -The basic purpose of the `@Controller` annotation is to act as a stereotype for the -annotated class, indicating its role. The dispatcher will scan such annotated classes -for mapped methods, detecting `@RequestMapping` annotations (see the next section). - -Annotated controller beans may be defined explicitly, using a standard Spring bean -definition in the dispatcher's context. However, the `@Controller` stereotype also -allows for autodetection, aligned with Spring 2.5's general support for detecting -component classes in the classpath and auto-registering bean definitions for them. - -To enable autodetection of such annotated controllers, you have to add component -scanning to your configuration. This is easily achieved by using the __spring-context__ -schema as shown in the following XML snippet: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - // ... - - ----- - - - -[[portlet-ann-requestmapping]] -==== Mapping requests with @RequestMapping - -The `@RequestMapping` annotation is used to map portlet modes like 'VIEW'/'EDIT' onto an -entire class or a particular handler method. Typically the type-level annotation maps a -specific mode (or mode plus parameter condition) onto a form controller, with additional -method-level annotations 'narrowing' the primary mapping for specific portlet request -parameters. - -[TIP] -==== - -`@RequestMapping` at the type level may be used for plain implementations of the -`Controller` interface as well. In this case, the request processing code would follow -the traditional `handle(Action|Render)Request` signature, while the controller's mapping -would be expressed through an `@RequestMapping` annotation. This works for pre-built -`Controller` base classes, such as `SimpleFormController`, too. - -In the following discussion, we'll focus on controllers that are based on annotated -handler methods. -==== - -The following is an example of a form controller from the PetPortal sample application -using this annotation: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Controller - @RequestMapping("EDIT") - @SessionAttributes("site") - public class PetSitesEditController { - - private Properties petSites; - - public void setPetSites(Properties petSites) { - this.petSites = petSites; - } - - @ModelAttribute("petSites") - public Properties getPetSites() { - return this.petSites; - } - - @RequestMapping // default (action=list) - public String showPetSites() { - return "petSitesEdit"; - } - - @RequestMapping(params = "action=add") // render phase - public String showSiteForm(Model model) { - // Used for the initial form as well as for redisplaying with errors. - if (!model.containsAttribute("site")) { - model.addAttribute("site", new PetSite()); - } - - return "petSitesAdd"; - } - - @RequestMapping(params = "action=add") // action phase - public void populateSite(@ModelAttribute("site") PetSite petSite, - BindingResult result, SessionStatus status, ActionResponse response) { - new PetSiteValidator().validate(petSite, result); - if (!result.hasErrors()) { - this.petSites.put(petSite.getName(), petSite.getUrl()); - status.setComplete(); - response.setRenderParameter("action", "list"); - } - } - - @RequestMapping(params = "action=delete") - public void removeSite(@RequestParam("site") String site, ActionResponse response) { - this.petSites.remove(site); - response.setRenderParameter("action", "list"); - } - } ----- - - - -[[portlet-ann-requestmapping-arguments]] -==== Supported handler method arguments -Handler methods which are annotated with `@RequestMapping` are allowed to have very -flexible signatures. They may have arguments of the following types, in arbitrary order -(except for validation results, which need to follow right after the corresponding -command object, if desired): - -* Request and/or response objects (Portlet API). You may choose any specific - request/response type, e.g. PortletRequest / ActionRequest / RenderRequest. An - explicitly declared action/render argument is also used for mapping specific request - types onto a handler method (in case of no other information given that differentiates - between action and render requests). -* Session object (Portlet API): of type PortletSession. An argument of this type will - enforce the presence of a corresponding session. As a consequence, such an argument - will never be `null`. -* `org.springframework.web.context.request.WebRequest` or - `org.springframework.web.context.request.NativeWebRequest`. Allows for generic request - parameter access as well as request/session attribute access, without ties to the - native Servlet/Portlet API. -* `java.util.Locale` for the current request locale (the portal locale in a Portlet - environment). -* `java.util.TimeZone` / `java.time.ZoneId` for the current request time zone. -* `java.io.InputStream` / `java.io.Reader` for access to the request's content. This - will be the raw InputStream/Reader as exposed by the Portlet API. -* `java.io.OutputStream` / `java.io.Writer` for generating the response's content. This - will be the raw OutputStream/Writer as exposed by the Portlet API. -* `@RequestParam` annotated parameters for access to specific Portlet request - parameters. Parameter values will be converted to the declared method argument type. -* `java.util.Map` / `org.springframework.ui.Model` / `org.springframework.ui.ModelMap` - for enriching the implicit model that will be exposed to the web view. -* Command/form objects to bind parameters to: as bean properties or fields, with - customizable type conversion, depending on `@InitBinder` methods and/or the - HandlerAdapter configuration - see the " `webBindingInitializer`" property on - `AnnotationMethodHandlerAdapter`. Such command objects along with their validation - results will be exposed as model attributes, by default using the non-qualified - command class name in property notation (e.g. "orderAddress" for type - "mypackage.OrderAddress"). Specify a parameter-level `ModelAttribute` annotation for - declaring a specific model attribute name. -* `org.springframework.validation.Errors` / - `org.springframework.validation.BindingResult` validation results for a preceding - command/form object (the immediate preceding argument). -* `org.springframework.web.bind.support.SessionStatus` status handle for marking form - processing as complete (triggering the cleanup of session attributes that have been - indicated by the `@SessionAttributes` annotation at the handler type level). - -The following return types are supported for handler methods: - -* A `ModelAndView` object, with the model implicitly enriched with command objects and - the results of `@ModelAttribute` annotated reference data accessor methods. -* A `Model` object, with the view name implicitly determined through a - `RequestToViewNameTranslator` and the model implicitly enriched with command objects - and the results of `@ModelAttribute` annotated reference data accessor methods. -* A `Map` object for exposing a model, with the view name implicitly determined through - a `RequestToViewNameTranslator` and the model implicitly enriched with command objects - and the results of `@ModelAttribute` annotated reference data accessor methods. -* A `View` object, with the model implicitly determined through command objects and - `@ModelAttribute` annotated reference data accessor methods. The handler method may - also programmatically enrich the model by declaring a `Model` argument (see above). -* A `String` value which is interpreted as view name, with the model implicitly - determined through command objects and `@ModelAttribute` annotated reference data - accessor methods. The handler method may also programmatically enrich the model by - declaring a `Model` argument (see above). -* `void` if the method handles the response itself (e.g. by writing the response content - directly). -* Any other return type will be considered a single model attribute to be exposed to the - view, using the attribute name specified through `@ModelAttribute` at the method level - (or the default attribute name based on the return type's class name otherwise). The - model will be implicitly enriched with command objects and the results of - `@ModelAttribute` annotated reference data accessor methods. - - - -[[portlet-ann-requestparam]] -==== Binding request parameters to method parameters with @RequestParam - -The `@RequestParam` annotation is used to bind request parameters to a method parameter -in your controller. - -The following code snippet from the PetPortal sample application shows the usage: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Controller - @RequestMapping("EDIT") - @SessionAttributes("site") - public class PetSitesEditController { - - // ... - - public void removeSite(@RequestParam("site") String site, ActionResponse response) { - this.petSites.remove(site); - response.setRenderParameter("action", "list"); - } - - // ... - - } ----- - -Parameters using this annotation are required by default, but you can specify that a -parameter is optional by setting `@RequestParam`'s `required` attribute to `false` -(e.g., `@RequestParam(value="id", required=false)`). - - - -[[portlet-ann-modelattrib]] -==== Providing a link to data from the model with @ModelAttribute - -`@ModelAttribute` has two usage scenarios in controllers. When placed on a method -parameter, `@ModelAttribute` is used to map a model attribute to the specific, annotated -method parameter (see the `populateSite()` method below). This is how the controller -gets a reference to the object holding the data entered in the form. In addition, the -parameter can be declared as the specific type of the form backing object rather than as -a generic `java.lang.Object`, thus increasing type safety. - -`@ModelAttribute` is also used at the method level to provide __reference data__ for the -model (see the `getPetSites()` method below). For this usage the method signature can -contain the same types as documented above for the `@RequestMapping` annotation. - -[NOTE] -==== -`@ModelAttribute` annotated methods will be executed __before__ the chosen -`@RequestMapping` annotated handler method. They effectively pre-populate the implicit -model with specific attributes, often loaded from a database. Such an attribute can then -already be accessed through `@ModelAttribute` annotated handler method parameters in the -chosen handler method, potentially with binding and validation applied to it. -==== - -The following code snippet shows these two usages of this annotation: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Controller - @RequestMapping("EDIT") - @SessionAttributes("site") - public class PetSitesEditController { - - // ... - - @ModelAttribute("petSites") - public Properties getPetSites() { - return this.petSites; - } - - @RequestMapping(params = "action=add") // action phase - public void populateSite( @ModelAttribute("site") PetSite petSite, BindingResult result, SessionStatus status, ActionResponse response) { - new PetSiteValidator().validate(petSite, result); - if (!result.hasErrors()) { - this.petSites.put(petSite.getName(), petSite.getUrl()); - status.setComplete(); - response.setRenderParameter("action", "list"); - } - } - } ----- - - - -[[portlet-ann-sessionattrib]] -==== Specifying attributes to store in a Session with @SessionAttributes - -The type-level `@SessionAttributes` annotation declares session attributes used by a -specific handler. This will typically list the names of model attributes or types of -model attributes which should be transparently stored in the session or some -conversational storage, serving as form-backing beans between subsequent requests. - -The following code snippet shows the usage of this annotation: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Controller - @RequestMapping("EDIT") - @SessionAttributes("site") - public class PetSitesEditController { - // ... - } ----- - - - -[[portlet-ann-webdatabinder]] -==== Customizing WebDataBinder initialization - -To customize request parameter binding with PropertyEditors, etc. via Spring's -`WebDataBinder`, you can either use `@InitBinder`-annotated methods within your -controller or externalize your configuration by providing a custom -`WebBindingInitializer`. - - -[[portlet-ann-initbinder]] -===== Customizing data binding with @InitBinder - -Annotating controller methods with `@InitBinder` allows you to configure web data -binding directly within your controller class. `@InitBinder` identifies methods which -initialize the `WebDataBinder` which will be used for populating command and form object -arguments of annotated handler methods. - -Such init-binder methods support all arguments that `@RequestMapping` supports, except -for command/form objects and corresponding validation result objects. Init-binder -methods must not have a return value. Thus, they are usually declared as `void`. Typical -arguments include `WebDataBinder` in combination with `WebRequest` or -`java.util.Locale`, allowing code to register context-specific editors. - -The following example demonstrates the use of `@InitBinder` for configuring a -`CustomDateEditor` for all `java.util.Date` form properties. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Controller - public class MyFormController { - - @InitBinder - public void initBinder(WebDataBinder binder) { - SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd"); - dateFormat.setLenient(false); - binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, false)); - } - - // ... - - } ----- - - -[[portlet-ann-webbindinginitializer]] -===== Configuring a custom WebBindingInitializer - -To externalize data binding initialization, you can provide a custom implementation of -the `WebBindingInitializer` interface, which you then enable by supplying a custom bean -configuration for an `AnnotationMethodHandlerAdapter`, thus overriding the default -configuration. - - - - -[[portlet-deployment]] -=== Portlet application deployment -The process of deploying a Spring Portlet MVC application is no different than deploying -any JSR-168 Portlet application. However, this area is confusing enough in general that -it is worth talking about here briefly. - -Generally, the portal/portlet container runs in one webapp in your servlet container and -your portlets run in another webapp in your servlet container. In order for the portlet -container webapp to make calls into your portlet webapp it must make cross-context calls -to a well-known servlet that provides access to the portlet services defined in your -`portlet.xml` file. - -The JSR-168 specification does not specify exactly how this should happen, so each -portlet container has its own mechanism for this, which usually involves some kind of -"deployment process" that makes changes to the portlet webapp itself and then registers -the portlets within the portlet container. - -At a minimum, the `web.xml` file in your portlet webapp is modified to inject the -well-known servlet that the portlet container will call. In some cases a single servlet -will service all portlets in the webapp, in other cases there will be an instance of the -servlet for each portlet. - -Some portlet containers will also inject libraries and/or configuration files into the -webapp as well. The portlet container must also make its implementation of the Portlet -JSP Tag Library available to your webapp. - -The bottom line is that it is important to understand the deployment needs of your -target portal and make sure they are met (usually by following the automated deployment -process it provides). Be sure to carefully review the documentation from your portal for -this process. - -Once you have deployed your portlet, review the resulting `web.xml` file for sanity. -Some older portals have been known to corrupt the definition of the -`ViewRendererServlet`, thus breaking the rendering of your portlets. - - - - - -[[websocket]] -== WebSocket Support -This part of the reference documentation covers Spring Framework's support for -WebSocket-style messaging in web applications including use of STOMP as an -application level WebSocket sub-protocol. - -<> establishes a frame of mind in which to think about -WebSocket, covering adoption challenges, design considerations, and thoughts on -when it is a good fit. - -<> reviews the Spring WebSocket API on the -server-side while <> explains the SockJS protocol and shows -how to configure and use it. - -<> introduces the STOMP messaging protocol. -<> demonstrates how to configure STOMP support in Spring. -<> and the following sections explain how to -write annotated message handling methods, send messages, choose message broker -options, as well as work with the special "user" destinations. Finally, -<> lists three approaches to testing STOMP/WebSocket -applications. - - - -[[websocket-intro]] -=== Introduction -The WebSocket protocol http://tools.ietf.org/html/rfc6455[RFC 6455] defines an important -new capability for web applications: full-duplex, two-way communication between client -and server. It is an exciting new capability on the heels of a long history of -techniques to make the web more interactive including Java applets, XMLHttpRequest, -Adobe Flash, ActiveXObject, various Comet techniques, server-sent events, and others. - -A proper introduction of the WebSocket protocol is beyond the scope of this -document. At a minimum however it's important to understand that HTTP is used only for -the initial handshake, which relies on a mechanism built into HTTP to request -a protocol upgrade (or in this case a protocol switch) to which the server can respond with -HTTP status 101 (switching protocols) if it agrees. Assuming the handshake succeeds -the TCP socket underlying the HTTP upgrade request remains open and both client and -server can use it to send messages to each other. - -Spring Framework 4 includes a new `spring-websocket` module with comprehensive -WebSocket support. It is compatible with the Java WebSocket API standard -(http://jcp.org/en/jsr/detail?id=356[JSR-356]) -and also provides additional value-add as explained in the rest of the introduction. - - - -[[websocket-into-fallback-options]] -==== WebSocket Fallback Options -An important challenge to adoption is the lack of support for WebSocket in some -browsers. Notably the first Internet Explorer version to support WebSocket is -version 10 (see http://caniuse.com/websockets for support by browser versions). -Furthermore, some restrictive proxies -may be configured in ways that either preclude the attempt to do HTTP upgrade -or otherwise break connection after some time because it has remained opened -for too long. A good overview on this topic from Peter Lubbers is available in -the InfoQ article -http://www.infoq.com/articles/Web-Sockets-Proxy-Servers["How HTML5 Web Sockets Interact With Proxy Servers"]. - - -Therefore to build a WebSocket application today, fallback options are required -to simulate the WebSocket API where necessary. -Spring Framework provides such transparent fallback -options based on the https://github.com/sockjs/sockjs-protocol[SockJS protocol]. -These options can be enabled through configuration and do not require -modifying the application otherwise. - - - -[[websocket-intro-architecture]] -==== A Messaging Architecture -Aside from short-to-midterm adoption challenges, using WebSocket -brings up important design considerations that are important to recognize -early on, especially in contrast to what we know about building web applications today. - -Today REST is a widely accepted, understood, and supported -architecture for building web applications. It is an architecture that relies -on having many URLs (__nouns__), a handful of HTTP methods (__verbs__), and -other principles such as using hypermedia (__links__), remaining stateless, etc. - -By contrast a WebSocket application may use a single URL only for the -initial HTTP handshake. All messages thereafter share and flow on the -same TCP connection. This points to an entirely different, asynchronous, -event-driven, messaging architecture. One that is much closer -to traditional messaging applications (e.g. JMS, AMQP). - -Spring Framework 4 includes a new `spring-messaging` module with key -abstractions from the -http://projects.spring.io/spring-integration/[Spring Integration] project -such as `Message`, `MessageChannel`, `MessageHandler` and others that can serve as -a foundation for such a messaging architecture. The module also includes a -set of annotations for mapping messages to methods, similar to the Spring MVC -annotation based programming model. - - - -[[websocket-intro-sub-protocol]] -==== Sub-Protocol Support in WebSocket -WebSocket does imply a __messaging architecture__ but does not mandate the -use of any specific __messaging protocol__. It is a very thin layer over TCP -that transforms a stream of bytes into a stream of messages -(either text or binary) and not much more. It is up to applications -to interpret the meaning of a message. - -Unlike HTTP, which is an application-level protocol, in the WebSocket protocol -there is simply not enough information in an incoming message for a framework -or container to know how to route it or process it. Therefore WebSocket is arguably -too low level for anything but a very trivial application. It can be done, but -it will likely lead to creating a framework on top. This is comparable to how -most web applications today are written using a web framework rather than the -Servlet API alone. - -For this reason the WebSocket RFC defines the use of -http://tools.ietf.org/html/rfc6455#section-1.9[sub-protocols]. -During the handshake, client and server can use the header -`Sec-WebSocket-Protocol` to agree on a sub-protocol, i.e. a higher, application-level -protocol to use. The use of a sub-protocol is not required, but -even if not used, applications will still need to choose a message -format that both client and server can understand. That format can be custom, -framework-specific, or a standard messaging protocol. - -Spring Framework provides support for using -http://stomp.github.io/stomp-specification-1.2.html#Abstract[STOMP] -- a simple, messaging protocol -originally created for use in scripting languages with frames inspired -by HTTP. STOMP is widely support and well suited for use over -WebSocket and over the web. - - - -[[websocket-intro-when-to-use]] -==== Should I Use WebSocket? -With all the design considerations surrounding the use of WebSocket, it is -reasonable to ask when is it appropriate to use? - -The best fit for WebSocket is in web applications where client and -server need to exchange events at high frequency and at low latency. Prime -candidates include but are not limited to applications in finance, games, -collaboration, and others. Such applications are both very sensitive to time -delays and also need to exchange a wide variety of messages at high -frequency. - -For other application types, however, this may not be the case. -For example, a news or social feed that shows breaking news as they become -available may be perfectly okay with simple polling once every few minutes. -Here latency is important, but it is acceptable if the news takes a -few minutes to appear. - -Even in cases where latency is crucial, if the volume of messages is -relatively low (e.g. monitoring network failures) the use of -https://spring.io/blog/2012/05/08/spring-mvc-3-2-preview-techniques-for-real-time-updates[long polling] -should be considered as a relatively simple alternative that -works reliably and is comparable by efficiency (again assuming the volume of -messages is relatively low). - -It is the combination of both low latency and high frequency of messages that can make -the use of the WebSocket protocol critical. Even in such applications, -the choice remains whether all client-server -communication should be done through WebSocket messages as opposed to using -HTTP and REST? The answer is going to vary by application, however, it is likely -that some functionality may be exposed over both WebSocket and as a REST API in -order to provide clients with alternatives. Furthermore, a REST API call may need -to broadcast a message to interested clients connected via WebSocket. - -Spring Framework allows `@Controller` and `@RestController` classes to have both -HTTP request handling and WebSocket message handling methods. -Furthermore, a Spring MVC request handling method, or any application -method for that matter, can easily broadcast a message to all interested -WebSocket clients or to a specific user. - - - - -[[websocket-server]] -=== WebSocket API -The Spring Framework provides a WebSocket API designed to adapt to various WebSocket engines. -For example, it runs on JSR-356 runtimes such as Tomcat (7.0.47+), GlassFish (4.0+) and -WildFly (8.0+) but can also adapt to other WebSocket runtimes such as the Jetty (9.1+) -native WebSocket support. - -[NOTE] -==== -As explained in the <>, direct use of a -WebSocket API is too low level for applications -- until assumptions are made about the -format of a message there is little a framework can do to interpret messages or route -them via annotations. This is why applications should consider using a sub-protocol -and Spring's <> support. - -When using a higher level protocol, the details of the WebSocket API become less -relevant, much like the details of TCP communication are not exposed to applications -when using HTTP. Nevertheless this section covers the details of using WebSocket -directly. -==== - - - -[[websocket-server-handler]] -==== Create and Configure a WebSocketHandler -Creating a WebSocket server is as simple as implementing `WebSocketHandler` or more -likely extending either `TextWebSocketHandler` or `BinaryWebSocketHandler`: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - import org.springframework.web.socket.WebSocketHandler; - import org.springframework.web.socket.WebSocketSession; - import org.springframework.web.socket.TextMessage; - - public class MyHandler extends TextWebSocketHandler { - - @Override - public void handleTextMessage(WebSocketSession session, TextMessage message) { - // ... - } - - } ----- - -There is dedicated WebSocket Java-config and XML namespace support for mapping the above -WebSocket handler at a specific URL: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - import org.springframework.web.socket.config.annotation.EnableWebSocket; - import org.springframework.web.socket.config.annotation.WebSocketConfigurer; - import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry; - - @Configuration - @EnableWebSocket - public class WebSocketConfig implements WebSocketConfigurer { - - @Override - public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { - registry.addHandler(myHandler(), "/myHandler"); - } - - @Bean - public WebSocketHandler myHandler() { - return new MyHandler(); - } - - } ----- - -XML configuration equivalent: - -[source,xml,indent=0] -[subs="verbatim,quotes,attributes"] ----- - - - - - - - - - ----- - -The above is for use in Spring MVC applications and should be included in the -configuration of a <>. However, Spring's WebSocket -support does not depend on Spring MVC. It is relatively simple to integrate a `WebSocketHandler` -into other HTTP serving environments with the help of -{javadoc-baseurl}/org/springframework/web/socket/server/support/WebSocketHttpRequestHandler.html[WebSocketHttpRequestHandler]. - - - -[[websocket-server-handshake]] -==== Customizing the WebSocket Handshake -The easiest way to customize the initial HTTP WebSocket handshake request is through -a `HandshakeInterceptor`, which exposes "before" and "after" the handshake methods. -Such an interceptor can be used to preclude the handshake or to make any attributes -available to the `WebSocketSession`. For example, there is a built-in interceptor -for passing HTTP session attributes to the WebSocket session: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Configuration - @EnableWebSocket - public class WebSocketConfig implements WebSocketConfigurer { - - @Override - public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { - registry.addHandler(new MyHandler(), "/myHandler") - .addInterceptors(new HttpSessionHandshakeInterceptor()); - } - - } ----- - -And the XML configuration equivalent: - -[source,xml,indent=0] -[subs="verbatim,quotes,attributes"] ----- - - - - - - - - - - - - ----- - -A more advanced option is to extend the `DefaultHandshakeHandler` that performs -the steps of the WebSocket handshake, including validating the client origin, -negotiating a sub-protocol, and others. An application may also need to use this -option if it needs to configure a custom `RequestUpgradeStrategy` in order to -adapt to a WebSocket server engine and version that is not yet supported -(also see <> for more on this subject). -Both the Java-config and XML namespace make it possible to configure a custom -`HandshakeHandler`. - - - -[[websocket-server-decorators]] -==== WebSocketHandler Decoration -Spring provides a `WebSocketHandlerDecorator` base class that can be used to decorate -a `WebSocketHandler` with additional behavior. Logging and exception handling -implementations are provided and added by default when using the WebSocket Java-config -or XML namespace. The `ExceptionWebSocketHandlerDecorator` catches all uncaught -exceptions arising from any WebSocketHandler method and closes the WebSocket -session with status `1011` that indicates a server error. - - - -[[websocket-server-deployment]] -==== Deployment Considerations -The Spring WebSocket API is easy to integrate into a Spring MVC application where -the `DispatcherServlet` serves both HTTP WebSocket handshake as well as other -HTTP requests. It is also easy to integrate into other HTTP processing scenarios -by invoking `WebSocketHttpRequestHandler`. This is convenient and easy to -understand. However, special considerations apply with regards to JSR-356 runtimes. - -The Java WebSocket API (JSR-356) provides two deployment mechanisms. The first -involves a Servlet container classpath scan (Servlet 3 feature) at startup; and -the other is a registration API to use at Servlet container initialization. -Neither of these mechanism make it possible to use a single "front controller" -for all HTTP processing -- including WebSocket handshake and all other HTTP -requests -- such as Spring MVC's `DispatcherServlet`. - -This is a significant limitation of JSR-356 that Spring's WebSocket support -addresses by providing a server-specific `RequestUpgradeStrategy` even when -running in a JSR-356 runtime. At present such support is available on -Tomcat 7.0.47+, Jetty 9.1+, GlassFish 4.0+, and WildFly 8.0+. Additional support will be -added as more WebSocket runtimes become available. - -[NOTE] -==== -A request to overcome the above limitation in the Java WebSocket API has been -created and can be followed at -https://java.net/jira/browse/WEBSOCKET_SPEC-211[WEBSOCKET_SPEC-211]. -Also note that Tomcat and Jetty already provide native API alternatives that -makes it easy to overcome the limitation. We are hopeful that more servers -will follow their example regardless of when it is addressed in the -Java WebSocket API. -==== - -A secondary consideration is that Servlet containers with JSR-356 support -are expected to perform an SCI scan that can slow down application startup, -in some cases dramatically. If a significant impact is observed after an -upgrade to a Servlet container version with JSR-356 support, it should -be possible to selectively enable or disable web fragments (and SCI scanning) -through the use of an `` element in `web.xml`: - -[source,xml,indent=0] -[subs="verbatim,quotes,attributes"] ----- - - - - - ----- - -You can then selectively enable web fragments by name, such as Spring's own -`SpringServletContainerInitializer` that provides support for the Servlet 3 -Java initialization API, if required: - -[source,xml,indent=0] -[subs="verbatim,quotes,attributes"] ----- - - - - spring_web - - - ----- - -[[websocket-server-runtime-configuration]] -==== Configuring the WebSocket Engine - -Each underlying WebSocket engine exposes configuration properties that control -runtime characteristics such as the size of message buffer sizes, idle timeout, -and others. - -For Tomcat, WildFly, and Glassfish add a `ServletServerContainerFactoryBean` to your -WebSocket Java config: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Configuration - @EnableWebSocket - public class WebSocketConfig implements WebSocketConfigurer { - - @Bean - public ServletServerContainerFactoryBean createWebSocketContainer() { - ServletServerContainerFactoryBean container = new ServletServerContainerFactoryBean(); - container.setMaxTextMessageBufferSize(8192); - container.setMaxBinaryMessageBufferSize(8192); - return container; - } - - } ----- - -or WebSocket XML namespace: - -[source,xml,indent=0] -[subs="verbatim,quotes,attributes"] ----- - - - - - - - - ----- - -[NOTE] -==== -For client side WebSocket configuration, you should use `WebSocketContainerFactoryBean` -(XML) or `ContainerProvider.getWebSocketContainer()` (Java config). -==== - -For Jetty, you'll need to supply a pre-configured Jetty `WebSocketServerFactory` and plug -that into Spring's `DefaultHandshakeHandler` through your WebSocket Java config: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Configuration - @EnableWebSocket - public class WebSocketConfig implements WebSocketConfigurer { - - @Override - public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { - registry.addHandler(echoWebSocketHandler(), - "/echo").setHandshakeHandler(handshakeHandler()); - } - - @Bean - public DefaultHandshakeHandler handshakeHandler() { - - WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.SERVER); - policy.setInputBufferSize(8192); - policy.setIdleTimeout(600000); - - return new DefaultHandshakeHandler( - new JettyRequestUpgradeStrategy(new WebSocketServerFactory(policy))); - } - - } ----- - -or WebSocket XML namespace: - -[source,xml,indent=0] -[subs="verbatim,quotes,attributes"] ----- - - - - - - - - - - - - - - - - - - - - - - - - - - ----- - - - - -[[websocket-fallback]] -=== SockJS Fallback Options -As explained in the <>, WebSocket is not -supported in all browsers yet and may be precluded by restrictive network proxies. -This is why Spring provides fallback options that emulate the WebSocket API as close -as possible based on the https://github.com/sockjs/sockjs-protocol[SockJS protocol]. - -[[websocket-fallback-sockjs-overview]] -==== Overview of SockJS - -The goal of SockJS is to let applications use a WebSocket API but fall back to -non-WebSocket alternatives when necessary at runtime, i.e. without the need to -change application code. - -SockJS consists of: - -* The https://github.com/sockjs/sockjs-protocol[SockJS protocol] -defined in the form of executable -http://sockjs.github.io/sockjs-protocol/sockjs-protocol-0.3.3.html[narrated tests]. -* The https://github.com/sockjs/sockjs-client[SockJS JavaScript client] - a client library for use in browsers. -* SockJS server implementations including one in the Spring Framework `spring-websocket` module. -* As of 4.1 `spring-websocket` also provides a SockJS Java client. - -SockJS is designed for use in browsers. It goes to great lengths -to support a wide range of browser versions using a variety of techniques. -For the full list of SockJS transport types and browsers see the -https://github.com/sockjs/sockjs-client[SockJS client] page. Transports -fall in 3 general categories: WebSocket, HTTP Streaming, and HTTP Long Polling. -For an overview of these categories see -https://spring.io/blog/2012/05/08/spring-mvc-3-2-preview-techniques-for-real-time-updates/[this blog post]. - -The SockJS client begins by sending `"GET /info"` to -obtain basic information from the server. After that it must decide what transport -to use. If possible WebSocket is used. If not, in most browsers -there is at least one HTTP streaming option and if not then HTTP (long) -polling is used. - -All transport requests have the following URL structure: ----- -http://host:port/myApp/myEndpoint/{server-id}/{session-id}/{transport} ----- - -* `{server-id}` - useful for routing requests in a cluster but not used otherwise. -* `{session-id}` - correlates HTTP requests belonging to a SockJS session. -* `{transport}` - indicates the transport type, e.g. "websocket", "xhr-streaming", etc. - -The WebSocket transport needs only a single HTTP request to do the WebSocket handshake. -All messages thereafter are exchanged on that socket. - -HTTP transports require more requests. Ajax/XHR streaming for example relies on -one long-running request for server-to-client messages and additional HTTP POST -requests for client-to-server messages. Long polling is similar except it -ends the current request after each server-to-client send. - -SockJS adds minimal message framing. For example the server sends the letter +o+ -("open" frame) initially, messages are sent as +a["message1","message2"]+ -(JSON-encoded array), the letter +h+ ("heartbeat" frame) if no messages flow -for 25 seconds by default, and the letter +c+ ("close" frame) to close the session. - -To learn more run an example in a browser and watch HTTP requests. -The SockJS client allows fixing the list of transports so it is possible to -see each transport one at a time. The SockJS client also provides a debug flag -which enables helpful messages in the browser console. On the server side enable -TRACE logging for `org.springframework.web.socket`. -For even more detail refer to the SockJS protocol -http://sockjs.github.io/sockjs-protocol/sockjs-protocol-0.3.3.html[narrated test]. - - -[[websocket-fallback-sockjs-enable]] -==== Enable SockJS -SockJS is easy to enable through a configuration: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Configuration - @EnableWebSocket - public class WebSocketConfig implements WebSocketConfigurer { - - @Override - public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { - registry.addHandler(myHandler(), "/myHandler").withSockJS(); - } - - @Bean - public WebSocketHandler myHandler() { - return new MyHandler(); - } - - } ----- - -and the XML configuration equivalent: - -[source,xml,indent=0] -[subs="verbatim,quotes,attributes"] ----- - - - - - - - - - - ----- - -The above is for use in Spring MVC applications and should be included in the -configuration of a <>. However, Spring's WebSocket -and SockJS support does not depend on Spring MVC. It is relatively simple to -integrate into other HTTP serving environments with the help of -{javadoc-baseurl}/org/springframework/web/socket/sockjs/support/SockJsHttpRequestHandler.html[SockJsHttpRequestHandler]. - -On the browser side, applications can use the -https://github.com/sockjs/sockjs-client[sockjs-client] that emulates the W3C -WebSocket API and communicates with the server to select the best -transport option depending on the browser it's running in. Review the -https://github.com/sockjs/sockjs-client[sockjs-client] page and the list of -transport types supported by browser. The client also provides several -configuration options, for example, to specify which transports to include. - -[[websocket-fallback-xhr-vs-iframe]] -==== HTTP Streaming in IE 8, 9: Ajax/XHR vs IFrame - -Internet Explorer 8 and 9 are and will remain common for some time. They are -a key reason for having SockJS. This section covers important -considerations about running in those browsers. - -SockJS client supports Ajax/XHR streaming in IE 8, 9 via Microsoft's -http://blogs.msdn.com/b/ieinternals/archive/2010/05/13/xdomainrequest-restrictions-limitations-and-workarounds.aspx[XDomainRequest]. -That works across domains but does not support sending cookies. -Cookies are very often essential for Java applications. -However since the SockJS client can be used with many server -types (not just Java ones), it needs to know whether cookies do matter. -If so the SockJS client prefers Ajax/XHR for streaming or otherwise it -relies on a iframe-based technique. - -The very first `"/info"` request from the SockJS client is a request for -information that can influence the client's choice of transports. -One of those details is whether the server application relies on cookies, -e.g. for authentication purposes or clustering with sticky sessions. -Spring's SockJS support includes a property called `sessionCookieNeeded`. -It is enabled by default since most Java applications rely on the `JSESSIONID` -cookie. If your application does not need it, you can turn off this option -and the SockJS client should choose `xdr-streaming` in IE 8 and 9. - -If you do use an iframe-based transport, and in any case, it is good to know -that browsers can be instructed to block the use of iframes on a given page by -setting the HTTP response header `X-Frame-Options` to `DENY`, -`SAMEORIGIN`, or `ALLOW-FROM `. This is used to prevent -https://www.owasp.org/index.php/Clickjacking[clickjacking]. - -[NOTE] -==== -Spring Security 3.2+ provides support for setting `X-Frame-Options` on every -response. By default the Spring Security Java config sets it to `DENY`. -In 3.2 the Spring Security XML namespace does not set that header by default -but may be configured to do so, and in the future it may set it by default. - -See http://docs.spring.io/spring-security/site/docs/3.2.2.RELEASE/reference/htmlsingle/#headers[Section 7.1. "Default Security Headers"] -of the Spring Security documentation for details no how to configure the -setting of the `X-Frame-Options` header. You may also check or watch -https://jira.spring.io/browse/SEC-2501[SEC-2501] for additional background. -==== - -If your application adds the `X-Frame-Options` response header (as it should!) -and relies on an iframe-based transport, you will need to set the header value to -`SAMEORIGIN` or `ALLOW-FROM `. Along with that the Spring SockJS -support also needs to know the location of the SockJS client because it is loaded -from the iframe. By default the iframe is set to download the SockJS client -from a CDN location. It is a good idea to configure this option to -a URL from the same origin as the application. - -In Java config this can be done as shown below. The XML namespace provides a -similar option on the `` element: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Configuration - @EnableWebSocket - public class WebSocketConfig implements WebSocketConfigurer { - - @Override - public void registerStompEndpoints(StompEndpointRegistry registry) { - registry.addEndpoint("/portfolio").withSockJS() - .setClientLibraryUrl("http://localhost:8080/myapp/js/sockjs-client.js"); - } - - // ... - - } ----- - -[NOTE] -==== -During initial development, do enable the SockJS client `devel` mode that prevents -the browser from caching SockJS requests (like the iframe) that would otherwise -be cached. For details on how to enable it see the -https://github.com/sockjs/sockjs-client[SockJS client] page. -==== - -[[websocket-fallback-sockjs-heartbeat]] -==== Heartbeat Messages - -The SockJS protocol requires servers to send heartbeat messages to preclude proxies -from concluding a connection is hung. The Spring SockJS configuiration has a property -called `heartbeatTime` that can be used to customize the frequency. By default a -heartbeat is sent after 25 seconds assuming no other messages were sent on that -connection. This 25 seconds value is in line with the following -http://tools.ietf.org/html/rfc6202[IETF recommendation] for public Internet applications. - -[NOTE] -==== -When using STOMP over WebSocket/SockJS, if the STOMP client and server negotiate -heartbeats to be exchanged, the SockJS heartbeats are disabled. -==== - -The Spring SockJS support also allows configuring the `TaskScheduler` to use -for scheduling heartbeats tasks. The task scheduler is backed by a thread pool -with default settings based on the number of available processors. Applications -should consider customizing the settings according to their specific needs. - -[[websocket-fallback-sockjs-servlet3-async]] -==== Servlet 3 Async Requests - -HTTP streaming and HTTP long polling SockJS transports require a connection to remain -open longer than usual. For an overview of these techniques see -https://spring.io/blog/2012/05/08/spring-mvc-3-2-preview-techniques-for-real-time-updates/[this blog post]. - -In Servlet containers this is done through Servlet 3 async support that -allows exiting the Servlet container thread processing a request and continuing -to write to the response from another thread. - -A specific issue is the Servlet API does not provide notifications for a client -that has gone away, see https://java.net/jira/browse/SERVLET_SPEC-44[SERVLET_SPEC-44]. -However, Servlet containers raise an exception on subseqeunt attempts to write -to the response. Since Spring's SockJS Service support sever-sent heartbeats (every -25 seconds by default), that means a client disconnect is usually detected within that -time period or earlier if a message are sent more frequently. - -[NOTE] -==== -As a result network IO failures may occur simply because a client has disconnected, which -can fill the log with unnecessary stack traces. Spring makes a best effort to identify -such network failures that represent client disconnects (specific to each server) and log -a more minimal message using the dedicated log category `DISCONNECTED_CLIENT_LOG_CATEGORY` -defined in `AbstractSockJsSession`. If you need to see the stack traces, set that -log category to TRACE. -==== - -[[websocket-fallback-cors]] -==== CORS Headers for SockJS - -The SockJS protocol uses CORS for cross-domain support in the XHR streaming and -polling transports. Therefore CORS headers are added automatically unless the -presence of CORS headers in the response is detected. So if an application is -already configured to provide CORS support, e.g. through a Servlet Filter, -Spring's SockJsService will skip this part. - -The following is the list of headers and values expected by SockJS: - -* `"Access-Control-Allow-Origin"` - intitialized from the value of the "origin" request header or "*". -* `"Access-Control-Allow-Credentials"` - always set to `true`. -* `"Access-Control-Request-Headers"` - initialized from values from the equivalent request header. -* `"Access-Control-Allow-Methods"` - the HTTP methods a transport supports (see `TransportType` enum). -* `"Access-Control-Max-Age"` - set to 31536000 (1 year). - -For the exact implementation see `addCorsHeaders` in `AbstractSockJsService` as well -as the `TransportType` enum in the source code. - -Alternatively if the CORS configuration allows it consider excluding URLs with the -SockJS endpoint prefix thus letting Spring's SockJsService handle it. - - -[[websocket-fallback-sockjs-client]] -==== SockJS Client - -A SockJS Java client is provided in order to connect to remote SockJS endpoints without -using a browser. This can be especially useful when there is a need of bidirectional -communication between 2 servers over a public network, i.e. where network proxies may -preclude the use of the WebSocket protocol. A SockJS Java client is also very useful -for testing purposes for example to simulate a large number of concurrent users. - -The SockJS Java client supports the "websocket", "xhr-streaming", and "xhr-polling" -transports. The remaining ones only make sense for use in a browser. - -The `WebSocketTransport` can be configured with: - -* `StandardWebSocketClient` in a JSR-356 runtime -* `JettyWebSocketClient` using the Jetty 9+ native WebSocket API -* Any implementation of Spring's `WebSocketClient` - -An `XhrTransport` by definition supports both "xhr-streaming" and "xhr-polling" since -from a client perspective there is no difference other than in the URL used to connect -to the server. At present there are two implementations: - -* `RestTemplateXhrTransport` uses the RestTemplate for HTTP requests. -* `JettyXhrTransport` uses Jetty's HttpClient for HTTP requests. - -The example below shows how to create a SockJS client and connect to a SockJS endpoint: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - List transports = new ArrayList<>(2); - transports.add(new WebSocketTransport(StandardWebSocketClient())); - transports.add(new RestTemplateXhrTransport()); - - SockJsClient sockJsClient = new SockJsClient(transports); - sockJsClient.doHandshake(new MyWebSocketHandler(), "ws://example.com:8080/sockjs"); ----- - -[NOTE] -==== -SockJS uses JSON formatted arrays for messages. By default Jackson 2 is used and needs -to be on the classpath. Alternatively you can configure a custom implementation of -`SockJsMessageCodec` and configure it on the SockJsClient. -==== - -To use the SockJsClient for simulating a large number of concurrent users you will -need to configure the underlying HTTP client (for XHR transports) to allow a sufficient -number of connections and threads. For example with Jetty: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- -HttpClient jettyHttpClient = new HttpClient(); -jettyHttpClient.setMaxConnectionsPerDestination(1000); -jettyHttpClient.setExecutor(new QueuedThreadPool(1000)); ----- - -Consider also customizing these server-side SockJS related properties (see Javadoc for details): - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- -@Configuration -public class WebSocketConfig extends WebSocketMessageBrokerConfigurationSupport { - - @Override - public void registerStompEndpoints(StompEndpointRegistry registry) { - registry.addEndpoint("/sockjs").withSockJS() - .setStreamBytesLimit(512 * 1024) - .setHttpMessageCacheSize(1000) - .setDisconnectDelay(30 * 1000); - } - - // ... - -} ----- - - - - -[[websocket-stomp]] -=== STOMP Over WebSocket Messaging Architecture -The WebSocket protocol defines two main types of messages -- text and binary -- -but leaves their content undefined. Instead it's expected that client and -server may agree on using a sub-protocol, i.e. a higher-level protocol that defines -the message content. Using a sub-protocol is optional but either way client -and server both need to understand how to interpret messages. - - - -[[websocket-stomp-overview]] -==== Overview of STOMP -http://stomp.github.io/stomp-specification-1.2.html#Abstract[STOMP] is a simple -messaging protocol originally created for scripting languages (such as Ruby, Python and -Perl) to connect to enterprise message brokers. It is designed to address a -subset of commonly used patterns in messaging protocols. STOMP can be used over -any reliable 2-way streaming network protocol such as TCP and WebSocket. - -STOMP is a frame based protocol with frames modelled on HTTP. This is the -structure of a frame: - ----- -COMMAND -header1:value1 -header2:value2 - -Body^@ ----- - -For example, a client can use the +SEND+ command to send a message or the -+SUBSCRIBE+ command to express interest in receiving messages. Both of these commands -require a +"destination"+ header that indicates where to send a message to, or likewise -what to subscribe to. - -Here is an example of a client sending a request to buy stock shares: - ----- -SEND -destination:/queue/trade -content-type:application/json -content-length:44 - -{"action":"BUY","ticker":"MMM","shares",44}^@ ----- - -Here is an example of a client subscribing to receive stock quotes: ----- -SUBSCRIBE -id:sub-1 -destination:/topic/price.stock.* - -^@ ----- - -[NOTE] -==== -The meaning of a destination is intentionally left opaque in the STOMP spec. It can -be any string and it's entirely up to STOMP servers to define the semantics and -the syntax of the destinations that they support. It is very common however, for -destinations to be path-like strings where `"/topic/.."` implies publish-subscribe -(__one-to-many__) and `"/queue/"` to implies point-to-point (__one-to-one__) message -exchanges. -==== - -STOMP servers can use the +MESSAGE+ command to broadcast messages to all subscribers. -Here is an example of a server sending a stock quote to a subscribed client: - ----- -MESSAGE -message-id:nxahklf6-1 -subscription:sub-1 -destination:/topic/price.stock.MMM - -{"ticker":"MMM","price":129.45}^@ ----- - -[NOTE] -==== -It's important to know that a server cannot send unsolicited messages. -All messages from a server must be in response to a specific client subscription -and the +"subscription-id"+ header of the server message must match -the +"id"+ header of the client subscription. -==== - -The above overview is intended to provide the most basic understanding of the -STOMP protocol. It is recommended to review the protocol -http://stomp.github.io/stomp-specification-1.2.html[specification], which is -easy to follow and manageable in terms of size. - -The following summarizes the benefits for an application from using STOMP over WebSocket: - -* Standard message format -* Application-level protocol with support for common messaging patterns -* Client-side support, e.g. https://github.com/jmesnil/stomp-websocket[stomp.js], https://github.com/cujojs/msgs[msgs.js] -* The ability to interpret, route, and process messages on both client and server-side -* The option to plug a message broker -- RabbitMQ, ActiveMQ, many others -- to broadcast messages (explained later) - -Most importantly the use of STOMP (vs plain WebSocket) enables the Spring Framework -to provide a programming model for application-level use in the same way that -Spring MVC provides a programming model based on HTTP. - - - -[[websocket-stomp-enable]] -==== Enable STOMP over WebSocket -The Spring Framework provides support for using STOMP over WebSocket through -the +spring-messaging+ and +spring-websocket+ modules. It's easy to enable it. - -Here is an example of configuring a STOMP WebSocket endpoint with SockJS fallback -options. The endpoint is available for clients to connect to at URL path `/app/portfolio`: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker; - import org.springframework.web.socket.config.annotation.StompEndpointRegistry; - - @Configuration - @EnableWebSocketMessageBroker - public class WebSocketConfig implements WebSocketMessageBrokerConfigurer { - - @Override - public void configureMessageBroker(MessageBrokerRegistry config) { - config.setApplicationDestinationPrefixes("/app"); - config.enableSimpleBroker("/queue", "/topic"); - } - - @Override - public void registerStompEndpoints(StompEndpointRegistry registry) { - registry.addEndpoint("/portfolio").withSockJS(); - } - - // ... - - } ----- - -XML configuration equivalent: - -[source,xml,indent=0] -[subs="verbatim,quotes,attributes"] ----- - - - - - - - - ... - - - ----- - -On the browser side, a client might connect as follows using -https://github.com/jmesnil/stomp-websocket[stomp.js] and the -https://github.com/sockjs/sockjs-client[sockjs-client]: - -[source,javascript,indent=0] -[subs="verbatim,quotes"] ----- - var socket = new SockJS("/spring-websocket-portfolio/portfolio"); - var stompClient = Stomp.over(socket); - - stompClient.connect({}, function(frame) { - } ----- - -Or if connecting via WebSocket (without SockJS): - -[source,javascript,indent=0] -[subs="verbatim,quotes"] ----- - var socket = new WebSocket("/spring-websocket-portfolio/portfolio"); - var stompClient = Stomp.over(socket); - - stompClient.connect({}, function(frame) { - } ----- - -Note that the stompClient above does not need to specify a `login` and `passcode` headers. -Even if it did, they would be ignored, or rather overridden, on the server side. See the -sections <> and -<> for more information on authentication. - - -[[websocket-stomp-message-flow]] -==== Flow of Messages - -When a STOMP endpoint is configured, the Spring application acts as the STOMP broker -to connected clients. It handles incoming messages and sends messages back. -This section provides a big picture overview of how messages flow inside the application. - -The `spring-messaging` module contains a number of abstractions that originated in the -https://spring.io/spring-integration[Spring Integration] project and are intended -for use as building blocks in messaging applications: - -* {javadoc-baseurl}/org/springframework/messaging/Message.html[Message] -- -represents a message with headers and a payload. -* {javadoc-baseurl}/org/springframework/messaging/MessageHandler.html[MessageHandler] -- -a contract for handling a message. -* {javadoc-baseurl}/org/springframework/messaging/MessageChannel.html[MessageChannel] -- -a contract for sending a message enabling loose coupling between senders and receivers. -* {javadoc-baseurl}/org/springframework/messaging/SubscribableChannel.html[SubscribableChannel] -- -extends `MessageChannel` and sends messages to registered `MessageHandler` subscribers. -* {javadoc-baseurl}/org/springframework/messaging/support/ExecutorSubscribableChannel.html[ExecutorSubscribableChannel] -- -a concrete implementation of `SubscribableChannel` that can deliver messages -asynchronously through a thread pool. - -The provided STOMP over WebSocket config, both Java and XML, uses the above to -assemble a concrete message flow including the following 3 channels: - -* `"clientInboundChannel"` -- for messages from WebSocket clients. Every incoming -WebSocket message carrying a STOMP frame is sent through this channel. -* `"clientOutboundChannel"` -- for messages to WebSocket clients. Every outgoing -STOMP message from the broker is sent through this channel before getting sent -to a client's WebSocket session. -* `"brokerChannel"` -- for messages to the broker from within the application. -Every message sent from the application to the broker passes through this channel. - -Messages on the `"clientInboundChannel"` can flow to annotated -methods for application handling (e.g. a stock trade execution request) or can -be forwarded to the broker (e.g. client subscribing for stock quotes). -The STOMP destination is used for simple prefix-based routing. For example -the "/app" prefix could route messages to annotated methods while the "/topic" -and "/queue" prefixes could route messages to the broker. - -When a message-handling annotated method has a return type, its return -value is sent as the payload of a Spring Message to the `"brokerChannel"`. -The broker in turn broadcasts the message to clients. Sending a message -to a destination can also be done from anywhere in the application with -the help of a messaging template. For example a an HTTP POST handling method -can broadcast a message to connected clients or a service component may -periodically broadcast stock quotes. - -Below is a simple example to illustrate the flow of messages: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Configuration - @EnableWebSocketMessageBroker - public class WebSocketConfig implements WebSocketMessageBrokerConfigurer { - - @Override - public void registerStompEndpoints(StompEndpointRegistry registry) { - registry.addEndpoint("/portfolio"); - } - - @Override - public void configureMessageBroker(MessageBrokerRegistry registry) { - registry.setApplicationDestinationPrefixes("/app"); - registry.enableSimpleBroker("/topic"); - } - - } - - @Controller - public class GreetingController { - - @MessageMapping("/greeting") { - public String handle(String greeting) { - return "[" + getTimestamp() + ": " + greeting; - } - - } - ----- - -The following explains the message flow for the above exmaple: - -* WebSocket clients connect to the WebSocket endpoint at "/portfolio". -* Subscriptions to "/topic/greeting" pass through the "clientInboundChannel" -and are forwarded to the broker. -* Greetings sent to "/app/greeting" pass through the "clientInboundChannel" -and are forwarded to the `GreetingController`. The controller adds the current -time and the return value is passed through the "brokerChannel" as message -to "/topic/greeting" (destination is selected based on a convention but can be -overridden via `@SendTo`). -* The broker in turn broadcasts messages to subscribers and they pass through -the `"clientOutboundChannel"`. - -The next section provides more details on annotated methods including the -kinds of arguments and return values supported. - - - -[[websocket-stomp-handle-annotations]] -==== Annotation Message Handling - -The `@MessageMapping` annotation is supported on methods of `@Controller` classes. -It can be used for mapping methods to message destinations and can also be combined -with the type-level `@MessageMapping` for expressing shared mappings across all -annotated methods within a controller. - -By default destination mappings are treated as Ant-style, slash-separated, path -patterns, e.g. "/foo*", "/foo/**". etc. They can also contain template variables, -e.g. "/foo/{id}" that can then be referenced via `@DestinationVariable`-annotated -method arguments. - -[NOTE] -==== -Applications can also use dot-separated destinations (vs slash). -See <>. -==== - -The following method arguments are supported for `@MessageMapping` methods: - -* `Message` method argument to get access to the complete message being processed. -* `@Payload`-annotated argument for access to the payload of a message, converted with -a `org.springframework.messaging.converter.MessageConverter`. -The presence of the annotation is not required since it is assumed by default. -Payload method arguments annotated with Validation annotations (like `@Validated`) will -be subject to JSR-303 validation. -* `@Header`-annotated arguments for access to a specific header value along with -type conversion using an `org.springframework.core.convert.converter.Converter` -if necessary. -* `@Headers`-annotated method argument that must also be assignable to `java.util.Map` -for access to all headers in the message. -* `MessageHeaders` method argument for getting access to a map of all headers. -* `MessageHeaderAccessor`, `SimpMessageHeaderAccessor`, or `StompHeaderAccessor` -for access to headers via typed accessor methods. -* `@DestinationVariable`-annotated arguments for access to template -variables extracted from the message destination. Values will be converted to -the declared method argument type as necessary. -* `java.security.Principal` method arguments reflecting the user logged in at -the time of the WebSocket HTTP handshake. - -The return value from an `@MessageMapping` method is converted with a -`org.springframework.messaging.converter.MessageConverter` and used as the body -of a new message that is then sent, by default, to the `"brokerChannel"` with -the same destination as the client message but using the prefix "/topic" by -default. An `@SendTo` message level annotation can be used to specify any -other destination instead. - -An `@SubscribeMapping` annotation can also be used to map subscription requests -to `@Controller` methods. It is supported on the method level, but can also be -combined with a type level `@MessageMapping` annotation that expresses shared -mappings across all message handling methods within the same controller. - -By default the return value from an `@SubscribeMapping` method is sent as a -message directly back to the connected client and does not pass through the -broker. This is useful for implementing request-reply message interactions; for -example, to fetch application data when the application UI is being initialized. -Or alternatively an `@SubscribeMapping` method can be annotated with `@SendTo` -in which case the resulting message is sent to the `"brokerChannel"` using -the specified target destination. - - -[[websocket-stomp-handle-send]] -==== Sending Messages - -What if you wanted to send messages to connected clients from any part of the -application? Any application component can send messages to the `"brokerChannel"`. -The easiest way to do that is to have a `SimpMessagingTemplate` injected, and -use it to send messages. Typically it should be easy to have it injected by -type, for example: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Controller - public class GreetingController { - - private SimpMessagingTemplate template; - - @Autowired - public GreetingController(SimpMessagingTemplate template) { - this.template = template; - } - - @RequestMapping(value="/greetings", method=POST) - public void greet(String greeting) { - String text = "[" + getTimestamp() + "]:" + greeting; - this.template.convertAndSend("/topic/greetings", text); - } - - } ----- - -But it can also be qualified by its name "brokerMessagingTemplate" if another -bean of the same type exists. - - -[[websocket-stomp-handle-simple-broker]] -==== Simple Broker - -The built-in, simple, message broker handles subscription requests from clients, -stores them in memory, and broadcasts messages to connected clients with matching -destinations. The broker supports path-like destinations, including subscriptions -to Ant-style destination patterns. - -[NOTE] -==== -Applications can also use dot-separated destinations (vs slash). -See <>. -==== - - - - -[[websocket-stomp-handle-broker-relay]] -==== Full-Featured Broker - -The simple broker is great for getting started but supports only a subset of -STOMP commands (e.g. no acks, receipts, etc), relies on a simple message -sending loop, and is not suitable for clustering. Instead, applications can -upgrade to using a full-featured message broker. - -Check the STOMP documentation for your message broker of choice (e.g. -http://www.rabbitmq.com/stomp.html[RabbitMQ], -http://activemq.apache.org/stomp.html[ActiveMQ], or other), install and run the -broker with STOMP support enabled. Then enable the STOMP broker relay in the -Spring configuration instead of the simple broker. - -Below is example configuration that enables a full-featured broker: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Configuration - @EnableWebSocketMessageBroker - public class WebSocketConfig implements WebSocketMessageBrokerConfigurer { - - @Override - public void registerStompEndpoints(StompEndpointRegistry registry) { - registry.addEndpoint("/portfolio").withSockJS(); - } - - @Override - public void configureMessageBroker(MessageBrokerRegistry registry) { - registry.enableStompBrokerRelay("/topic", "/queue"); - registry.setApplicationDestinationPrefixes("/app"); - } - - } ----- - -XML configuration equivalent: - -[source,xml,indent=0] -[subs="verbatim,quotes,attributes"] ----- - - - - - - - - - - ----- - -The "STOMP broker relay" in the above configuration is a Spring -http://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/messaging/MessageHandler.html[MessageHandler] -that handles messages by forwarding them to an external message broker. -To do so it establishes TCP connections to the broker, forwards all -messages to it, and reversely forwards all messages received -from the broker to clients through their WebSocket sessions. Essentially -it acts as a "relay" forwarding messages in both directions. - -[NOTE] -==== -Please add a dependency on `org.projectreactor:reactor-net` for TCP connection management. -==== - -Furthermore, application components (e.g. HTTP request handling methods, -business services, etc) can also send messages to the broker relay, as described -in <>, in order to broadcast messages to -subscribed WebSocket clients. - -In effect, the broker relay enables robust and scalable message broadcasting. - -[[websocket-stomp-handle-broker-relay-configure]] -==== Connections To Full-Featured Broker - -A STOMP broker relay maintains a single "system" TCP connection to the broker. -This connection is used for messages originating from the server-side application -only, not for receiving messages. You can configure the STOMP credentials -for this connection, i.e. the STOMP frame `login` and `passcode` headers. This -is exposed in both the XML namespace and the Java config as the -++systemLogin++/++systemPasscode++ properties with default values ++guest++/++guest++. - -The STOMP broker relay also creates a separate TCP connection for every connected -WebSocket client. You can configure the STOMP credentials to use for all TCP -connections created on behalf of clients. This is exposed in both the XML namespace -and the Java config as the `clientLogin`/`clientPasscode` properties with default -values ++guest++/++guest++. - -[NOTE] -==== -The STOMP broker relay always sets the `login` and `passcode` headers on every CONNECT -frame it forwards to the broker on behalf of clients. Therefore WebSocket clients -need not set those headers, they will be ignored. As the following section explains -instead WebSocket clients should rely on HTTP authentication to protect the WebSocket -endpoint and establish the client identity. -==== - -The STOMP broker relay also sends and receives heartbeats to and from the message -broker over the "system" TCP connection. You can configure the intervals for sending -and receiving heartbeats (10 seconds each by default). If connectivity to the broker -is lost, the broker relay will continue to try to reconnect, every 5 seconds, -until it succeeds. - -[NOTE] -==== -A Spring bean can implement `ApplicationListener` in order -to receive notifications when the "system" connection to the broker is lost and -re-established. For example a Stock Quote service broadcasting stock quotes can -stop trying to send messages when there is no active "system" connection. -==== - -The STOMP broker relay can also be configured with a `virtualHost` property. -The value of this property will be set as the `host` header of every CONNECT frame -and may be useful for example in a cloud environment where the actual host to which -the TCP connection is established is different from the host providing the -cloud-based STOMP service. - -[[websocket-stomp-destination-separator]] -==== Using Dot as Separator in `@MessageMapping` Destinations - -Although slash-separated path patterns are familiar to web developers, in messaging -it is common to use "." as separator for example in the names of topics, queues, -exchanges, etc. Applications can also switch to using "." (dot) instead of "/" (slash) -as the separator in `@MessageMapping` mappings by configuring a custom `AntPathMatcher`. - -In Java config: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Configuration - @EnableWebSocketMessageBroker - public class WebsocketConfig extends AbstractWebSocketMessageBrokerConfigurer { - - // ... - - @Override - public void configureMessageBroker(MessageBrokerRegistry registry) { - registry.enableStompBrokerRelay("/queue/", "/topic/"); - registry.setApplicationDestinationPrefixes("/app"); - registry.setPathMatcher(new AntPathMatcher(".")); - } - - } ----- - -In XML config: - -[source,xml,indent=0] -[subs="verbatim,quotes,attributes"] ----- - - - - - - - - - - - - ----- - -And below is a simple example to illustrate a controller with "." separator: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Controller - @MessageMapping("foo") - public class FooController { - - @MessageMapping("bar.{baz}") - public void handleBaz(@DestinationVariable String baz) { - } - - } ----- - -If the application prefix is set to "/app" then the foo method is effectively mapped to "/app/foo.bar.{baz}". - - - - -[[websocket-stomp-authentication]] -==== Authentication - -In a WebSocket-style application it is often useful to know who sent a message. -Therefore some form of authentication is needed to establish the user identity -and associate it with the current session. - -Existing Web applications already use HTTP based authentication. -For example Spring Security can secure the HTTP URLs of the application as usual. -Since a WebSocket session begins with an HTTP handshake, that means URLs mapped -to STOMP/WebSocket are already automatically protected and require authentication. -Moreover the page that opens the WebSocket connection is itself likely protected -and so by the time of the actual handshake, the user should have been authenticated. - -When a WebSocket handshake is made and a new WebSocket session created, -Spring's WebSocket support automatically transfers the `java.security.Principal` -from the HTTP request to the WebSocket session. After that every message flowing -through the application on that WebSocket session is enriched with -the user information. It's present in the message as a header. -Controller methods can access the current user by adding a method argument of -type `javax.security.Principal`. - -Note that even though the STOMP `CONNECT` frame has "login" and "passcode" headers -that can be used for authentication, Spring's STOMP WebSocket support ignores them -and currently expects users to have been authenticated already via HTTP. - -In some cases it may be useful to assign an identity to WebSocket session even -when the user has not formally authenticated. For example a mobile app might -assign some identity to anonymous users, perhaps based on geographical location. -The do that currently, an application can sub-class `DefaultHandshakeHandler` -and override the `determineUser` method. The custom handshake handler can then -be plugged in (see examples in <>). - - - -[[websocket-stomp-user-destination]] -==== User Destinations - -An application can send messages targeting a specific user. -Spring's STOMP support recognizes destinations prefixed with `"/user/"`. -For example, a client might subscribe to the destination `"/user/queue/position-updates"`. -This destination will be handled by the `UserDestinationMessageHandler` and -transformed into a destination unique to the user session, -e.g. `"/queue/position-updates-user123"`. This provides the convenience of subscribing -to a generically named destination while at the same time ensuring no collisions -with other users subscribing to the same destination so that each user can receive -unique stock position updates. - -On the sending side messages can be sent to a destination such as -`"/user/{username}/queue/position-updates"`, which in turn will be translated -by the `UserDestinationMessageHandler` into one or more destinations, one for each -session associated with the user. This allows any component within the application to -send messages targeting a specific user without necessarily knowing anything more -than their name and the generic destination. This is also supported through an -annotation as well as a messaging template. - -For example message-handling method can send messages to the user associated with -the message being handled through the `@SendToUser` annotation: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- -@Controller -public class PortfolioController { - - @MessageMapping("/trade") - @SendToUser("/queue/position-updates") - public TradeResult executeTrade(Trade trade, Principal principal) { - // ... - return tradeResult; - } -} ----- - -If the user has more than one sessions, by default all of the sessions subscribed -to the given destination are targeted. However sometimes, it may be necessary to -target only the session that sent the message being handled. This can be done by -setting the `broadcast` attribute to false, for example: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- -@Controller -public class MyController { - - @MessageMapping("/action") - public void handleAction() throws Exception{ - // raise MyBusinessException here - } - - @MessageExceptionHandler - @SendToUser(value="/queue/errors", broadcast=false) - public ApplicationError handleException(MyBusinessException exception) { - // ... - return appError; - } -} ----- - - -[NOTE] -==== -While user destinations generally imply an authenticated user, it isn't required -strictly. A WebSocket session that is not associated with an authenticated user -can subscribe to a user destination. In such cases the `@SendToUser` annotation -will behave exactly the same as with `broadcast=false`, i.e. targeting only the -session that sent the message being handled. -==== - -It is also possible to send a message to user destinations from any application -component by injecting the `SimpMessageTemplate` created by the Java config or -XML namespace, for example (the bean name is "brokerMessagingTemplate` if required -for qualification with `@Qualifier`): - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- -@Service -public class TradeServiceImpl implements TradeService { - - private final SimpMessageTemplate messagingTemplate; - - @Autowired - public TradeServiceImpl(SimpMessageTemplate messagingTemplate) { - this.messagingTemplate = messagingTemplate; - } - - // ... - - public void afterTradeExecuted(Trade trade) { - this.messagingTemplate.convertAndSendToUser( - trade.getUserName(), "/queue/position-updates", trade.getResult()); - } -} ----- - -[NOTE] -==== -When using user destinations with an external message broker, check the broker -documentation on how to manage inactive queues, so that when the user session is -over, all unique user queues are removed. For example, RabbitMQ creates auto-delete -queues when destinations like `/exchange/amq.direct/position-updates` are used. -So in that case the client could subscribe to `/user/exchange/amq.direct/position-updates`. -ActiveMQ has http://activemq.apache.org/delete-inactive-destinations.html[configuration options] -for purging inactive destinations. -==== - - - - -[[websocket-stomp-appplication-context-events]] -==== Listening To ApplicationContext Events and Intercepting Messages - -Several `ApplicationContext` events (listed below) are published and can be -received by implementing Spring's `ApplicationListener` interface. - -* `BrokerAvailabilityEvent` -- indicates when the broker becomes available/unavailable. -While the "simple" broker becomes available immediately on startup and remains so while -the application is running, the STOMP "broker relay" may lose its connection -to the full featured broker for example if the broker is restarted. The broker relay -has reconnect logic and will re-establish the "system" connection to the broker -when it comes back, hence this event is published whenever the state changes from connected -to disconnected and vice versa. Components using the `SimpMessagingTemplate` should -subscribe to this event and avoid sending messages at times when the broker is not -available. In any case they should be prepared to handle `MessageDeliveryException` -when sending a message. -* `SessionConnectEvent` -- published when a new STOMP CONNECT is received -indicating the start of a new client session. The event contains the message representing the -connect including the session id, user information (if any), and any custom headers the client -may have sent. This is useful for tracking client sessions. Components subscribed -to this event can wrap the contained message using `SimpMessageHeaderAccessor` or -`StompMessageHeaderAccessor`. -* `SessionConnectedEvent` -- published shortly after a `SessionConnectEvent` when the -broker has sent a STOMP CONNECTED frame in response to the CONNECT. At this point the -STOMP session can be considered fully established. -* `SessionSubscribeEvent` -- published when a new STOMP SUBSCRIBE is received. -* `SessionUnsubscribeEvent` -- published when a new STOMP UNSUBSCRIBE is received. -* `SessionDisconnectEvent` -- published when a STOMP session ends. The DISCONNECT may -have been sent from the client or it may also be automatically generated when the -WebSocket session is closed. In some cases this event may be published more than once -per session. Components should be idempotent to multiple disconnect events. - -[NOTE] -==== -When using a full-featured broker, the STOMP "broker relay" automatically reconnects the -"system" connection should the broker become temporarily unavailable. Client connections -however are not automatically reconnected. Assuming heartbeats are enabled, the client -will typically notice the broker is not responding within 10 seconds. Clients need to -implement their own reconnect logic. -==== - -Furthermore, an application can directly intercept every incoming and outgoing message by -registering a `ChannelInterceptor` on the respective message channel. For example -to intercept inbound messages: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Configuration - @EnableWebSocketMessageBroker - public class WebsocketConfig extends AbstractWebSocketMessageBrokerConfigurer { - - @Override - public void configureClientInboundChannel(ChannelRegistration registration) { - registration.setInterceptors(new MyChannelInterceptor()); - } - } ----- - -A custom `ChannelInterceptor` can extend the empty method base class -`ChannelInterceptorAdapter` and use `StompHeaderAccessor` or `SimpMessageHeaderAccessor` -to access information about the message. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class MyChannelInterceptor extends ChannelInterceptorAdapter { - - @Override - public Message preSend(Message message, MessageChannel channel) { - StompHeaderAccessor accessor = StompHeaderAccessor.wrap(message); - StompCommand command = accessor.getStompCommand(); - // ... - return message; - } - } ----- - - - -[[websocket-stomp-websocket-scope]] -==== WebSocket Scope - -Each WebSocket session has a map of attributes. The map is attached as a header to -inbound client messages and may be accessed from a controller method, for example: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- -@Controller -public class MyController { - - @MessageMapping("/action") - public void handle(SimpMessageHeaderAccessor headerAccessor) { - Map attrs = headerAccessor.getSessionAttributes(); - // ... - } -} ----- - -It is also possible to declare a Spring-managed bean in the `"websocket"` scope. -WebSocket-scoped beans can be injected into controllers and any channel interceptors -registered on the "clientInboundChannel". Those are typically singletons and live -longer than any individual WebSocket session. Therefore you will need to use a -scope proxy mode for WebSocket-scoped beans: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- -@Component -@Scope(value="websocket", proxyMode = ScopedProxyMode.TARGET_CLASS) -public class MyBean { - - @PostConstruct - public void init() { - // Invoked after dependencies injected - } - - // ... - - @PreDestroy - public void destroy() { - // Invoked when the WebSocket session ends - } -} - -@Controller -public class MyController { - - private final MyBean myBean; - - @Autowired - public MyController(MyBean myBean) { - this.myBean = myBean; - } - - @MessageMapping("/action") - public void handle() { - // this.myBean from the current WebSocket session - } -} ----- - -As with any custom scope, Spring initializes a new MyBean instance the first -time it is accessed from the controller and stores the instance in the WebSocket -session attributes. The same instance is returned subsequently until the session -ends. WebSocket-scoped beans will have all Spring lifecycle methods invoked as -shown in the examples above. - - - -[[websocket-stomp-configuration-performance]] -==== Configuration and Performance - -There is no silver bullet when it comes to performance. Many factors may -affect it including the size of messages, the volume, whether application -methods perform work that requires blocking, as well as external factors -such as network speed and others. The goal of this section is to provide -an overview of the available configuration options along with some thoughts -on how to reason about scaling. - -In a messaging application messages are passed through channels for asynchronous -executions backed by thread pools. Configuring such an application requires -good knowledge of the channels and the flow of messages. Therefore it is -recommended to review <>. - -The obvious place to start is to configure the thread pools backing the -`"clientInboundChannel"` and the `"clientOutboundChannel"`. By default both -are configured at twice the number of available processors. - -If the handling of messages in annotated methods is mainly CPU bound then the -number of threads for the `"clientInboundChannel"` should remain close to the -number of processors. If the work they do is more IO bound and requires blocking -or waiting on a database or other external system then the thread pool size -will need to be increased. - -[NOTE] -==== -`ThreadPoolExecutor` has 3 important properties. Those are the core and -the max thread pool size as well as the capacity for the queue to store -tasks for which there are no available threads. - -A common point of confusion is that configuring the core pool size (e.g. 10) -and max pool size (e.g. 20) results in a thread pool with 10 to 20 threads. -In fact if the capacity is left at its default value of Integer.MAX_VALUE -then the thread pool will never increase beyond the core pool size since -all additional tasks will be queued. - -Please review the Javadoc of `ThreadPoolExecutor` to learn how these -properties work and understand the various queuing strategies. -==== - -On the `"clientOutboundChannel"` side it is all about sending messages to WebSocket -clients. If clients are on a fast network then the number of threads should -remain close to the number of available processors. If they are slow or on -low bandwidth they will take longer to consume messages and put a burden on the -thread pool. Therefore increasing the thread pool size will be necessary. - -While the workload for the "clientInboundChannel" is possible to predict -- -after all it is based on what the application does -- how to configure the -"clientOutboundChannel" is harder as it is based on factors beyond -the control of the application. For this reason there are two additional -properties related to the sending of messages. Those are the `"sendTimeLimit"` -and the `"sendBufferSizeLimit"`. Those are used to configure how long a -send is allowed to take and how much data can be buffered when sending -messages to a client. - -The general idea is that at any given time only a single thread may be used -to send to a client. All additional messages meanwhile get buffered and you -can use these properties to decide how long sending a message is allowed to -take and how much data can be buffered in the mean time. Please review the -Javadoc of XML schema for this configuration for important additional details. - -Here is example configuration: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Configuration - @EnableWebSocketMessageBroker - public class WebSocketConfig implements WebSocketMessageBrokerConfigurer { - - @Override - public void configureWebSocketTransport(WebSocketTransportRegistration registration) { - registration.setSendTimeLimit(15 * 1000).setSendBufferSizeLimit(512 * 1024); - } - - // ... - - } ----- - -[source,xml,indent=0] -[subs="verbatim,quotes,attributes"] ----- - - - - - - - - ----- - -The WebSocket transport configuration shown above can also be used to configure the -maximum allowed size for incoming STOMP messages. Although in theory a WebSocket -message can be almost unlimited in size, in pracitce WebSocket servers impose -limits. For example 8K on Tomcat and 64K on Jetty. For this reason STOMP clients -such as stomp.js split larger STOMP messages at 16K boundaries and send them as -multiple WebSocket messages thus requiring the server to buffer and re-assemble. - -Spring's STOMP over WebSocket support does this so applications can configure the -maximum size for STOMP messages irrespective of WebSocket server specific message -sizes. Do keep in mind that the WebSocket message size will be automatically -adjusted if necessary to ensure they can carry 16K WebSocket messages at a -minimum. - -Here is example configuration: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Configuration - @EnableWebSocketMessageBroker - public class WebSocketConfig implements WebSocketMessageBrokerConfigurer { - - @Override - public void configureWebSocketTransport(WebSocketTransportRegistration registration) { - registration.setMessageSizeLimit(128 * 1024); - } - - // ... - - } ----- - -[source,xml,indent=0] -[subs="verbatim,quotes,attributes"] ----- - - - - - - - - ----- - -An important point about scaling is using multiple application instances. -Currently it is not possible to do that with the simple broker. -However when using a full-featured broker such as RabbitMQ, each application -instance connects to the broker and messages broadcast from one application -instance can be broadcast through the broker to WebSocket clients connected -through any other application instances. - - - -[[websocket-stomp-stats]] -==== Runtime Monitoring - -When using `@EnableWebSocketMessageBroker` or `` key -infrastructure components automatically gather stats and counters that provide -important insight into the internal state of the application. The configuration -also declares a bean of type `WebSocketMessageBrokerStats` that gathers all -available information in one place and by default logs it at INFO once -every 30 minutes. This bean can be exported to JMX through Spring's -`MBeanExporter` for viewing at runtime for example through JDK's jconsole. -Below is a summary of the available information. - -Client WebSocket Sessions:: - Current::: indicates how many client sessions there are - currently with the count further broken down by WebSocket vs HTTP - streaming and polling SockJS sessions. - Total::: indicates how many total sessions have been established. - Abnormally Closed::: - Connect Failures:::: these are sessions that got established but were - closed after not having received any messages within 60 seconds. This is - usually an indication of proxy or network issues. - Send Limit Exceeded:::: sessions closed after exceeding the configured send - timeout or the send buffer limits which can occur with slow clients - (see previous section). - Transport Errors:::: sessions closed after a transport error such as - failure to read or write to a WebSocket connection or - HTTP request/response. - STOMP Frames::: the total number of CONNECT, CONNECTED, and DISCONNECT frames - processed indicating how many clients connected on the STOMP level. Note that - the DISCONNECT count may be lower when sessions get closed abnormally or when - clients close without sending a DISCONNECT frame. -STOMP Broker Relay:: - TCP Connections::: indicates how many TCP connections on behalf of client - WebSocket sessions are established to the broker. This should be equal to the - number of client WebSocket sessions + 1 additional shared "system" connection - for sending messages from within the application. - STOMP Frames::: the total number of CONNECT, CONNECTED, and DISCONNECT frames - forwarded to or received from the broker on behalf of clients. Note that a - DISCONNECT frame is sent to the broker regardless of how the client WebSocket - session was closed. Therefore a lower DISCONNECT frame count is an indication - that the broker is pro-actively closing connections, may be because of a - heartbeat that didn't arrive in time, an invalid input frame, or other. -Client Inbound Channel:: stats from thread pool backing the "clientInboundChannel" - providing insight into the health of incoming message processing. Tasks queueing - up here is an indication the application may be too slow to handle messages. - If there I/O bound tasks (e.g. slow database query, HTTP request to 3rd party - REST API, etc) consider increasing the thread pool size. -Client Outbound Channel:: stats from the thread pool backing the "clientOutboundChannel" - providing insight into the health of broadcasting messages to clients. Tasks - queueing up here is an indication clients are too slow to consume messages. - One way to address this is to increase the thread pool size to accommodate the - number of concurrent slow clients expected. Another option is to reduce the - send timeout and send buffer size limits (see the previous section). -SockJS Task Scheduler:: stats from thread pool of the SockJS task scheduler which - is used to send heartbeats. Note that when heartbeats are negotiated on the - STOMP level the SockJS heartbeats are disabled. - -[[websocket-stomp-testing]] -==== Testing Annotated Controller Methods - -There are two main approaches to testing applications using Spring's STOMP over -WebSocket support. The first is to write server-side tests verifying the functionality -of controllers and their annotated message handling methods. The second is to write -full end-to-end tests that involve running a client and a server. - -The two approaches are not mutually exclusive. On the contrary each has a place -in an overall test strategy. Server-side tests are more focused and easier to write -and maintain. End-to-end integration tests on the other hand are more complete and -test much more but they're also more involved to write and maintain. - -The simplest form of server-side tests is to write controller unit tests. However -this is not useful enough since much of what a controller does depends on its -annotations. Pure unit tests simply can't test that. - -Ideally controllers under test should be invoked as they are at runtime, much like -the approach to testing controllers handling HTTP requests using the Spring MVC Test -framework. i.e. without running a Servlet container but relying on the Spring Framework -to invoke the annotated controllers. Just like with Spring MVC Test here there are two -two possible alternatives, either using a "context-based" or "standalone" setup: - -1. Load the actual Spring configuration with the help of the -Spring TestContext framework, inject "clientInboundChannel" as a test field, and -use it to send messages to be handled by controller methods. - -2. Manually set up the minimum Spring framework infrastructure required to invoke -controllers (namely the `SimpAnnotationMethodMessageHandler`) and pass messages for -controllers directly to it. - -Both of these setup scenarios are demonstrated in the -https://github.com/rstoyanchev/spring-websocket-portfolio/tree/master/src/test/java/org/springframework/samples/portfolio/web[tests for the stock portfolio] -sample application. - -The second approach is to create end-to-end integration tests. For that you will need -to run a WebSocket server in embedded mode and connect to it as a WebSocket client -sending WebSocket messages containing STOMP frames. -The https://github.com/rstoyanchev/spring-websocket-portfolio/tree/master/src/test/java/org/springframework/samples/portfolio/web[tests for the stock portfolio] -sample application also demonstrate this approach using Tomcat as the embedded -WebSocket server and a simple STOMP client for test purposes. - -[[spring-integration]] -= Integration -[partintro] --- -This part of the reference documentation covers the Spring Framework's integration with -a number of Java EE (and related) technologies. - -* <> -* <> -* <> -* <> -* <> -* <> -* <> -* <> -* <> --- - - - - - -[[remoting]] -== Remoting and web services using Spring - - - - -[[remoting-introduction]] -=== Introduction -Spring features integration classes for remoting support using various technologies. The -remoting support eases the development of remote-enabled services, implemented by your -usual (Spring) POJOs. Currently, Spring supports the following remoting technologies: - -* __Remote Method Invocation (RMI)__. Through the use of the `RmiProxyFactoryBean` and - the `RmiServiceExporter` Spring supports both traditional RMI (with `java.rmi.Remote` - interfaces and `java.rmi.RemoteException`) and transparent remoting via RMI invokers - (with any Java interface). -* __Spring's HTTP invoker__. Spring provides a special remoting strategy which allows - for Java serialization via HTTP, supporting any Java interface (just like the RMI - invoker). The corresponding support classes are `HttpInvokerProxyFactoryBean` and - `HttpInvokerServiceExporter`. -* __Hessian__. By using Spring's `HessianProxyFactoryBean` and the - `HessianServiceExporter` you can transparently expose your services using the - lightweight binary HTTP-based protocol provided by Caucho. -* __Burlap__. Burlap is Caucho's XML-based alternative to Hessian. Spring provides - support classes such as `BurlapProxyFactoryBean` and `BurlapServiceExporter`. -* __JAX-WS__. Spring provides remoting support for web services via JAX-WS (the - successor of JAX-RPC, as introduced in Java EE 5 and Java 6). -* __JMS__. Remoting using JMS as the underlying protocol is supported via the - `JmsInvokerServiceExporter` and `JmsInvokerProxyFactoryBean` classes. -* __AMQP__. Remoting using AMQP as the underlying protocol is supported by the Spring - AMQP project. - -While discussing the remoting capabilities of Spring, we'll use the following domain -model and corresponding services: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class Account implements Serializable{ - - private String name; - - public String getName(){ - return name; - } - - public void setName(String name) { - this.name = name; - } - - } ----- - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public interface AccountService { - - public void insertAccount(Account account); - - public List getAccounts(String name); - - } ----- - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public interface RemoteAccountService extends Remote { - - public void insertAccount(Account account) throws RemoteException; - - public List getAccounts(String name) throws RemoteException; - - } ----- - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - // the implementation doing nothing at the moment - public class AccountServiceImpl implements AccountService { - - public void insertAccount(Account acc) { - // do something... - } - - public List getAccounts(String name) { - // do something... - } - - } ----- - -We will start exposing the service to a remote client by using RMI and talk a bit about -the drawbacks of using RMI. We'll then continue to show an example using Hessian as the -protocol. - - - - -[[remoting-rmi]] -=== Exposing services using RMI -Using Spring's support for RMI, you can transparently expose your services through the -RMI infrastructure. After having this set up, you basically have a configuration similar -to remote EJBs, except for the fact that there is no standard support for security -context propagation or remote transaction propagation. Spring does provide hooks for -such additional invocation context when using the RMI invoker, so you can for example -plug in security frameworks or custom security credentials here. - - - -[[remoting-rmi-server]] -==== Exporting the service using the RmiServiceExporter - -Using the `RmiServiceExporter`, we can expose the interface of our AccountService object -as RMI object. The interface can be accessed by using `RmiProxyFactoryBean`, or via -plain RMI in case of a traditional RMI service. The `RmiServiceExporter` explicitly -supports the exposing of any non-RMI services via RMI invokers. - -Of course, we first have to set up our service in the Spring container: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - ----- - -Next we'll have to expose our service using the `RmiServiceExporter`: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - ----- - -As you can see, we're overriding the port for the RMI registry. Often, your application -server also maintains an RMI registry and it is wise to not interfere with that one. -Furthermore, the service name is used to bind the service under. So right now, the -service will be bound at `'rmi://HOST:1199/AccountService'`. We'll use the URL later on -to link in the service at the client side. - -[NOTE] -==== -The `servicePort` property has been omitted (it defaults to 0). This means that an -anonymous port will be used to communicate with the service. -==== - - - -[[remoting-rmi-client]] -==== Linking in the service at the client -Our client is a simple object using the `AccountService` to manage accounts: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class SimpleObject { - - private AccountService accountService; - - public void setAccountService(AccountService accountService) { - this.accountService = accountService; - } - - // additional methods using the accountService - - } ----- - -To link in the service on the client, we'll create a separate Spring container, -containing the simple object and the service linking configuration bits: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - ----- - -That's all we need to do to support the remote account service on the client. Spring -will transparently create an invoker and remotely enable the account service through the -`RmiServiceExporter`. At the client we're linking it in using the `RmiProxyFactoryBean`. - - - - -[[remoting-caucho-protocols]] -=== Using Hessian or Burlap to remotely call services via HTTP -Hessian offers a binary HTTP-based remoting protocol. It is developed by Caucho and more -information about Hessian itself can be found at http://www.caucho.com[]. - - - -[[remoting-caucho-protocols-hessian]] -==== Wiring up the DispatcherServlet for Hessian and co. - -Hessian communicates via HTTP and does so using a custom servlet. Using Spring's -`DispatcherServlet` principles, as known from Spring Web MVC usage, you can easily wire -up such a servlet exposing your services. First we'll have to create a new servlet in -your application (this is an excerpt from `'web.xml'`): - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - remoting - org.springframework.web.servlet.DispatcherServlet - 1 - - - - remoting - /remoting/* - ----- - -You're probably familiar with Spring's `DispatcherServlet` principles and if so, you -know that now you'll have to create a Spring container configuration resource named -`'remoting-servlet.xml'` (after the name of your servlet) in the `'WEB-INF'` directory. -The application context will be used in the next section. - -Alternatively, consider the use of Spring's simpler `HttpRequestHandlerServlet`. This -allows you to embed the remote exporter definitions in your root application context (by -default in `'WEB-INF/applicationContext.xml'`), with individual servlet definitions -pointing to specific exporter beans. Each servlet name needs to match the bean name of -its target exporter in this case. - - - -[[remoting-caucho-protocols-hessian-server]] -==== Exposing your beans by using the HessianServiceExporter - -In the newly created application context called `remoting-servlet.xml`, we'll create a -`HessianServiceExporter` exporting your services: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - ----- - -Now we're ready to link in the service at the client. No explicit handler mapping is -specified, mapping request URLs onto services, so `BeanNameUrlHandlerMapping` will be -used: Hence, the service will be exported at the URL indicated through its bean name -within the containing `DispatcherServlet`'s mapping (as defined above): -`'http://HOST:8080/remoting/AccountService'`. - -Alternatively, create a `HessianServiceExporter` in your root application context (e.g. -in `'WEB-INF/applicationContext.xml'`): - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - ----- - -In the latter case, define a corresponding servlet for this exporter in `'web.xml'`, -with the same end result: The exporter getting mapped to the request path -`/remoting/AccountService`. Note that the servlet name needs to match the bean name of -the target exporter. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - accountExporter - org.springframework.web.context.support.HttpRequestHandlerServlet - - - - accountExporter - /remoting/AccountService - ----- - - - -[[remoting-caucho-protocols-hessian-client]] -==== Linking in the service on the client -Using the `HessianProxyFactoryBean` we can link in the service at the client. The same -principles apply as with the RMI example. We'll create a separate bean factory or -application context and mention the following beans where the `SimpleObject` is using -the `AccountService` to manage accounts: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - ----- - - - -[[remoting-caucho-protocols-burlap]] -==== Using Burlap -We won't discuss Burlap, the XML-based equivalent of Hessian, in detail here, since it -is configured and set up in exactly the same way as the Hessian variant explained above. -Just replace the word `Hessian` with `Burlap` and you're all set to go. - - - -[[remoting-caucho-protocols-security]] -==== Applying HTTP basic authentication to a service exposed through Hessian or Burlap -One of the advantages of Hessian and Burlap is that we can easily apply HTTP basic -authentication, because both protocols are HTTP-based. Your normal HTTP server security -mechanism can easily be applied through using the `web.xml` security features, for -example. Usually, you don't use per-user security credentials here, but rather shared -credentials defined at the `Hessian/BurlapProxyFactoryBean` level (similar to a JDBC -`DataSource`). - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - ----- - -This is an example where we explicitly mention the `BeanNameUrlHandlerMapping` and set -an interceptor allowing only administrators and operators to call the beans mentioned in -this application context. - -[NOTE] -==== -Of course, this example doesn't show a flexible kind of security infrastructure. For -more options as far as security is concerned, have a look at the Spring Security project -at http://projects.spring.io/spring-security/[]. -==== - - - - -[[remoting-httpinvoker]] -=== Exposing services using HTTP invokers -As opposed to Burlap and Hessian, which are both lightweight protocols using their own -slim serialization mechanisms, Spring HTTP invokers use the standard Java serialization -mechanism to expose services through HTTP. This has a huge advantage if your arguments -and return types are complex types that cannot be serialized using the serialization -mechanisms Hessian and Burlap use (refer to the next section for more considerations -when choosing a remoting technology). - -Under the hood, Spring uses either the standard facilities provided by the JDK or -Apache `HttpComponents` to perform HTTP calls. Use the latter if you need more -advanced and easier-to-use functionality. Refer to -http://hc.apache.org/httpcomponents-client-ga/[hc.apache.org/httpcomponents-client-ga/] -for more information. - - - -[[remoting-httpinvoker-server]] -==== Exposing the service object -Setting up the HTTP invoker infrastructure for a service object resembles closely the -way you would do the same using Hessian or Burlap. Just as Hessian support provides the -`HessianServiceExporter`, Spring's HttpInvoker support provides the -`org.springframework.remoting.httpinvoker.HttpInvokerServiceExporter`. - -To expose the `AccountService` (mentioned above) within a Spring Web MVC -`DispatcherServlet`, the following configuration needs to be in place in the -dispatcher's application context: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - ----- - -Such an exporter definition will be exposed through the `DispatcherServlet`'s standard -mapping facilities, as explained in the section on Hessian. - -Alternatively, create an `HttpInvokerServiceExporter` in your root application context -(e.g. in `'WEB-INF/applicationContext.xml'`): - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - ----- - -In addition, define a corresponding servlet for this exporter in `'web.xml'`, with the -servlet name matching the bean name of the target exporter: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - accountExporter - org.springframework.web.context.support.HttpRequestHandlerServlet - - - - accountExporter - /remoting/AccountService - ----- - -If you are running outside of a servlet container and are using Oracle's Java 6, then you -can use the built-in HTTP server implementation. You can configure the -`SimpleHttpServerFactoryBean` together with a `SimpleHttpInvokerServiceExporter` as is -shown in this example: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - - - - - - ----- - - - -[[remoting-httpinvoker-client]] -==== Linking in the service at the client -Again, linking in the service from the client much resembles the way you would do it -when using Hessian or Burlap. Using a proxy, Spring will be able to translate your calls -to HTTP POST requests to the URL pointing to the exported service. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - ----- - -As mentioned before, you can choose what HTTP client you want to use. By default, the -`HttpInvokerProxy` uses the JDK's HTTP functionality, but you can also use the Apache -`HttpComponents` client by setting the `httpInvokerRequestExecutor` property: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - ----- - - - - -[[remoting-web-services]] -=== Web services -Spring provides full support for standard Java web services APIs: - -* Exposing web services using JAX-WS -* Accessing web services using JAX-WS - -In addition to stock support for JAX-WS in Spring Core, the Spring portfolio also -features http://www.springframework.org/spring-ws[Spring Web Services], a solution for -contract-first, document-driven web services - highly recommended for building modern, -future-proof web services. - - - -[[remoting-web-services-jaxws-export-servlet]] -==== Exposing servlet-based web services using JAX-WS -Spring provides a convenient base class for JAX-WS servlet endpoint implementations - -`SpringBeanAutowiringSupport`. To expose our `AccountService` we extend Spring's -`SpringBeanAutowiringSupport` class and implement our business logic here, usually -delegating the call to the business layer. We'll simply use Spring's `@Autowired` -annotation for expressing such dependencies on Spring-managed beans. - -[source,java,indent=0] ----- - /** - * JAX-WS compliant AccountService implementation that simply delegates - * to the AccountService implementation in the root web application context. - * - * This wrapper class is necessary because JAX-WS requires working with dedicated - * endpoint classes. If an existing service needs to be exported, a wrapper that - * extends SpringBeanAutowiringSupport for simple Spring bean autowiring (through - * the @Autowired annotation) is the simplest JAX-WS compliant way. - * - * This is the class registered with the server-side JAX-WS implementation. - * In the case of a Java EE 5 server, this would simply be defined as a servlet - * in web.xml, with the server detecting that this is a JAX-WS endpoint and reacting - * accordingly. The servlet name usually needs to match the specified WS service name. - * - * The web service engine manages the lifecycle of instances of this class. - * Spring bean references will just be wired in here. - */ - import org.springframework.web.context.support.SpringBeanAutowiringSupport; - - @WebService(serviceName="AccountService") - public class AccountServiceEndpoint extends SpringBeanAutowiringSupport { - - @Autowired - private AccountService biz; - - @WebMethod - public void insertAccount(Account acc) { - biz.insertAccount(acc); - } - - @WebMethod - public Account[] getAccounts(String name) { - return biz.getAccounts(name); - } - - } ----- - -Our `AccountServletEndpoint` needs to run in the same web application as the Spring -context to allow for access to Spring's facilities. This is the case by default in Java -EE 5 environments, using the standard contract for JAX-WS servlet endpoint deployment. -See Java EE 5 web service tutorials for details. - - - -[[remoting-web-services-jaxws-export-standalone]] -==== Exporting standalone web services using JAX-WS -The built-in JAX-WS provider that comes with Oracle's JDK 1.6 supports exposure of web -services using the built-in HTTP server that's included in JDK 1.6 as well. Spring's -`SimpleJaxWsServiceExporter` detects all `@WebService` annotated beans in the Spring -application context, exporting them through the default JAX-WS server (the JDK 1.6 HTTP -server). - -In this scenario, the endpoint instances are defined and managed as Spring beans -themselves; they will be registered with the JAX-WS engine but their lifecycle will be -up to the Spring application context. This means that Spring functionality like explicit -dependency injection may be applied to the endpoint instances. Of course, -annotation-driven injection through `@Autowired` will work as well. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - ... - - - ... ----- - -The `AccountServiceEndpoint` may derive from Spring's `SpringBeanAutowiringSupport` but -doesn't have to since the endpoint is a fully Spring-managed bean here. This means that -the endpoint implementation may look like as follows, without any superclass declared - -and Spring's `@Autowired` configuration annotation still being honored: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @WebService(serviceName="AccountService") - public class AccountServiceEndpoint { - - @Autowired - private AccountService biz; - - @WebMethod - public void insertAccount(Account acc) { - biz.insertAccount(acc); - } - - @WebMethod - public List getAccounts(String name) { - return biz.getAccounts(name); - } - - } ----- - - - -[[remoting-web-services-jaxws-export-ri]] -==== Exporting web services using the JAX-WS RI's Spring support -Oracle's JAX-WS RI, developed as part of the GlassFish project, ships Spring support as -part of its JAX-WS Commons project. This allows for defining JAX-WS endpoints as -Spring-managed beans, similar to the standalone mode discussed in the previous section - -but this time in a Servlet environment. __Note that this is not portable in a Java EE 5 -environment; it is mainly intended for non-EE environments such as Tomcat, embedding the -JAX-WS RI as part of the web application.__ - -The difference to the standard style of exporting servlet-based endpoints is that the -lifecycle of the endpoint instances themselves will be managed by Spring here, and that -there will be only one JAX-WS servlet defined in `web.xml`. With the standard Java EE 5 -style (as illustrated above), you'll have one servlet definition per service endpoint, -with each endpoint typically delegating to Spring beans (through the use of -`@Autowired`, as shown above). - -Check out https://jax-ws-commons.java.net/spring/[https://jax-ws-commons.java.net/spring/] -for details on setup and usage style. - - - -[[remoting-web-services-jaxws-access]] -==== Accessing web services using JAX-WS -Spring provides two factory beans to create JAX-WS web service proxies, namely -`LocalJaxWsServiceFactoryBean` and `JaxWsPortProxyFactoryBean`. The former can only -return a JAX-WS service class for us to work with. The latter is the full-fledged -version that can return a proxy that implements our business service interface. In this -example we use the latter to create a proxy for the `AccountService` endpoint (again): - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - ----- - -Where `serviceInterface` is our business interface the clients will use. -`wsdlDocumentUrl` is the URL for the WSDL file. Spring needs this a startup time to -create the JAX-WS Service. `namespaceUri` corresponds to the targetNamespace in the -.wsdl file. `serviceName` corresponds to the service name in the .wsdl file. `portName` -corresponds to the port name in the .wsdl file. - -Accessing the web service is now very easy as we have a bean factory for it that will -expose it as `AccountService` interface. We can wire this up in Spring: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - ... - - ----- - -From the client code we can access the web service just as if it was a normal class: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class AccountClientImpl { - - private AccountService service; - - public void setService(AccountService service) { - this.service = service; - } - - public void foo() { - service.insertAccount(...); - } - } ----- - -[NOTE] -==== -The above is slightly simplified in that JAX-WS requires endpoint interfaces -and implementation classes to be annotated with `@WebService`, `@SOAPBinding` etc -annotations. This means that you cannot (easily) use plain Java interfaces and -implementation classes as JAX-WS endpoint artifacts; you need to annotate them -accordingly first. Check the JAX-WS documentation for details on those requirements. -==== - - - - -[[remoting-jms]] -=== JMS -It is also possible to expose services transparently using JMS as the underlying -communication protocol. The JMS remoting support in the Spring Framework is pretty basic -- it sends and receives on the `same thread` and in the __same non-transactional__ -`Session`, and as such throughput will be very implementation dependent. Note that these -single-threaded and non-transactional constraints apply only to Spring's JMS -__remoting__ support. See <> for information on Spring's rich support for JMS-based -__messaging__. - -The following interface is used on both the server and the client side. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - package com.foo; - - public interface CheckingAccountService { - - public void cancelAccount(Long accountId); - - } ----- - -The following simple implementation of the above interface is used on the server-side. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - package com.foo; - - public class SimpleCheckingAccountService implements CheckingAccountService { - - public void cancelAccount(Long accountId) { - System.out.println("Cancelling account [" + accountId + "]"); - } - - } ----- - -This configuration file contains the JMS-infrastructure beans that are shared on both -the client and server. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - - - - - ----- - - - -[[remoting-jms-server]] -==== Server-side configuration -On the server, you just need to expose the service object using the -`JmsInvokerServiceExporter`. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - - - - - - - - - - - ----- - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - package com.foo; - - import org.springframework.context.support.ClassPathXmlApplicationContext; - - public class Server { - - public static void main(String[] args) throws Exception { - new ClassPathXmlApplicationContext(new String[]{"com/foo/server.xml", "com/foo/jms.xml"}); - } - - } ----- - - - -[[remoting-jms-client]] -==== Client-side configuration -The client merely needs to create a client-side proxy that will implement the agreed -upon interface ( `CheckingAccountService`). The resulting object created off the back of -the following bean definition can be injected into other client side objects, and the -proxy will take care of forwarding the call to the server-side object via JMS. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - - - ----- - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - package com.foo; - - import org.springframework.context.ApplicationContext; - import org.springframework.context.support.ClassPathXmlApplicationContext; - - public class Client { - - public static void main(String[] args) throws Exception { - ApplicationContext ctx = new ClassPathXmlApplicationContext( - new String[] {"com/foo/client.xml", "com/foo/jms.xml"}); - CheckingAccountService service = (CheckingAccountService) ctx.getBean("checkingAccountService"); - service.cancelAccount(new Long(10)); - } - - } ----- - -You may also wish to investigate the support provided by the -http://lingo.codehaus.org/[Lingo] project, which (to quote the homepage blurb) "__... is -a lightweight POJO based remoting and messaging library based on the Spring Framework's -remoting libraries which extends it to support JMS.__" - - - - -[[remoting-amqp]] -=== AMQP -Refer to the http://docs.spring.io/spring-amqp/reference/html/amqp.html#remoting[Spring -AMQP Reference Document 'Spring Remoting with AMQP' section] for more information. - - - - -[[remoting-autodection-remote-interfaces]] -=== Auto-detection is not implemented for remote interfaces -The main reason why auto-detection of implemented interfaces does not occur for remote -interfaces is to avoid opening too many doors to remote callers. The target object might -implement internal callback interfaces like `InitializingBean` or `DisposableBean` which -one would not want to expose to callers. - -Offering a proxy with all interfaces implemented by the target usually does not matter -in the local case. But when exporting a remote service, you should expose a specific -service interface, with specific operations intended for remote usage. Besides internal -callback interfaces, the target might implement multiple business interfaces, with just -one of them intended for remote exposure. For these reasons, we __require__ such a -service interface to be specified. - -This is a trade-off between configuration convenience and the risk of accidental -exposure of internal methods. Always specifying a service interface is not too much -effort, and puts you on the safe side regarding controlled exposure of specific methods. - - - - -[[remoting-considerations]] -=== Considerations when choosing a technology -Each and every technology presented here has its drawbacks. You should carefully -consider your needs, the services you are exposing and the objects you'll be sending -over the wire when choosing a technology. - -When using RMI, it's not possible to access the objects through the HTTP protocol, -unless you're tunneling the RMI traffic. RMI is a fairly heavy-weight protocol in that -it supports full-object serialization which is important when using a complex data model -that needs serialization over the wire. However, RMI-JRMP is tied to Java clients: It is -a Java-to-Java remoting solution. - -Spring's HTTP invoker is a good choice if you need HTTP-based remoting but also rely on -Java serialization. It shares the basic infrastructure with RMI invokers, just using -HTTP as transport. Note that HTTP invokers are not only limited to Java-to-Java remoting -but also to Spring on both the client and server side. (The latter also applies to -Spring's RMI invoker for non-RMI interfaces.) - -Hessian and/or Burlap might provide significant value when operating in a heterogeneous -environment, because they explicitly allow for non-Java clients. However, non-Java -support is still limited. Known issues include the serialization of Hibernate objects in -combination with lazily-initialized collections. If you have such a data model, consider -using RMI or HTTP invokers instead of Hessian. - -JMS can be useful for providing clusters of services and allowing the JMS broker to take -care of load balancing, discovery and auto-failover. By default: Java serialization is -used when using JMS remoting but the JMS provider could use a different mechanism for -the wire formatting, such as XStream to allow servers to be implemented in other -technologies. - -Last but not least, EJB has an advantage over RMI in that it supports standard -role-based authentication and authorization and remote transaction propagation. It is -possible to get RMI invokers or HTTP invokers to support security context propagation as -well, although this is not provided by core Spring: There are just appropriate hooks for -plugging in third-party or custom solutions here. - - - - -[[rest-client-access]] -=== Accessing RESTful services on the Client -The `RestTemplate` is the core class for client-side access to RESTful services. It is -conceptually similar to other template classes in Spring, such as `JdbcTemplate` and -`JmsTemplate` and other template classes found in other Spring portfolio projects. -`RestTemplate`'s behavior is customized by providing callback methods and configuring -the `HttpMessageConverter` used to marshal objects into the HTTP request body and to -unmarshal any response back into an object. As it is common to use XML as a message -format, Spring provides a `MarshallingHttpMessageConverter` that uses the Object-to-XML -framework that is part of the `org.springframework.oxm` package. This gives you a wide -range of choices of XML to Object mapping technologies to choose from. - -This section describes how to use the `RestTemplate` and its associated -`HttpMessageConverters`. - - - -[[rest-resttemplate]] -==== RestTemplate -Invoking RESTful services in Java is typically done using a helper class such as Apache -HttpComponents `HttpClient`. For common REST operations this approach is too low level as -shown below. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - String uri = "http://example.com/hotels/1/bookings"; - - PostMethod post = new PostMethod(uri); - String request = // create booking request content - post.setRequestEntity(new StringRequestEntity(request)); - - httpClient.executeMethod(post); - - if (HttpStatus.SC_CREATED == post.getStatusCode()) { - Header location = post.getRequestHeader("Location"); - if (location != null) { - System.out.println("Created new booking at :" + location.getValue()); - } - } ----- - -RestTemplate provides higher level methods that correspond to each of the six main HTTP -methods that make invoking many RESTful services a one-liner and enforce REST best -practices. - - -[NOTE] -==== -RestTemplate has an asynchronous counter-part: see <>. -==== - -[[rest-overview-of-resttemplate-methods-tbl]] -.Overview of RestTemplate methods -[cols="1,3"] -|=== -| HTTP Method | RestTemplate Method - -| DELETE -| {javadoc-baseurl}/org/springframework/web/client/RestTemplate.html#delete(String,%20Object...)[delete] - -| GET -| {javadoc-baseurl}/org/springframework/web/client/RestTemplate.html#getForObject(String,%20Class,%20Object...)[getForObject] - {javadoc-baseurl}/org/springframework/web/client/RestTemplate.html#getForEntity(String,%20Class,%20Object...)[getForEntity] - -| HEAD -| {javadoc-baseurl}/org/springframework/web/client/RestTemplate.html#headForHeaders(String,%20Object...)[headForHeaders(String - url, String... urlVariables)] - -| OPTIONS -| {javadoc-baseurl}/org/springframework/web/client/RestTemplate.html#optionsForAllow(String,%20Object...)[optionsForAllow(String - url, String... urlVariables)] - -| POST -| {javadoc-baseurl}/org/springframework/web/client/RestTemplate.html#postForLocation(String,%20Object,%20Object...)[postForLocation(String - url, Object request, String... urlVariables)] - {javadoc-baseurl}/org/springframework/web/client/RestTemplate.html#postForObject(java.lang.String,%20java.lang.Object,%20java.lang.Class,%20java.lang.String...)[postForObject(String - url, Object request, Class responseType, String... uriVariables)] - -| PUT -| {javadoc-baseurl}/org/springframework/web/client/RestTemplate.html#put(String,%20Object,%20Object...)[put(String - url, Object request, String...urlVariables)] - -| PATCH and others -| {javadoc-baseurl}/org/springframework/web/client/RestTemplate.html#exchange(java.lang.String,%20org.springframework.http.HttpMethod,%20org.springframework.http.HttpEntity,%20java.lang.Class,%20java.lang.Object...)[exchange] - {javadoc-baseurl}/org/springframework/web/client/RestTemplate.html#execute(java.lang.String,%20org.springframework.http.HttpMethod,%20org.springframework.web.client.RequestCallback,%20org.springframework.web.client.ResponseExtractor,%20java.lang.Object...)[execute] -|=== - -The names of `RestTemplate` methods follow a naming convention, the first part indicates -what HTTP method is being invoked and the second part indicates what is returned. For -example, the method `getForObject()` will perform a GET, convert the HTTP response into -an object type of your choice and return that object. The method `postForLocation()` -will do a POST, converting the given object into a HTTP request and return the response -HTTP Location header where the newly created object can be found. In case of an -exception processing the HTTP request, an exception of the type `RestClientException` -will be thrown; this behavior can be changed by plugging in another -`ResponseErrorHandler` implementation into the `RestTemplate`. - -The `exchange` and `execute` methods are generalized versions of the more -specific methods listed above them and can support additional combinations and methods, -like HTTP PATCH. However, note that the underlying HTTP library must also support the -desired combination. The JDK `HttpURLConnection` does not support the `PATCH` method, but -Apache HttpComponents HttpClient version 4.2 or later does. They also enable -`RestTemplate` to read an HTTP response to a generic type (e.g. `List`), using a -`ParameterizedTypeReference`, a new class that enables capturing and passing generic -type info. - -Objects passed to and returned from these methods are converted to and from HTTP -messages by `HttpMessageConverter` instances. Converters for the main mime types are -registered by default, but you can also write your own converter and register it via the -`messageConverters()` bean property. The default converter instances registered with the -template are `ByteArrayHttpMessageConverter`, `StringHttpMessageConverter`, -`FormHttpMessageConverter` and `SourceHttpMessageConverter`. You can override these -defaults using the `messageConverters()` bean property as would be required if using the -`MarshallingHttpMessageConverter` or `MappingJackson2HttpMessageConverter`. - -Each method takes URI template arguments in two forms, either as a `String` variable -length argument or a `Map`. For example, - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - String result = restTemplate.getForObject( - "http://example.com/hotels/{hotel}/bookings/{booking}", String.class,"42", "21"); ----- - -using variable length arguments and - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - Map vars = Collections.singletonMap("hotel", "42"); - String result = restTemplate.getForObject( - "http://example.com/hotels/{hotel}/rooms/{hotel}", String.class, vars); ----- - -using a `Map`. - -To create an instance of `RestTemplate` you can simply call the default no-arg -constructor. This will use standard Java classes from the `java.net` package as the -underlying implementation to create HTTP requests. This can be overridden by specifying -an implementation of `ClientHttpRequestFactory`. Spring provides the implementation -`HttpComponentsClientHttpRequestFactory` that uses the Apache HttpComponents -`HttpClient` to create requests. `HttpComponentsClientHttpRequestFactory` is configured -using an instance of `org.apache.http.client.HttpClient` which can in turn be configured -with credentials information or connection pooling functionality. - -[TIP] -==== -Note that the `java.net` implementation for HTTP requests may raise an exception when -accessing the status of a response that represents an error (e.g. 401). If this is an -issue, switch to `HttpComponentsClientHttpRequestFactory` instead. -==== -The previous example using Apache HttpComponents `HttpClient` directly rewritten to use -the `RestTemplate` is shown below - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - uri = "http://example.com/hotels/{id}/bookings"; - - RestTemplate template = new RestTemplate(); - - Booking booking = // create booking object - - URI location = template.postForLocation(uri, booking, "1"); ----- - -To use Apache HttpComponents instead of the native `java.net` functionality, construct -the `RestTemplate` as follows: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - RestTemplate template = new RestTemplate(new HttpComponentsClientHttpRequestFactory()); ----- - -[TIP] -==== -Apache HttpClient supports gzip encoding. To use it, -construct a `HttpComponentsClientHttpRequestFactory` like so: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - HttpClient httpClient = HttpClientBuilder.create().build(); - ClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(httpClient); - RestTemplate restTemplate = new RestTemplate(requestFactory); ----- -==== -The general callback interface is `RequestCallback` and is called when the execute -method is invoked. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public T execute(String url, HttpMethod method, RequestCallback requestCallback, - ResponseExtractor responseExtractor, String... urlVariables) - - // also has an overload with urlVariables as a Map. ----- - -The `RequestCallback` interface is defined as - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public interface RequestCallback { - void doWithRequest(ClientHttpRequest request) throws IOException; - } ----- - -and allows you to manipulate the request headers and write to the request body. When -using the execute method you do not have to worry about any resource management, the -template will always close the request and handle any errors. Refer to the API -documentation for more information on using the execute method and the meaning of its -other method arguments. - - -[[rest-resttemplate-uri]] -===== Working with the URI -For each of the main HTTP methods, the `RestTemplate` provides variants that either take -a String URI or `java.net.URI` as the first argument. - -The String URI variants accept template arguments as a String variable length argument -or as a `Map`. They also assume the URL String is not encoded and needs -to be encoded. For example the following: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - restTemplate.getForObject("http://example.com/hotel list", String.class); ----- - -will perform a GET on `http://example.com/hotel%20list`. That means if the input URL -String is already encoded, it will be encoded twice -- i.e. -`http://example.com/hotel%20list` will become `http://example.com/hotel%2520list`. If -this is not the intended effect, use the `java.net.URI` method variant, which assumes -the URL is already encoded is also generally useful if you want to reuse a single (fully -expanded) `URI` multiple times. - -The `UriComponentsBuilder` class can be used to build and encode the `URI` including -support for URI templates. For example you can start with a URL String: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - UriComponents uriComponents = UriComponentsBuilder.fromUriString( - "http://example.com/hotels/{hotel}/bookings/{booking}").build() - .expand("42", "21") - .encode(); - - URI uri = uriComponents.toUri(); ----- - -Or specify each URI component individually: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - UriComponents uriComponents = UriComponentsBuilder.newInstance() - .scheme("http").host("example.com").path("/hotels/{hotel}/bookings/{booking}").build() - .expand("42", "21") - .encode(); - - URI uri = uriComponents.toUri(); ----- - - -[[rest-template-headers]] -===== Dealing with request and response headers -Besides the methods described above, the `RestTemplate` also has the `exchange()` -method, which can be used for arbitrary HTTP method execution based on the `HttpEntity` -class. - -Perhaps most importantly, the `exchange()` method can be used to add request headers and -read response headers. For example: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - HttpHeaders requestHeaders = new HttpHeaders(); - requestHeaders.set("MyRequestHeader", "MyValue"); - HttpEntity requestEntity = new HttpEntity(requestHeaders); - - HttpEntity response = template.exchange( - "http://example.com/hotels/{hotel}", - HttpMethod.GET, requestEntity, String.class, "42"); - - String responseHeader = response.getHeaders().getFirst("MyResponseHeader"); - String body = response.getBody(); ----- - -In the above example, we first prepare a request entity that contains the -`MyRequestHeader` header. We then retrieve the response, and read the `MyResponseHeader` -and body. - -[[rest-template-jsonview]] -===== Jackson JSON Views support - -It is possible to specify a http://wiki.fasterxml.com/JacksonJsonViews[Jackson JSON View] -to serialize only a subset of the object properties. For example: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - JacksonSerializationValue jsv = new JacksonSerializationValue(new User("eric", "7!jd#h23"), - User.WithoutPasswordView.class); - HttpEntity entity = new HttpEntity(jsv); - String s = template.postForObject("http://example.com/user", entity, String.class); ----- - - -[[rest-message-conversion]] -==== HTTP Message Conversion -Objects passed to and returned from the methods `getForObject()`, `postForLocation()`, -and `put()` are converted to HTTP requests and from HTTP responses by -`HttpMessageConverters`. The `HttpMessageConverter` interface is shown below to give you -a better feel for its functionality - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public interface HttpMessageConverter { - - // Indicate whether the given class and media type can be read by this converter. - boolean canRead(Class clazz, MediaType mediaType); - - // Indicate whether the given class and media type can be written by this converter. - boolean canWrite(Class clazz, MediaType mediaType); - - // Return the list of MediaType objects supported by this converter. - List getSupportedMediaTypes(); - - // Read an object of the given type from the given input message, and returns it. - T read(Class clazz, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException; - - // Write an given object to the given output message. - void write(T t, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException; - - } ----- - -Concrete implementations for the main media (mime) types are provided in the framework -and are registered by default with the `RestTemplate` on the client-side and with -`AnnotationMethodHandlerAdapter` on the server-side. - -The implementations of ++HttpMessageConverter++s are described in the following sections. -For all converters a default media type is used but can be overridden by setting the -`supportedMediaTypes` bean property - - -[[rest-string-converter]] -===== StringHttpMessageConverter -An `HttpMessageConverter` implementation that can read and write Strings from the HTTP -request and response. By default, this converter supports all text media types ( -`text/*`), and writes with a `Content-Type` of `text/plain`. - - -[[rest-form-converter]] -===== FormHttpMessageConverter -An `HttpMessageConverter` implementation that can read and write form data from the HTTP -request and response. By default, this converter reads and writes the media type -`application/x-www-form-urlencoded`. Form data is read from and written into a -`MultiValueMap`. - - -[[rest-byte-converter]] -===== ByteArrayHttpMessageConverter -An `HttpMessageConverter` implementation that can read and write byte arrays from the -HTTP request and response. By default, this converter supports all media types ( `*/*`), -and writes with a `Content-Type` of `application/octet-stream`. This can be overridden -by setting the `supportedMediaTypes` property, and overriding `getContentType(byte[])`. - - -[[rest-marhsalling-converter]] -===== MarshallingHttpMessageConverter -An `HttpMessageConverter` implementation that can read and write XML using Spring's -`Marshaller` and `Unmarshaller` abstractions from the `org.springframework.oxm` package. -This converter requires a `Marshaller` and `Unmarshaller` before it can be used. These -can be injected via constructor or bean properties. By default this converter supports ( -`text/xml`) and ( `application/xml`). - - -[[rest-mapping-json-converter]] -===== MappingJackson2HttpMessageConverter -An `HttpMessageConverter` implementation that can read and write JSON using Jackson's -`ObjectMapper`. JSON mapping can be customized as needed through the use of Jackson's -provided annotations. When further control is needed, a custom `ObjectMapper` can be -injected through the `ObjectMapper` property for cases where custom JSON -serializers/deserializers need to be provided for specific types. By default this -converter supports ( `application/json`). - - -[[rest-mapping-xml-converter]] -===== MappingJackson2XmlHttpMessageConverter -An `HttpMessageConverter` implementation that can read and write XML using -https://github.com/FasterXML/jackson-dataformat-xml[Jackson XML] extension's -`XmlMapper`. XML mapping can be customized as needed through the use of JAXB -or Jackson's provided annotations. When further control is needed, a custom `XmlMapper` -can be injected through the `ObjectMapper` property for cases where custom XML -serializers/deserializers need to be provided for specific types. By default this -converter supports ( `application/xml`). - - -[[rest-source-converter]] -===== SourceHttpMessageConverter -An `HttpMessageConverter` implementation that can read and write -`javax.xml.transform.Source` from the HTTP request and response. Only `DOMSource`, -`SAXSource`, and `StreamSource` are supported. By default, this converter supports ( -`text/xml`) and ( `application/xml`). - - -[[rest-buffered-image-converter]] -===== BufferedImageHttpMessageConverter -An `HttpMessageConverter` implementation that can read and write -`java.awt.image.BufferedImage` from the HTTP request and response. This converter reads -and writes the media type supported by the Java I/O API. - -[[rest-async-resttemplate]] -==== Async RestTemplate - -Web applications often need to query external REST services those days. The very nature of -HTTP and synchronous calls can lead up to challenges when scaling applications for those -needs: multiple threads may be blocked, waiting for remote HTTP responses. - -`AsyncRestTemplate` and <>'s APIs are very similar; see -<>. The main difference between those APIs is -that `AsyncRestTemplate` returns -{javadoc-baseurl}/org/springframework/util/concurrent/ListenableFuture.html[`ListenableFuture`] -wrappers as opposed to concrete results. - -The previous `RestTemplate` example translates to: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - // async call - Future> futureEntity = template.getForEntity( - "http://example.com/hotels/{hotel}/bookings/{booking}", String.class, "42", "21"); - - // get the concrete result - synchronous call - ResponseEntity entity = futureEntity.get(); ----- - -{javadoc-baseurl}/org/springframework/util/concurrent/ListenableFuture.html[`ListenableFuture`] -accepts completion callbacks: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - ListenableFuture> futureEntity = template.getForEntity( - "http://example.com/hotels/{hotel}/bookings/{booking}", String.class, "42", "21"); - - // register a callback - futureEntity.addCallback(new ListenableFutureCallback>() { - @Override - public void onSuccess(ResponseEntity entity) { - //... - } - - @Override - public void onFailure(Throwable t) { - //... - } - }); ----- - -[NOTE] -==== -The default `AsyncRestTemplate` constructor registers a -{javadoc-baseurl}/org/springframework/core/task/SimpleAsyncTaskExecutor.html[`SimpleAsyncTaskExecutor` -] for executing HTTP requests. -When dealing with a large number of short-lived requests, a thread-pooling TaskExecutor -implementation like -{javadoc-baseurl}/org/springframework/scheduling/concurrent/ThreadPoolTaskExecutor.html[`ThreadPoolTaskExecutor`] -may be a good choice. -==== - -See the -{javadoc-baseurl}/org/springframework/util/concurrent/ListenableFuture.html[`ListenableFuture` javadocs] -and -{javadoc-baseurl}/org/springframework/web/client/AsyncRestTemplate.html[`AsyncRestTemplate` javadocs] -for more details. - - - - - -[[ejb]] -== Enterprise JavaBeans (EJB) integration - - - - -[[ejb-introduction]] -=== Introduction -As a lightweight container, Spring is often considered an EJB replacement. We do believe -that for many if not most applications and use cases, Spring as a container, combined -with its rich supporting functionality in the area of transactions, ORM and JDBC access, -is a better choice than implementing equivalent functionality via an EJB container and -EJBs. - -However, it is important to note that using Spring does not prevent you from using EJBs. -In fact, Spring makes it much easier to access EJBs and implement EJBs and functionality -within them. Additionally, using Spring to access services provided by EJBs allows the -implementation of those services to later transparently be switched between local EJB, -remote EJB, or POJO (plain old Java object) variants, without the client code having to -be changed. - -In this chapter, we look at how Spring can help you access and implement EJBs. Spring -provides particular value when accessing stateless session beans (SLSBs), so we'll begin -by discussing this. - - - - -[[ejb-access]] -=== Accessing EJBs - - - -[[ejb-access-concepts]] -==== Concepts -To invoke a method on a local or remote stateless session bean, client code must -normally perform a JNDI lookup to obtain the (local or remote) EJB Home object, then use -a 'create' method call on that object to obtain the actual (local or remote) EJB object. -One or more methods are then invoked on the EJB. - -To avoid repeated low-level code, many EJB applications use the Service Locator and -Business Delegate patterns. These are better than spraying JNDI lookups throughout -client code, but their usual implementations have significant disadvantages. For example: - -* Typically code using EJBs depends on Service Locator or Business Delegate singletons, - making it hard to test. -* In the case of the Service Locator pattern used without a Business Delegate, - application code still ends up having to invoke the create() method on an EJB home, - and deal with the resulting exceptions. Thus it remains tied to the EJB API and the - complexity of the EJB programming model. -* Implementing the Business Delegate pattern typically results in significant code - duplication, where we have to write numerous methods that simply call the same method - on the EJB. - -The Spring approach is to allow the creation and use of proxy objects, normally -configured inside a Spring container, which act as codeless business delegates. You do -not need to write another Service Locator, another JNDI lookup, or duplicate methods in -a hand-coded Business Delegate unless you are actually adding real value in such code. - - - -[[ejb-access-local]] -==== Accessing local SLSBs -Assume that we have a web controller that needs to use a local EJB. We'll follow best -practice and use the EJB Business Methods Interface pattern, so that the EJB's local -interface extends a non EJB-specific business methods interface. Let's call this -business methods interface `MyComponent`. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public interface MyComponent { - ... - } ----- - -One of the main reasons to use the Business Methods Interface pattern is to ensure that -synchronization between method signatures in local interface and bean implementation -class is automatic. Another reason is that it later makes it much easier for us to -switch to a POJO (plain old Java object) implementation of the service if it makes sense -to do so. Of course we'll also need to implement the local home interface and provide an -implementation class that implements `SessionBean` and the `MyComponent` business -methods interface. Now the only Java coding we'll need to do to hook up our web tier -controller to the EJB implementation is to expose a setter method of type `MyComponent` -on the controller. This will save the reference as an instance variable in the -controller: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - private MyComponent myComponent; - - public void setMyComponent(MyComponent myComponent) { - this.myComponent = myComponent; - } ----- - -We can subsequently use this instance variable in any business method in the controller. -Now assuming we are obtaining our controller object out of a Spring container, we can -(in the same context) configure a `LocalStatelessSessionProxyFactoryBean` instance, -which will be the EJB proxy object. The configuration of the proxy, and setting of the -`myComponent` property of the controller is done with a configuration entry such as: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - ----- - -There's a lot of work happening behind the scenes, courtesy of the Spring AOP framework, -although you aren't forced to work with AOP concepts to enjoy the results. The -`myComponent` bean definition creates a proxy for the EJB, which implements the business -method interface. The EJB local home is cached on startup, so there's only a single JNDI -lookup. Each time the EJB is invoked, the proxy invokes the `classname` method on the -local EJB and invokes the corresponding business method on the EJB. - -The `myController` bean definition sets the `myComponent` property of the controller -class to the EJB proxy. - -Alternatively (and preferably in case of many such proxy definitions), consider using -the `` configuration element in Spring's "jee" namespace: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - ----- - -This EJB access mechanism delivers huge simplification of application code: the web tier -code (or other EJB client code) has no dependence on the use of EJB. If we want to -replace this EJB reference with a POJO or a mock object or other test stub, we could -simply change the `myComponent` bean definition without changing a line of Java code. -Additionally, we haven't had to write a single line of JNDI lookup or other EJB plumbing -code as part of our application. - -Benchmarks and experience in real applications indicate that the performance overhead of -this approach (which involves reflective invocation of the target EJB) is minimal, and -is typically undetectable in typical use. Remember that we don't want to make -fine-grained calls to EJBs anyway, as there's a cost associated with the EJB -infrastructure in the application server. - -There is one caveat with regards to the JNDI lookup. In a bean container, this class is -normally best used as a singleton (there simply is no reason to make it a prototype). -However, if that bean container pre-instantiates singletons (as do the various XML -`ApplicationContext` variants) you may have a problem if the bean container is loaded -before the EJB container loads the target EJB. That is because the JNDI lookup will be -performed in the `init()` method of this class and then cached, but the EJB will not -have been bound at the target location yet. The solution is to not pre-instantiate this -factory object, but allow it to be created on first use. In the XML containers, this is -controlled via the `lazy-init` attribute. - -Although this will not be of interest to the majority of Spring users, those doing -programmatic AOP work with EJBs may want to look at `LocalSlsbInvokerInterceptor`. - - - -[[ejb-access-remote]] -==== Accessing remote SLSBs -Accessing remote EJBs is essentially identical to accessing local EJBs, except that the -`SimpleRemoteStatelessSessionProxyFactoryBean` or `` configuration -element is used. Of course, with or without Spring, remote invocation semantics apply; a -call to a method on an object in another VM in another computer does sometimes have to -be treated differently in terms of usage scenarios and failure handling. - -Spring's EJB client support adds one more advantage over the non-Spring approach. -Normally it is problematic for EJB client code to be easily switched back and forth -between calling EJBs locally or remotely. This is because the remote interface methods -must declare that they throw `RemoteException`, and client code must deal with this, -while the local interface methods don't. Client code written for local EJBs which needs -to be moved to remote EJBs typically has to be modified to add handling for the remote -exceptions, and client code written for remote EJBs which needs to be moved to local -EJBs, can either stay the same but do a lot of unnecessary handling of remote -exceptions, or needs to be modified to remove that code. With the Spring remote EJB -proxy, you can instead not declare any thrown `RemoteException` in your Business Method -Interface and implementing EJB code, have a remote interface which is identical except -that it does throw `RemoteException`, and rely on the proxy to dynamically treat the two -interfaces as if they were the same. That is, client code does not have to deal with the -checked `RemoteException` class. Any actual `RemoteException` that is thrown during the -EJB invocation will be re-thrown as the non-checked `RemoteAccessException` class, which -is a subclass of `RuntimeException`. The target service can then be switched at will -between a local EJB or remote EJB (or even plain Java object) implementation, without -the client code knowing or caring. Of course, this is optional; there is nothing -stopping you from declaring `RemoteExceptions` in your business interface. - - - -[[ejb-access-ejb2-ejb3]] -==== Accessing EJB 2.x SLSBs versus EJB 3 SLSBs -Accessing EJB 2.x Session Beans and EJB 3 Session Beans via Spring is largely -transparent. Spring's EJB accessors, including the `` and -`` facilities, transparently adapt to the actual component at runtime. -They handle a home interface if found (EJB 2.x style), or perform straight component -invocations if no home interface is available (EJB 3 style). - -Note: For EJB 3 Session Beans, you could effectively use a `JndiObjectFactoryBean` / -`` as well, since fully usable component references are exposed for -plain JNDI lookups there. Defining explicit `` / `` -lookups simply provides consistent and more explicit EJB access configuration. - - - - -[[ejb-implementation]] -=== Using Spring's EJB implementation support classes - - - -[[ejb-implementation-ejb3]] -==== EJB 3 injection interceptor -For EJB 3 Session Beans and Message-Driven Beans, Spring provides a convenient -interceptor that resolves Spring's `@Autowired` annotation in the EJB component -class: `org.springframework.ejb.interceptor.SpringBeanAutowiringInterceptor`. This -interceptor can be applied through an `@Interceptors` annotation in the EJB component -class, or through an `interceptor-binding` XML element in the EJB deployment descriptor. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Stateless - @Interceptors(SpringBeanAutowiringInterceptor.class) - public class MyFacadeEJB implements MyFacadeLocal { - - // automatically injected with a matching Spring bean - @Autowired - private MyComponent myComp; - - // for business method, delegate to POJO service impl. - public String myFacadeMethod(...) { - return myComp.myMethod(...); - } - - ... - - } ----- - -`SpringBeanAutowiringInterceptor` by default obtains target beans from a -`ContextSingletonBeanFactoryLocator`, with the context defined in a bean definition file -named `beanRefContext.xml`. By default, a single context definition is expected, which -is obtained by type rather than by name. However, if you need to choose between multiple -context definitions, a specific locator key is required. The locator key (i.e. the name -of the context definition in `beanRefContext.xml`) can be explicitly specified either -through overriding the `getBeanFactoryLocatorKey` method in a custom -`SpringBeanAutowiringInterceptor` subclass. - -Alternatively, consider overriding `SpringBeanAutowiringInterceptor`'s `getBeanFactory` -method, e.g. obtaining a shared `ApplicationContext` from a custom holder class. - - - - - -[[jms]] -== JMS (Java Message Service) - - - - -[[jms-introduction]] -=== Introduction -Spring provides a JMS integration framework that simplifies the use of the JMS API much -like Spring's integration does for the JDBC API. - -JMS can be roughly divided into two areas of functionality, namely the production and -consumption of messages. The `JmsTemplate` class is used for message production and -synchronous message reception. For asynchronous reception similar to Java EE's -message-driven bean style, Spring provides a number of message listener containers that -are used to create Message-Driven POJOs (MDPs). Spring also provides a declarative way -of creating message listeners. - -The package `org.springframework.jms.core` provides the core functionality for using -JMS. It contains JMS template classes that simplify the use of the JMS by handling the -creation and release of resources, much like the `JdbcTemplate` does for JDBC. The -design principle common to Spring template classes is to provide helper methods to -perform common operations and for more sophisticated usage, delegate the essence of the -processing task to user implemented callback interfaces. The JMS template follows the -same design. The classes offer various convenience methods for the sending of messages, -consuming a message synchronously, and exposing the JMS session and message producer to -the user. - -The package `org.springframework.jms.support` provides `JMSException` translation -functionality. The translation converts the checked `JMSException` hierarchy to a -mirrored hierarchy of unchecked exceptions. If there are any provider specific -subclasses of the checked `javax.jms.JMSException`, this exception is wrapped in the -unchecked `UncategorizedJmsException`. - -The package `org.springframework.jms.support.converter` provides a `MessageConverter` -abstraction to convert between Java objects and JMS messages. - -The package `org.springframework.jms.support.destination` provides various strategies -for managing JMS destinations, such as providing a service locator for destinations -stored in JNDI. - -The package `org.springframework.jms.annotation` provides the necessary infrastructure -to support annotation-driven listener endpoints using `@JmsListener`. - -The package `org.springframework.jms.config` provides the parser implementation for the -`jms` namespace as well the java config support to configure listener containers and -create listener endpoints. - -Finally, the package `org.springframework.jms.connection` provides an implementation of -the `ConnectionFactory` suitable for use in standalone applications. It also contains an -implementation of Spring's `PlatformTransactionManager` for JMS (the cunningly named -`JmsTransactionManager`). This allows for seamless integration of JMS as a transactional -resource into Spring's transaction management mechanisms. - - - - -[[jms-using]] -=== Using Spring JMS - - - -[[jms-jmstemplate]] -==== JmsTemplate - -The `JmsTemplate` class is the central class in the JMS core package. It simplifies the -use of JMS since it handles the creation and release of resources when sending or -synchronously receiving messages. - -Code that uses the `JmsTemplate` only needs to implement callback interfaces giving them -a clearly defined high level contract. The `MessageCreator` callback interface creates a -message given a `Session` provided by the calling code in `JmsTemplate`. In order to -allow for more complex usage of the JMS API, the callback `SessionCallback` provides the -user with the JMS session and the callback `ProducerCallback` exposes a `Session` and -`MessageProducer` pair. - -The JMS API exposes two types of send methods, one that takes delivery mode, priority, -and time-to-live as Quality of Service (QOS) parameters and one that takes no QOS -parameters which uses default values. Since there are many send methods in -`JmsTemplate`, the setting of the QOS parameters have been exposed as bean properties to -avoid duplication in the number of send methods. Similarly, the timeout value for -synchronous receive calls is set using the property `setReceiveTimeout`. - -Some JMS providers allow the setting of default QOS values administratively through the -configuration of the `ConnectionFactory`. This has the effect that a call to -`MessageProducer`'s send method `send(Destination destination, Message message)` will -use different QOS default values than those specified in the JMS specification. In order -to provide consistent management of QOS values, the `JmsTemplate` must therefore be -specifically enabled to use its own QOS values by setting the boolean property -`isExplicitQosEnabled` to `true`. - -For convenience, `JmsTemplate` also exposes a basic request-reply operation that allows -to send a message and wait for a reply on a temporary queue that is created as part of -the operation. - -[NOTE] -==== -Instances of the `JmsTemplate` class are __thread-safe once configured__. This is -important because it means that you can configure a single instance of a `JmsTemplate` -and then safely inject this __shared__ reference into multiple collaborators. To be -clear, the `JmsTemplate` is stateful, in that it maintains a reference to a -`ConnectionFactory`, but this state is __not__ conversational state. -==== - -As of Spring Framework 4.1, `JmsMessagingTemplate` is built on top of `JmsTemplate` -and provides an integration with the messaging abstraction, i.e. -`org.springframework.messaging.Message`. This allows you to create the message to -send in generic manner. - - -[[jms-connections]] -==== Connections -The `JmsTemplate` requires a reference to a `ConnectionFactory`. The `ConnectionFactory` -is part of the JMS specification and serves as the entry point for working with JMS. It -is used by the client application as a factory to create connections with the JMS -provider and encapsulates various configuration parameters, many of which are vendor -specific such as SSL configuration options. - -When using JMS inside an EJB, the vendor provides implementations of the JMS interfaces -so that they can participate in declarative transaction management and perform pooling -of connections and sessions. In order to use this implementation, Java EE containers -typically require that you declare a JMS connection factory as a `resource-ref` inside -the EJB or servlet deployment descriptors. To ensure the use of these features with the -`JmsTemplate` inside an EJB, the client application should ensure that it references the -managed implementation of the `ConnectionFactory`. - - -[[jms-caching-resources]] -===== Caching Messaging Resources -The standard API involves creating many intermediate objects. To send a message the -following 'API' walk is performed - -[literal] -[subs="verbatim,quotes"] ----- -ConnectionFactory->Connection->Session->MessageProducer->send ----- - -Between the ConnectionFactory and the Send operation there are three intermediate -objects that are created and destroyed. To optimise the resource usage and increase -performance two implementations of `ConnectionFactory` are provided. - - -[[jms-connection-factory]] -===== SingleConnectionFactory -Spring provides an implementation of the `ConnectionFactory` interface, -`SingleConnectionFactory`, that will return the same `Connection` on all -`createConnection()` calls and ignore calls to `close()`. This is useful for testing and -standalone environments so that the same connection can be used for multiple -`JmsTemplate` calls that may span any number of transactions. `SingleConnectionFactory` -takes a reference to a standard `ConnectionFactory` that would typically come from JNDI. - - -[[jdbc-connection-factory-caching]] -===== CachingConnectionFactory -The `CachingConnectionFactory` extends the functionality of `SingleConnectionFactory` -and adds the caching of Sessions, MessageProducers, and MessageConsumers. The initial -cache size is set to 1, use the property `SessionCacheSize` to increase the number of -cached sessions. Note that the number of actual cached sessions will be more than that -number as sessions are cached based on their acknowledgment mode, so there can be up to -4 cached session instances when `SessionCacheSize` is set to one, one for each -`AcknowledgementMode`. MessageProducers and MessageConsumers are cached within their -owning session and also take into account the unique properties of the producers and -consumers when caching. MessageProducers are cached based on their destination. -MessageConsumers are cached based on a key composed of the destination, selector, -noLocal delivery flag, and the durable subscription name (if creating durable consumers). - - - -[[jms-destinations]] -==== Destination Management -Destinations, like ConnectionFactories, are JMS administered objects that can be stored -and retrieved in JNDI. When configuring a Spring application context you can use the -JNDI factory class `JndiObjectFactoryBean` / `` to perform dependency -injection on your object's references to JMS destinations. However, often this strategy -is cumbersome if there are a large number of destinations in the application or if there -are advanced destination management features unique to the JMS provider. Examples of -such advanced destination management would be the creation of dynamic destinations or -support for a hierarchical namespace of destinations. The `JmsTemplate` delegates the -resolution of a destination name to a JMS destination object to an implementation of the -interface `DestinationResolver`. `DynamicDestinationResolver` is the default -implementation used by `JmsTemplate` and accommodates resolving dynamic destinations. A -`JndiDestinationResolver` is also provided that acts as a service locator for -destinations contained in JNDI and optionally falls back to the behavior contained in -`DynamicDestinationResolver`. - -Quite often the destinations used in a JMS application are only known at runtime and -therefore cannot be administratively created when the application is deployed. This is -often because there is shared application logic between interacting system components -that create destinations at runtime according to a well-known naming convention. Even -though the creation of dynamic destinations is not part of the JMS specification, most -vendors have provided this functionality. Dynamic destinations are created with a name -defined by the user which differentiates them from temporary destinations and are often -not registered in JNDI. The API used to create dynamic destinations varies from provider -to provider since the properties associated with the destination are vendor specific. -However, a simple implementation choice that is sometimes made by vendors is to -disregard the warnings in the JMS specification and to use the `TopicSession` method -`createTopic(String topicName)` or the `QueueSession` method `createQueue(String -queueName)` to create a new destination with default destination properties. Depending -on the vendor implementation, `DynamicDestinationResolver` may then also create a -physical destination instead of only resolving one. - -The boolean property `pubSubDomain` is used to configure the `JmsTemplate` with -knowledge of what JMS domain is being used. By default the value of this property is -false, indicating that the point-to-point domain, Queues, will be used. This property -used by `JmsTemplate` determines the behavior of dynamic destination resolution via -implementations of the `DestinationResolver` interface. - -You can also configure the `JmsTemplate` with a default destination via the property -`defaultDestination`. The default destination will be used with send and receive -operations that do not refer to a specific destination. - - - -[[jms-mdp]] -==== Message Listener Containers -One of the most common uses of JMS messages in the EJB world is to drive message-driven -beans (MDBs). Spring offers a solution to create message-driven POJOs (MDPs) in a way -that does not tie a user to an EJB container. (See <> -for detailed coverage of Spring's MDP support.) As from Spring Framework 4.1, endpoint -methods can be simply annotated using `@JmsListener` see <> for more -details. - -A message listener container is used to receive messages from a JMS message queue and -drive the `MessageListener` that is injected into it. The listener container is -responsible for all threading of message reception and dispatches into the listener for -processing. A message listener container is the intermediary between an MDP and a -messaging provider, and takes care of registering to receive messages, participating in -transactions, resource acquisition and release, exception conversion and suchlike. This -allows you as an application developer to write the (possibly complex) business logic -associated with receiving a message (and possibly responding to it), and delegates -boilerplate JMS infrastructure concerns to the framework. - -There are two standard JMS message listener containers packaged with Spring, each with -its specialised feature set. - - -[[jms-mdp-simple]] -===== SimpleMessageListenerContainer -This message listener container is the simpler of the two standard flavors. It creates a -fixed number of JMS sessions and consumers at startup, registers the listener using the -standard JMS `MessageConsumer.setMessageListener()` method, and leaves it up the JMS -provider to perform listener callbacks. This variant does not allow for dynamic adaption -to runtime demands or for participation in externally managed transactions. -Compatibility-wise, it stays very close to the spirit of the standalone JMS -specification - but is generally not compatible with Java EE's JMS restrictions. - - -[[jms-mdp-default]] -===== DefaultMessageListenerContainer -This message listener container is the one used in most cases. In contrast to -`SimpleMessageListenerContainer`, this container variant does allow for dynamic adaption -to runtime demands and is able to participate in externally managed transactions. Each -received message is registered with an XA transaction when configured with a -`JtaTransactionManager`; so processing may take advantage of XA transaction semantics. -This listener container strikes a good balance between low requirements on the JMS -provider, advanced functionality such as transaction participation, and compatibility -with Java EE environments. - -The cache level of the container can be customized. Note that when no caching is enabled, -a new connection and a new session is created for each message reception. Combining this -with a non durable subscription with high loads may lead to message lost. Make sure to -use a proper cache level in such case. - -This container also has recoverable capabilities when the broker goes down. By default, -a simple `BackOff` implementation retries every 5 seconds. It is possible to specify -a custom `BackOff` implementation for more fine-grained recovery options, see -`ExponentialBackOff` for an example. - - -[[jms-tx]] -==== Transaction management -Spring provides a `JmsTransactionManager` that manages transactions for a single JMS -`ConnectionFactory`. This allows JMS applications to leverage the managed transaction -features of Spring as described in <>. The `JmsTransactionManager` performs -local resource transactions, binding a JMS Connection/Session pair from the specified -`ConnectionFactory` to the thread. `JmsTemplate` automatically detects such -transactional resources and operates on them accordingly. - -In a Java EE environment, the `ConnectionFactory` will pool Connections and Sessions, so -those resources are efficiently reused across transactions. In a standalone environment, -using Spring's `SingleConnectionFactory` will result in a shared JMS `Connection`, with -each transaction having its own independent `Session`. Alternatively, consider the use -of a provider-specific pooling adapter such as ActiveMQ's `PooledConnectionFactory` -class. - -`JmsTemplate` can also be used with the `JtaTransactionManager` and an XA-capable JMS -`ConnectionFactory` for performing distributed transactions. Note that this requires the -use of a JTA transaction manager as well as a properly XA-configured ConnectionFactory! -(Check your Java EE server's / JMS provider's documentation.) - -Reusing code across a managed and unmanaged transactional environment can be confusing -when using the JMS API to create a `Session` from a `Connection`. This is because the -JMS API has only one factory method to create a `Session` and it requires values for the -transaction and acknowledgement modes. In a managed environment, setting these values is -the responsibility of the environment's transactional infrastructure, so these values -are ignored by the vendor's wrapper to the JMS Connection. When using the `JmsTemplate` -in an unmanaged environment you can specify these values through the use of the -properties `sessionTransacted` and `sessionAcknowledgeMode`. When using a -`PlatformTransactionManager` with `JmsTemplate`, the template will always be given a -transactional JMS `Session`. - - - - -[[jms-sending]] -=== Sending a Message - -The `JmsTemplate` contains many convenience methods to send a message. There are send -methods that specify the destination using a `javax.jms.Destination` object and those -that specify the destination using a string for use in a JNDI lookup. The send method -that takes no destination argument uses the default destination. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - import javax.jms.ConnectionFactory; - import javax.jms.JMSException; - import javax.jms.Message; - import javax.jms.Queue; - import javax.jms.Session; - - import org.springframework.jms.core.MessageCreator; - import org.springframework.jms.core.JmsTemplate; - - public class JmsQueueSender { - - private JmsTemplate jmsTemplate; - private Queue queue; - - public void setConnectionFactory(ConnectionFactory cf) { - this.jmsTemplate = new JmsTemplate(cf); - } - - public void setQueue(Queue queue) { - this.queue = queue; - } - - public void simpleSend() { - this.jmsTemplate.send(this.queue, new MessageCreator() { - public Message createMessage(Session session) throws JMSException { - return session.createTextMessage("hello queue world"); - } - }); - } - } ----- - -This example uses the `MessageCreator` callback to create a text message from the -supplied `Session` object. The `JmsTemplate` is constructed by passing a reference to a -`ConnectionFactory`. As an alternative, a zero argument constructor and -`connectionFactory` is provided and can be used for constructing the instance in -JavaBean style (using a BeanFactory or plain Java code). Alternatively, consider -deriving from Spring's `JmsGatewaySupport` convenience base class, which provides -pre-built bean properties for JMS configuration. - -The method `send(String destinationName, MessageCreator creator)` lets you send a -message using the string name of the destination. If these names are registered in JNDI, -you should set the `destinationResolver` property of the template to an instance of -`JndiDestinationResolver`. - -If you created the `JmsTemplate` and specified a default destination, the -`send(MessageCreator c)` sends a message to that destination. - - - -[[jms-msg-conversion]] -==== Using Message Converters -In order to facilitate the sending of domain model objects, the `JmsTemplate` has -various send methods that take a Java object as an argument for a message's data -content. The overloaded methods `convertAndSend()` and `receiveAndConvert()` in -`JmsTemplate` delegate the conversion process to an instance of the `MessageConverter` -interface. This interface defines a simple contract to convert between Java objects and -JMS messages. The default implementation `SimpleMessageConverter` supports conversion -between `String` and `TextMessage`, `byte[]` and `BytesMesssage`, and `java.util.Map` -and `MapMessage`. By using the converter, you and your application code can focus on the -business object that is being sent or received via JMS and not be concerned with the -details of how it is represented as a JMS message. - -The sandbox currently includes a `MapMessageConverter` which uses reflection to convert -between a JavaBean and a `MapMessage`. Other popular implementation choices you might -implement yourself are Converters that use an existing XML marshalling package, such as -JAXB, Castor, XMLBeans, or XStream, to create a `TextMessage` representing the object. - -To accommodate the setting of a message's properties, headers, and body that can not be -generically encapsulated inside a converter class, the `MessagePostProcessor` interface -gives you access to the message after it has been converted, but before it is sent. The -example below demonstrates how to modify a message header and a property after a -`java.util.Map` is converted to a message. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public void sendWithConversion() { - Map map = new HashMap(); - map.put("Name", "Mark"); - map.put("Age", new Integer(47)); - jmsTemplate.convertAndSend("testQueue", map, new MessagePostProcessor() { - public Message postProcessMessage(Message message) throws JMSException { - message.setIntProperty("AccountID", 1234); - message.setJMSCorrelationID("123-00001"); - return message; - } - }); - } ----- - -This results in a message of the form: - -[literal] -[subs="verbatim,quotes"] ----- -MapMessage={ - Header={ - ... standard headers ... - CorrelationID={123-00001} - } - Properties={ - AccountID={Integer:1234} - } - Fields={ - Name={String:Mark} - Age={Integer:47} - } -} ----- - - - -[[jms-callbacks]] -==== SessionCallback and ProducerCallback - -While the send operations cover many common usage scenarios, there are cases when you -want to perform multiple operations on a JMS `Session` or `MessageProducer`. The -`SessionCallback` and `ProducerCallback` expose the JMS `Session` and `Session` / -`MessageProducer` pair respectively. The `execute()` methods on `JmsTemplate` execute -these callback methods. - - - - -[[jms-receiving]] -=== Receiving a message - - - -[[jms-receiving-sync]] -==== Synchronous Reception -While JMS is typically associated with asynchronous processing, it is possible to -consume messages synchronously. The overloaded `receive(..)` methods provide this -functionality. During a synchronous receive, the calling thread blocks until a message -becomes available. This can be a dangerous operation since the calling thread can -potentially be blocked indefinitely. The property `receiveTimeout` specifies how long -the receiver should wait before giving up waiting for a message. - - - -[[jms-asynchronousMessageReception]] -==== Asynchronous Reception - Message-Driven POJOs - -[NOTE] -==== -Spring also supports annotated-listener endpoints through the use of the `@JmsListener` -and provides an open infrastructure to register endpoints programmatically. This -is by far the most convenient way to setup an asynchronous receiver, see -<> for more details. -==== - -In a fashion similar to a Message-Driven Bean (MDB) in the EJB world, the Message-Driven -POJO (MDP) acts as a receiver for JMS messages. The one restriction (but see also below -for the discussion of the `MessageListenerAdapter` class) on an MDP is that it must -implement the `javax.jms.MessageListener` interface. Please also be aware that in the -case where your POJO will be receiving messages on multiple threads, it is important to -ensure that your implementation is thread-safe. - -Below is a simple implementation of an MDP: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - import javax.jms.JMSException; - import javax.jms.Message; - import javax.jms.MessageListener; - import javax.jms.TextMessage; - - public class ExampleListener implements MessageListener { - - public void onMessage(Message message) { - if (message instanceof TextMessage) { - try { - System.out.println(((TextMessage) message).getText()); - } - catch (JMSException ex) { - throw new RuntimeException(ex); - } - } - else { - throw new IllegalArgumentException("Message must be of type TextMessage"); - } - } - - } ----- - -Once you've implemented your `MessageListener`, it's time to create a message listener -container. - -Find below an example of how to define and configure one of the message listener -containers that ships with Spring (in this case the `DefaultMessageListenerContainer`). - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - **** - ----- - -Please refer to the Spring javadocs of the various message listener containers for a full -description of the features supported by each implementation. - - - -[[jms-receiving-async-session-aware-message-listener]] -==== the SessionAwareMessageListener interface - -The `SessionAwareMessageListener` interface is a Spring-specific interface that provides -a similar contract to the JMS `MessageListener` interface, but also provides the message -handling method with access to the JMS `Session` from which the `Message` was received. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - package org.springframework.jms.listener; - - public interface SessionAwareMessageListener { - - void onMessage(Message message, Session session) throws JMSException; - - } ----- - -You can choose to have your MDPs implement this interface (in preference to the standard -JMS `MessageListener` interface) if you want your MDPs to be able to respond to any -received messages (using the `Session` supplied in the `onMessage(Message, Session)` -method). All of the message listener container implementations that ship with Spring -have support for MDPs that implement either the `MessageListener` or -`SessionAwareMessageListener` interface. Classes that implement the -`SessionAwareMessageListener` come with the caveat that they are then tied to Spring -through the interface. The choice of whether or not to use it is left entirely up to you -as an application developer or architect. - -Please note that the `'onMessage(..)'` method of the `SessionAwareMessageListener` -interface throws `JMSException`. In contrast to the standard JMS `MessageListener` -interface, when using the `SessionAwareMessageListener` interface, it is the -responsibility of the client code to handle any exceptions thrown. - - - -[[jms-receiving-async-message-listener-adapter]] -==== the MessageListenerAdapter - -The `MessageListenerAdapter` class is the final component in Spring's asynchronous -messaging support: in a nutshell, it allows you to expose almost __any__ class as a MDP -(there are of course some constraints). - -Consider the following interface definition. Notice that although the interface extends -neither the `MessageListener` nor `SessionAwareMessageListener` interfaces, it can still -be used as a MDP via the use of the `MessageListenerAdapter` class. Notice also how the -various message handling methods are strongly typed according to the __contents__ of the -various `Message` types that they can receive and handle. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public interface MessageDelegate { - - void handleMessage(String message); - - void handleMessage(Map message); - - void handleMessage(byte[] message); - - void handleMessage(Serializable message); - - } ----- - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class DefaultMessageDelegate implements MessageDelegate { - // implementation elided for clarity... - } ----- - -In particular, note how the above implementation of the `MessageDelegate` interface (the -above `DefaultMessageDelegate` class) has __no__ JMS dependencies at all. It truly is a -POJO that we will make into an MDP via the following configuration. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - ** - - - - ** - - - - - - **** - ----- - -Below is an example of another MDP that can only handle the receiving of JMS -`TextMessage` messages. Notice how the message handling method is actually called -`'receive'` (the name of the message handling method in a `MessageListenerAdapter` -defaults to `'handleMessage'`), but it is configurable (as you will see below). Notice -also how the `'receive(..)'` method is strongly typed to receive and respond only to JMS -`TextMessage` messages. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public interface TextMessageDelegate { - - void receive(TextMessage message); - - } ----- - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class DefaultTextMessageDelegate implements TextMessageDelegate { - // implementation elided for clarity... - } ----- - -The configuration of the attendant `MessageListenerAdapter` would look like this: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - - - ----- - -Please note that if the above `'messageListener'` receives a JMS `Message` of a type -other than `TextMessage`, an `IllegalStateException` will be thrown (and subsequently -swallowed). Another of the capabilities of the `MessageListenerAdapter` class is the -ability to automatically send back a response `Message` if a handler method returns a -non-void value. Consider the interface and class: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public interface ResponsiveTextMessageDelegate { - - // notice the return type... - String receive(TextMessage message); - - } ----- - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class DefaultResponsiveTextMessageDelegate implements ResponsiveTextMessageDelegate { - // implementation elided for clarity... - } ----- - -If the above `DefaultResponsiveTextMessageDelegate` is used in conjunction with a -`MessageListenerAdapter` then any non-null value that is returned from the execution of -the `'receive(..)'` method will (in the default configuration) be converted into a -`TextMessage`. The resulting `TextMessage` will then be sent to the `Destination` (if -one exists) defined in the JMS Reply-To property of the original `Message`, or the -default `Destination` set on the `MessageListenerAdapter` (if one has been configured); -if no `Destination` is found then an `InvalidDestinationException` will be thrown (and -please note that this exception __will not__ be swallowed and __will__ propagate up the -call stack). - - - -[[jms-tx-participation]] -==== Processing messages within transactions -Invoking a message listener within a transaction only requires reconfiguration of the -listener container. - -Local resource transactions can simply be activated through the `sessionTransacted` flag -on the listener container definition. Each message listener invocation will then operate -within an active JMS transaction, with message reception rolled back in case of listener -execution failure. Sending a response message (via `SessionAwareMessageListener`) will -be part of the same local transaction, but any other resource operations (such as -database access) will operate independently. This usually requires duplicate message -detection in the listener implementation, covering the case where database processing -has committed but message processing failed to commit. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - **** - ----- - -For participating in an externally managed transaction, you will need to configure a -transaction manager and use a listener container which supports externally managed -transactions: typically `DefaultMessageListenerContainer`. - -To configure a message listener container for XA transaction participation, you'll want -to configure a `JtaTransactionManager` (which, by default, delegates to the Java EE -server's transaction subsystem). Note that the underlying JMS ConnectionFactory needs to -be XA-capable and properly registered with your JTA transaction coordinator! (Check your -Java EE server's configuration of JNDI resources.) This allows message reception as well -as e.g. database access to be part of the same transaction (with unified commit -semantics, at the expense of XA transaction log overhead). - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - ----- - -Then you just need to add it to our earlier container configuration. The container will -take care of the rest. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - **** - ----- - - - - -[[jms-jca-message-endpoint-manager]] -=== Support for JCA Message Endpoints -Beginning with version 2.5, Spring also provides support for a JCA-based -`MessageListener` container. The `JmsMessageEndpointManager` will attempt to -automatically determine the `ActivationSpec` class name from the provider's -`ResourceAdapter` class name. Therefore, it is typically possible to just provide -Spring's generic `JmsActivationSpecConfig` as shown in the following example. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - - ----- - -Alternatively, you may set up a `JmsMessageEndpointManager` with a given -`ActivationSpec` object. The `ActivationSpec` object may also come from a JNDI lookup -(using ``). - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - - - ----- - -Using Spring's `ResourceAdapterFactoryBean`, the target `ResourceAdapter` may be -configured locally as depicted in the following example. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - - - ----- - -The specified `WorkManager` may also point to an environment-specific thread pool - -typically through `SimpleTaskWorkManager's` "asyncTaskExecutor" property. Consider -defining a shared thread pool for all your `ResourceAdapter` instances if you happen to -use multiple adapters. - -In some environments (e.g. WebLogic 9 or above), the entire `ResourceAdapter` object may -be obtained from JNDI instead (using ``). The Spring-based message -listeners can then interact with the server-hosted `ResourceAdapter`, also using the -server's built-in `WorkManager`. - -Please consult the JavaDoc for `JmsMessageEndpointManager`, `JmsActivationSpecConfig`, -and `ResourceAdapterFactoryBean` for more details. - -Spring also provides a generic JCA message endpoint manager which is not tied to JMS: -`org.springframework.jca.endpoint.GenericMessageEndpointManager`. This component allows -for using any message listener type (e.g. a CCI MessageListener) and any -provider-specific ActivationSpec object. Check out your JCA provider's documentation to -find out about the actual capabilities of your connector, and consult -`GenericMessageEndpointManager`'s JavaDoc for the Spring-specific configuration details. - -[NOTE] -==== -JCA-based message endpoint management is very analogous to EJB 2.1 Message-Driven Beans; -it uses the same underlying resource provider contract. Like with EJB 2.1 MDBs, any -message listener interface supported by your JCA provider can be used in the Spring -context as well. Spring nevertheless provides explicit 'convenience' support for JMS, -simply because JMS is the most common endpoint API used with the JCA endpoint management -contract. -==== - - - -[[jms-annotated]] -=== Annotation-driven listener endpoints -The easiest way to receive a message asynchronously is to use the annotated listener -endpoint infrastructure. In a nutshell, it allows you to expose a method of a managed -bean as a JMS listener endpoint. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Component - public class MyService { - - @JmsListener(destination = "myDestination") - public void processOrder(String data) { ... } - } ----- - -The idea of the example above is that whenever a message is available on the -`javax.jms.Destination` "myDestination", the `processOrder` method is invoked -accordingly (in this case, with the content of the JMS message similarly to -what the <> -provides). - -The annotated endpoint infrastructure creates a message listener container -behind the scenes for each annotated method, using a `JmsListenerContainerFactory`. - -[[jms-annotated-support]] -==== Enable listener endpoint annotations - -To enable support for `@JmsListener` annotations add `@EnableJms` to one of -your `@Configuration` classes. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Configuration - @EnableJms - public class AppConfig { - - @Bean - public DefaultJmsListenerContainerFactory jmsListenerContainerFactory() { - DefaultJmsListenerContainerFactory factory = - new DefaultJmsListenerContainerFactory(); - factory.setConnectionFactory(connectionFactory()); - factory.setDestinationResolver(destinationResolver()); - factory.setConcurrency("3-10"); - return factory; - } - } ----- - -By default, the infrastructure looks for a bean named `jmsListenerContainerFactory` -as the source for the factory to use to create message listener containers. In this -case, and ignoring the JMS infrastructure setup, the `processOrder` method can be -invoked with a core poll size of 3 threads and a maximum pool size of 10 threads. - -It is possible to customize the listener container factory to use per annotation or -an explicit default can be configured by implementing the `JmsListenerConfigurer` -interface. The default is only required if at least one endpoint is registered -without a specific container factory. See the javadoc for full details and examples. - -If you prefer <> use the `` -element. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - ----- - -[[jms-annotated-programmatic-registration]] -==== Programmatic endpoints registration - -`JmsListenerEndpoint` provides a model of an JMS endpoint and is responsible for configuring -the container for that model. The infrastructure allows you to configure endpoints -programmatically in addition to the ones that are detected by the `JmsListener` annotation. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Configuration - @EnableJms - public class AppConfig implements JmsListenerConfigurer { - - @Override - public void configureJmsListeners(JmsListenerEndpointRegistrar registrar) { - SimpleJmsListenerEndpoint endpoint = new SimpleJmsListenerEndpoint(); - endpoint.setDestination("anotherQueue"); - endpoint.setMessageListener(message -> { - // processing - }); - registrar.registerEndpoint(endpoint); - } - } ----- - -In the example above, we used `SimpleJmsListenerEndpoint` which provides the actual -`MessageListener` to invoke but you could just as well build your own endpoint variant -describing a custom invocation mechanism. - -It should be noted that you could just as well skip the use of `@JmsListener` altogether -and only register your endpoints programmatically through `JmsListenerConfigurer`. - -[[jms-annotated-method-signature]] -==== Annotated endpoint method signature - -So far, we have been injecting a simple `String` in our endpoint but it can actually -have a very flexible method signature. Let's rewrite it to inject the `Order` with -a custom header: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Component - public class MyService { - - @JmsListener(destination = "myDestination") - public void processOrder(Order order, @Header("order_type") String orderType) { - ... - } - } ----- - -These are the main elements you can inject in JMS listener endpoints: - -* The raw `javax.jms.Message` or any of its subclasses (provided of course that it - matches the incoming message type). -* The `javax.jms.Session` for optional access to the native JMS API e.g. for sending - a custom reply. -* The `org.springframework.messaging.Message` representing the incoming JMS message. - Note that this message holds both the custom and the standard headers (as defined - by `JmsHeaders`). -* `@Header`-annotated method arguments to extract a specific header value, including - standard JMS headers. -* `@Headers`-annotated argument that must also be assignable to `java.util.Map` for - getting access to all headers. -* A non-annotated element that is not one of the supported types (i.e. `Message` and - `Session`) is considered to be the payload. You can make that explicit by annotating - the parameter with `@Payload`. You can also turn on validation by adding an extra - `@Validated`. - -The ability to inject Spring's `Message` abstraction is particularly useful to benefit -from all the information stored in the transport-specific message without relying on -transport-specific API. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @JmsListener(destination = "myDestination") - public void processOrder(Message order) { ... } ----- - -Handling of method arguments is provided by `DefaultJmsHandlerMethodFactory` which can be -further customized to support additional method arguments. The conversion and validation -support can be customized there as well. - -For instance, if we want to make sure our `Order` is valid before processing it, we can -annotate the payload with `@Valid` and configure the necessary validator as follows: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Configuration - @EnableJms - public class AppConfig implements JmsListenerConfigurer { - - @Override - public void configureJmsListeners(JmsListenerEndpointRegistrar registrar) { - registrar.setJmsHandlerMethodFactory(myJmsHandlerMethodFactory()); - } - - @Bean - public DefaultJmsHandlerMethodFactory myJmsHandlerMethodFactory() { - DefaultJmsHandlerMethodFactory factory = new DefaultJmsHandlerMethodFactory(); - factory.setValidator(myValidator()); - return factory; - } - } ----- - -[[jms-annotated-reply]] -==== Reply management - -The existing support in <> -already allows your method to have a non-`void` return type. When that's the case, the result of -the invocation is encapsulated in a `javax.jms.Message` sent either in the destination specified -in the `JMSReplyTo` header of the original message or in the default destination configured on -the listener. That default destination can now be set using the `@SendTo` annotation of the -messaging abstraction. - -Assuming our `processOrder` method should now return an `OrderStatus`, it is possible to write it -as follow to automatically send a reply: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @JmsListener(destination = "myDestination") - @SendTo("status") - public OrderStatus processOrder(Order order) { - // order processing - return status; - } ----- - -If you need to set additional headers in a transport-independent manner, you could return a -`Message` instead, something like: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @JmsListener(destination = "myDestination") - @SendTo("status") - public Message processOrder(Order order) { - // order processing - return MessageBuilder - .withPayload(status) - .setHeader("code", 1234) - .build(); - } ----- - -[[jms-namespace]] -=== JMS Namespace Support -Spring provides an XML namespace for simplifying JMS configuration. To use the JMS -namespace elements you will need to reference the JMS schema: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - ----- - -The namespace consists of three top-level elements: ``, `` -and ``. `>. `` and `` -defines shared listener container configuration and may contain `` child elements. Here -is an example of a basic configuration for two listeners. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - ----- - -The example above is equivalent to creating two distinct listener container bean -definitions and two distinct `MessageListenerAdapter` bean definitions as demonstrated -in <>. In addition to the attributes shown -above, the `listener` element may contain several optional ones. The following table -describes all available attributes: - -[[jms-namespace-listener-tbl]] -.Attributes of the JMS element -[cols="1,6"] -|=== -| Attribute| Description - -| id -| A bean name for the hosting listener container. If not specified, a bean name will be - automatically generated. - -| destination __(required)__ -| The destination name for this listener, resolved through the `DestinationResolver` - strategy. - -| ref __(required)__ -| The bean name of the handler object. - -| method -| The name of the handler method to invoke. If the `ref` points to a `MessageListener` - or Spring `SessionAwareMessageListener`, this attribute may be omitted. - -| response-destination -| The name of the default response destination to send response messages to. This will - be applied in case of a request message that does not carry a "JMSReplyTo" field. The - type of this destination will be determined by the listener-container's - "destination-type" attribute. Note: This only applies to a listener method with a - return value, for which each result object will be converted into a response message. - -| subscription -| The name of the durable subscription, if any. - -| selector -| An optional message selector for this listener. - -| concurrency -| The number of concurrent sessions/consumers to start for this listener. Can either be - a simple number indicating the maximum number (e.g. "5") or a range indicating the lower - as well as the upper limit (e.g. "3-5"). Note that a specified minimum is just a hint - and might be ignored at runtime. Default is the value provided by the container -|=== - -The `` element also accepts several optional attributes. This -allows for customization of the various strategies (for example, `taskExecutor` and -`destinationResolver`) as well as basic JMS settings and resource references. Using -these attributes, it is possible to define highly-customized listener containers while -still benefiting from the convenience of the namespace. - -Such settings can be automatically exposed as a `JmsListenerContainerFactory` by -specifying the id of the bean to expose through the `factory-id` attribute. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - ----- - -The following table describes all available attributes. Consult the class-level javadocs -of the `AbstractMessageListenerContainer` and its concrete subclasses for more details -on the individual properties. The javadocs also provide a discussion of transaction -choices and message redelivery scenarios. - -[[jms-namespace-listener-container-tbl]] -.Attributes of the JMS element -[cols="1,6"] -|=== -| Attribute| Description - -| container-type -| The type of this listener container. Available options are: `default`, `simple`, - `default102`, or `simple102` (the default value is `'default'`). - -| container-class -| A custom listener container implementation class as fully qualified class name. - Default is Spring's standard `DefaultMessageListenerContainer` or - `SimpleMessageListenerContainer`, according to the "container-type" attribute. - -| factory-id -| Exposes the settings defined by this element as a `JmsListenerContainerFactory` - with the specified id so that they can be reused with other endpoints. - -| connection-factory -| A reference to the JMS `ConnectionFactory` bean (the default bean name is - `'connectionFactory'`). - -| task-executor -| A reference to the Spring `TaskExecutor` for the JMS listener invokers. - -| destination-resolver -| A reference to the `DestinationResolver` strategy for resolving JMS `Destinations`. - -| message-converter -| A reference to the `MessageConverter` strategy for converting JMS Messages to listener - method arguments. Default is a `SimpleMessageConverter`. - -| error-handler -| A reference to an `ErrorHandler` strategy for handling any uncaught Exceptions that - may occur during the execution of the `MessageListener`. - -| destination-type -| The JMS destination type for this listener: `queue`, `topic`, `durableTopic`, `sharedTopic` - or `sharedDurableTopic`. This enables potentially the `pubSubDomain`, `subscriptionDurable` - and `subscriptionShared` properties of the container. The default is `queue` (i.e. disabling - those 3 properties). - -| client-id -| The JMS client id for this listener container. Needs to be specified when using - durable subscriptions. - -| cache -| The cache level for JMS resources: `none`, `connection`, `session`, `consumer` or - `auto`. By default ( `auto`), the cache level will effectively be "consumer", unless - an external transaction manager has been specified - in which case the effective - default will be `none` (assuming Java EE-style transaction management where the given - ConnectionFactory is an XA-aware pool). - -| acknowledge -| The native JMS acknowledge mode: `auto`, `client`, `dups-ok` or `transacted`. A value - of `transacted` activates a locally transacted `Session`. As an alternative, specify - the `transaction-manager` attribute described below. Default is `auto`. - -| transaction-manager -| A reference to an external `PlatformTransactionManager` (typically an XA-based - transaction coordinator, e.g. Spring's `JtaTransactionManager`). If not specified, - native acknowledging will be used (see "acknowledge" attribute). - -| concurrency -| The number of concurrent sessions/consumers to start for each listener. Can either be - a simple number indicating the maximum number (e.g. "5") or a range indicating the - lower as well as the upper limit (e.g. "3-5"). Note that a specified minimum is just a - hint and might be ignored at runtime. Default is 1; keep concurrency limited to 1 in - case of a topic listener or if queue ordering is important; consider raising it for - general queues. - -| prefetch -| The maximum number of messages to load into a single session. Note that raising this - number might lead to starvation of concurrent consumers! - -| receive-timeout -| The timeout to use for receive calls (in milliseconds). The default is `1000` ms (1 - sec); `-1` indicates no timeout at all. - -| back-off -| Specify the `BackOff` instance to use to compute the interval between recovery - attempts. If the `BackOffExecution` implementation returns `BackOffExecution#STOP`, - the listener container will not further attempt to recover. The `recovery-interval` - value is ignored when this property is set. The default is a `FixedBackOff` with - an interval of 5000 ms, that is 5 seconds. - -| recovery-interval -| Specify the interval between recovery attempts, in milliseconds. Convenience - way to create a `FixedBackOff` with the specified interval. For more recovery - options, consider specifying a BackOff instance instead. The default is 5000 ms, - that is 5 seconds. - -| phase -| The lifecycle phase within which this container should start and stop. The lower the - value the earlier this container will start and the later it will stop. The default is - `Integer.MAX_VALUE` meaning the container will start as late as possible and stop as - soon as possible. -|=== - -Configuring a JCA-based listener container with the "jms" schema support is very similar. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - ----- - -The available configuration options for the JCA variant are described in the following -table: - -[[jms-namespace-jca-listener-container-tbl]] -.Attributes of the JMS element -[cols="1,6"] -|=== -| Attribute| Description - -| factory-id -| Exposes the settings defined by this element as a `JmsListenerContainerFactory` - with the specified id so that they can be reused with other endpoints. - -| resource-adapter -| A reference to the JCA `ResourceAdapter` bean (the default bean name is - `'resourceAdapter'`). - -| activation-spec-factory -| A reference to the `JmsActivationSpecFactory`. The default is to autodetect the JMS - provider and its `ActivationSpec` class (see `DefaultJmsActivationSpecFactory`) - -| destination-resolver -| A reference to the `DestinationResolver` strategy for resolving JMS `Destinations`. - -| message-converter -| A reference to the `MessageConverter` strategy for converting JMS Messages to listener - method arguments. Default is a `SimpleMessageConverter`. - -| destination-type -| The JMS destination type for this listener: `queue`, `topic`, `durableTopic`, `sharedTopic` - or `sharedDurableTopic`. This enables potentially the `pubSubDomain`, `subscriptionDurable` - and `subscriptionShared` properties of the container. The default is `queue` (i.e. disabling - those 3 properties). - -| client-id -| The JMS client id for this listener container. Needs to be specified when using - durable subscriptions. - -| acknowledge -| The native JMS acknowledge mode: `auto`, `client`, `dups-ok` or `transacted`. A value - of `transacted` activates a locally transacted `Session`. As an alternative, specify - the `transaction-manager` attribute described below. Default is `auto`. - -| transaction-manager -| A reference to a Spring `JtaTransactionManager` or a - `javax.transaction.TransactionManager` for kicking off an XA transaction for each - incoming message. If not specified, native acknowledging will be used (see the - "acknowledge" attribute). - -| concurrency -| The number of concurrent sessions/consumers to start for each listener. Can either be - a simple number indicating the maximum number (e.g. "5") or a range indicating the - lower as well as the upper limit (e.g. "3-5"). Note that a specified minimum is just a - hint and will typically be ignored at runtime when using a JCA listener container. - Default is 1. - -| prefetch -| The maximum number of messages to load into a single session. Note that raising this - number might lead to starvation of concurrent consumers! -|=== - - - - - -[[jmx]] -== JMX - - - - -[[jmx-introduction]] -=== Introduction -The JMX support in Spring provides you with the features to easily and transparently -integrate your Spring application into a JMX infrastructure. - -.JMX? -**** -This chapter is not an introduction to JMX... it doesn't try to explain the motivations -of why one might want to use JMX (or indeed what the letters JMX actually stand for). If -you are new to JMX, check out <> at the end of this chapter. -**** - -Specifically, Spring's JMX support provides four core features: - -* The automatic registration of __any__ Spring bean as a JMX MBean -* A flexible mechanism for controlling the management interface of your beans -* The declarative exposure of MBeans over remote, JSR-160 connectors -* The simple proxying of both local and remote MBean resources - -These features are designed to work without coupling your application components to -either Spring or JMX interfaces and classes. Indeed, for the most part your application -classes need not be aware of either Spring or JMX in order to take advantage of the -Spring JMX features. - - - - -[[jmx-exporting]] -=== Exporting your beans to JMX -The core class in Spring's JMX framework is the `MBeanExporter`. This class is -responsible for taking your Spring beans and registering them with a JMX `MBeanServer`. -For example, consider the following class: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - package org.springframework.jmx; - - public class JmxTestBean implements IJmxTestBean { - - private String name; - private int age; - private boolean isSuperman; - - public int getAge() { - return age; - } - - public void setAge(int age) { - this.age = age; - } - - public void setName(String name) { - this.name = name; - } - - public String getName() { - return name; - } - - public int add(int x, int y) { - return x + y; - } - - public void dontExposeMe() { - throw new RuntimeException(); - } - } ----- - -To expose the properties and methods of this bean as attributes and operations of an -MBean you simply configure an instance of the `MBeanExporter` class in your -configuration file and pass in the bean as shown below: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - - - - - - - ----- - -The pertinent bean definition from the above configuration snippet is the `exporter` -bean. The `beans` property tells the `MBeanExporter` exactly which of your beans must be -exported to the JMX `MBeanServer`. In the default configuration, the key of each entry -in the `beans` `Map` is used as the `ObjectName` for the bean referenced by the -corresponding entry value. This behavior can be changed as described in <>. - -With this configuration the `testBean` bean is exposed as an MBean under the -`ObjectName` `bean:name=testBean1`. By default, all __public__ properties of the bean -are exposed as attributes and all __public__ methods (bar those inherited from the -`Object` class) are exposed as operations. - -[NOTE] -==== -`MBeanExporter` is a `Lifecycle` bean (see <>) -and MBeans are exported as late as possible during the application lifecycle by default. It -is possible to configure the `phase` at which the export happens or disable automatic -registration by setting the `autoStartup` flag. -==== - - -[[jmx-exporting-mbeanserver]] -==== Creating an MBeanServer - -The above configuration assumes that the application is running in an environment that -has one (and only one) `MBeanServer` already running. In this case, Spring will attempt -to locate the running `MBeanServer` and register your beans with that server (if any). -This behavior is useful when your application is running inside a container such as -Tomcat or IBM WebSphere that has its own `MBeanServer`. - -However, this approach is of no use in a standalone environment, or when running inside -a container that does not provide an `MBeanServer`. To address this you can create an -`MBeanServer` instance declaratively by adding an instance of the -`org.springframework.jmx.support.MBeanServerFactoryBean` class to your configuration. -You can also ensure that a specific `MBeanServer` is used by setting the value of the -`MBeanExporter`'s `server` property to the `MBeanServer` value returned by an -`MBeanServerFactoryBean`; for example: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - - - - - - - - - - - - - ----- - -Here an instance of `MBeanServer` is created by the `MBeanServerFactoryBean` and is -supplied to the `MBeanExporter` via the server property. When you supply your own -`MBeanServer` instance, the `MBeanExporter` will not attempt to locate a running -`MBeanServer` and will use the supplied `MBeanServer` instance. For this to work -correctly, you must (of course) have a JMX implementation on your classpath. - - - -[[jmx-mbean-server]] -==== Reusing an existing MBeanServer - -If no server is specified, the `MBeanExporter` tries to automatically detect a running -`MBeanServer`. This works in most environment where only one `MBeanServer` instance is -used, however when multiple instances exist, the exporter might pick the wrong server. -In such cases, one should use the `MBeanServer` `agentId` to indicate which instance to -be used: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - - - ... - - ----- - -For platforms/cases where the existing `MBeanServer` has a dynamic (or unknown) -`agentId` which is retrieved through lookup methods, one should use -<>: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - - - - ----- - - - -[[jmx-exporting-lazy]] -==== Lazy-initialized MBeans -If you configure a bean with the `MBeanExporter` that is also configured for lazy -initialization, then the `MBeanExporter` will __not__ break this contract and will avoid -instantiating the bean. Instead, it will register a proxy with the `MBeanServer` and -will defer obtaining the bean from the container until the first invocation on the proxy -occurs. - - - -[[jmx-exporting-auto]] -==== Automatic registration of MBeans -Any beans that are exported through the `MBeanExporter` and are already valid MBeans are -registered as-is with the `MBeanServer` without further intervention from Spring. MBeans -can be automatically detected by the `MBeanExporter` by setting the `autodetect` -property to `true`: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - ----- - -Here, the bean called `spring:mbean=true` is already a valid JMX MBean and will be -automatically registered by Spring. By default, beans that are autodetected for JMX -registration have their bean name used as the `ObjectName`. This behavior can be -overridden as detailed in <>. - - - -[[jmx-exporting-registration-behavior]] -==== Controlling the registration behavior -Consider the scenario where a Spring `MBeanExporter` attempts to register an `MBean` -with an `MBeanServer` using the `ObjectName` `'bean:name=testBean1'`. If an `MBean` -instance has already been registered under that same `ObjectName`, the default behavior -is to fail (and throw an `InstanceAlreadyExistsException`). - -It is possible to control the behavior of exactly what happens when an `MBean` is -registered with an `MBeanServer`. Spring's JMX support allows for three different -registration behaviors to control the registration behavior when the registration -process finds that an `MBean` has already been registered under the same `ObjectName`; -these registration behaviors are summarized on the following table: - -[[jmx-registration-behaviors]] -.Registration Behaviors -[cols="1,4"] -|=== -| Registration behavior| Explanation - -| `REGISTRATION_FAIL_ON_EXISTING` -| This is the default registration behavior. If an `MBean` instance has already been - registered under the same `ObjectName`, the `MBean` that is being registered will not - be registered and an `InstanceAlreadyExistsException` will be thrown. The existing - `MBean` is unaffected. - -| `REGISTRATION_IGNORE_EXISTING` -| If an `MBean` instance has already been registered under the same `ObjectName`, the - `MBean` that is being registered will __not__ be registered. The existing `MBean` is - unaffected, and no `Exception` will be thrown. This is useful in settings where - multiple applications want to share a common `MBean` in a shared `MBeanServer`. - -| `REGISTRATION_REPLACE_EXISTING` -| If an `MBean` instance has already been registered under the same `ObjectName`, the - existing `MBean` that was previously registered will be unregistered and the new - `MBean` will be registered in its place (the new `MBean` effectively replaces the - previous instance). -|=== - -The above values are defined as constants on the `MBeanRegistrationSupport` class (the -`MBeanExporter` class derives from this superclass). If you want to change the default -registration behavior, you simply need to set the value of the -`registrationBehaviorName` property on your `MBeanExporter` definition to one of those -values. - -The following example illustrates how to effect a change from the default registration -behavior to the `REGISTRATION_REPLACE_EXISTING` behavior: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - - - - - - - - - - ----- - - - - -[[jmx-interface]] -=== Controlling the management interface of your beans -In the previous example, you had little control over the management interface of your -bean; __all__ of the __public__ properties and methods of each exported bean was exposed -as JMX attributes and operations respectively. To exercise finer-grained control over -exactly which properties and methods of your exported beans are actually exposed as JMX -attributes and operations, Spring JMX provides a comprehensive and extensible mechanism -for controlling the management interfaces of your beans. - - - -[[jmx-interface-assembler]] -==== the MBeanInfoAssembler Interface - -Behind the scenes, the `MBeanExporter` delegates to an implementation of the -`org.springframework.jmx.export.assembler.MBeanInfoAssembler` interface which is -responsible for defining the management interface of each bean that is being exposed. -The default implementation, -`org.springframework.jmx.export.assembler.SimpleReflectiveMBeanInfoAssembler`, simply -defines a management interface that exposes all public properties and methods (as you -saw in the previous examples). Spring provides two additional implementations of the -`MBeanInfoAssembler` interface that allow you to control the generated management -interface using either source-level metadata or any arbitrary interface. - - - -[[jmx-interface-metadata]] -==== Using Source-Level Metadata (Java annotations) -Using the `MetadataMBeanInfoAssembler` you can define the management interfaces for your -beans using source level metadata. The reading of metadata is encapsulated by the -`org.springframework.jmx.export.metadata.JmxAttributeSource` interface. Spring JMX -provides a default implementation which uses Java annotations, namely -`org.springframework.jmx.export.annotation.AnnotationJmxAttributeSource`. The -`MetadataMBeanInfoAssembler` __must__ be configured with an implementation instance of -the `JmxAttributeSource` interface for it to function correctly (there is __no__ -default). - -To mark a bean for export to JMX, you should annotate the bean class with the -`ManagedResource` annotation. Each method you wish to expose as an operation must be -marked with the `ManagedOperation` annotation and each property you wish to expose must -be marked with the `ManagedAttribute` annotation. When marking properties you can omit -either the annotation of the getter or the setter to create a write-only or read-only -attribute respectively. - -The example below shows the annotated version of the `JmxTestBean` class that you saw -earlier: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - package org.springframework.jmx; - - import org.springframework.jmx.export.annotation.ManagedResource; - import org.springframework.jmx.export.annotation.ManagedOperation; - import org.springframework.jmx.export.annotation.ManagedAttribute; - - @ManagedResource( - objectName="bean:name=testBean4", - description="My Managed Bean", - log=true, - logFile="jmx.log", - currencyTimeLimit=15, - persistPolicy="OnUpdate", - persistPeriod=200, - persistLocation="foo", - persistName="bar") - public class AnnotationTestBean implements IJmxTestBean { - - private String name; - private int age; - - @ManagedAttribute(description="The Age Attribute", currencyTimeLimit=15) - public int getAge() { - return age; - } - - public void setAge(int age) { - this.age = age; - } - - @ManagedAttribute(description="The Name Attribute", - currencyTimeLimit=20, - defaultValue="bar", - persistPolicy="OnUpdate") - public void setName(String name) { - this.name = name; - } - - @ManagedAttribute(defaultValue="foo", persistPeriod=300) - public String getName() { - return name; - } - - @ManagedOperation(description="Add two numbers") - @ManagedOperationParameters({ - @ManagedOperationParameter(name = "x", description = "The first number"), - @ManagedOperationParameter(name = "y", description = "The second number")}) - public int add(int x, int y) { - return x + y; - } - - public void dontExposeMe() { - throw new RuntimeException(); - } - - } ----- - -Here you can see that the `JmxTestBean` class is marked with the `ManagedResource` -annotation and that this `ManagedResource` annotation is configured with a set of -properties. These properties can be used to configure various aspects of the MBean that -is generated by the `MBeanExporter`, and are explained in greater detail later in -section entitled <>. - -You will also notice that both the `age` and `name` properties are annotated with the -`ManagedAttribute` annotation, but in the case of the `age` property, only the getter is -marked. This will cause both of these properties to be included in the management -interface as attributes, but the `age` attribute will be read-only. - -Finally, you will notice that the `add(int, int)` method is marked with the -`ManagedOperation` attribute whereas the `dontExposeMe()` method is not. This will cause -the management interface to contain only one operation, `add(int, int)`, when using the -`MetadataMBeanInfoAssembler`. - -The configuration below shows how you configure the `MBeanExporter` to use the -`MetadataMBeanInfoAssembler`: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - - - - - - - - - - - - - - - - - ----- - -Here you can see that an `MetadataMBeanInfoAssembler` bean has been configured with an -instance of the `AnnotationJmxAttributeSource` class and passed to the `MBeanExporter` -through the assembler property. This is all that is required to take advantage of -metadata-driven management interfaces for your Spring-exposed MBeans. - - - -[[jmx-interface-metadata-types]] -==== Source-Level Metadata Types -The following source level metadata types are available for use in Spring JMX: - -[[jmx-metadata-types]] -.Source-Level Metadata Types -|=== -| Purpose| Annotation| Annotation Type - -| Mark all instances of a `Class` as JMX managed resources -| `@ManagedResource` -| Class - -| Mark a method as a JMX operation -| `@ManagedOperation` -| Method - -| Mark a getter or setter as one half of a JMX attribute -| `@ManagedAttribute` -| Method (only getters and setters) - -| Define descriptions for operation parameters -| `@ManagedOperationParameter` and `@ManagedOperationParameters` -| Method -|=== - -The following configuration parameters are available for use on these source-level -metadata types: - -[[jmx-metadata-parameters]] -.Source-Level Metadata Parameters -[cols="1,3,1"] -|=== -| Parameter| Description| Applies to - -| `ObjectName` -| Used by `MetadataNamingStrategy` to determine the `ObjectName` of a managed resource -| `ManagedResource` - -| `description` -| Sets the friendly description of the resource, attribute or operation -| `ManagedResource`, `ManagedAttribute`, `ManagedOperation`, `ManagedOperationParameter` - -| `currencyTimeLimit` -| Sets the value of the `currencyTimeLimit` descriptor field -| `ManagedResource`, `ManagedAttribute` - -| `defaultValue` -| Sets the value of the `defaultValue` descriptor field -| `ManagedAttribute` - -| `log` -| Sets the value of the `log` descriptor field -| `ManagedResource` - -| `logFile` -| Sets the value of the `logFile` descriptor field -| `ManagedResource` - -| `persistPolicy` -| Sets the value of the `persistPolicy` descriptor field -| `ManagedResource` - -| `persistPeriod` -| Sets the value of the `persistPeriod` descriptor field -| `ManagedResource` - -| `persistLocation` -| Sets the value of the `persistLocation` descriptor field -| `ManagedResource` - -| `persistName` -| Sets the value of the `persistName` descriptor field -| `ManagedResource` - -| `name` -| Sets the display name of an operation parameter -| `ManagedOperationParameter` - -| `index` -| Sets the index of an operation parameter -| `ManagedOperationParameter` -|=== - - - -[[jmx-interface-autodetect]] -==== the AutodetectCapableMBeanInfoAssembler interface - -To simplify configuration even further, Spring introduces the -`AutodetectCapableMBeanInfoAssembler` interface which extends the `MBeanInfoAssembler` -interface to add support for autodetection of MBean resources. If you configure the -`MBeanExporter` with an instance of `AutodetectCapableMBeanInfoAssembler` then it is -allowed to "vote" on the inclusion of beans for exposure to JMX. - -Out of the box, the only implementation of the `AutodetectCapableMBeanInfo` interface is -the `MetadataMBeanInfoAssembler` which will vote to include any bean which is marked -with the `ManagedResource` attribute. The default approach in this case is to use the -bean name as the `ObjectName` which results in a configuration like this: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - - - - - - - - - - - - - ----- - -Notice that in this configuration no beans are passed to the `MBeanExporter`; however, -the `JmxTestBean` will still be registered since it is marked with the `ManagedResource` -attribute and the `MetadataMBeanInfoAssembler` detects this and votes to include it. The -only problem with this approach is that the name of the `JmxTestBean` now has business -meaning. You can address this issue by changing the default behavior for `ObjectName` -creation as defined in <>. - - - -[[jmx-interface-java]] -==== Defining management interfaces using Java interfaces -In addition to the `MetadataMBeanInfoAssembler`, Spring also includes the -`InterfaceBasedMBeanInfoAssembler` which allows you to constrain the methods and -properties that are exposed based on the set of methods defined in a collection of -interfaces. - -Although the standard mechanism for exposing MBeans is to use interfaces and a simple -naming scheme, the `InterfaceBasedMBeanInfoAssembler` extends this functionality by -removing the need for naming conventions, allowing you to use more than one interface -and removing the need for your beans to implement the MBean interfaces. - -Consider this interface that is used to define a management interface for the -`JmxTestBean` class that you saw earlier: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public interface IJmxTestBean { - - public int add(int x, int y); - - public long myOperation(); - - public int getAge(); - - public void setAge(int age); - - public void setName(String name); - - public String getName(); - - } ----- - -This interface defines the methods and properties that will be exposed as operations and -attributes on the JMX MBean. The code below shows how to configure Spring JMX to use -this interface as the definition for the management interface: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - - - - - org.springframework.jmx.IJmxTestBean - - - - - - - - - - - ----- - -Here you can see that the `InterfaceBasedMBeanInfoAssembler` is configured to use the -`IJmxTestBean` interface when constructing the management interface for any bean. It is -important to understand that beans processed by the `InterfaceBasedMBeanInfoAssembler` -are __not__ required to implement the interface used to generate the JMX management -interface. - -In the case above, the `IJmxTestBean` interface is used to construct all management -interfaces for all beans. In many cases this is not the desired behavior and you may -want to use different interfaces for different beans. In this case, you can pass -`InterfaceBasedMBeanInfoAssembler` a `Properties` instance via the `interfaceMappings` -property, where the key of each entry is the bean name and the value of each entry is a -comma-separated list of interface names to use for that bean. - -If no management interface is specified through either the `managedInterfaces` or -`interfaceMappings` properties, then the `InterfaceBasedMBeanInfoAssembler` will reflect -on the bean and use all of the interfaces implemented by that bean to create the -management interface. - - - -[[jmx-interface-methodnames]] -==== Using MethodNameBasedMBeanInfoAssembler - -The `MethodNameBasedMBeanInfoAssembler` allows you to specify a list of method names -that will be exposed to JMX as attributes and operations. The code below shows a sample -configuration for this: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - - - add,myOperation,getName,setName,getAge - - - - ----- - -Here you can see that the methods `add` and `myOperation` will be exposed as JMX -operations and `getName()`, `setName(String)` and `getAge()` will be exposed as the -appropriate half of a JMX attribute. In the code above, the method mappings apply to -beans that are exposed to JMX. To control method exposure on a bean-by-bean basis, use -the `methodMappings` property of `MethodNameMBeanInfoAssembler` to map bean names to -lists of method names. - - - - -[[jmx-naming]] -=== Controlling the ObjectNames for your beans - -Behind the scenes, the `MBeanExporter` delegates to an implementation of the -`ObjectNamingStrategy` to obtain ++ObjectName++s for each of the beans it is registering. -The default implementation, `KeyNamingStrategy`, will, by default, use the key of the -`beans` `Map` as the `ObjectName`. In addition, the `KeyNamingStrategy` can map the key -of the `beans` `Map` to an entry in a `Properties` file (or files) to resolve the -`ObjectName`. In addition to the `KeyNamingStrategy`, Spring provides two additional -`ObjectNamingStrategy` implementations: the `IdentityNamingStrategy` that builds an -`ObjectName` based on the JVM identity of the bean and the `MetadataNamingStrategy` that -uses source level metadata to obtain the `ObjectName`. - - - -[[jmx-naming-properties]] -==== Reading ObjectNames from Properties - -You can configure your own `KeyNamingStrategy` instance and configure it to read -++ObjectName++s from a `Properties` instance rather than use bean key. The -`KeyNamingStrategy` will attempt to locate an entry in the `Properties` with a key -corresponding to the bean key. If no entry is found or if the `Properties` instance is -`null` then the bean key itself is used. - -The code below shows a sample configuration for the `KeyNamingStrategy`: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - - - - - - - - - - - - - bean:name=testBean1 - - - - names1.properties,names2.properties - - - - ----- - -Here an instance of `KeyNamingStrategy` is configured with a `Properties` instance that -is merged from the `Properties` instance defined by the mapping property and the -properties files located in the paths defined by the mappings property. In this -configuration, the `testBean` bean will be given the `ObjectName` `bean:name=testBean1` -since this is the entry in the `Properties` instance that has a key corresponding to the -bean key. - -If no entry in the `Properties` instance can be found then the bean key name is used as -the `ObjectName`. - - - -[[jmx-naming-metadata]] -==== Using the MetadataNamingStrategy - -The `MetadataNamingStrategy` uses the `objectName` property of the `ManagedResource` -attribute on each bean to create the `ObjectName`. The code below shows the -configuration for the `MetadataNamingStrategy`: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - - - - - - - - - - - - - - - - ----- - -If no `objectName` has been provided for the `ManagedResource` attribute, then an -`ObjectName` will be created with the following -format:__[fully-qualified-package-name]:type=[short-classname],name=[bean-name]__. For -example, the generated `ObjectName` for the following bean would be: -__com.foo:type=MyClass,name=myBean__. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - ----- - - - -[[jmx-context-mbeanexport]] -==== Configuring annotation based MBean export -If you prefer using <> to define -your management interfaces, then a convenience subclass of `MBeanExporter` is available: -`AnnotationMBeanExporter`. When defining an instance of this subclass, the -`namingStrategy`, `assembler`, and `attributeSource` configuration is no longer needed, -since it will always use standard Java annotation-based metadata (autodetection is -always enabled as well). In fact, rather than defining an `MBeanExporter` bean, an even -simpler syntax is supported by the `@EnableMBeanExport` `@Configuration` annotation. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Configuration - @EnableMBeanExport - public class AppConfig { - - } ----- - -If you prefer XML based configuration the ' `context:mbean-export'` element serves the -same purpose. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - ----- - -You can provide a reference to a particular MBean `server` if necessary, and the -`defaultDomain` attribute (a property of `AnnotationMBeanExporter`) accepts an alternate -value for the generated MBean `ObjectNames`' domains. This would be used in place of the -fully qualified package name as described in the previous section on -<>. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @EnableMBeanExport(server="myMBeanServer", defaultDomain="myDomain") - @Configuration - ContextConfiguration { - - } ----- - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - ----- - -[NOTE] -==== -Do not use interface-based AOP proxies in combination with autodetection of JMX -annotations in your bean classes. Interface-based proxies 'hide' the target class, which -also hides the JMX managed resource annotations. Hence, use target-class proxies in that -case: through setting the 'proxy-target-class' flag on ``, -``, etc. Otherwise, your JMX beans might be silently ignored at -startup... -==== - - - - -[[jmx-jsr160]] -=== JSR-160 Connectors -For remote access, Spring JMX module offers two `FactoryBean` implementations inside the -`org.springframework.jmx.support` package for creating both server- and client-side -connectors. - - - -[[jmx-jsr160-server]] -==== Server-side Connectors -To have Spring JMX create, start and expose a JSR-160 `JMXConnectorServer` use the -following configuration: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - ----- - -By default `ConnectorServerFactoryBean` creates a `JMXConnectorServer` bound to -`"service:jmx:jmxmp://localhost:9875"`. The `serverConnector` bean thus exposes the -local `MBeanServer` to clients through the JMXMP protocol on localhost, port 9875. Note -that the JMXMP protocol is marked as optional by the JSR 160 specification: currently, -the main open-source JMX implementation, MX4J, and the one provided with the JDK -do __not__ support JMXMP. - -To specify another URL and register the `JMXConnectorServer` itself with the -`MBeanServer` use the `serviceUrl` and `ObjectName` properties respectively: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - ----- - -If the `ObjectName` property is set Spring will automatically register your connector -with the `MBeanServer` under that `ObjectName`. The example below shows the full set of -parameters which you can pass to the `ConnectorServerFactoryBean` when creating a -JMXConnector: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - - - - ----- - -Note that when using a RMI-based connector you need the lookup service (tnameserv or -rmiregistry) to be started in order for the name registration to complete. If you are -using Spring to export remote services for you via RMI, then Spring will already have -constructed an RMI registry. If not, you can easily start a registry using the following -snippet of configuration: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - ----- - - - -[[jmx-jsr160-client]] -==== Client-side Connectors -To create an `MBeanServerConnection` to a remote JSR-160 enabled `MBeanServer` use the -`MBeanServerConnectionFactoryBean` as shown below: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - ----- - - - -[[jmx-jsr160-protocols]] -==== JMX over Burlap/Hessian/SOAP -JSR-160 permits extensions to the way in which communication is done between the client -and the server. The examples above are using the mandatory RMI-based implementation -required by the JSR-160 specification (IIOP and JRMP) and the (optional) JMXMP. By using -other providers or JMX implementations (such as http://mx4j.sourceforge.net[MX4J]) you -can take advantage of protocols like SOAP, Hessian, Burlap over simple HTTP or SSL and -others: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - ----- - -In the case of the above example, MX4J 3.0.0 was used; see the official MX4J -documentation for more information. - - - - -[[jmx-proxy]] -=== Accessing MBeans via Proxies -Spring JMX allows you to create proxies that re-route calls to MBeans registered in a -local or remote `MBeanServer`. These proxies provide you with a standard Java interface -through which you can interact with your MBeans. The code below shows how to configure a -proxy for an MBean running in a local `MBeanServer`: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - ----- - -Here you can see that a proxy is created for the MBean registered under the -`ObjectName`: `bean:name=testBean`. The set of interfaces that the proxy will implement -is controlled by the `proxyInterfaces` property and the rules for mapping methods and -properties on these interfaces to operations and attributes on the MBean are the same -rules used by the `InterfaceBasedMBeanInfoAssembler`. - -The `MBeanProxyFactoryBean` can create a proxy to any MBean that is accessible via an -`MBeanServerConnection`. By default, the local `MBeanServer` is located and used, but -you can override this and provide an `MBeanServerConnection` pointing to a remote -`MBeanServer` to cater for proxies pointing to remote MBeans: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - - ----- - -Here you can see that we create an `MBeanServerConnection` pointing to a remote machine -using the `MBeanServerConnectionFactoryBean`. This `MBeanServerConnection` is then -passed to the `MBeanProxyFactoryBean` via the `server` property. The proxy that is -created will forward all invocations to the `MBeanServer` via this -`MBeanServerConnection`. - - - - -[[jmx-notifications]] -=== Notifications -Spring's JMX offering includes comprehensive support for JMX notifications. - - - -[[jmx-notifications-listeners]] -==== Registering Listeners for Notifications -Spring's JMX support makes it very easy to register any number of -`NotificationListeners` with any number of MBeans (this includes MBeans exported by -Spring's `MBeanExporter` and MBeans registered via some other mechanism). By way of an -example, consider the scenario where one would like to be informed (via a -`Notification`) each and every time an attribute of a target MBean changes. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - package com.example; - - import javax.management.AttributeChangeNotification; - import javax.management.Notification; - import javax.management.NotificationFilter; - import javax.management.NotificationListener; - - public class ConsoleLoggingNotificationListener - implements NotificationListener, NotificationFilter { - - public void handleNotification(Notification notification, Object handback) { - System.out.println(notification); - System.out.println(handback); - } - - public boolean isNotificationEnabled(Notification notification) { - return AttributeChangeNotification.class.isAssignableFrom(notification.getClass()); - } - - } ----- - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - - - - - - - - - - - - - - - - ----- - -With the above configuration in place, every time a JMX `Notification` is broadcast from -the target MBean ( `bean:name=testBean1`), the `ConsoleLoggingNotificationListener` bean -that was registered as a listener via the `notificationListenerMappings` property will -be notified. The `ConsoleLoggingNotificationListener` bean can then take whatever action -it deems appropriate in response to the `Notification`. - -You can also use straight bean names as the link between exported beans and listeners: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - - - - - - - - - - - - - - - - ----- - -If one wants to register a single `NotificationListener` instance for all of the beans -that the enclosing `MBeanExporter` is exporting, one can use the special wildcard `'*'` -(sans quotes) as the key for an entry in the `notificationListenerMappings` property -map; for example: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - ----- - -If one needs to do the inverse (that is, register a number of distinct listeners against -an MBean), then one has to use the `notificationListeners` list property instead (and in -preference to the `notificationListenerMappings` property). This time, instead of -configuring simply a `NotificationListener` for a single MBean, one configures -`NotificationListenerBean` instances... a `NotificationListenerBean` encapsulates a -`NotificationListener` and the `ObjectName` (or `ObjectNames`) that it is to be -registered against in an `MBeanServer`. The `NotificationListenerBean` also encapsulates -a number of other properties such as a `NotificationFilter` and an arbitrary handback -object that can be used in advanced JMX notification scenarios. - -The configuration when using `NotificationListenerBean` instances is not wildly -different to what was presented previously: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - - - - - - - - - - bean:name=testBean1 - - - - - - - - - - - - - ----- - -The above example is equivalent to the first notification example. Lets assume then that -we want to be given a handback object every time a `Notification` is raised, and that -additionally we want to filter out extraneous `Notifications` by supplying a -`NotificationFilter`. (For a full discussion of just what a handback object is, and -indeed what a `NotificationFilter` is, please do consult that section of the JMX -specification (1.2) entitled 'The JMX Notification Model'.) - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - - - - - - - - - - bean:name=testBean1 - bean:name=testBean2 - - - - - - - - - - - - - - - - - - - - - - - - - - - ----- - - - -[[jmx-notifications-publishing]] -==== Publishing Notifications -Spring provides support not just for registering to receive `Notifications`, but also -for publishing `Notifications`. - -[NOTE] -==== -Please note that this section is really only relevant to Spring managed beans that have -been exposed as MBeans via an `MBeanExporter`; any existing, user-defined MBeans should -use the standard JMX APIs for notification publication. -==== - -The key interface in Spring's JMX notification publication support is the -`NotificationPublisher` interface (defined in the -`org.springframework.jmx.export.notification` package). Any bean that is going to be -exported as an MBean via an `MBeanExporter` instance can implement the related -`NotificationPublisherAware` interface to gain access to a `NotificationPublisher` -instance. The `NotificationPublisherAware` interface simply supplies an instance of a -`NotificationPublisher` to the implementing bean via a simple setter method, which the -bean can then use to publish `Notifications`. - -As stated in the javadocs of the `NotificationPublisher` class, managed beans that are -publishing events via the `NotificationPublisher` mechanism are __not__ responsible for -the state management of any notification listeners and the like ... Spring's JMX support -will take care of handling all the JMX infrastructure issues. All one need do as an -application developer is implement the `NotificationPublisherAware` interface and start -publishing events using the supplied `NotificationPublisher` instance. Note that the -`NotificationPublisher` will be set __after__ the managed bean has been registered with -an `MBeanServer`. - -Using a `NotificationPublisher` instance is quite straightforward... one simply creates -a JMX `Notification` instance (or an instance of an appropriate `Notification` -subclass), populates the notification with the data pertinent to the event that is to be -published, and one then invokes the `sendNotification(Notification)` on the -`NotificationPublisher` instance, passing in the `Notification`. - -Find below a simple example... in this scenario, exported instances of the `JmxTestBean` -are going to publish a `NotificationEvent` every time the `add(int, int)` operation is -invoked. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - package org.springframework.jmx; - - import org.springframework.jmx.export.notification.NotificationPublisherAware; - import org.springframework.jmx.export.notification.NotificationPublisher; - import javax.management.Notification; - - public class JmxTestBean implements IJmxTestBean, NotificationPublisherAware { - - private String name; - private int age; - private boolean isSuperman; - private NotificationPublisher publisher; - - // other getters and setters omitted for clarity - - public int add(int x, int y) { - int answer = x + y; - this.publisher.sendNotification(new Notification("add", this, 0)); - return answer; - } - - public void dontExposeMe() { - throw new RuntimeException(); - } - - public void setNotificationPublisher(NotificationPublisher notificationPublisher) { - this.publisher = notificationPublisher; - } - - } ----- - -The `NotificationPublisher` interface and the machinery to get it all working is one of -the nicer features of Spring's JMX support. It does however come with the price tag of -coupling your classes to both Spring and JMX; as always, the advice here is to be -pragmatic... if you need the functionality offered by the `NotificationPublisher` and -you can accept the coupling to both Spring and JMX, then do so. - - - - -[[jmx-resources]] -=== Further Resources -This section contains links to further resources about JMX. - -* The http://www.oracle.com/technetwork/java/javase/tech/javamanagement-140525.html[JMX -homepage] at Oracle -* The http://jcp.org/aboutJava/communityprocess/final/jsr003/index3.html[JMX - specification] (JSR-000003) -* The http://jcp.org/aboutJava/communityprocess/final/jsr160/index.html[JMX Remote API - specification] (JSR-000160) -* The http://mx4j.sourceforge.net/[MX4J homepage] (an Open Source implementation of - various JMX specs) - - - - - -[[cci]] -== JCA CCI - - - - -[[cci-introduction]] -=== Introduction -Java EE provides a specification to standardize access to enterprise information systems -(EIS): the JCA (Java EE Connector Architecture). This specification is divided into -several different parts: - -* SPI (Service provider interfaces) that the connector provider must implement. These - interfaces constitute a resource adapter which can be deployed on a Java EE - application server. In such a scenario, the server manages connection pooling, - transaction and security (managed mode). The application server is also responsible - for managing the configuration, which is held outside the client application. A - connector can be used without an application server as well; in this case, the - application must configure it directly (non-managed mode). -* CCI (Common Client Interface) that an application can use to interact with the - connector and thus communicate with an EIS. An API for local transaction demarcation - is provided as well. - -The aim of the Spring CCI support is to provide classes to access a CCI connector in -typical Spring style, leveraging the Spring Framework's general resource and transaction -management facilities. - -[NOTE] -==== -The client side of connectors doesn't alway use CCI. Some connectors expose their own -APIs, only providing JCA resource adapter to use the system contracts of a Java EE -container (connection pooling, global transactions, security). Spring does not offer -special support for such connector-specific APIs. -==== - - - - -[[cci-config]] -=== Configuring CCI - - - -[[cci-config-connector]] -==== Connector configuration -The base resource to use JCA CCI is the `ConnectionFactory` interface. The connector -used must provide an implementation of this interface. - -To use your connector, you can deploy it on your application server and fetch the -`ConnectionFactory` from the server's JNDI environment (managed mode). The connector -must be packaged as a RAR file (resource adapter archive) and contain a `ra.xml` file to -describe its deployment characteristics. The actual name of the resource is specified -when you deploy it. To access it within Spring, simply use Spring's -`JndiObjectFactoryBean` / `` fetch the factory by its JNDI name. - -Another way to use a connector is to embed it in your application (non-managed mode), -not using an application server to deploy and configure it. Spring offers the -possibility to configure a connector as a bean, through a provided `FactoryBean` ( -`LocalConnectionFactoryBean`). In this manner, you only need the connector library in -the classpath (no RAR file and no `ra.xml` descriptor needed). The library must be -extracted from the connector's RAR file, if necessary. - -Once you have got access to your `ConnectionFactory` instance, you can inject it into -your components. These components can either be coded against the plain CCI API or -leverage Spring's support classes for CCI access (e.g. `CciTemplate`). - -[NOTE] -==== -When you use a connector in non-managed mode, you can't use global transactions because -the resource is never enlisted / delisted in the current global transaction of the -current thread. The resource is simply not aware of any global Java EE transactions that -might be running. -==== - - - -[[cci-config-connectionfactory]] -==== ConnectionFactory configuration in Spring - -In order to make connections to the EIS, you need to obtain a `ConnectionFactory` from -the application server if you are in a managed mode, or directly from Spring if you are -in a non-managed mode. - -In a managed mode, you access a `ConnectionFactory` from JNDI; its properties will be -configured in the application server. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - ----- - -In non-managed mode, you must configure the `ConnectionFactory` you want to use in the -configuration of Spring as a JavaBean. The `LocalConnectionFactoryBean` class offers -this setup style, passing in the `ManagedConnectionFactory` implementation of your -connector, exposing the application-level CCI `ConnectionFactory`. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - - ----- - -[NOTE] -==== -You can't directly instantiate a specific `ConnectionFactory`. You need to go through -the corresponding implementation of the `ManagedConnectionFactory` interface for your -connector. This interface is part of the JCA SPI specification. -==== - - - -[[cci-config-cci-connections]] -==== Configuring CCI connections -JCA CCI allow the developer to configure the connections to the EIS using the -`ConnectionSpec` implementation of your connector. In order to configure its properties, -you need to wrap the target connection factory with a dedicated adapter, -`ConnectionSpecConnectionFactoryAdapter`. So, the dedicated `ConnectionSpec` can be -configured with the property `connectionSpec` (as an inner bean). - -This property is not mandatory because the CCI `ConnectionFactory` interface defines two -different methods to obtain a CCI connection. Some of the `ConnectionSpec` properties -can often be configured in the application server (in managed mode) or on the -corresponding local `ManagedConnectionFactory` implementation. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public interface ConnectionFactory implements Serializable, Referenceable { - ... - Connection getConnection() throws ResourceException; - Connection getConnection(ConnectionSpec connectionSpec) throws ResourceException; - ... - } ----- - -Spring provides a `ConnectionSpecConnectionFactoryAdapter` that allows for specifying a -`ConnectionSpec` instance to use for all operations on a given factory. If the adapter's -`connectionSpec` property is specified, the adapter uses the `getConnection` variant -with the `ConnectionSpec` argument, otherwise the variant without argument. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - - - - - - - - - - - ----- - - - -[[cci-config-single-connection]] -==== Using a single CCI connection -If you want to use a single CCI connection, Spring provides a further -`ConnectionFactory` adapter to manage this. The `SingleConnectionFactory` adapter class -will open a single connection lazily and close it when this bean is destroyed at -application shutdown. This class will expose special `Connection` proxies that behave -accordingly, all sharing the same underlying physical connection. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - - - - - - ----- - -[NOTE] -==== -This `ConnectionFactory` adapter cannot directly be configured with a `ConnectionSpec`. -Use an intermediary `ConnectionSpecConnectionFactoryAdapter` that the -`SingleConnectionFactory` talks to if you require a single connection for a specific -`ConnectionSpec`. -==== - - - - -[[cci-using]] -=== Using Spring's CCI access support - - - -[[cci-record-creator]] -==== Record conversion -One of the aims of the JCA CCI support is to provide convenient facilities for -manipulating CCI records. The developer can specify the strategy to create records and -extract datas from records, for use with Spring's `CciTemplate`. The following -interfaces will configure the strategy to use input and output records if you don't want -to work with records directly in your application. - -In order to create an input `Record`, the developer can use a dedicated implementation -of the `RecordCreator` interface. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public interface RecordCreator { - - Record createRecord(RecordFactory recordFactory) throws ResourceException, DataAccessException; - - } ----- - -As you can see, the `createRecord(..)` method receives a `RecordFactory` instance as -parameter, which corresponds to the `RecordFactory` of the `ConnectionFactory` used. -This reference can be used to create `IndexedRecord` or `MappedRecord` instances. The -following sample shows how to use the `RecordCreator` interface and indexed/mapped -records. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class MyRecordCreator implements RecordCreator { - - public Record createRecord(RecordFactory recordFactory) throws ResourceException { - IndexedRecord input = recordFactory.createIndexedRecord("input"); - input.add(new Integer(id)); - return input; - } - - } ----- - -An output `Record` can be used to receive data back from the EIS. Hence, a specific -implementation of the `RecordExtractor` interface can be passed to Spring's -`CciTemplate` for extracting data from the output `Record`. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public interface RecordExtractor { - - Object extractData(Record record) throws ResourceException, SQLException, DataAccessException; - - } ----- - -The following sample shows how to use the `RecordExtractor` interface. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class MyRecordExtractor implements RecordExtractor { - - public Object extractData(Record record) throws ResourceException { - CommAreaRecord commAreaRecord = (CommAreaRecord) record; - String str = new String(commAreaRecord.toByteArray()); - String field1 = string.substring(0,6); - String field2 = string.substring(6,1); - return new OutputObject(Long.parseLong(field1), field2); - } - - } ----- - - - -[[cci-using-template]] -==== the CciTemplate - -The `CciTemplate` is the central class of the core CCI support package ( -`org.springframework.jca.cci.core`). It simplifies the use of CCI since it handles the -creation and release of resources. This helps to avoid common errors like forgetting to -always close the connection. It cares for the lifecycle of connection and interaction -objects, letting application code focus on generating input records from application -data and extracting application data from output records. - -The JCA CCI specification defines two distinct methods to call operations on an EIS. The -CCI `Interaction` interface provides two execute method signatures: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public interface javax.resource.cci.Interaction { - - ... - - boolean execute(InteractionSpec spec, Record input, Record output) throws ResourceException; - - Record execute(InteractionSpec spec, Record input) throws ResourceException; - - ... - - } ----- - -Depending on the template method called, `CciTemplate` will know which `execute` method -to call on the interaction. In any case, a correctly initialized `InteractionSpec` -instance is mandatory. - -`CciTemplate.execute(..)` can be used in two ways: - -* With direct `Record` arguments. In this case, you simply need to pass the CCI input - record in, and the returned object be the corresponding CCI output record. -* With application objects, using record mapping. In this case, you need to provide - corresponding `RecordCreator` and `RecordExtractor` instances. - -With the first approach, the following methods of the template will be used. These -methods directly correspond to those on the `Interaction` interface. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class CciTemplate implements CciOperations { - - public Record execute(InteractionSpec spec, Record inputRecord) - throws DataAccessException { ... } - - public void execute(InteractionSpec spec, Record inputRecord, Record outputRecord) - throws DataAccessException { ... } - - } ----- - -With the second approach, we need to specify the record creation and record extraction -strategies as arguments. The interfaces used are those describe in the previous section -on record conversion. The corresponding `CciTemplate` methods are the following: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class CciTemplate implements CciOperations { - - public Record execute(InteractionSpec spec, - RecordCreator inputCreator) throws DataAccessException { - // ... - } - - public Object execute(InteractionSpec spec, Record inputRecord, - RecordExtractor outputExtractor) throws DataAccessException { - // ... - } - - public Object execute(InteractionSpec spec, RecordCreator creator, - RecordExtractor extractor) throws DataAccessException { - // ... - } - - } ----- - -Unless the `outputRecordCreator` property is set on the template (see the following -section), every method will call the corresponding `execute` method of the CCI -`Interaction` with two parameters: `InteractionSpec` and input `Record`, receiving an -output `Record` as return value. - -`CciTemplate` also provides methods to create `IndexRecord` and `MappedRecord` outside a -`RecordCreator` implementation, through its `createIndexRecord(..)` and -`createMappedRecord(..)` methods. This can be used within DAO implementations to create -`Record` instances to pass into corresponding `CciTemplate.execute(..)` methods. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class CciTemplate implements CciOperations { - - public IndexedRecord createIndexedRecord(String name) throws DataAccessException { ... } - - public MappedRecord createMappedRecord(String name) throws DataAccessException { ... } - - } ----- - - - -[[cci-using-dao]] -==== DAO support -Spring's CCI support provides a abstract class for DAOs, supporting injection of a -`ConnectionFactory` or a `CciTemplate` instances. The name of the class is -`CciDaoSupport`: It provides simple `setConnectionFactory` and `setCciTemplate` methods. -Internally, this class will create a `CciTemplate` instance for a passed-in -`ConnectionFactory`, exposing it to concrete data access implementations in subclasses. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public abstract class CciDaoSupport { - - public void setConnectionFactory(ConnectionFactory connectionFactory) { - // ... - } - - public ConnectionFactory getConnectionFactory() { - // ... - } - - public void setCciTemplate(CciTemplate cciTemplate) { - // ... - } - - public CciTemplate getCciTemplate() { - // ... - } - - } ----- - - - -[[automatic-output-generation]] -==== Automatic output record generation -If the connector used only supports the `Interaction.execute(..)` method with input and -output records as parameters (that is, it requires the desired output record to be -passed in instead of returning an appropriate output record), you can set the -`outputRecordCreator` property of the `CciTemplate` to automatically generate an output -record to be filled by the JCA connector when the response is received. This record will -be then returned to the caller of the template. - -This property simply holds an implementation of the `RecordCreator` interface, used for -that purpose. The `RecordCreator` interface has already been discussed in -<>. The `outputRecordCreator` property must be directly specified on -the `CciTemplate`. This could be done in the application code like so: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - cciTemplate.setOutputRecordCreator(new EciOutputRecordCreator()); ----- - -Or (recommended) in the Spring configuration, if the `CciTemplate` is configured as a -dedicated bean instance: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - ----- - -[NOTE] -==== -As the `CciTemplate` class is thread-safe, it will usually be configured as a shared -instance. -==== - - - -[[template-summary]] -==== Summary -The following table summarizes the mechanisms of the `CciTemplate` class and the -corresponding methods called on the CCI `Interaction` interface: - -[[cci-interaction-execute-methods]] -.Usage of Interaction execute methods -[cols="3,1,3"] -|=== -| CciTemplate method signature| CciTemplate outputRecordCreator property| execute method called on the CCI Interaction - -| Record execute(InteractionSpec, Record) -| not set -| Record execute(InteractionSpec, Record) - -| Record execute(InteractionSpec, Record) -| set -| boolean execute(InteractionSpec, Record, Record) - -| void execute(InteractionSpec, Record, Record) -| not set -| void execute(InteractionSpec, Record, Record) - -| void execute(InteractionSpec, Record, Record) -| set -| void execute(InteractionSpec, Record, Record) - -| Record execute(InteractionSpec, RecordCreator) -| not set -| Record execute(InteractionSpec, Record) - -| Record execute(InteractionSpec, RecordCreator) -| set -| void execute(InteractionSpec, Record, Record) - -| Record execute(InteractionSpec, Record, RecordExtractor) -| not set -| Record execute(InteractionSpec, Record) - -| Record execute(InteractionSpec, Record, RecordExtractor) -| set -| void execute(InteractionSpec, Record, Record) - -| Record execute(InteractionSpec, RecordCreator, RecordExtractor) -| not set -| Record execute(InteractionSpec, Record) - -| Record execute(InteractionSpec, RecordCreator, RecordExtractor) -| set -| void execute(InteractionSpec, Record, Record) -|=== - - - -[[cci-straight]] -==== Using a CCI Connection and Interaction directly - -`CciTemplate` also offers the possibility to work directly with CCI connections and -interactions, in the same manner as `JdbcTemplate` and `JmsTemplate`. This is useful -when you want to perform multiple operations on a CCI connection or interaction, for -example. - -The interface `ConnectionCallback` provides a CCI `Connection` as argument, in order to -perform custom operations on it, plus the CCI `ConnectionFactory` which the `Connection` -was created with. The latter can be useful for example to get an associated -`RecordFactory` instance and create indexed/mapped records, for example. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public interface ConnectionCallback { - - Object doInConnection(Connection connection, ConnectionFactory connectionFactory) - throws ResourceException, SQLException, DataAccessException; - - } ----- - -The interface `InteractionCallback` provides the CCI `Interaction`, in order to perform -custom operations on it, plus the corresponding CCI `ConnectionFactory`. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public interface InteractionCallback { - - Object doInInteraction(Interaction interaction, ConnectionFactory connectionFactory) - throws ResourceException, SQLException, DataAccessException; - - } ----- - -[NOTE] -==== -`InteractionSpec` objects can either be shared across multiple template calls or newly -created inside every callback method. This is completely up to the DAO implementation. -==== - - - -[[cci-template-example]] -==== Example for CciTemplate usage - -In this section, the usage of the `CciTemplate` will be shown to acces to a CICS with -ECI mode, with the IBM CICS ECI connector. - -Firstly, some initializations on the CCI `InteractionSpec` must be done to specify which -CICS program to access and how to interact with it. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - ECIInteractionSpec interactionSpec = new ECIInteractionSpec(); - interactionSpec.setFunctionName("MYPROG"); - interactionSpec.setInteractionVerb(ECIInteractionSpec.SYNC_SEND_RECEIVE); ----- - -Then the program can use CCI via Spring's template and specify mappings between custom -objects and CCI `Records`. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class MyDaoImpl extends CciDaoSupport implements MyDao { - - public OutputObject getData(InputObject input) { - ECIInteractionSpec interactionSpec = ...; - - OutputObject output = (ObjectOutput) getCciTemplate().execute(interactionSpec, - new RecordCreator() { - public Record createRecord(RecordFactory recordFactory) throws ResourceException { - return new CommAreaRecord(input.toString().getBytes()); - } - }, - new RecordExtractor() { - public Object extractData(Record record) throws ResourceException { - CommAreaRecord commAreaRecord = (CommAreaRecord)record; - String str = new String(commAreaRecord.toByteArray()); - String field1 = string.substring(0,6); - String field2 = string.substring(6,1); - return new OutputObject(Long.parseLong(field1), field2); - } - }); - - return output; - } - } ----- - -As discussed previously, callbacks can be used to work directly on CCI connections or -interactions. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class MyDaoImpl extends CciDaoSupport implements MyDao { - - public OutputObject getData(InputObject input) { - ObjectOutput output = (ObjectOutput) getCciTemplate().execute( - new ConnectionCallback() { - public Object doInConnection(Connection connection, - ConnectionFactory factory) throws ResourceException { - - // do something... - - } - }); - } - return output; - } - - } ----- - -[NOTE] -==== -With a `ConnectionCallback`, the `Connection` used will be managed and closed by the -`CciTemplate`, but any interactions created on the connection must be managed by the -callback implementation. -==== - -For a more specific callback, you can implement an `InteractionCallback`. The passed-in -`Interaction` will be managed and closed by the `CciTemplate` in this case. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class MyDaoImpl extends CciDaoSupport implements MyDao { - - public String getData(String input) { - ECIInteractionSpec interactionSpec = ...; - String output = (String) getCciTemplate().execute(interactionSpec, - new InteractionCallback() { - public Object doInInteraction(Interaction interaction, - ConnectionFactory factory) throws ResourceException { - Record input = new CommAreaRecord(inputString.getBytes()); - Record output = new CommAreaRecord(); - interaction.execute(holder.getInteractionSpec(), input, output); - return new String(output.toByteArray()); - } - }); - return output; - } - - } ----- - -For the examples above, the corresponding configuration of the involved Spring beans -could look like this in non-managed mode: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - - - - - - - ----- - -In managed mode (that is, in a Java EE environment), the configuration could look as -follows: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - ----- - - - - -[[cci-object]] -=== Modeling CCI access as operation objects -The `org.springframework.jca.cci.object` package contains support classes that allow you -to access the EIS in a different style: through reusable operation objects, analogous to -Spring's JDBC operation objects (see JDBC chapter). This will usually encapsulate the -CCI API: an application-level input object will be passed to the operation object, so it -can construct the input record and then convert the received record data to an -application-level output object and return it. - -[NOTE] -==== -This approach is internally based on the `CciTemplate` class and the -`RecordCreator` / `RecordExtractor` interfaces, reusing the machinery of Spring's core -CCI support. -==== - - - -[[cci-object-mapping-record]] -==== MappingRecordOperation - -`MappingRecordOperation` essentially performs the same work as `CciTemplate`, but -represents a specific, pre-configured operation as an object. It provides two template -methods to specify how to convert an input object to a input record, and how to convert -an output record to an output object (record mapping): - -* `createInputRecord(..)` to specify how to convert an input object to an input `Record` -* `extractOutputData(..)` to specify how to extract an output object from an output - `Record` - -Here are the signatures of these methods: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public abstract class MappingRecordOperation extends EisOperation { - - ... - - protected abstract Record createInputRecord(RecordFactory recordFactory, - Object inputObject) throws ResourceException, DataAccessException { - // ... - } - - protected abstract Object extractOutputData(Record outputRecord) - throws ResourceException, SQLException, DataAccessException { - // ... - } - - ... - - } ----- - -Thereafter, in order to execute an EIS operation, you need to use a single execute -method, passing in an application-level input object and receiving an application-level -output object as result: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public abstract class MappingRecordOperation extends EisOperation { - - ... - - public Object execute(Object inputObject) throws DataAccessException { - } - - ... - } ----- - -As you can see, contrary to the `CciTemplate` class, this `execute(..)` method does not -have an `InteractionSpec` as argument. Instead, the `InteractionSpec` is global to the -operation. The following constructor must be used to instantiate an operation object -with a specific `InteractionSpec`: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - InteractionSpec spec = ...; - MyMappingRecordOperation eisOperation = new MyMappingRecordOperation(getConnectionFactory(), spec); - ... ----- - - - -[[cci-object-mapping-comm-area]] -==== MappingCommAreaOperation - -Some connectors use records based on a COMMAREA which represents an array of bytes -containing parameters to send to the EIS and data returned by it. Spring provides a -special operation class for working directly on COMMAREA rather than on records. The -`MappingCommAreaOperation` class extends the `MappingRecordOperation` class to provide -such special COMMAREA support. It implicitly uses the `CommAreaRecord` class as input -and output record type, and provides two new methods to convert an input object into an -input COMMAREA and the output COMMAREA into an output object. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public abstract class MappingCommAreaOperation extends MappingRecordOperation { - - ... - - protected abstract byte[] objectToBytes(Object inObject) - throws IOException, DataAccessException; - - protected abstract Object bytesToObject(byte[] bytes) - throws IOException, DataAccessException; - - ... - - } ----- - - - -[[cci-automatic-record-gen]] -==== Automatic output record generation -As every `MappingRecordOperation` subclass is based on CciTemplate internally, the same -way to automatically generate output records as with `CciTemplate` is available. Every -operation object provides a corresponding `setOutputRecordCreator(..)` method. For -further information, see <>. - - - -[[cci-object-summary]] -==== Summary -The operation object approach uses records in the same manner as the `CciTemplate` class. - -[[cci-interaction-methods]] -.Usage of Interaction execute methods -[cols="3,1,3"] -|=== -| MappingRecordOperation method signature| MappingRecordOperation outputRecordCreator property| execute method called on the CCI Interaction - -| Object execute(Object) -| not set -| Record execute(InteractionSpec, Record) - -| Object execute(Object) -| set -| boolean execute(InteractionSpec, Record, Record) -|=== - - - -[[cci-objects-mappring-record-example]] -==== Example for MappingRecordOperation usage - -In this section, the usage of the `MappingRecordOperation` will be shown to access a -database with the Blackbox CCI connector. - -[NOTE] -==== -The original version of this connector is provided by the Java EE SDK (version 1.3), -available from Oracle. -==== - -Firstly, some initializations on the CCI `InteractionSpec` must be done to specify which -SQL request to execute. In this sample, we directly define the way to convert the -parameters of the request to a CCI record and the way to convert the CCI result record -to an instance of the `Person` class. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class PersonMappingOperation extends MappingRecordOperation { - - public PersonMappingOperation(ConnectionFactory connectionFactory) { - setConnectionFactory(connectionFactory); - CciInteractionSpec interactionSpec = new CciConnectionSpec(); - interactionSpec.setSql("select * from person where person_id=?"); - setInteractionSpec(interactionSpec); - } - - protected Record createInputRecord(RecordFactory recordFactory, - Object inputObject) throws ResourceException { - Integer id = (Integer) inputObject; - IndexedRecord input = recordFactory.createIndexedRecord("input"); - input.add(new Integer(id)); - return input; - } - - protected Object extractOutputData(Record outputRecord) - throws ResourceException, SQLException { - ResultSet rs = (ResultSet) outputRecord; - Person person = null; - if (rs.next()) { - Person person = new Person(); - person.setId(rs.getInt("person_id")); - person.setLastName(rs.getString("person_last_name")); - person.setFirstName(rs.getString("person_first_name")); - } - return person; - } - } ----- - -Then the application can execute the operation object, with the person identifier as -argument. Note that operation object could be set up as shared instance, as it is -thread-safe. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class MyDaoImpl extends CciDaoSupport implements MyDao { - - public Person getPerson(int id) { - PersonMappingOperation query = new PersonMappingOperation(getConnectionFactory()); - Person person = (Person) query.execute(new Integer(id)); - return person; - } - } ----- - -The corresponding configuration of Spring beans could look as follows in non-managed mode: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - - - - - - - - - - - - - - - ----- - -In managed mode (that is, in a Java EE environment), the configuration could look as -follows: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - - - - - - - - ----- - - - -[[cci-objects-mapping-comm-area-example]] -==== Example for MappingCommAreaOperation usage - -In this section, the usage of the `MappingCommAreaOperation` will be shown: accessing a -CICS with ECI mode with the IBM CICS ECI connector. - -Firstly, the CCI `InteractionSpec` needs to be initialized to specify which CICS program -to access and how to interact with it. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public abstract class EciMappingOperation extends MappingCommAreaOperation { - - public EciMappingOperation(ConnectionFactory connectionFactory, String programName) { - setConnectionFactory(connectionFactory); - ECIInteractionSpec interactionSpec = new ECIInteractionSpec(), - interactionSpec.setFunctionName(programName); - interactionSpec.setInteractionVerb(ECIInteractionSpec.SYNC_SEND_RECEIVE); - interactionSpec.setCommareaLength(30); - setInteractionSpec(interactionSpec); - setOutputRecordCreator(new EciOutputRecordCreator()); - } - - private static class EciOutputRecordCreator implements RecordCreator { - public Record createRecord(RecordFactory recordFactory) throws ResourceException { - return new CommAreaRecord(); - } - } - - } ----- - -The abstract `EciMappingOperation` class can then be subclassed to specify mappings -between custom objects and `Records`. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class MyDaoImpl extends CciDaoSupport implements MyDao { - - public OutputObject getData(Integer id) { - EciMappingOperation query = new EciMappingOperation(getConnectionFactory(), "MYPROG") { - - protected abstract byte[] objectToBytes(Object inObject) throws IOException { - Integer id = (Integer) inObject; - return String.valueOf(id); - } - - protected abstract Object bytesToObject(byte[] bytes) throws IOException; - String str = new String(bytes); - String field1 = str.substring(0,6); - String field2 = str.substring(6,1); - String field3 = str.substring(7,1); - return new OutputObject(field1, field2, field3); - } - }); - - return (OutputObject) query.execute(new Integer(id)); - } - - } ----- - -The corresponding configuration of Spring beans could look as follows in non-managed mode: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - - - - - - - ----- - -In managed mode (that is, in a Java EE environment), the configuration could look as -follows: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - ----- - - - - -[[cci-tx]] -=== Transactions -JCA specifies several levels of transaction support for resource adapters. The kind of -transactions that your resource adapter supports is specified in its `ra.xml` file. -There are essentially three options: none (for example with CICS EPI connector), local -transactions (for example with a CICS ECI connector), global transactions (for example -with an IMS connector). - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - XATransaction - - ----- - -For global transactions, you can use Spring's generic transaction infrastructure to -demarcate transactions, with `JtaTransactionManager` as backend (delegating to the Java -EE server's distributed transaction coordinator underneath). - -For local transactions on a single CCI `ConnectionFactory`, Spring provides a specific -transaction management strategy for CCI, analogous to the `DataSourceTransactionManager` -for JDBC. The CCI API defines a local transaction object and corresponding local -transaction demarcation methods. Spring's `CciLocalTransactionManager` executes such -local CCI transactions, fully compliant with Spring's generic -`PlatformTransactionManager` abstraction. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - ----- - -Both transaction strategies can be used with any of Spring's transaction demarcation -facilities, be it declarative or programmatic. This is a consequence of Spring's generic -`PlatformTransactionManager` abstraction, which decouples transaction demarcation from -the actual execution strategy. Simply switch between `JtaTransactionManager` and -`CciLocalTransactionManager` as needed, keeping your transaction demarcation as-is. - -For more information on Spring's transaction facilities, see the chapter entitled -<>. - - - - - -[[mail]] -== Email - - - - -[[mail-introduction]] -=== Introduction - -.Library dependencies -**** -The following additional jars to be on the classpath of your application in order to be -able to use the Spring Framework's email library. - -* The https://java.net/projects/javamail/pages/Home[JavaMail] `mail.jar` library -* The http://www.oracle.com/technetwork/java/jaf11-139815.html[JAF] - `activation.jar` library - -All of these libraries are freely available on the web. -**** - -The Spring Framework provides a helpful utility library for sending email that shields -the user from the specifics of the underlying mailing system and is responsible for low -level resource handling on behalf of the client. - -The `org.springframework.mail` package is the root level package for the Spring -Framework's email support. The central interface for sending emails is the `MailSender` -interface; a simple value object encapsulating the properties of a simple mail such as -__from__ and __to__ (plus many others) is the `SimpleMailMessage` class. This package -also contains a hierarchy of checked exceptions which provide a higher level of -abstraction over the lower level mail system exceptions with the root exception being -`MailException`. Please refer to the javadocs for more information on the rich mail -exception hierarchy. - -The `org.springframework.mail.javamail.JavaMailSender` interface adds specialized -__JavaMail__ features such as MIME message support to the `MailSender` interface (from -which it inherits). `JavaMailSender` also provides a callback interface for preparation -of JavaMail MIME messages, called -`org.springframework.mail.javamail.MimeMessagePreparator` - - - - -[[mail-usage]] -=== Usage -Let's assume there is a business interface called `OrderManager`: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public interface OrderManager { - - void placeOrder(Order order); - - } ----- - -Let us also assume that there is a requirement stating that an email message with an -order number needs to be generated and sent to a customer placing the relevant order. - - - -[[mail-usage-simple]] -==== Basic MailSender and SimpleMailMessage usage - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - import org.springframework.mail.MailException; - import org.springframework.mail.MailSender; - import org.springframework.mail.SimpleMailMessage; - - public class SimpleOrderManager implements OrderManager { - - private MailSender mailSender; - private SimpleMailMessage templateMessage; - - public void setMailSender(MailSender mailSender) { - this.mailSender = mailSender; - } - - public void setTemplateMessage(SimpleMailMessage templateMessage) { - this.templateMessage = templateMessage; - } - - public void placeOrder(Order order) { - - // Do the business calculations... - - // Call the collaborators to persist the order... - - // Create a thread safe "copy" of the template message and customize it - SimpleMailMessage msg = new SimpleMailMessage(this.templateMessage); - msg.setTo(order.getCustomer().getEmailAddress()); - msg.setText( - "Dear " + order.getCustomer().getFirstName() - + order.getCustomer().getLastName() - + ", thank you for placing order. Your order number is " - + order.getOrderNumber()); - try{ - this.mailSender.send(msg); - } - catch (MailException ex) { - // simply log it and go on... - System.err.println(ex.getMessage()); - } - } - - } ----- - -Find below the bean definitions for the above code: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - - - - - - - ----- - - - -[[mail-usage-mime]] -==== Using the JavaMailSender and the MimeMessagePreparator - -Here is another implementation of `OrderManager` using the `MimeMessagePreparator` -callback interface. Please note in this case that the `mailSender` property is of type -`JavaMailSender` so that we are able to use the JavaMail `MimeMessage` class: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - import javax.mail.Message; - import javax.mail.MessagingException; - import javax.mail.internet.InternetAddress; - import javax.mail.internet.MimeMessage; - - import javax.mail.internet.MimeMessage; - import org.springframework.mail.MailException; - import org.springframework.mail.javamail.JavaMailSender; - import org.springframework.mail.javamail.MimeMessagePreparator; - - public class SimpleOrderManager implements OrderManager { - - private JavaMailSender mailSender; - - public void setMailSender(JavaMailSender mailSender) { - this.mailSender = mailSender; - } - - public void placeOrder(final Order order) { - - // Do the business calculations... - - // Call the collaborators to persist the order... - - MimeMessagePreparator preparator = new MimeMessagePreparator() { - - public void prepare(MimeMessage mimeMessage) throws Exception { - - mimeMessage.setRecipient(Message.RecipientType.TO, - new InternetAddress(order.getCustomer().getEmailAddress())); - mimeMessage.setFrom(new InternetAddress("mail@mycompany.com")); - mimeMessage.setText( - "Dear " + order.getCustomer().getFirstName() + " " - + order.getCustomer().getLastName() - + ", thank you for placing order. Your order number is " - + order.getOrderNumber()); - } - }; - - try { - this.mailSender.send(preparator); - } - catch (MailException ex) { - // simply log it and go on... - System.err.println(ex.getMessage()); - } - } - - } ----- - -[NOTE] -==== -The mail code is a crosscutting concern and could well be a candidate for refactoring -into a <>, which then could be executed at appropriate -joinpoints on the `OrderManager` target. -==== - -The Spring Framework's mail support ships with the standard JavaMail implementation. -Please refer to the relevant javadocs for more information. - - - - -[[mail-javamail-mime]] -=== Using the JavaMail MimeMessageHelper - -A class that comes in pretty handy when dealing with JavaMail messages is the -`org.springframework.mail.javamail.MimeMessageHelper` class, which shields you from -having to use the verbose JavaMail API. Using the `MimeMessageHelper` it is pretty easy -to create a `MimeMessage`: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - // of course you would use DI in any real-world cases - JavaMailSenderImpl sender = new JavaMailSenderImpl(); - sender.setHost("mail.host.com"); - - MimeMessage message = sender.createMimeMessage(); - MimeMessageHelper helper = new MimeMessageHelper(message); - helper.setTo("test@host.com"); - helper.setText("Thank you for ordering!"); - - sender.send(message); ----- - - - -[[mail-javamail-mime-attachments]] -==== Sending attachments and inline resources -Multipart email messages allow for both attachments and inline resources. Examples of -inline resources would be images or a stylesheet you want to use in your message, but -that you don't want displayed as an attachment. - - -[[mail-javamail-mime-attachments-attachment]] -===== Attachments -The following example shows you how to use the `MimeMessageHelper` to send an email -along with a single JPEG image attachment. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - JavaMailSenderImpl sender = new JavaMailSenderImpl(); - sender.setHost("mail.host.com"); - - MimeMessage message = sender.createMimeMessage(); - - // use the true flag to indicate you need a multipart message - MimeMessageHelper helper = new MimeMessageHelper(message, true); - helper.setTo("test@host.com"); - - helper.setText("Check out this image!"); - - // let's attach the infamous windows Sample file (this time copied to c:/) - FileSystemResource file = new FileSystemResource(new File("c:/Sample.jpg")); - helper.addAttachment("CoolImage.jpg", file); - - sender.send(message); ----- - - -[[mail-javamail-mime-attachments-inline]] -===== Inline resources -The following example shows you how to use the `MimeMessageHelper` to send an email -along with an inline image. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - JavaMailSenderImpl sender = new JavaMailSenderImpl(); - sender.setHost("mail.host.com"); - - MimeMessage message = sender.createMimeMessage(); - - // use the true flag to indicate you need a multipart message - MimeMessageHelper helper = new MimeMessageHelper(message, true); - helper.setTo("test@host.com"); - - // use the true flag to indicate the text included is HTML - helper.setText("", true); - - // let's include the infamous windows Sample file (this time copied to c:/) - FileSystemResource res = new FileSystemResource(new File("c:/Sample.jpg")); - helper.addInline("identifier1234", res); - - sender.send(message); ----- - -[WARNING] -==== - -Inline resources are added to the mime message using the specified `Content-ID` ( -`identifier1234` in the above example). The order in which you are adding the text and -the resource are __very__ important. Be sure to __first add the text__ and after that -the resources. If you are doing it the other way around, it won't work! -==== - - - -[[mail-templates]] -==== Creating email content using a templating library -The code in the previous examples explicitly created the content of the email message, -using methods calls such as `message.setText(..)`. This is fine for simple cases, and it -is okay in the context of the aforementioned examples, where the intent was to show you -the very basics of the API. - -In your typical enterprise application though, you are not going to create the content -of your emails using the above approach for a number of reasons. - -* Creating HTML-based email content in Java code is tedious and error prone -* There is no clear separation between display logic and business logic -* Changing the display structure of the email content requires writing Java code, - recompiling, redeploying... - -Typically the approach taken to address these issues is to use a template library such -as FreeMarker or Velocity to define the display structure of email content. This leaves -your code tasked only with creating the data that is to be rendered in the email -template and sending the email. It is definitely a best practice for when the content of -your emails becomes even moderately complex, and with the Spring Framework's support -classes for FreeMarker and Velocity becomes quite easy to do. Find below an example of -using the Velocity template library to create email content. - - -[[mail-templates-example]] -===== A Velocity-based example -To use http://velocity.apache.org[Velocity] to create your email template(s), you will -need to have the Velocity libraries available on your classpath. You will also need to -create one or more Velocity templates for the email content that your application needs. -Find below the Velocity template that this example will be using. As you can see it is -HTML-based, and since it is plain text it can be created using your favorite HTML or -text editor. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - # in the com/foo/package - - -

Hi ${user.userName}, welcome to the Chipping Sodbury On-the-Hill message boards!

- -
- Your email address is ${user.emailAddress}. -
- - ----- - -Find below some simple code and Spring XML configuration that makes use of the above -Velocity template to create email content and send email(s). - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - package com.foo; - - import org.apache.velocity.app.VelocityEngine; - import org.springframework.mail.javamail.JavaMailSender; - import org.springframework.mail.javamail.MimeMessageHelper; - import org.springframework.mail.javamail.MimeMessagePreparator; - import org.springframework.ui.velocity.VelocityEngineUtils; - - import javax.mail.internet.MimeMessage; - import java.util.HashMap; - import java.util.Map; - - public class SimpleRegistrationService implements RegistrationService { - - private JavaMailSender mailSender; - private VelocityEngine velocityEngine; - - public void setMailSender(JavaMailSender mailSender) { - this.mailSender = mailSender; - } - - public void setVelocityEngine(VelocityEngine velocityEngine) { - this.velocityEngine = velocityEngine; - } - - public void register(User user) { - - // Do the registration logic... - - sendConfirmationEmail(user); - } - - private void sendConfirmationEmail(final User user) { - MimeMessagePreparator preparator = new MimeMessagePreparator() { - public void prepare(MimeMessage mimeMessage) throws Exception { - MimeMessageHelper message = new MimeMessageHelper(mimeMessage); - message.setTo(user.getEmailAddress()); - message.setFrom("webmaster@csonth.gov.uk"); // could be parameterized... - Map model = new HashMap(); - model.put("user", user); - String text = VelocityEngineUtils.mergeTemplateIntoString( - velocityEngine, "com/dns/registration-confirmation.vm", model); - message.setText(text, true); - } - }; - this.mailSender.send(preparator); - } - - } ----- - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - - - - - - - - - resource.loader=class - class.resource.loader.class=org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader - - - - - ----- - - - - - -[[scheduling]] -== Task Execution and Scheduling - - - - -[[scheduling-introduction]] -=== Introduction -The Spring Framework provides abstractions for asynchronous execution and scheduling of -tasks with the `TaskExecutor` and `TaskScheduler` interfaces, respectively. Spring also -features implementations of those interfaces that support thread pools or delegation to -CommonJ within an application server environment. Ultimately the use of these -implementations behind the common interfaces abstracts away the differences between Java -SE 5, Java SE 6 and Java EE environments. - -Spring also features integration classes for supporting scheduling with the `Timer`, -part of the JDK since 1.3, and the Quartz Scheduler ( http://quartz-scheduler.org[]). -Both of those schedulers are set up using a `FactoryBean` with optional references to -`Timer` or `Trigger` instances, respectively. Furthermore, a convenience class for both -the Quartz Scheduler and the `Timer` is available that allows you to invoke a method of -an existing target object (analogous to the normal `MethodInvokingFactoryBean` -operation). - - - - -[[scheduling-task-executor]] -=== The Spring TaskExecutor abstraction - -Spring 2.0 introduces a new abstraction for dealing with executors. Executors are the -Java 5 name for the concept of thread pools. The "executor" naming is due to the fact -that there is no guarantee that the underlying implementation is actually a pool; an -executor may be single-threaded or even synchronous. Spring's abstraction hides -implementation details between Java SE 1.4, Java SE 5 and Java EE environments. - -Spring's `TaskExecutor` interface is identical to the `java.util.concurrent.Executor` -interface. In fact, its primary reason for existence was to abstract away the need for -Java 5 when using thread pools. The interface has a single method `execute(Runnable -task)` that accepts a task for execution based on the semantics and configuration of the -thread pool. - -The `TaskExecutor` was originally created to give other Spring components an abstraction -for thread pooling where needed. Components such as the `ApplicationEventMulticaster`, -JMS's `AbstractMessageListenerContainer`, and Quartz integration all use the -`TaskExecutor` abstraction to pool threads. However, if your beans need thread pooling -behavior, it is possible to use this abstraction for your own needs. - - - -[[scheduling-task-executor-types]] -==== TaskExecutor types - -There are a number of pre-built implementations of `TaskExecutor` included with the -Spring distribution. In all likelihood, you shouldn't ever need to implement your own. - -* `SimpleAsyncTaskExecutor` - This implementation does not reuse any threads, rather it starts up a new thread - for each invocation. However, it does support a concurrency limit which will block - any invocations that are over the limit until a slot has been freed up. If you - re looking for true pooling, keep scrolling further down the page. -* `SyncTaskExecutor` - This implementation doesn't execute invocations asynchronously. Instead, each - invocation takes place in the calling thread. It is primarily used in situations - where multi-threading isn't necessary such as simple test cases. -* `ConcurrentTaskExecutor` - This implementation is an adapter for a `java.util.concurrent.Executor` object. - There is an alternative, `ThreadPoolTaskExecutor, that exposes the `Executor` - configuration parameters as bean properties. It is rare to need to use the - `ConcurrentTaskExecutor` but if the <> - isn't flexible enough for your needs, the `ConcurrentTaskExecutor` is an alternative. -* `SimpleThreadPoolTaskExecutor` - This implementation is actually a subclass of Quartz's `SimpleThreadPool` which - listens to Spring's lifecycle callbacks. This is typically used when you have a - thread pool that may need to be shared by both Quartz and non-Quartz components. -* `ThreadPoolTaskExecutor` - This implementation is the most commonly used one. It exposes bean properties for - configuring a java.util.concurrent.ThreadPoolExecutor` and wraps it in a `TaskExecutor`. - If you need to adapt to a different kind of `java.util.concurrent.Executor`, it is - recommended that you use a <> instead. -* `TimerTaskExecutor` - This implementation uses a single `TimerTask` as its backing implementation. - It's different from the <> in that the method - invocations are executed in a separate thread, although they are effectively - synchronously batched in that thread. -* `WorkManagerTaskExecutor` - -+ - -**** -CommonJ is a set of specifications jointly developed between BEA and IBM. These -specifications are not Java EE standards, but are standard across BEA's and IBM's -Application Server implementations. -**** - -+ - -This implementation uses the CommonJ WorkManager as its backing implementation and is -the central convenience class for setting up a CommonJ WorkManager reference in a Spring -context. Similar to the <>, -this class implements the WorkManager interface and therefore can be used directly as a -WorkManager as well. - - - -[[scheduling-task-executor-usage]] -==== Using a TaskExecutor - -Spring's `TaskExecutor` implementations are used as simple JavaBeans. In the example -below, we define a bean that uses the `ThreadPoolTaskExecutor` to asynchronously print -out a set of messages. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - import org.springframework.core.task.TaskExecutor; - - public class TaskExecutorExample { - - private class MessagePrinterTask implements Runnable { - - private String message; - - public MessagePrinterTask(String message) { - this.message = message; - } - - public void run() { - System.out.println(message); - } - - } - - private TaskExecutor taskExecutor; - - public TaskExecutorExample(TaskExecutor taskExecutor) { - this.taskExecutor = taskExecutor; - } - - public void printMessages() { - for(int i = 0; i < 25; i++) { - taskExecutor.execute(new MessagePrinterTask("Message" + i)); - } - } - - } ----- - -As you can see, rather than retrieving a thread from the pool and executing yourself, -you add your `Runnable` to the queue and the `TaskExecutor` uses its internal rules to -decide when the task gets executed. - -To configure the rules that the `TaskExecutor` will use, simple bean properties have -been exposed. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - - ----- - - - - -[[scheduling-task-scheduler]] -=== The Spring TaskScheduler abstraction - -In addition to the `TaskExecutor` abstraction, Spring 3.0 introduces a `TaskScheduler` -with a variety of methods for scheduling tasks to run at some point in the future. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public interface TaskScheduler { - - ScheduledFuture schedule(Runnable task, Trigger trigger); - - ScheduledFuture schedule(Runnable task, Date startTime); - - ScheduledFuture scheduleAtFixedRate(Runnable task, Date startTime, long period); - - ScheduledFuture scheduleAtFixedRate(Runnable task, long period); - - ScheduledFuture scheduleWithFixedDelay(Runnable task, Date startTime, long delay); - - ScheduledFuture scheduleWithFixedDelay(Runnable task, long delay); - - } ----- - -The simplest method is the one named 'schedule' that takes a `Runnable` and `Date` only. -That will cause the task to run once after the specified time. All of the other methods -are capable of scheduling tasks to run repeatedly. The fixed-rate and fixed-delay -methods are for simple, periodic execution, but the method that accepts a Trigger is -much more flexible. - - - -[[scheduling-trigger-interface]] -==== the Trigger interface - -The `Trigger` interface is essentially inspired by JSR-236, which, as of Spring 3.0, has -not yet been officially implemented. The basic idea of the `Trigger` is that execution -times may be determined based on past execution outcomes or even arbitrary conditions. -If these determinations do take into account the outcome of the preceding execution, -that information is available within a `TriggerContext`. The `Trigger` interface itself -is quite simple: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public interface Trigger { - - Date nextExecutionTime(TriggerContext triggerContext); - - } ----- - -As you can see, the `TriggerContext` is the most important part. It encapsulates all of -the relevant data, and is open for extension in the future if necessary. The -`TriggerContext` is an interface (a `SimpleTriggerContext` implementation is used by -default). Here you can see what methods are available for `Trigger` implementations. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public interface TriggerContext { - - Date lastScheduledExecutionTime(); - - Date lastActualExecutionTime(); - - Date lastCompletionTime(); - - } ----- - - - -[[scheduling-trigger-implementations]] -==== Trigger implementations - -Spring provides two implementations of the `Trigger` interface. The most interesting one -is the `CronTrigger`. It enables the scheduling of tasks based on cron expressions. For -example the following task is being scheduled to run 15 minutes past each hour but only -during the 9-to-5 "business hours" on weekdays. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - scheduler.schedule(task, new CronTrigger("* 15 9-17 * * MON-FRI")); ----- - -The other out-of-the-box implementation is a `PeriodicTrigger` that accepts a fixed -period, an optional initial delay value, and a boolean to indicate whether the period -should be interpreted as a fixed-rate or a fixed-delay. Since the `TaskScheduler` -interface already defines methods for scheduling tasks at a fixed-rate or with a -fixed-delay, those methods should be used directly whenever possible. The value of the -`PeriodicTrigger` implementation is that it can be used within components that rely on -the `Trigger` abstraction. For example, it may be convenient to allow periodic triggers, -cron-based triggers, and even custom trigger implementations to be used interchangeably. -Such a component could take advantage of dependency injection so that such `Triggers` -could be configured externally. - - - -[[scheduling-task-scheduler-implementations]] -==== TaskScheduler implementations - -As with Spring's `TaskExecutor` abstraction, the primary benefit of the `TaskScheduler` -is that code relying on scheduling behavior need not be coupled to a particular -scheduler implementation. The flexibility this provides is particularly relevant when -running within Application Server environments where threads should not be created -directly by the application itself. For such cases, Spring provides a -`TimerManagerTaskScheduler` that delegates to a CommonJ TimerManager instance, typically -configured with a JNDI-lookup. - -A simpler alternative, the `ThreadPoolTaskScheduler`, can be used whenever external -thread management is not a requirement. Internally, it delegates to a -`ScheduledExecutorService` instance. `ThreadPoolTaskScheduler` actually implements -Spring's `TaskExecutor` interface as well, so that a single instance can be used for -asynchronous execution __as soon as possible__ as well as scheduled, and potentially -recurring, executions. - - - - -[[scheduling-annotation-support]] -=== Annotation Support for Scheduling and Asynchronous Execution -Spring provides annotation support for both task scheduling and asynchronous method -execution. - - - -[[scheduling-enable-annotation-support]] -==== Enable scheduling annotations -To enable support for `@Scheduled` and `@Async` annotations add `@EnableScheduling` and -`@EnableAsync` to one of your `@Configuration` classes: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Configuration - @EnableAsync - @EnableScheduling - public class AppConfig { - } ----- - -You are free to pick and choose the relevant annotations for your application. For -example, if you only need support for `@Scheduled`, simply omit `@EnableAsync`. For more -fine-grained control you can additionally implement the `SchedulingConfigurer` and/or -`AsyncConfigurer` interfaces. See the javadocs for full details. - -If you prefer XML configuration use the `` element. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - ----- - -Notice with the above XML that an executor reference is provided for handling those -tasks that correspond to methods with the `@Async` annotation, and the scheduler -reference is provided for managing those methods annotated with `@Scheduled`. - - - -[[scheduling-annotation-support-scheduled]] -==== The @Scheduled Annotation -The @Scheduled annotation can be added to a method along with trigger metadata. For -example, the following method would be invoked every 5 seconds with a fixed delay, -meaning that the period will be measured from the completion time of each preceding -invocation. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Scheduled(fixedDelay=5000) - public void doSomething() { - // something that should execute periodically - } ----- - -If a fixed rate execution is desired, simply change the property name specified within -the annotation. The following would be executed every 5 seconds measured between the -successive start times of each invocation. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Scheduled(fixedRate=5000) - public void doSomething() { - // something that should execute periodically - } ----- - -For fixed-delay and fixed-rate tasks, an initial delay may be specified indicating the -number of milliseconds to wait before the first execution of the method. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Scheduled(initialDelay=1000, fixedRate=5000) - public void doSomething() { - // something that should execute periodically - } ----- - -If simple periodic scheduling is not expressive enough, then a cron expression may be -provided. For example, the following will only execute on weekdays. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Scheduled(cron="*/5 * * * * MON-FRI") - public void doSomething() { - // something that should execute on weekdays only - } ----- - -[TIP] -==== -You can additionally use the `zone` attribute to specify the time zone in which the cron -expression will be resolved. -==== - - -Notice that the methods to be scheduled must have void returns and must not expect any -arguments. If the method needs to interact with other objects from the Application -Context, then those would typically have been provided through dependency injection. - -[NOTE] -==== -Make sure that you are not initializing multiple instances of the same @Scheduled -annotation class at runtime, unless you do want to schedule callbacks to each such -instance. Related to this, make sure that you do not use @Configurable on bean classes -which are annotated with @Scheduled and registered as regular Spring beans with the -container: You would get double initialization otherwise, once through the container and -once through the @Configurable aspect, with the consequence of each @Scheduled method -being invoked twice. -==== - - - -[[scheduling-annotation-support-async]] -==== The @Async Annotation -The `@Async` annotation can be provided on a method so that invocation of that method -will occur asynchronously. In other words, the caller will return immediately upon -invocation and the actual execution of the method will occur in a task that has been -submitted to a Spring `TaskExecutor`. In the simplest case, the annotation may be -applied to a `void`-returning method. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Async - void doSomething() { - // this will be executed asynchronously - } ----- - -Unlike the methods annotated with the `@Scheduled` annotation, these methods can expect -arguments, because they will be invoked in the "normal" way by callers at runtime rather -than from a scheduled task being managed by the container. For example, the following is -a legitimate application of the `@Async` annotation. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Async - void doSomething(String s) { - // this will be executed asynchronously - } ----- - -Even methods that return a value can be invoked asynchronously. However, such methods -are required to have a `Future` typed return value. This still provides the benefit of -asynchronous execution so that the caller can perform other tasks prior to calling -`get()` on that Future. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Async - Future returnSomething(int i) { - // this will be executed asynchronously - } ----- - -`@Async` can not be used in conjunction with lifecycle callbacks such as -`@PostConstruct`. To asynchronously initialize Spring beans you currently have to use a -separate initializing Spring bean that invokes the `@Async` annotated method on the -target then. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class SampleBeanImpl implements SampleBean { - - @Async - void doSomething() { - // ... - } - - } - - public class SampleBeanInititalizer { - - private final SampleBean bean; - - public SampleBeanInitializer(SampleBean bean) { - this.bean = bean; - } - - @PostConstruct - public void initialize() { - bean.doSomething(); - } - - } ----- - - - -[[scheduling-annotation-support-qualification]] -==== Executor qualification with @Async -By default when specifying `@Async` on a method, the executor that will be used is the -one supplied to the 'annotation-driven' element as described above. However, the `value` -attribute of the `@Async` annotation can be used when needing to indicate that an -executor other than the default should be used when executing a given method. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Async("otherExecutor") - void doSomething(String s) { - // this will be executed asynchronously by "otherExecutor" - } ----- - -In this case, "otherExecutor" may be the name of any `Executor` bean in the Spring -container, or may be the name of a __qualifier__ associated with any `Executor`, e.g. as -specified with the `` element or Spring's `@Qualifier` annotation. - - - -[[scheduling-annotation-support-exception]] -==== Exception management with @Async -When an `@Async` method has a `Future` typed return value, it is easy to manage -an exception that was thrown during the method execution as this exception will -be thrown when calling `get` on the `Future` result. With a void return type -however, the exception is uncaught and cannot be transmitted. For those cases, an -`AsyncUncaughtExceptionHandler` can be provided to handle such exceptions. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class MyAsyncUncaughtExceptionHandler implements AsyncUncaughtExceptionHandler { - - @Override - public void handleUncaughtException(Throwable ex, Method method, Object... params) { - // handle exception - } - } ----- - -By default, the exception is simply logged. A custom `AsyncUncaughtExceptionHandler` can -be defined _via_ `AsyncConfigurer` or the `task:annotation-driven` XML element. - -[[scheduling-task-namespace]] -=== The Task Namespace -Beginning with Spring 3.0, there is an XML namespace for configuring `TaskExecutor` and -`TaskScheduler` instances. It also provides a convenient way to configure tasks to be -scheduled with a trigger. - - - -[[scheduling-task-namespace-scheduler]] -==== The 'scheduler' element -The following element will create a `ThreadPoolTaskScheduler` instance with the -specified thread pool size. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - ----- - -The value provided for the 'id' attribute will be used as the prefix for thread names -within the pool. The 'scheduler' element is relatively straightforward. If you do not -provide a 'pool-size' attribute, the default thread pool will only have a single thread. -There are no other configuration options for the scheduler. - - - -[[scheduling-task-namespace-executor]] -==== The 'executor' element -The following will create a `ThreadPoolTaskExecutor` instance: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - ----- - -As with the scheduler above, the value provided for the 'id' attribute will be used as -the prefix for thread names within the pool. As far as the pool size is concerned, the -'executor' element supports more configuration options than the 'scheduler' element. For -one thing, the thread pool for a `ThreadPoolTaskExecutor` is itself more configurable. -Rather than just a single size, an executor's thread pool may have different values for -the __core__ and the __max__ size. If a single value is provided then the executor will -have a fixed-size thread pool (the core and max sizes are the same). However, the -'executor' element's 'pool-size' attribute also accepts a range in the form of "min-max". - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - ----- - -As you can see from that configuration, a 'queue-capacity' value has also been provided. -The configuration of the thread pool should also be considered in light of the -executor's queue capacity. For the full description of the relationship between pool -size and queue capacity, consult the documentation for -http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/ThreadPoolExecutor.html[ThreadPoolExecutor]. -The main idea is that when a task is submitted, the executor will first try to use a -free thread if the number of active threads is currently less than the core size. If the -core size has been reached, then the task will be added to the queue as long as its -capacity has not yet been reached. Only then, if the queue's capacity __has__ been -reached, will the executor create a new thread beyond the core size. If the max size has -also been reached, then the executor will reject the task. - -By default, the queue is __unbounded__, but this is rarely the desired configuration, -because it can lead to `OutOfMemoryErrors` if enough tasks are added to that queue while -all pool threads are busy. Furthermore, if the queue is unbounded, then the max size has -no effect at all. Since the executor will always try the queue before creating a new -thread beyond the core size, a queue must have a finite capacity for the thread pool to -grow beyond the core size (this is why a __fixed size__ pool is the only sensible case -when using an unbounded queue). - -In a moment, we will review the effects of the keep-alive setting which adds yet another -factor to consider when providing a pool size configuration. First, let's consider the -case, as mentioned above, when a task is rejected. By default, when a task is rejected, -a thread pool executor will throw a `TaskRejectedException`. However, the rejection -policy is actually configurable. The exception is thrown when using the default -rejection policy which is the `AbortPolicy` implementation. For applications where some -tasks can be skipped under heavy load, either the `DiscardPolicy` or -`DiscardOldestPolicy` may be configured instead. Another option that works well for -applications that need to throttle the submitted tasks under heavy load is the -`CallerRunsPolicy`. Instead of throwing an exception or discarding tasks, that policy -will simply force the thread that is calling the submit method to run the task itself. -The idea is that such a caller will be busy while running that task and not able to -submit other tasks immediately. Therefore it provides a simple way to throttle the -incoming load while maintaining the limits of the thread pool and queue. Typically this -allows the executor to "catch up" on the tasks it is handling and thereby frees up some -capacity on the queue, in the pool, or both. Any of these options can be chosen from an -enumeration of values available for the 'rejection-policy' attribute on the 'executor' -element. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - ----- - - - -[[scheduling-task-namespace-scheduled-tasks]] -==== The 'scheduled-tasks' element -The most powerful feature of Spring's task namespace is the support for configuring -tasks to be scheduled within a Spring Application Context. This follows an approach -similar to other "method-invokers" in Spring, such as that provided by the JMS namespace -for configuring Message-driven POJOs. Basically a "ref" attribute can point to any -Spring-managed object, and the "method" attribute provides the name of a method to be -invoked on that object. Here is a simple example. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - ----- - -As you can see, the scheduler is referenced by the outer element, and each individual -task includes the configuration of its trigger metadata. In the preceding example, that -metadata defines a periodic trigger with a fixed delay indicating the number of -milliseconds to wait after each task execution has completed. Another option is -'fixed-rate', indicating how often the method should be executed regardless of how long -any previous execution takes. Additionally, for both fixed-delay and fixed-rate tasks an -'initial-delay' parameter may be specified indicating the number of milliseconds to wait -before the first execution of the method. For more control, a "cron" attribute may be -provided instead. Here is an example demonstrating these other options. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - ----- - - - - -[[scheduling-quartz]] -=== Using the Quartz Scheduler -Quartz uses `Trigger`, `Job` and `JobDetail` objects to realize scheduling of all kinds -of jobs. For the basic concepts behind Quartz, have a look at -http://quartz-scheduler.org[]. For convenience purposes, Spring offers a couple of -classes that simplify the usage of Quartz within Spring-based applications. - - - -[[scheduling-quartz-jobdetail]] -==== Using the JobDetailBean -`JobDetail` objects contain all information needed to run a job. The Spring Framework -provides a `JobDetailBean` that makes the `JobDetail` more of an actual JavaBean with -sensible defaults. Let's have a look at an example: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - ----- - -The job detail bean has all information it needs to run the job ( `ExampleJob`). The -timeout is specified in the job data map. The job data map is available through the -`JobExecutionContext` (passed to you at execution time), but the `JobDetailBean` also -maps the properties from the job data map to properties of the actual job. So in this -case, if the `ExampleJob` contains a property named `timeout`, the `JobDetailBean` will -automatically apply it: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - package example; - - public class ExampleJob extends QuartzJobBean { - - private int timeout; - - /** - * Setter called after the ExampleJob is instantiated - * with the value from the JobDetailBean (5) - */ - public void setTimeout(int timeout) { - this.timeout = timeout; - } - - protected void executeInternal(JobExecutionContext ctx) throws JobExecutionException { - // do the actual work - } - - } ----- - -All additional settings from the job detail bean are of course available to you as well. - -[NOTE] -==== -Using the `name` and `group` properties, you can modify the name and the group -of the job, respectively. By default, the name of the job matches the bean name of the -job detail bean (in the example above, this is `exampleJob`). -==== - - - -[[scheduling-quartz-method-invoking-job]] -==== Using the MethodInvokingJobDetailFactoryBean - -Often you just need to invoke a method on a specific object. Using the -`MethodInvokingJobDetailFactoryBean` you can do exactly this: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - ----- - -The above example will result in the `doIt` method being called on the -`exampleBusinessObject` method (see below): - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class ExampleBusinessObject { - - // properties and collaborators - - public void doIt() { - // do the actual work - } - } ----- - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - ----- - -Using the `MethodInvokingJobDetailFactoryBean`, you don't need to create one-line jobs -that just invoke a method, and you only need to create the actual business object and -wire up the detail object. - -By default, Quartz Jobs are stateless, resulting in the possibility of jobs interfering -with each other. If you specify two triggers for the same `JobDetail`, it might be -possible that before the first job has finished, the second one will start. If -`JobDetail` classes implement the `Stateful` interface, this won't happen. The second -job will not start before the first one has finished. To make jobs resulting from the -`MethodInvokingJobDetailFactoryBean` non-concurrent, set the `concurrent` flag to -`false`. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - ----- - -[NOTE] -==== -By default, jobs will run in a concurrent fashion. -==== - - - -[[scheduling-quartz-cron]] -==== Wiring up jobs using triggers and the SchedulerFactoryBean - -We've created job details and jobs. We've also reviewed the convenience bean that allows -you to invoke a method on a specific object. Of course, we still need to schedule the -jobs themselves. This is done using triggers and a `SchedulerFactoryBean`. Several -triggers are available within Quartz and Spring offers two Quartz `FactoryBean` -implementations with convenient defaults: `CronTriggerFactoryBean` and -`SimpleTriggerFactoryBean`. - -Triggers need to be scheduled. Spring offers a `SchedulerFactoryBean` that exposes -triggers to be set as properties. `SchedulerFactoryBean` schedules the actual jobs with -those triggers. - -Find below a couple of examples: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - - - - - - - ----- - -Now we've set up two triggers, one running every 50 seconds with a starting delay of 10 -seconds and one every morning at 6 AM. To finalize everything, we need to set up the -`SchedulerFactoryBean`: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - ----- - -More properties are available for the `SchedulerFactoryBean` for you to set, such as the -calendars used by the job details, properties to customize Quartz with, etc. Have a look -at the -{javadoc-baseurl}/org/springframework/scheduling/quartz/SchedulerFactoryBean.html[`SchedulerFactoryBean` -javadocs] for more information. - - - - - -[[dynamic-language]] -== Dynamic language support - - - - -[[dynamic-language-introduction]] -=== Introduction -Spring 2.0 introduces comprehensive support for using classes and objects that have been -defined using a dynamic language (such as JRuby) with Spring. This support allows you to -write any number of classes in a supported dynamic language, and have the Spring -container transparently instantiate, configure and dependency inject the resulting -objects. - -The dynamic languages currently supported are: - -* JRuby 1.5+ -* Groovy 1.8+ -* BeanShell 2.0 - -.Why only these languages? -**** -The supported languages were chosen because __a)__ the languages have a lot of traction in -the Java enterprise community, __b)__ no requests were made for other languages at the time -that this support was added, and __c)__ the Spring developers were most familiar with -them. -**** - -Fully working examples of where this dynamic language support can be immediately useful -are described in <>. - - - - -[[dynamic-language-a-first-example]] -=== A first example -This bulk of this chapter is concerned with describing the dynamic language support in -detail. Before diving into all of the ins and outs of the dynamic language support, -let's look at a quick example of a bean defined in a dynamic language. The dynamic -language for this first bean is Groovy (the basis of this example was taken from the -Spring test suite, so if you want to see equivalent examples in any of the other -supported languages, take a look at the source code). - -Find below the `Messenger` interface that the Groovy bean is going to be implementing, -and note that this interface is defined in plain Java. Dependent objects that are -injected with a reference to the `Messenger` won't know that the underlying -implementation is a Groovy script. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - package org.springframework.scripting; - - public interface Messenger { - - String getMessage(); - - } ----- - -Here is the definition of a class that has a dependency on the `Messenger` interface. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - package org.springframework.scripting; - - public class DefaultBookingService implements BookingService { - - private Messenger messenger; - - public void setMessenger(Messenger messenger) { - this.messenger = messenger; - } - - public void processBooking() { - // use the injected Messenger object... - } - - } ----- - -Here is an implementation of the `Messenger` interface in Groovy. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - // from the file 'Messenger.groovy' - package org.springframework.scripting.groovy; - - // import the Messenger interface (written in Java) that is to be implemented - import org.springframework.scripting.Messenger - - // define the implementation in Groovy - class GroovyMessenger implements Messenger { - - String message - - } ----- - -Finally, here are the bean definitions that will effect the injection of the -Groovy-defined `Messenger` implementation into an instance of the -`DefaultBookingService` class. - -[NOTE] -==== -To use the custom dynamic language tags to define dynamic-language-backed beans, you -need to have the XML Schema preamble at the top of your Spring XML configuration file. -You also need to be using a Spring `ApplicationContext` implementation as your IoC -container. Using the dynamic-language-backed beans with a plain `BeanFactory` -implementation is supported, but you have to manage the plumbing of the Spring internals -to do so. - -For more information on schema-based configuration, see <>. -==== - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - - - - - - - ----- - -The `bookingService` bean (a `DefaultBookingService`) can now use its private -`messenger` member variable as normal because the `Messenger` instance that was injected -into it __is__ a `Messenger` instance. There is nothing special going on here, just -plain Java and plain Groovy. - -Hopefully the above XML snippet is self-explanatory, but don't worry unduly if it isn't. -Keep reading for the in-depth detail on the whys and wherefores of the above -configuration. - - - - -[[dynamic-language-beans]] -=== Defining beans that are backed by dynamic languages -This section describes exactly how you define Spring managed beans in any of the -supported dynamic languages. - -Please note that this chapter does not attempt to explain the syntax and idioms of the -supported dynamic languages. For example, if you want to use Groovy to write certain of -the classes in your application, then the assumption is that you already know Groovy. If -you need further details about the dynamic languages themselves, please -consult <> at the end of this chapter. - - - -[[dynamic-language-beans-concepts]] -==== Common concepts -The steps involved in using dynamic-language-backed beans are as follows: - -* Write the test for the dynamic language source code (naturally) -* __Then__ write the dynamic language source code itself :) -* Define your dynamic-language-backed beans using the appropriate `` - element in the XML configuration (you can of course define such beans programmatically - using the Spring API - although you will have to consult the source code for - directions on how to do this as this type of advanced configuration is not covered in - this chapter). Note this is an iterative step. You will need at least one bean - definition per dynamic language source file (although the same dynamic language source - file can of course be referenced by multiple bean definitions). - -The first two steps (testing and writing your dynamic language source files) are beyond -the scope of this chapter. Refer to the language specification and / or reference manual -for your chosen dynamic language and crack on with developing your dynamic language -source files. You __will__ first want to read the rest of this chapter though, as -Spring's dynamic language support does make some (small) assumptions about the contents -of your dynamic language source files. - - -[[dynamic-language-beans-concepts-xml-language-element]] -===== The element -The final step involves defining dynamic-language-backed bean definitions, one for each -bean that you want to configure (this is no different from normal JavaBean -configuration). However, instead of specifying the fully qualified classname of the -class that is to be instantiated and configured by the container, you use the -`` element to define the dynamic language-backed bean. - -Each of the supported languages has a corresponding `` element: - -* `` (JRuby) -* `` (Groovy) -* `` (BeanShell) - -The exact attributes and child elements that are available for configuration depends on -exactly which language the bean has been defined in (the language-specific sections -below provide the full lowdown on this). - - -[[dynamic-language-refreshable-beans]] -===== Refreshable beans -One of the (if not __the__) most compelling value adds of the dynamic language support -in Spring is the__'refreshable bean'__ feature. - -A refreshable bean is a dynamic-language-backed bean that with a small amount of -configuration, a dynamic-language-backed bean can monitor changes in its underlying -source file resource, and then reload itself when the dynamic language source file is -changed (for example when a developer edits and saves changes to the file on the -filesystem). - -This allows a developer to deploy any number of dynamic language source files as part of -an application, configure the Spring container to create beans backed by dynamic -language source files (using the mechanisms described in this chapter), and then later, -as requirements change or some other external factor comes into play, simply edit a -dynamic language source file and have any change they make reflected in the bean that is -backed by the changed dynamic language source file. There is no need to shut down a -running application (or redeploy in the case of a web application). The -dynamic-language-backed bean so amended will pick up the new state and logic from the -changed dynamic language source file. - -[NOTE] -==== -Please note that this feature is __off__ by default. -==== - -Let's take a look at an example to see just how easy it is to start using refreshable -beans. To __turn on__ the refreshable beans feature, you simply have to specify exactly -__one__ additional attribute on the `` element of your bean definition. -So if we stick with <> from earlier in this -chapter, here's what we would change in the Spring XML configuration to effect -refreshable beans: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - script-source="classpath:Messenger.groovy"> - - - - - - - - ----- - -That really is all you have to do. The `'refresh-check-delay'` attribute defined on the -`'messenger'` bean definition is the number of milliseconds after which the bean will be -refreshed with any changes made to the underlying dynamic language source file. You can -turn off the refresh behavior by assigning a negative value to the -`'refresh-check-delay'` attribute. Remember that, by default, the refresh behavior is -disabled. If you don't want the refresh behavior, then simply don't define the attribute. - -If we then run the following application we can exercise the refreshable feature; please -do excuse the __'jumping-through-hoops-to-pause-the-execution'__ shenanigans in this -next slice of code. The `System.in.read()` call is only there so that the execution of -the program pauses while I (the author) go off and edit the underlying dynamic language -source file so that the refresh will trigger on the dynamic-language-backed bean when -the program resumes execution. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - import org.springframework.context.ApplicationContext; - import org.springframework.context.support.ClassPathXmlApplicationContext; - import org.springframework.scripting.Messenger; - - public final class Boot { - - public static void main(final String[] args) throws Exception { - ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml"); - Messenger messenger = (Messenger) ctx.getBean("messenger"); - System.out.println(messenger.getMessage()); - // pause execution while I go off and make changes to the source file... - System.in.read(); - System.out.println(messenger.getMessage()); - } - } ----- - -Let's assume then, for the purposes of this example, that all calls to the -`getMessage()` method of `Messenger` implementations have to be changed such that the -message is surrounded by quotes. Below are the changes that I (the author) make to the -`Messenger.groovy` source file when the execution of the program is paused. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - package org.springframework.scripting - - class GroovyMessenger implements Messenger { - - private String message = "Bingo" - - public String getMessage() { - // change the implementation to surround the message in quotes - return "'" + this.message + "'" - } - - public void setMessage(String message) { - this.message = message - } - } ----- - -When the program executes, the output before the input pause will be __I Can Do The -Frug__. After the change to the source file is made and saved, and the program resumes -execution, the result of calling the `getMessage()` method on the -dynamic-language-backed `Messenger` implementation will be __'I Can Do The Frug'__ -(notice the inclusion of the additional quotes). - -It is important to understand that changes to a script will __not__ trigger a refresh if -the changes occur within the window of the `'refresh-check-delay'` value. It is equally -important to understand that changes to the script are __not__ actually 'picked up' until -a method is called on the dynamic-language-backed bean. It is only when a method is -called on a dynamic-language-backed bean that it checks to see if its underlying script -source has changed. Any exceptions relating to refreshing the script (such as -encountering a compilation error, or finding that the script file has been deleted) will -result in a __fatal__ exception being propagated to the calling code. - -The refreshable bean behavior described above does __not__ apply to dynamic language -source files defined using the `` element notation (see -<>). Additionally, it __only__ applies to beans where -changes to the underlying source file can actually be detected; for example, by code -that checks the last modified date of a dynamic language source file that exists on the -filesystem. - - -[[dynamic-language-beans-inline]] -===== Inline dynamic language source files -The dynamic language support can also cater for dynamic language source files that are -embedded directly in Spring bean definitions. More specifically, the -`` element allows you to define dynamic language source immediately -inside a Spring configuration file. An example will perhaps make the inline script -feature crystal clear: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - package org.springframework.scripting.groovy; - - import org.springframework.scripting.Messenger - - class GroovyMessenger implements Messenger { - String message - } - - - - ----- - -If we put to one side the issues surrounding whether it is good practice to define -dynamic language source inside a Spring configuration file, the `` -element can be useful in some scenarios. For instance, we might want to quickly add a -Spring `Validator` implementation to a Spring MVC `Controller`. This is but a moment's -work using inline source. (See <> for such an -example.) - -Find below an example of defining the source for a JRuby-based bean directly in a Spring -XML configuration file using the `inline:` notation. (Notice the use of the < -characters to denote a `'<'` character. In such a case surrounding the inline source in -a `` region might be better.) - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - require 'java' - - include_class 'org.springframework.scripting.Messenger' - - class RubyMessenger < Messenger - - def setMessage(message) - @@message = message - end - - def getMessage - @@message - end - - end - - - - ----- - - -[[dynamic-language-beans-ctor-injection]] -===== Understanding Constructor Injection in the context of dynamic-language-backed beans -There is one __very__ important thing to be aware of with regard to Spring's dynamic -language support. Namely, it is not (currently) possible to supply constructor arguments -to dynamic-language-backed beans (and hence constructor-injection is not available for -dynamic-language-backed beans). In the interests of making this special handling of -constructors and properties 100% clear, the following mixture of code and configuration -will __not__ work. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - // from the file 'Messenger.groovy' - package org.springframework.scripting.groovy; - - import org.springframework.scripting.Messenger - - class GroovyMessenger implements Messenger { - - GroovyMessenger() {} - - // this constructor is not available for Constructor Injection - GroovyMessenger(String message) { - this.message = message; - } - - String message - - String anotherMessage - - } ----- - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - - ----- - -In practice this limitation is not as significant as it first appears since setter -injection is the injection style favored by the overwhelming majority of developers -anyway (let's leave the discussion as to whether that is a good thing to another day). - - - -[[dynamic-language-beans-jruby]] -==== JRuby beans - -.The JRuby library dependencies -**** -The JRuby scripting support in Spring requires the following libraries to be on the -classpath of your application. - -* `jruby.jar` -**** - -From the JRuby homepage... - -"__JRuby is an 100% pure-Java implementation of the Ruby programming language.__" - -In keeping with the Spring philosophy of offering choice, Spring's dynamic language -support also supports beans defined in the JRuby language. The JRuby language is based -on the quite intuitive Ruby language, and has support for inline regular expressions, -blocks (closures), and a whole host of other features that do make solutions for some -domain problems a whole lot easier to develop. - -The implementation of the JRuby dynamic language support in Spring is interesting in -that what happens is this: Spring creates a JDK dynamic proxy implementing all of the -interfaces that are specified in the `'script-interfaces'` attribute value of the -`` element (this is why you __must__ supply at least one interface in the -value of the attribute, and (accordingly) program to interfaces when using JRuby-backed -beans). - -Let us look at a fully working example of using a JRuby-based bean. Here is the JRuby -implementation of the `Messenger` interface that was defined earlier in this chapter -(for your convenience it is repeated below). - -[source,ruby,indent=0] -[subs="verbatim,quotes"] ----- - package org.springframework.scripting; - - public interface Messenger { - - String getMessage(); - - } ----- - -[source,ruby,indent=0] -[subs="verbatim,quotes"] ----- - require 'java' - - class RubyMessenger - include org.springframework.scripting.Messenger - - def setMessage(message) - @@message = message - end - - def getMessage - @@message - end - end - - # this last line is not essential (but see below) - RubyMessenger.new ----- - -And here is the Spring XML that defines an instance of the `RubyMessenger` JRuby bean. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - ----- - -Take note of the last line of that JRuby source ( `'RubyMessenger.new'`). When using -JRuby in the context of Spring's dynamic language support, you are encouraged to -instantiate and return a new instance of the JRuby class that you want to use as a -dynamic-language-backed bean as the result of the execution of your JRuby source. You -can achieve this by simply instantiating a new instance of your JRuby class on the last -line of the source file like so: - -[source,ruby,indent=0] -[subs="verbatim,quotes"] ----- - require 'java' - - include_class 'org.springframework.scripting.Messenger' - - # class definition same as above... - - # instantiate and return a new instance of the RubyMessenger class - RubyMessenger.new ----- - -If you forget to do this, it is not the end of the world; this will however result in -Spring having to trawl (reflectively) through the type representation of your JRuby -class looking for a class to instantiate. In the grand scheme of things this will be so -fast that you'll never notice it, but it is something that can be avoided by simply -having a line such as the one above as the last line of your JRuby script. If you don't -supply such a line, or if Spring cannot find a JRuby class in your script to instantiate -then an opaque `ScriptCompilationException` will be thrown immediately after the source -is executed by the JRuby interpreter. The key text that identifies this as the root -cause of an exception can be found immediately below (so if your Spring container throws -the following exception when creating your dynamic-language-backed bean and the -following text is there in the corresponding stacktrace, this will hopefully allow you -to identify and then easily rectify the issue): - -[literal] -[subs="verbatim,quotes"] ----- -org.springframework.scripting.ScriptCompilationException: Compilation of JRuby script returned '' ----- - -To rectify this, simply instantiate a new instance of whichever class you want to expose -as a JRuby-dynamic-language-backed bean (as shown above). Please also note that you can -actually define as many classes and objects as you want in your JRuby script; what is -important is that the source file as a whole must return an object (for Spring to -configure). - -See <> for some scenarios where you might want to use -JRuby-based beans. - - - -[[dynamic-language-beans-groovy]] -==== Groovy beans - -.The Groovy library dependencies -**** - -The Groovy scripting support in Spring requires the following libraries to be on the -classpath of your application. - -* `groovy-1.8.jar` -* `asm-3.2.jar` -* `antlr-2.7.7.jar` -**** - -From the Groovy homepage... - -"__Groovy is an agile dynamic language for the Java 2 Platform that has many of the -features that people like so much in languages like Python, Ruby and Smalltalk, making -them available to Java developers using a Java-like syntax. __" - -If you have read this chapter straight from the top, you will already have -<> of a Groovy-dynamic-language-backed -bean. Let's look at another example (again using an example from the Spring test suite). - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - package org.springframework.scripting; - - public interface Calculator { - - int add(int x, int y); - - } ----- - -Here is an implementation of the `Calculator` interface in Groovy. - -[source,groovy,indent=0] -[subs="verbatim,quotes"] ----- - // from the file 'calculator.groovy' - package org.springframework.scripting.groovy - - class GroovyCalculator implements Calculator { - - int add(int x, int y) { - x + y - } - - } ----- - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - <-- from the file 'beans.xml' --> - - - ----- - -Lastly, here is a small application to exercise the above configuration. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - package org.springframework.scripting; - - import org.springframework.context.ApplicationContext; - import org.springframework.context.support.ClassPathXmlApplicationContext; - - public class Main { - - public static void Main(String[] args) { - ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml"); - Calculator calc = (Calculator) ctx.getBean("calculator"); - System.out.println(calc.add(2, 8)); - } - } ----- - -The resulting output from running the above program will be (unsurprisingly) __10__. -(Exciting example, huh? Remember that the intent is to illustrate the concept. Please -consult the dynamic language showcase project for a more complex example, or indeed -<> later in this chapter). - -It is important that you __do not__ define more than one class per Groovy source file. -While this is perfectly legal in Groovy, it is (arguably) a bad practice: in the -interests of a consistent approach, you should (in the opinion of this author) respect -the standard Java conventions of one (public) class per source file. - - -[[dynamic-language-beans-groovy-customizer]] -===== Customizing Groovy objects via a callback -The `GroovyObjectCustomizer` interface is a callback that allows you to hook additional -creation logic into the process of creating a Groovy-backed bean. For example, -implementations of this interface could invoke any required initialization method(s), or -set some default property values, or specify a custom `MetaClass`. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public interface GroovyObjectCustomizer { - - void customize(GroovyObject goo); - - } ----- - -The Spring Framework will instantiate an instance of your Groovy-backed bean, and will -then pass the created `GroovyObject` to the specified `GroovyObjectCustomizer` if one -has been defined. You can do whatever you like with the supplied `GroovyObject` -reference: it is expected that the setting of a custom `MetaClass` is what most folks -will want to do with this callback, and you can see an example of doing that below. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public final class SimpleMethodTracingCustomizer implements GroovyObjectCustomizer { - - public void customize(GroovyObject goo) { - DelegatingMetaClass metaClass = new DelegatingMetaClass(goo.getMetaClass()) { - - public Object invokeMethod(Object object, String methodName, Object[] arguments) { - System.out.println("Invoking '" + methodName + "'."); - return super.invokeMethod(object, methodName, arguments); - } - }; - metaClass.initialize(); - goo.setMetaClass(metaClass); - } - - } ----- - -A full discussion of meta-programming in Groovy is beyond the scope of the Spring -reference manual. Consult the relevant section of the Groovy reference manual, or do a -search online: there are plenty of articles concerning this topic. Actually making use -of a `GroovyObjectCustomizer` is easy if you are using the Spring namespace support. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - ----- - -If you are not using the Spring namespace support, you can still use the -`GroovyObjectCustomizer` functionality. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - - ----- - - - -[[dynamic-language-beans-bsh]] -==== BeanShell beans - -.The BeanShell library dependencies -**** - -The BeanShell scripting support in Spring requires the following libraries to be on the -classpath of your application. - -* `bsh-2.0b4.jar` -**** - -From the BeanShell homepage... - -"__BeanShell is a small, free, embeddable Java source interpreter with dynamic language -features, written in Java. BeanShell dynamically executes standard Java syntax and -extends it with common scripting conveniences such as loose types, commands, and method -closures like those in Perl and JavaScript.__" - -In contrast to Groovy, BeanShell-backed bean definitions require some (small) additional -configuration. The implementation of the BeanShell dynamic language support in Spring is -interesting in that what happens is this: Spring creates a JDK dynamic proxy -implementing all of the interfaces that are specified in the `'script-interfaces'` -attribute value of the `` element (this is why you __must__ supply at least -one interface in the value of the attribute, and (accordingly) program to interfaces -when using BeanShell-backed beans). This means that every method call on a -BeanShell-backed object is going through the JDK dynamic proxy invocation mechanism. - -Let's look at a fully working example of using a BeanShell-based bean that implements -the `Messenger` interface that was defined earlier in this chapter (repeated below for -your convenience). - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - package org.springframework.scripting; - - public interface Messenger { - - String getMessage(); - - } ----- - -Here is the BeanShell 'implementation' (the term is used loosely here) of the -`Messenger` interface. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - String message; - - String getMessage() { - return message; - } - - void setMessage(String aMessage) { - message = aMessage; - } ----- - -And here is the Spring XML that defines an 'instance' of the above 'class' (again, the -term is used very loosely here). - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - ----- - -See <> for some scenarios where you might want to use -BeanShell-based beans. - - - - -[[dynamic-language-scenarios]] -=== Scenarios -The possible scenarios where defining Spring managed beans in a scripting language would -be beneficial are, of course, many and varied. This section describes two possible use -cases for the dynamic language support in Spring. - - - -[[dynamic-language-scenarios-controllers]] -==== Scripted Spring MVC Controllers -One group of classes that may benefit from using dynamic-language-backed beans is that -of Spring MVC controllers. In pure Spring MVC applications, the navigational flow -through a web application is to a large extent determined by code encapsulated within -your Spring MVC controllers. As the navigational flow and other presentation layer logic -of a web application needs to be updated to respond to support issues or changing -business requirements, it may well be easier to effect any such required changes by -editing one or more dynamic language source files and seeing those changes being -immediately reflected in the state of a running application. - -Remember that in the lightweight architectural model espoused by projects such as -Spring, you are typically aiming to have a really __thin__ presentation layer, with all -the meaty business logic of an application being contained in the domain and service -layer classes. Developing Spring MVC controllers as dynamic-language-backed beans allows -you to change presentation layer logic by simply editing and saving text files; any -changes to such dynamic language source files will (depending on the configuration) -automatically be reflected in the beans that are backed by dynamic language source files. - -[NOTE] -==== -In order to effect this automatic 'pickup' of any changes to dynamic-language-backed -beans, you will have had to enable the 'refreshable beans' functionality. See -<> for a full treatment of this feature. -==== - -Find below an example of an `org.springframework.web.servlet.mvc.Controller` implemented -using the Groovy dynamic language. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - // from the file '/WEB-INF/groovy/FortuneController.groovy' - package org.springframework.showcase.fortune.web - - import org.springframework.showcase.fortune.service.FortuneService - import org.springframework.showcase.fortune.domain.Fortune - import org.springframework.web.servlet.ModelAndView - import org.springframework.web.servlet.mvc.Controller - - import javax.servlet.http.HttpServletRequest - import javax.servlet.http.HttpServletResponse - - class FortuneController implements Controller { - - @Property FortuneService fortuneService - - ModelAndView handleRequest(HttpServletRequest request, - HttpServletResponse httpServletResponse) { - return new ModelAndView("tell", "fortune", this.fortuneService.tellFortune()) - } - - } ----- - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - ----- - - - -[[dynamic-language-scenarios-validators]] -==== Scripted Validators -Another area of application development with Spring that may benefit from the -flexibility afforded by dynamic-language-backed beans is that of validation. It __may__ -be easier to express complex validation logic using a loosely typed dynamic language -(that may also have support for inline regular expressions) as opposed to regular Java. - -Again, developing validators as dynamic-language-backed beans allows you to change -validation logic by simply editing and saving a simple text file; any such changes will -(depending on the configuration) automatically be reflected in the execution of a -running application and would not require the restart of an application. - -[NOTE] -==== -Please note that in order to effect the automatic 'pickup' of any changes to -dynamic-language-backed beans, you will have had to enable the 'refreshable beans' -feature. See <> for a full and detailed treatment of -this feature. -==== - -Find below an example of a Spring `org.springframework.validation.Validator` implemented -using the Groovy dynamic language. (See <> for a discussion of the -`Validator` interface.) - -[source,groovy,indent=0] -[subs="verbatim,quotes"] ----- - import org.springframework.validation.Validator - import org.springframework.validation.Errors - import org.springframework.beans.TestBean - - class TestBeanValidator implements Validator { - - boolean supports(Class clazz) { - return TestBean.class.isAssignableFrom(clazz) - } - - void validate(Object bean, Errors errors) { - if(bean.name?.trim()?.size() > 0) { - return - } - errors.reject("whitespace", "Cannot be composed wholly of whitespace.") - } - - } ----- - - - - -[[dynamic-language-final-notes]] -=== Bits and bobs -This last section contains some bits and bobs related to the dynamic language support. - - - -[[dynamic-language-final-notes-aop]] -==== AOP - advising scripted beans -It is possible to use the Spring AOP framework to advise scripted beans. The Spring AOP -framework actually is unaware that a bean that is being advised might be a scripted -bean, so all of the AOP use cases and functionality that you may be using or aim to use -will work with scripted beans. There is just one (small) thing that you need to be aware -of when advising scripted beans... you cannot use class-based proxies, you must -use <>. - -You are of course not just limited to advising scripted beans... you can also write -aspects themselves in a supported dynamic language and use such beans to advise other -Spring beans. This really would be an advanced use of the dynamic language support -though. - - - -[[dynamic-language-final-notes-scopes]] -==== Scoping -In case it is not immediately obvious, scripted beans can of course be scoped just like -any other bean. The `scope` attribute on the various `` elements allows -you to control the scope of the underlying scripted bean, just as it does with a regular -bean. (The default scope is <>, just as it is -with 'regular' beans.) - -Find below an example of using the `scope` attribute to define a Groovy bean scoped as -a <>. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - - - - - ----- - -See <> in <> for a fuller discussion of the scoping support -in the Spring Framework. - - - - -[[dynamic-language-resources]] -=== Further Resources -Find below links to further resources about the various dynamic languages described in -this chapter. - -* The http://jruby.codehaus.org/[JRuby] homepage -* The http://groovy.codehaus.org/[Groovy] homepage -* The http://www.beanshell.org/[BeanShell] homepage - -Some of the more active members of the Spring community have also added support for a -number of additional dynamic languages above and beyond the ones covered in this -chapter. While it is possible that such third party contributions may be added to the -list of languages supported by the main Spring distribution, your best bet for seeing if -your favorite scripting language is supported is the -https://springmodules.dev.java.net/[Spring Modules project]. - - - - - -[[cache]] -== Cache Abstraction - - - - -[[cache-introduction]] -=== Introduction -Since version 3.1, Spring Framework provides support for transparently adding caching -into an existing Spring application. Similar to the <> support, -the caching abstraction allows consistent use of various caching solutions with minimal -impact on the code. - -As from Spring 4.1, the cache abstraction has been significantly improved with the -support of <> and more customization options. - - - -[[cache-strategies]] -=== Understanding the cache abstraction -.Cache vs Buffer -**** - -The terms "buffer" and "cache" tend to be used interchangeably; note however they -represent different things. A buffer is used traditionally as an intermediate temporary -store for data between a fast and a slow entity. As one party would have to __wait__ for -the other affecting performance, the buffer alleviates this by allowing entire blocks of -data to move at once rather then in small chunks. The data is written and read only once -from the buffer. Furthermore, the buffers are __visible__ to at least one party which is -aware of it. - -A cache on the other hand by definition is hidden and neither party is aware that -caching occurs.It as well improves performance but does that by allowing the same data -to be read multiple times in a fast fashion. - -A further explanation of the differences between two can be found -http://en.wikipedia.org/wiki/Cache_(computing)#The_difference_between_buffer_and_cache[here]. -**** - -At its core, the abstraction applies caching to Java methods, reducing thus the number -of executions based on the information available in the cache. That is, each time a -__targeted__ method is invoked, the abstraction will apply a caching behavior checking -whether the method has been already executed for the given arguments. If it has, then -the cached result is returned without having to execute the actual method; if it has -not, then method is executed, the result cached and returned to the user so that, the -next time the method is invoked, the cached result is returned. This way, expensive -methods (whether CPU or IO bound) can be executed only once for a given set of -parameters and the result reused without having to actually execute the method again. -The caching logic is applied transparently without any interference to the invoker. - -[IMPORTANT] -==== - -Obviously this approach works only for methods that are guaranteed to return the same -output (result) for a given input (or arguments) no matter how many times it is being -executed. -==== - -Other cache-related operations are provided by the abstraction such as the ability -to update the content of the cache or remove one of all entries. These are useful if -the cache deals with data that can change during the course of the application. - -Just like other services in the Spring Framework, the caching service is an -abstraction (not a cache implementation) and requires the use of an actual storage to -store the cache data - that is, the abstraction frees the developer from having to write -the caching logic but does not provide the actual stores. This abstraction is -materialized by the `org.springframework.cache.Cache` and -`org.springframework.cache.CacheManager` interfaces. - -There are <> of that abstraction -available out of the box: JDK `java.util.concurrent.ConcurrentMap` based caches, -http://ehcache.org/[EhCache], Gemfire cache, -https://code.google.com/p/guava-libraries/wiki/CachesExplained[Guava caches] and -JSR-107 compliant caches. See <> for more information on plugging in -other cache stores/providers. - -[IMPORTANT] -==== -The caching abstraction has no special handling of multi-threaded and multi-process -environments as such features are handled by the cache implementation. . -==== - -If you have a multi-process environment (i.e. an application deployed on several nodes), -you will need to configure your cache provider accordingly. Depending on your use cases, -a copy of the same data on several nodes may be enough but if you change the data during -the course of the application, you may need to enable other propagation mechanisms. - -Caching a particular item is a direct equivalent of the typical get-if-not-found-then- -proceed-and-put-eventually code blocks found with programmatic cache interaction: no locks -are applied and several threads may try to load the same item concurrently. The same applies -to eviction: if several threads are trying to update or evict data concurrently, you may -use stale data. Certain cache providers offer advanced features in that area, refer to -the documentation of the cache provider that you are using for more details. - -To use the cache abstraction, the developer needs to take care of two aspects: - -* caching declaration - identify the methods that need to be cached and their policy -* cache configuration - the backing cache where the data is stored and read from - - -[[cache-annotations]] -=== Declarative annotation-based caching -For caching declaration, the abstraction provides a set of Java annotations: - -* `@Cacheable` triggers cache population -* `@CacheEvict` triggers cache eviction -* `@CachePut` updates the cache without interfering with the method execution -* `@Caching` regroups multiple cache operations to be applied on a method -* `@CacheConfig` shares some common cache-related settings at class-level - -Let us take a closer look at each annotation: - -[[cache-annotations-cacheable]] -==== @Cacheable annotation - -As the name implies, `@Cacheable` is used to demarcate methods that are cacheable - that -is, methods for whom the result is stored into the cache so on subsequent invocations -(with the same arguments), the value in the cache is returned without having to actually -execute the method. In its simplest form, the annotation declaration requires the name -of the cache associated with the annotated method: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Cacheable("books") - public Book findBook(ISBN isbn) {...} ----- - -In the snippet above, the method `findBook` is associated with the cache named `books`. -Each time the method is called, the cache is checked to see whether the invocation has -been already executed and does not have to be repeated. While in most cases, only one -cache is declared, the annotation allows multiple names to be specified so that more -than one cache are being used. In this case, each of the caches will be checked before -executing the method - if at least one cache is hit, then the associated value will be -returned: - -[NOTE] -==== -All the other caches that do not contain the value will be updated as well even though -the cached method was not actually executed. -==== - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Cacheable({"books", "isbns"}) - public Book findBook(ISBN isbn) {...} ----- - - -[[cache-annotations-cacheable-default-key]] -===== Default Key Generation -Since caches are essentially key-value stores, each invocation of a cached method needs -to be translated into a suitable key for cache access. Out of the box, the caching -abstraction uses a simple `KeyGenerator` based on the following algorithm: - -* If no params are given, return `SimpleKey.EMPTY`. -* If only one param is given, return that instance. -* If more the one param is given, return a `SimpleKey` containing all parameters. - -This approach works well for most use-cases; As long as parameters have __natural keys__ -and implement valid `hashCode()` and `equals()` methods. If that is not the case then the -strategy needs to be changed. - -To provide a different __default__ key generator, one needs to implement the -`org.springframework.cache.interceptor.KeyGenerator` interface. - - -[NOTE] -==== -The default key generation strategy changed with the release of Spring 4.0. Earlier -versions of Spring used a key generation strategy that, for multiple key parameters, -only considered the `hashCode()` of parameters and not `equals()`; this could cause -unexpected key collisions (see https://jira.spring.io/browse/SPR-10237[SPR-10237] -for background). The new 'SimpleKeyGenerator' uses a compound key for such scenarios. - -If you want to keep using the previous key strategy, you can configure the deprecated -`org.springframework.cache.interceptor.DefaultKeyGenerator` class or create a custom -hash-based 'KeyGenerator' implementation. -==== - - -[[cache-annotations-cacheable-key]] -===== Custom Key Generation Declaration -Since caching is generic, it is quite likely the target methods have various signatures -that cannot be simply mapped on top of the cache structure. This tends to become obvious -when the target method has multiple arguments out of which only some are suitable for -caching (while the rest are used only by the method logic). For example: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Cacheable("books") - public Book findBook(ISBN isbn, boolean checkWarehouse, boolean includeUsed) ----- - -At first glance, while the two `boolean` arguments influence the way the book is found, -they are no use for the cache. Further more what if only one of the two is important -while the other is not? - -For such cases, the `@Cacheable` annotation allows the user to specify how the key is -generated through its `key` attribute. The developer can use <> to -pick the arguments of interest (or their nested properties), perform operations or even -invoke arbitrary methods without having to write any code or implement any interface. -This is the recommended approach over the -<> since methods tend to be -quite different in signatures as the code base grows; while the default strategy might -work for some methods, it rarely does for all methods. - -Below are some examples of various SpEL declarations - if you are not familiar with it, -do yourself a favor and read <>: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Cacheable(value="books", **key="#isbn"**) - public Book findBook(ISBN isbn, boolean checkWarehouse, boolean includeUsed) - - @Cacheable(value="books", **key="#isbn.rawNumber"**) - public Book findBook(ISBN isbn, boolean checkWarehouse, boolean includeUsed) - - @Cacheable(value="books", **key="T(someType).hash(#isbn)"**) - public Book findBook(ISBN isbn, boolean checkWarehouse, boolean includeUsed) ----- - -The snippets above show how easy it is to select a certain argument, one of its -properties or even an arbitrary (static) method. - -If the algorithm responsible to generate the key is too specific or if it needs -to be shared, you may define a custom `keyGenerator` on the operation. To do -this, specify the name of the `KeyGenerator` bean implementation to use: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Cacheable(value="books", **keyGenerator="myKeyGenerator"**) - public Book findBook(ISBN isbn, boolean checkWarehouse, boolean includeUsed) ----- - - -[NOTE] -==== -The `key` and `keyGenerator` parameters are mutually exclusive and an operation -specifying both will result in an exception. -==== - -[[cache-annotations-cacheable-default-cache-resolver]] -===== Default Cache Resolution - -Out of the box, the caching abstraction uses a simple `CacheResolver` that -retrieves the cache(s) defined at the operation level using the configured -`CacheManager`. - -To provide a different __default__ cache resolver, one needs to implement the -`org.springframework.cache.interceptor.CacheResolver` interface. - - -[[cache-annotations-cacheable-cache-resolver]] -===== Custom cache resolution - -The default cache resolution fits well for applications working with a -single `CacheManager` and with no complex cache resolution requirements. - -For applications working with several cache managers, it is possible -to set the `cacheManager` to use per operation: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Cacheable(value="books", **cacheManager="anotherCacheManager"**) - public Book findBook(ISBN isbn) {...} ----- - -It is also possible to replace the `CacheResolver` entirely in a similar -fashion as for <>. The -resolution is requested for every cache operation, giving a chance to -the implementation to actually resolve the cache(s) to use based on -runtime arguments: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Cacheable(**cacheResolver="runtimeCacheResolver"**) - public Book findBook(ISBN isbn) {...} ----- - -[NOTE] -==== -Since Spring 4.1, the `value` attribute of the cache annotations are no longer -mandatory since this particular information can be provided by the `CacheResolver` -regardless of the content of the annotation. - -Similarly to `key` and `keyGenerator`, the `cacheManager` and `cacheResolver` -parameters are mutually exclusive and an operation specifying both will -result in an exception as a custom `CacheManager` will be ignored by the -`CacheResolver` implementation. This is probably not what you expect. -==== - -[[cache-annotations-cacheable-condition]] -===== Conditional caching -Sometimes, a method might not be suitable for caching all the time (for example, it -might depend on the given arguments). The cache annotations support such functionality -through the `conditional` parameter which takes a `SpEL` expression that is evaluated to -either `true` or `false`. If `true`, the method is cached - if not, it behaves as if the -method is not cached, that is executed every since time no matter what values are in the -cache or what arguments are used. A quick example - the following method will be cached -only if the argument `name` has a length shorter than 32: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Cacheable(value="book", **condition="#name.length < 32"**) - public Book findBook(String name) ----- - -In addition the `conditional` parameter, the `unless` parameter can be used to veto the -adding of a value to the cache. Unlike `conditional`, `unless` expressions are evaluated -__after__ the method has been called. Expanding on the previous example - perhaps we -only want to cache paperback books: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Cacheable(value="book", condition="#name.length < 32", **unless="#result.hardback"**) - public Book findBook(String name) ----- - - -[[cache-spel-context]] -===== Available caching SpEL evaluation context - -Each `SpEL` expression evaluates again a dedicated -<>. In addition to the build in parameters, the -framework provides dedicated caching related metadata such as the argument names. The -next table lists the items made available to the context so one can use them for key and -conditional computations: - -[[cache-spel-context-tbl]] -.Cache SpEL available metadata -|=== -| Name| Location| Description| Example - -| methodName -| root object -| The name of the method being invoked -| `#root.methodName` - -| method -| root object -| The method being invoked -| `#root.method.name` - -| target -| root object -| The target object being invoked -| `#root.target` - -| targetClass -| root object -| The class of the target being invoked -| `#root.targetClass` - -| args -| root object -| The arguments (as array) used for invoking the target -| `#root.args[0]` - -| caches -| root object -| Collection of caches against which the current method is executed -| `#root.caches[0].name` - -| __argument name__ -| evaluation context -| Name of any of the method argument. If for some reason the names are not available - (ex: no debug information), the argument names are also available under the `a<#arg>` - where __#arg__ stands for the argument index (starting from 0). -| `iban` or `a0` (one can also use `p0` or `p<#arg>` notation as an alias). - -| result -| evaluation context -| The result of the method call (the value to be cached). Only available in `unless`' - expressions, `cache put` expression (to compute the `key`) or `cache evict` - expression (when `beforeInvocation` is `false`). -| `#result` -|=== - - -[[cache-annotations-put]] -==== @CachePut annotation - -For cases where the cache needs to be updated without interfering with the method -execution, one can use the `@CachePut` annotation. That is, the method will always be -executed and its result placed into the cache (according to the `@CachePut` options). It -supports the same options as `@Cacheable` and should be used for cache population rather -than method flow optimization: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @CachePut(value="book", key="#isbn") - public Book updateBook(ISBN isbn, BookDescriptor descriptor) ----- - - -[IMPORTANT] -==== -Note that using `@CachePut` and `@Cacheable` annotations on the same method is generally -strongly discouraged because they have different behaviors. While the latter causes the -method execution to be skipped by using the cache, the former forces the execution in -order to execute a cache update. This leads to unexpected behavior and with the exception of -specific corner-cases (such as annotations having conditions that exclude them from each -other), such declaration should be avoided. Note also that such condition should not rely -on the result object (i.e. the `#result` variable) as these are validated upfront to confirm -the exclusion. -==== - - -[[cache-annotations-evict]] -==== @CacheEvict annotation - -The cache abstraction allows not just population of a cache store but also eviction. -This process is useful for removing stale or unused data from the cache. Opposed to -`@Cacheable`, annotation `@CacheEvict` demarcates methods that perform cache -__eviction__, that is methods that act as triggers for removing data from the cache. -Just like its sibling, `@CacheEvict` requires specifying one (or multiple) caches -that are affected by the action, allows a custom cache and key resolution or a -condition to be specified but in addition, features an extra parameter -`allEntries` which indicates whether a cache-wide eviction needs to be performed -rather then just an entry one (based on the key): - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @CacheEvict(value="books", **allEntries=true**) - public void loadBooks(InputStream batch) ----- - -This option comes in handy when an entire cache region needs to be cleared out - rather -then evicting each entry (which would take a long time since it is inefficient), all the -entries are removed in one operation as shown above. Note that the framework will ignore -any key specified in this scenario as it does not apply (the entire cache is evicted not -just one entry). - -One can also indicate whether the eviction should occur after (the default) or before -the method executes through the `beforeInvocation` attribute. The former provides the -same semantics as the rest of the annotations - once the method completes successfully, -an action (in this case eviction) on the cache is executed. If the method does not -execute (as it might be cached) or an exception is thrown, the eviction does not occur. -The latter ( `beforeInvocation=true`) causes the eviction to occur always, before the -method is invoked - this is useful in cases where the eviction does not need to be tied -to the method outcome. - -It is important to note that void methods can be used with `@CacheEvict` - as the -methods act as triggers, the return values are ignored (as they don't interact with the -cache) - this is not the case with `@Cacheable` which adds/updates data into the cache -and thus requires a result. - - - -[[cache-annotations-caching]] -==== @Caching annotation - -There are cases when multiple annotations of the same type, such as `@CacheEvict` or -`@CachePut` need to be specified, for example because the condition or the key -expression is different between different caches. Unfortunately Java does not support -such declarations however there is a workaround - using an __enclosing__ annotation, in -this case, `@Caching`. `@Caching` allows multiple nested `@Cacheable`, `@CachePut` and -`@CacheEvict` to be used on the same method: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Caching(evict = { @CacheEvict("primary"), @CacheEvict(value="secondary", key="#p0") }) - public Book importBooks(String deposit, Date date) ----- - - -[[cache-annotations-config]] -==== @CacheConfig annotation - -So far we have seen that caching operations offered many customization options and -these can be set on an operation basis. However, some of the customization options -can be tedious to configure if they apply to all operations of the class. For -instance, specifying the name of the cache to use for every cache operation of the -class could be replaced by a single class-level definition. This is where `@CacheConfig` -comes into play. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - **@CacheConfig("books")** - public class BookRepositoryImpl implements BookRepository { - - @Cacheable - public Book findBook(ISBN isbn) {...} - } ----- - -`@CacheConfig` is a class-level annotation that allows to share the cache names, the custom -`KeyGenerator`, the custom `CacheManager` and finally the custom `CacheResolver`. Placing -this annotation on the class does not turn on any caching operation. - -An operation-level customization will always override a customization set on `@CacheConfig`. This -gives therefore three levels of customizations per cache operation: - -* Globally configured, available for `CacheManager`, `KeyGenerator` -* At class level, using `@CacheConfig` -* At the operation level - -[[cache-annotation-enable]] -==== Enable caching annotations -It is important to note that even though declaring the cache annotations does not -automatically trigger their actions - like many things in Spring, the feature has to be -declaratively enabled (which means if you ever suspect caching is to blame, you can -disable it by removing only one configuration line rather than all the annotations in -your code). - -To enable caching annotations add the annotation `@EnableCaching` to one of your -`@Configuration` classes: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Configuration - @EnableCaching - public class AppConfig { - } ----- - -Alternatively for XML configuration use the `cache:annotation-driven` element: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - ----- - -Both the `cache:annotation-driven` element and `@EnableCaching` annotation allow various -options to be specified that influence the way the caching behavior is added to the -application through AOP. The configuration is intentionally similar with that of -<>: - -[[cache-annotation-driven-settings]] -.Cache annotation settings -[cols="1,1,1,3"] -|=== -| XML Attribute| Annotation Attribute| Default| Description - -| `cache-manager` -| N/A (See `CachingConfigurer` javadocs) -| cacheManager -| Name of cache manager to use. A default `CacheResolver` will be initialized behind - the scenes with this cache manager (or `cacheManager`if not set). For more - fine-grained management of the cache resolution, consider setting the 'cache-resolver' - attribute. - -| `cache-resolver` -| N/A (See `CachingConfigurer` javadocs) -| A `SimpleCacheResolver` using the configured `cacheManager`. -| The bean name of the CacheResolver that is to be used to resolve the backing caches. - This attribute is not required, and only needs to be specified as an alternative to - the 'cache-manager' attribute. - -| `key-generator` -| N/A (See `CachingConfigurer` javadocs) -| `SimpleKeyGenerator` -| Name of the custom key generator to use. - -| `error-handler` -| N/A (See `CachingConfigurer` javadocs) -| `SimpleCacheErrorHandler` -| Name of the custom cache error handler to use. By default, any exception throw during - a cache related operations are thrown back at the client. - -| `mode` -| `mode` -| proxy -| The default mode "proxy" processes annotated beans to be proxied using Spring's AOP - framework (following proxy semantics, as discussed above, applying to method calls - coming in through the proxy only). The alternative mode "aspectj" instead weaves the - affected classes with Spring's AspectJ caching aspect, modifying the target class byte - code to apply to any kind of method call. AspectJ weaving requires spring-aspects.jar - in the classpath as well as load-time weaving (or compile-time weaving) enabled. (See - <> for details on how to set up load-time weaving.) - -| `proxy-target-class` -| `proxyTargetClass` -| false -| Applies to proxy mode only. Controls what type of caching proxies are created for - classes annotated with the `@Cacheable` or `@CacheEvict` annotations. If the - `proxy-target-class` attribute is set to `true`, then class-based proxies are created. - If `proxy-target-class` is `false` or if the attribute is omitted, then standard JDK - interface-based proxies are created. (See <> for a detailed examination - of the different proxy types.) - -| `order` -| `order` -| Ordered.LOWEST_PRECEDENCE -| Defines the order of the cache advice that is applied to beans annotated with - `@Cacheable` or `@CacheEvict`. (For more information about the rules related to - ordering of AOP advice, see <>.) No specified ordering - means that the AOP subsystem determines the order of the advice. -|=== - -[NOTE] -==== -`` only looks for `@Cacheable/@CachePut/@CacheEvict/@Caching` -on beans in the same application context it is defined in. This means that, if you put -`` in a `WebApplicationContext` for a `DispatcherServlet`, it -only checks for beans in your controllers, and not your services. See <> -for more information. -==== - -.Method visibility and cache annotations -**** -When using proxies, you should apply the cache annotations only to methods with -__public__ visibility. If you do annotate protected, private or package-visible methods -with these annotations, no error is raised, but the annotated method does not exhibit -the configured caching settings. Consider the use of AspectJ (see below) if you need to -annotate non-public methods as it changes the bytecode itself. -**** - -[TIP] -==== -Spring recommends that you only annotate concrete classes (and methods of concrete -classes) with the `@Cache*` annotation, as opposed to annotating interfaces. You -certainly can place the `@Cache*` annotation on an interface (or an interface method), -but this works only as you would expect it to if you are using interface-based proxies. -The fact that Java annotations are __not inherited from interfaces__ means that if you -are using class-based proxies ( `proxy-target-class="true"`) or the weaving-based aspect -( `mode="aspectj"`), then the caching settings are not recognized by the proxying and -weaving infrastructure, and the object will not be wrapped in a caching proxy, which -would be decidedly __bad__. -==== - -[NOTE] -==== -In proxy mode (which is the default), only external method calls coming in through the -proxy are intercepted. This means that self-invocation, in effect, a method within the -target object calling another method of the target object, will not lead to an actual -caching at runtime even if the invoked method is marked with `@Cacheable` - considering -using the aspectj mode in this case. -==== - - - -[[cache-annotation-stereotype]] -==== Using custom annotations - -.Custom annotation and AspectJ -**** -This feature only works out-of-the-box with the proxy-based approach but can be enabled -with a bit of extra effort using AspectJ. - -The `spring-aspects` module defines an aspect for the standard annotations only. If you -have defined your own annotations, you also need to define an aspect for those. Check -`AnnotationCacheAspect` for an example. -**** - -The caching abstraction allows you to use your own annotations to identify what method -triggers cache population or eviction. This is quite handy as a template mechanism as it -eliminates the need to duplicate cache annotation declarations (especially useful if the -key or condition are specified) or if the foreign imports (`org.springframework`) are -not allowed in your code base. Similar to the rest of the -<> annotations, `@Cacheable`, `@CachePut`, -`@CacheEvict` and `@CacheConfig` can be used as <>, -that is annotations that can annotate other annotations. To wit, let us replace a common -`@Cacheable` declaration with our own, custom annotation: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Retention(RetentionPolicy.RUNTIME) - @Target({ElementType.METHOD}) - @Cacheable(value="books", key="#isbn") - public @interface SlowService { - } ----- - -Above, we have defined our own `SlowService` annotation which itself is annotated with -`@Cacheable` - now we can replace the following code: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Cacheable(value="books", key="#isbn") - public Book findBook(ISBN isbn, boolean checkWarehouse, boolean includeUsed) ----- - -with: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @SlowService - public Book findBook(ISBN isbn, boolean checkWarehouse, boolean includeUsed) ----- - -Even though `@SlowService` is not a Spring annotation, the container automatically picks -up its declaration at runtime and understands its meaning. Note that as mentioned -<>, the annotation-driven behavior needs to be enabled. - - -[[cache-jsr-107]] -=== JCache (JSR-107) annotations - -Since the Spring Framework 4.1, the caching abstraction fully supports the JCache -standard annotations: these are `@CacheResult`, `@CacheEvict`, `@CacheRemove` and -`@CacheRemoveAll` as well as the `@CacheDefaults`, `@CacheKey` and `@CacheValue` -companions. These annotations can be used right the way without migrating your -cache store to JSR-107: the internal implementation uses Spring's caching abstraction -and provides default `CacheResolver` and `KeyGenerator` implementations that are -compliant with the specification. In other words, if you are already using Spring's -caching abstraction, you can switch to these standard annotations without changing -your cache storage (or configuration, for that matter). - -[[cache-jsr-107-summary]] -==== Features summary - -For those who are familiar with Spring's caching annotations, the following table -describes the main differences between the Spring annotations and the JSR-107 -counterpart: - -.Spring vs. JSR-107 caching annotations -[cols="1,1,3"] -|=== -| Spring| JSR-107| Remark - -| `@Cacheable` -| `@CacheResult` -| Fairly similar. `@CacheResult` can cache specific exceptions and force the - execution of the method regardless of the content of the cache. - -| `@CachePut` -| `@CachePut` -| While Spring updates the cache with the result of the method invocation, JCache - requires to pass it as an argument that is annotated with `@CacheValue`. Due - to this difference, JCache allows to update the cache before or after the - actual method invocation. - -| `@CacheEvict` -| `@CacheRemove` -| Fairly similar. `@CacheRemove` supports a conditional evict in case the - method invocation results in an exception. - -| `@CacheEvict(allEntries=true)` -| `@CacheRemoveAll` -| See `@CacheRemove`. - -| `@CacheConfig` -| `@CacheDefaults` -| Allows to configure the same concepts, in a similar fashion. -|=== - -JCache has the notion of `javax.cache.annotation.CacheResolver` that is identical -to the Spring's `CacheResolver` interface, except that JCache only supports a single -cache. By default, a simple implementation retrieves the cache to use based on -the name declared on the annotation. It should be noted that if no cache name -is specified on the annotation, a default is automatically generated, check the -javadoc of `@CacheResult#cacheName()` for more information. - -`CacheResolver` instances are retrieved by a `CacheResolverFactory`. It is -possible to customize the factory per cache operation: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @CacheResult(value="books", *cacheResolverFactory=MyCacheResolverFactory.class*) - public Book findBook(ISBN isbn) ----- - -[NOTE] -==== -For all referenced _classes_, Spring tries to locate a bean with the given type. If -more than one match exists, a new instance is created and can use the regular -bean lifecycle callbacks such as dependency injection. -==== - -Keys are generated by a `javax.cache.annotation.CacheKeyGenerator` that serves the -same purpose as Spring's `KeyGenerator`. By default, all method arguments are taken -into account unless at least one parameter is annotated with `@CacheKey`. This is -similar to Spring's <>. For instance these are identical operations, one using Spring's -abstraction and the other with JCache: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Cacheable(value="books", **key="#isbn"**) - public Book findBook(ISBN isbn, boolean checkWarehouse, boolean includeUsed) - - @CacheResult(cacheName="books") - public Book findBook(**@CacheKey** ISBN isbn, boolean checkWarehouse, boolean includeUsed) ----- - -The `CacheKeyResolver` to use can also be specified on the operation, in a similar -fashion as the `CacheResolverFactory`. - -JCache can manage exceptions thrown by annotated methods: this can prevent an update of -the cache but it can also cache the exception as an indicator of the failure instead of -calling the method again. Let's assume that `InvalidIsbnNotFoundException` is thrown if -the structure of the ISBN is invalid. This is a permanent failure, no book could ever be -retrieved with such parameter. The following caches the exception so that further calls -with the same, invalid ISBN, throws the cached exception directly instead of invoking -the method again. - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @CacheResult(cacheName="books", **exceptionCacheName="failures"** - **cachedExceptions = InvalidIsbnNotFoundException.class**) - public Book findBook(ISBN isbn) ----- - - -==== Enabling JSR-107 support - -Nothing specific needs to be done to enable the JSR-107 support alongside Spring's -declarative annotation support. Both `@EnableCaching` and the -`cache:annotation-driven` element will enable automatically the JCache support -if both the JSR-107 API and the `spring-context-support` module are present in -the classpath. - -[NOTE] -==== -Depending of your use case, the choice is basically yours. You can even mix -and match services using the JSR-107 API and others using Spring's own -annotations. Be aware however that if these services are impacting the same -caches, a consistent and identical key generation implementation should be used. -==== - - -[[cache-declarative-xml]] -=== Declarative XML-based caching -If annotations are not an option (no access to the sources or no external code), one can -use XML for declarative caching. So instead of annotating the methods for caching, one -specifies the target method and the caching directives externally (similar to the -declarative transaction management <>). -The previous example can be translated into: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - - - - - - - - - - ----- - -In the configuration above, the `bookService` is made cacheable. The caching semantics -to apply are encapsulated in the `cache:advice` definition which instructs method -`findBooks` to be used for putting data into the cache while method `loadBooks` for -evicting data. Both definitions are working against the `books` cache. - -The `aop:config` definition applies the cache advice to the appropriate points in the -program by using the AspectJ pointcut expression (more information is available in -<>). In the example above, all methods from the `BookService` are considered and -the cache advice applied to them. - -The declarative XML caching supports all of the annotation-based model so moving between -the two should be fairly easy - further more both can be used inside the same -application. The XML based approach does not touch the target code however it is -inherently more verbose; when dealing with classes with overloaded methods that are -targeted for caching, identifying the proper methods does take an extra effort since the -`method` argument is not a good discriminator - in these cases, the AspectJ pointcut can -be used to cherry pick the target methods and apply the appropriate caching -functionality. However through XML, it is easier to apply a package/group/interface-wide -caching (again due to the AspectJ pointcut) and to create template-like definitions (as -we did in the example above by defining the target cache through the `cache:definitions` -`cache` attribute). - - - - -[[cache-store-configuration]] -=== Configuring the cache storage -Out of the box, the cache abstraction provides several storages integration. To use -them, one needs to simply declare an appropriate `CacheManager` - an entity that -controls and manages ++Cache++s and can be used to retrieve these for storage. - - -[[cache-store-configuration-jdk]] -==== JDK ConcurrentMap-based Cache - -The JDK-based `Cache` implementation resides under -`org.springframework.cache.concurrent` package. It allows one to use `ConcurrentHashMap` -as a backing `Cache` store. - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - - ----- - -The snippet above uses the `SimpleCacheManager` to create a `CacheManager` for the two -nested `ConcurrentMapCache` instances named __default__ and __books__. Note that the -names are configured directly for each cache. - -As the cache is created by the application, it is bound to its lifecycle, making it -suitable for basic use cases, tests or simple applications. The cache scales well and is -very fast but it does not provide any management or persistence capabilities nor -eviction contracts. - - - -[[cache-store-configuration-ehcache]] -==== EhCache-based Cache - -The EhCache implementation is located under `org.springframework.cache.ehcache` package. -Again, to use it, one simply needs to declare the appropriate `CacheManager`: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - ----- - -This setup bootstraps the ehcache library inside Spring IoC (through the `ehcache` bean) which -is then wired into the dedicated `CacheManager` implementation. Note the entire -ehcache-specific configuration is read from `ehcache.xml`. - -[[cache-store-configuration-guava]] -==== Guava Cache - -The Guava implementation is located under `org.springframework.cache.guava` package and -provides access to several features of Guava. - -Configuring a `CacheManager` that creates the cache on demand is straightforward: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - ----- - -It is also possible to provide the caches to use explicitly. In that case, only those -will be made available by the manager: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - default - books - - - ----- - -The Guava `CacheManager` also supports customs `CacheBuilder` and `CacheLoader`. See -the https://code.google.com/p/guava-libraries/wiki/CachesExplained[Guava documentation] -for more information about those. - -[[cache-store-configuration-gemfire]] -==== GemFire-based Cache - -GemFire is a memory-oriented/disk-backed, elastically scalable, continuously available, -active (with built-in pattern-based subscription notifications), globally replicated -database and provides fully-featured edge caching. For further information on how to use -GemFire as a CacheManager (and more), please refer to the -http://docs.spring.io/spring-gemfire/docs/current/reference/htmlsingle/[Spring Data GemFire -reference documentation]. - -[[cache-store-configuration-jsr107]] -==== JSR-107 Cache - -JSR-107 compliant caches can also be used by Spring's caching abstraction. The JCache -implementation is located under `org.springframework.cache.jcache` package. - -Again, to use it, one simply needs to declare the appropriate `CacheManager`: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - ----- - +include::remoting.adoc[] -[[cache-store-configuration-noop]] -==== Dealing with caches without a backing store -Sometimes when switching environments or doing testing, one might have cache -declarations without an actual backing cache configured. As this is an invalid -configuration, at runtime an exception will be thrown since the caching infrastructure -is unable to find a suitable store. In situations like this, rather then removing the -cache declarations (which can prove tedious), one can wire in a simple, dummy cache that -performs no caching - that is, forces the cached methods to be executed every time: +include::ejb.adoc[] -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - - ----- +include::jms.adoc[] -The `CompositeCacheManager` above chains multiple ++CacheManager++s and additionally, -through the `fallbackToNoOpCache` flag, adds a __no op__ cache that for all the -definitions not handled by the configured cache managers. That is, every cache -definition not found in either `jdkCache` or `gemfireCache` (configured above) will be -handled by the no op cache, which will not store any information causing the target -method to be executed every time. +include::jmx.adoc[] +include::cci.adoc[] +include::mail.adoc[] +include::scheduling.adoc[] -[[cache-plug]] -=== Plugging-in different back-end caches -Clearly there are plenty of caching products out there that can be used as a backing -store. To plug them in, one needs to provide a `CacheManager` and `Cache` implementation -since unfortunately there is no available standard that we can use instead. This may -sound harder than it is since in practice, the classes tend to be simple -http://en.wikipedia.org/wiki/Adapter_pattern[adapter]s that map the caching abstraction -framework on top of the storage API as the `ehcache` classes can show. Most -`CacheManager` classes can use the classes in `org.springframework.cache.support` -package, such as `AbstractCacheManager` which takes care of the boiler-plate code -leaving only the actual __mapping__ to be completed. We hope that in time, the libraries -that provide integration with Spring can fill in this small configuration gap. +include::dynamic-languages.adoc[] +include::cache.adoc[] +[[spring-appendices]] += Appendices +[[migration-4.0]] +== Migrating to Spring Framework 4.0 +Migration guides for upgrading from previous releases of the Spring Framework are now +provided as a Wiki page. For details please refer to +https://github.com/spring-projects/spring-framework/wiki/Migrating-from-earlier-versions-of-the-spring-framework -[[cache-specific-config]] -=== How can I set the TTL/TTI/Eviction policy/XXX feature? -Directly through your cache provider. The cache abstraction is... well, an abstraction -not a cache implementation. The solution you are using might support various data -policies and different topologies which other solutions do not (take for example the JDK -`ConcurrentHashMap`) - exposing that in the cache abstraction would be useless simply -because there would no backing support. Such functionality should be controlled directly -through the backing cache, when configuring it or through its native API. +include::classic-spring.adoc[] +include::classic-aop-spring.adoc[] +include::xsd-configuration.adoc[] +include::xml-custom.adoc[] +include::spring-tld.adoc[] -include::appendix.adoc[] +include::spring-form-tld.adoc[] diff --git a/src/asciidoc/jdbc.adoc b/src/asciidoc/jdbc.adoc new file mode 100644 index 000000000000..9fee30d36ae5 --- /dev/null +++ b/src/asciidoc/jdbc.adoc @@ -0,0 +1,2643 @@ +[[jdbc]] +== Data access with JDBC + + + + +[[jdbc-introduction]] +=== Introduction to Spring Framework JDBC +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. + +[[jdbc-who-does-what]] +.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. + + + +[[jdbc-choose-style]] +==== Choosing an approach for JDBC database access +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. + + + +[[jdbc-packages]] +==== Package hierarchy +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. See <>, <>, and +<> + +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 in-memory database instances using Java database engines such as HSQL and H2. +See <> and <> + +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 of course objects returned by +queries are "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. See <>. + + + + +[[jdbc-core]] +=== Using the JDBC core classes to control basic JDBC processing and error handling + + + +[[jdbc-JdbcTemplate]] +==== JdbcTemplate + +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 ++ResultSet++s 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 `DataSource` should always be configured as a bean in the Spring IoC container. In +the first case the bean is given to the service directly; in the second case it is given +to the prepared template. +==== + +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). + + +[[jdbc-JdbcTemplate-examples]] +===== Examples of JdbcTemplate class usage +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. + +[[jdbc-JdbcTemplate-examples-query]] +====== Querying (SELECT) +Here is a simple query for getting the number of rows in a relation: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + int rowCount = this.jdbcTemplate.queryForObject("select count(*) from t_actor", Integer.class); +---- + +A simple query using a bind variable: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + int countOfActorsNamedJoe = this.jdbcTemplate.queryForObject( + "select count(*) from t_actor where first_name = ?", Integer.class, "Joe"); +---- + +Querying for a `String`: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + 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: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + Actor actor = this.jdbcTemplate.queryForObject( + "select first_name, last_name from t_actor where id = ?", + new Object[]{1212L}, + new RowMapper() { + 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: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + List actors = this.jdbcTemplate.query( + "select first_name, last_name from t_actor", + new RowMapper() { + 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` inner 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: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public List findAllActors() { + return this.jdbcTemplate.query( "select first_name, last_name from t_actor", new ActorMapper()); + } + + private static final class ActorMapper implements RowMapper { + + 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; + } + } +---- + +[[jdbc-JdbcTemplate-examples-update]] +====== Updating (INSERT/UPDATE/DELETE) with jdbcTemplate +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. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + this.jdbcTemplate.update( + "insert into t_actor (first_name, last_name) values (?, ?)", + "Leonor", "Watling"); +---- + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + this.jdbcTemplate.update( + "update t_actor set last_name = ? where id = ?", + "Banjo", 5276L); +---- + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + this.jdbcTemplate.update( + "delete from actor where id = ?", + Long.valueOf(actorId)); +---- + +[[jdbc-JdbcTemplate-examples-other]] +====== Other jdbcTemplate operations +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. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + 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 <>. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + this.jdbcTemplate.update( + "call SUPPORT.REFRESH_ACTORS_SUMMARY(?)", + Long.valueOf(unionId)); +---- + + +[[jdbc-JdbcTemplate-idioms]] +===== JdbcTemplate best practices + +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 +<> 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: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + 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. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + + + + + + + + + + +---- + +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`. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + **@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: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + + + + + + + + + +---- + +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`. + + + +[[jdbc-NamedParameterJdbcTemplate]] +==== NamedParameterJdbcTemplate + +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. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + // 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. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + // 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 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 http://www.oracle.com/technetwork/java/javase/documentation/spec-136004.html[the +JavaBean conventions]), and uses the properties of the wrapped JavaBean as the source +of named parameter values. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + 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... + + } +---- + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + // 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. + +See also <> for guidelines on using the +`NamedParameterJdbcTemplate` class in the context of an application. + + + +[[jdbc-SQLExceptionTranslator]] +==== SQLExceptionTranslator + +`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 `SQLErrorCodesFactory` is used by default to define Error codes and custom exception +translations. They are looked up in a file named `sql-error-codes.xml` from the +classpath and the matching `SQLErrorCodes` instance is located based on the database +name from the database metadata of the database in use. +==== +* 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 the `customSqlExceptionTranslator` property of the `SQLErrorCodes` class. +* The list of instances of the `CustomSQLErrorCodesTranslation` class, provided for the + `customTranslations` property of the `SQLErrorCodes` 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 + the `SQLStateSQLExceptionTranslator`. + +You can extend `SQLErrorCodeSQLExceptionTranslator:` + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + 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: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + 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`. + + + +[[jdbc-statements-executing]] +==== Executing statements +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: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + 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))"); + } + } +---- + + + +[[jdbc-statements-querying]] +==== Running queries +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`. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + 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: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + private JdbcTemplate jdbcTemplate; + + public void setDataSource(DataSource dataSource) { + this.jdbcTemplate = new JdbcTemplate(dataSource); + } + + public List> getList() { + return this.jdbcTemplate.queryForList("select * from mytable"); + } +---- + +The list returned would look something like this: + +[literal] +[subs="verbatim,quotes"] +---- +[{name=Bob, id=1}, {name=Mary, id=2}] +---- + + + +[[jdbc-updates]] +==== Updating the database +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. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + 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); + } + } +---- + + + +[[jdbc-auto-genereted-keys]] +==== Retrieving auto-generated keys +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: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + 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 +---- + + + + +[[jdbc-connections]] +=== Controlling database connections + + + +[[jdbc-datasource]] +==== DataSource + +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 `DriverManagerDataSource` class should only be used for testing purposes +since it does not provide pooling and will perform poorly when multiple requests for a +connection are made. +==== +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: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + 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: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + +---- + +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: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + +---- + +C3P0 configuration: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + +---- + + + +[[jdbc-DataSourceUtils]] +==== DataSourceUtils + +The `DataSourceUtils` class is a convenient and powerful helper class that provides +`static` methods to obtain connections from JNDI and close connections if necessary. It +supports thread-bound connections with, for example, `DataSourceTransactionManager`. + + + +[[jdbc-SmartDataSource]] +==== SmartDataSource + +The `SmartDataSource` interface should be implemented by classes that can provide a +connection to a relational database. It extends the `DataSource` interface to allow +classes using it to query whether the connection should be closed after a given +operation. This usage is efficient when you know that you will reuse a connection. + + + +[[jdbc-AbstractDataSource]] +==== AbstractDataSource + +`AbstractDataSource` is an `abstract` base class for Spring's `DataSource` +implementations that implements code that is common to all `DataSource` implementations. +You extend the `AbstractDataSource` class if you are writing your own `DataSource` +implementation. + + + +[[jdbc-SingleConnectionDataSource]] +==== SingleConnectionDataSource + +The `SingleConnectionDataSource` class is an implementation of the `SmartDataSource` +interface that wraps a __single__ `Connection` that is __not__ closed after each use. +Obviously, this is not multi-threading capable. + +If any client code calls `close` in the assumption of a pooled connection, as when using +persistence tools, set the `suppressClose` property to `true`. This setting returns a +close-suppressing proxy wrapping the physical connection. Be aware that you will not be +able to cast this to a native Oracle `Connection` or the like anymore. + +This is primarily a test class. For example, it enables easy testing of code outside an +application server, in conjunction with a simple JNDI environment. In contrast to +`DriverManagerDataSource`, it reuses the same connection all the time, avoiding +excessive creation of physical connections. + + + +[[jdbc-DriverManagerDataSource]] +==== DriverManagerDataSource + +The `DriverManagerDataSource` class is an implementation of the standard `DataSource` +interface that configures a plain JDBC driver through bean properties, and returns a new +`Connection` every time. + +This implementation is useful for test and stand-alone environments outside of a Java EE +container, either as a `DataSource` bean in a Spring IoC container, or in conjunction +with a simple JNDI environment. Pool-assuming `Connection.close()` calls will simply +close the connection, so any `DataSource`-aware persistence code should work. However, +using JavaBean-style connection pools such as `commons-dbcp` is so easy, even in a test +environment, that it is almost always preferable to use such a connection pool over +`DriverManagerDataSource`. + + + +[[jdbc-TransactionAwareDataSourceProxy]] +==== TransactionAwareDataSourceProxy + +`TransactionAwareDataSourceProxy` is a proxy for a target `DataSource`, which wraps that +target `DataSource` to add awareness of Spring-managed transactions. In this respect, it +is similar to a transactional JNDI `DataSource` as provided by a Java EE server. + +[NOTE] +==== +It is rarely desirable to use this class, except when already existing code that must be +called and passed a standard JDBC `DataSource` interface implementation. In this case, +it's possible to still have this code be usable, and at the same time have this code +participating in Spring managed transactions. It is generally preferable to write your +own new code using the higher level abstractions for resource management, such as +`JdbcTemplate` or `DataSourceUtils`. +==== + +__(See the `TransactionAwareDataSourceProxy` javadocs for more details.)__ + + + +[[jdbc-DataSourceTransactionManager]] +==== DataSourceTransactionManager + +The `DataSourceTransactionManager` class is a `PlatformTransactionManager` +implementation for single JDBC datasources. It binds a JDBC connection from the +specified data source to the currently executing thread, potentially allowing for one +thread connection per data source. + +Application code is required to retrieve the JDBC connection through +`DataSourceUtils.getConnection(DataSource)` instead of Java EE's standard +`DataSource.getConnection`. It throws unchecked `org.springframework.dao` exceptions +instead of checked `SQLExceptions`. All framework classes like `JdbcTemplate` use this +strategy implicitly. If not used with this transaction manager, the lookup strategy +behaves exactly like the common one - it can thus be used in any case. + +The `DataSourceTransactionManager` class supports custom isolation levels, and timeouts +that get applied as appropriate JDBC statement query timeouts. To support the latter, +application code must either use `JdbcTemplate` or call the +`DataSourceUtils.applyTransactionTimeout(..)` method for each created statement. + +This implementation can be used instead of `JtaTransactionManager` in the single +resource case, as it does not require the container to support JTA. Switching between +both is just a matter of configuration, if you stick to the required connection lookup +pattern. JTA does not support custom isolation levels! + + + +[[jdbc-NativeJdbcExtractor]] +==== NativeJdbcExtractor +Sometimes you need to access vendor specific JDBC methods that differ from the standard +JDBC API. This can be problematic if you are running in an application server or with a +`DataSource` that wraps the `Connection`, `Statement` and `ResultSet` objects with its +own wrapper objects. To gain access to the native objects you can configure your +`JdbcTemplate` or `OracleLobHandler` with a `NativeJdbcExtractor`. + +The `NativeJdbcExtractor` comes in a variety of flavors to match your execution +environment: + +* SimpleNativeJdbcExtractor +* C3P0NativeJdbcExtractor +* CommonsDbcpNativeJdbcExtractor +* JBossNativeJdbcExtractor +* WebLogicNativeJdbcExtractor +* WebSphereNativeJdbcExtractor +* XAPoolNativeJdbcExtractor + +Usually the `SimpleNativeJdbcExtractor` is sufficient for unwrapping a `Connection` +object in most environments. See the javadocs for more details. + + + + +[[jdbc-advanced-jdbc]] +=== JDBC batch operations +Most JDBC drivers provide improved performance if you batch multiple calls to the same +prepared statement. By grouping updates into batches you limit the number of round trips +to the database. + + + +[[jdbc-batch-classic]] +==== Basic batch operations with the JdbcTemplate +You accomplish `JdbcTemplate` batch processing by implementing two methods of a special +interface, `BatchPreparedStatementSetter`, and passing that in as the second parameter +in your `batchUpdate` method call. Use the `getBatchSize` method to provide the size of +the current batch. Use the `setValues` method to set the values for the parameters of +the prepared statement. This method will be called the number of times that you +specified in the `getBatchSize` call. The following example updates the actor table +based on entries in a list. The entire list is used as the batch in this example: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class JdbcActorDao implements ActorDao { + private JdbcTemplate jdbcTemplate; + + public void setDataSource(DataSource dataSource) { + this.jdbcTemplate = new JdbcTemplate(dataSource); + } + + public int[] batchUpdate(final List actors) { + int[] updateCounts = jdbcTemplate.batchUpdate("update t_actor set first_name = ?, " + + "last_name = ? where id = ?", + new BatchPreparedStatementSetter() { + public void setValues(PreparedStatement ps, int i) throws SQLException { + ps.setString(1, actors.get(i).getFirstName()); + ps.setString(2, actors.get(i).getLastName()); + ps.setLong(3, actors.get(i).getId().longValue()); + } + + public int getBatchSize() { + return actors.size(); + } + }); + return updateCounts; + } + + // ... additional methods + } +---- + +If you are processing a stream of updates or reading from a file, then you might have a +preferred batch size, but the last batch might not have that number of entries. In this +case you can use the `InterruptibleBatchPreparedStatementSetter` interface, which allows +you to interrupt a batch once the input source is exhausted. The `isBatchExhausted` method +allows you to signal the end of the batch. + + + +[[jdbc-batch-list]] +==== Batch operations with a List of objects +Both the `JdbcTemplate` and the `NamedParameterJdbcTemplate` provides an alternate way +of providing the batch update. Instead of implementing a special batch interface, you +provide all parameter values in the call as a list. The framework loops over these +values and uses an internal prepared statement setter. The API varies depending on +whether you use named parameters. For the named parameters you provide an array of +`SqlParameterSource`, one entry for each member of the batch. You can use the +`SqlParameterSource.createBatch` method to create this array, passing in either an array +of JavaBeans or an array of Maps containing the parameter values. + +This example shows a batch update using named parameters: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class JdbcActorDao implements ActorDao { + private NamedParameterTemplate namedParameterJdbcTemplate; + + public void setDataSource(DataSource dataSource) { + this.namedParameterJdbcTemplate = new NamedParameterJdbcTemplate(dataSource); + } + + public int[] batchUpdate(final List actors) { + SqlParameterSource[] batch = SqlParameterSourceUtils.createBatch(actors.toArray()); + int[] updateCounts = namedParameterJdbcTemplate.batchUpdate( + "update t_actor set first_name = :firstName, last_name = :lastName where id = :id", + batch); + return updateCounts; + } + + // ... additional methods + } +---- + +For an SQL statement using the classic "?" placeholders, you pass in a list containing an +object array with the update values. This object array must have one entry for each +placeholder in the SQL statement, and they must be in the same order as they are defined +in the SQL statement. + +The same example using classic JDBC "?" placeholders: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class JdbcActorDao implements ActorDao { + + private JdbcTemplate jdbcTemplate; + + public void setDataSource(DataSource dataSource) { + this.jdbcTemplate = new JdbcTemplate(dataSource); + } + + public int[] batchUpdate(final List actors) { + List batch = new ArrayList(); + for (Actor actor : actors) { + Object[] values = new Object[] { + actor.getFirstName(), + actor.getLastName(), + actor.getId()}; + batch.add(values); + } + int[] updateCounts = jdbcTemplate.batchUpdate( + "update t_actor set first_name = ?, last_name = ? where id = ?", + batch); + return updateCounts; + } + + // ... additional methods + + } +---- + +All of the above batch update methods return an int array containing the number of +affected rows for each batch entry. This count is reported by the JDBC driver. If the +count is not available, the JDBC driver returns a -2 value. + + + +[[jdbc-batch-multi]] +==== Batch operations with multiple batches +The last example of a batch update deals with batches that are so large that you want to +break them up into several smaller batches. You can of course do this with the methods +mentioned above by making multiple calls to the `batchUpdate` method, but there is now a +more convenient method. This method takes, in addition to the SQL statement, a +Collection of objects containing the parameters, the number of updates to make for each +batch and a `ParameterizedPreparedStatementSetter` to set the values for the parameters +of the prepared statement. The framework loops over the provided values and breaks the +update calls into batches of the size specified. + +This example shows a batch update using a batch size of 100: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class JdbcActorDao implements ActorDao { + + private JdbcTemplate jdbcTemplate; + + public void setDataSource(DataSource dataSource) { + this.jdbcTemplate = new JdbcTemplate(dataSource); + } + + public int[][] batchUpdate(final Collection actors) { + int[][] updateCounts = jdbcTemplate.batchUpdate( + "update t_actor set first_name = ?, last_name = ? where id = ?", + actors, + 100, + new ParameterizedPreparedStatementSetter() { + public void setValues(PreparedStatement ps, Actor argument) throws SQLException { + ps.setString(1, argument.getFirstName()); + ps.setString(2, argument.getLastName()); + ps.setLong(3, argument.getId().longValue()); + } + }); + return updateCounts; + } + + // ... additional methods + + } +---- + +The batch update methods for this call returns an array of int arrays containing an array +entry for each batch with an array of the number of affected rows for each update. The top +level array's length indicates the number of batches executed and the second level array's +length indicates the number of updates in that batch. The number of updates in each batch +should be the the batch size provided for all batches except for the last one that might +be less, depending on the total number of update objects provided. The update count for +each update statement is the one reported by the JDBC driver. If the count is not +available, the JDBC driver returns a -2 value. + + + + +[[jdbc-simple-jdbc]] +=== Simplifying JDBC operations with the SimpleJdbc classes +The `SimpleJdbcInsert` and `SimpleJdbcCall` classes provide a simplified configuration +by taking advantage of database metadata that can be retrieved through the JDBC driver. +This means there is less to configure up front, although you can override or turn off +the metadata processing if you prefer to provide all the details in your code. + + + +[[jdbc-simple-jdbc-insert-1]] +==== Inserting data using SimpleJdbcInsert +Let's start by looking at the `SimpleJdbcInsert` class with the minimal amount of +configuration options. You should instantiate the `SimpleJdbcInsert` in the data access +layer's initialization method. For this example, the initializing method is the +`setDataSource` method. You do not need to subclass the `SimpleJdbcInsert` class; simply +create a new instance and set the table name using the `withTableName` method. +Configuration methods for this class follow the "fluid" style that returns the instance +of the `SimpleJdbcInsert`, which allows you to chain all configuration methods. This +example uses only one configuration method; you will see examples of multiple ones later. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class JdbcActorDao implements ActorDao { + + private JdbcTemplate jdbcTemplate; + private SimpleJdbcInsert insertActor; + + public void setDataSource(DataSource dataSource) { + this.jdbcTemplate = new JdbcTemplate(dataSource); + this.insertActor = new SimpleJdbcInsert(dataSource).withTableName("t_actor"); + } + + public void add(Actor actor) { + Map parameters = new HashMap(3); + parameters.put("id", actor.getId()); + parameters.put("first_name", actor.getFirstName()); + parameters.put("last_name", actor.getLastName()); + insertActor.execute(parameters); + } + + // ... additional methods + } +---- + +The execute method used here takes a plain `java.utils.Map` as its only parameter. The +important thing to note here is that the keys used for the Map must match the column +names of the table as defined in the database. This is because we read the metadata in +order to construct the actual insert statement. + + + +[[jdbc-simple-jdbc-insert-2]] +==== Retrieving auto-generated keys using SimpleJdbcInsert +This example uses the same insert as the preceding, but instead of passing in the id it +retrieves the auto-generated key and sets it on the new Actor object. When you create +the `SimpleJdbcInsert`, in addition to specifying the table name, you specify the name +of the generated key column with the `usingGeneratedKeyColumns` method. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class JdbcActorDao implements ActorDao { + + private JdbcTemplate jdbcTemplate; + private SimpleJdbcInsert insertActor; + + public void setDataSource(DataSource dataSource) { + this.jdbcTemplate = new JdbcTemplate(dataSource); + this.insertActor = new SimpleJdbcInsert(dataSource) + .withTableName("t_actor") + .usingGeneratedKeyColumns("id"); + } + + public void add(Actor actor) { + Map parameters = new HashMap(2); + parameters.put("first_name", actor.getFirstName()); + parameters.put("last_name", actor.getLastName()); + Number newId = insertActor.executeAndReturnKey(parameters); + actor.setId(newId.longValue()); + } + + // ... additional methods + } +---- + +The main difference when executing the insert by this second approach is that you do not +add the id to the Map and you call the `executeReturningKey` method. This returns a +`java.lang.Number` object with which you can create an instance of the numerical type that +is used in our domain class. You cannot rely on all databases to return a specific Java +class here; `java.lang.Number` is the base class that you can rely on. If you have +multiple auto-generated columns, or the generated values are non-numeric, then you can +use a `KeyHolder` that is returned from the `executeReturningKeyHolder` method. + + + +[[jdbc-simple-jdbc-insert-3]] +==== Specifying columns for a SimpleJdbcInsert +You can limit the columns for an insert by specifying a list of column names with the +`usingColumns` method: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class JdbcActorDao implements ActorDao { + + private JdbcTemplate jdbcTemplate; + private SimpleJdbcInsert insertActor; + + public void setDataSource(DataSource dataSource) { + this.jdbcTemplate = new JdbcTemplate(dataSource); + this.insertActor = new SimpleJdbcInsert(dataSource) + .withTableName("t_actor") + .usingColumns("first_name", "last_name") + .usingGeneratedKeyColumns("id"); + } + + public void add(Actor actor) { + Map parameters = new HashMap(2); + parameters.put("first_name", actor.getFirstName()); + parameters.put("last_name", actor.getLastName()); + Number newId = insertActor.executeAndReturnKey(parameters); + actor.setId(newId.longValue()); + } + + // ... additional methods + + } +---- + +The execution of the insert is the same as if you had relied on the metadata to determine +which columns to use. + + + +[[jdbc-simple-jdbc-parameters]] +==== Using SqlParameterSource to provide parameter values +Using a `Map` to provide parameter values works fine, but it's not the most convenient +class to use. Spring provides a couple of implementations of the `SqlParameterSource` +interface that can be used instead.The first one is `BeanPropertySqlParameterSource`, +which is a very convenient class if you have a JavaBean-compliant class that contains +your values. It will use the corresponding getter method to extract the parameter +values. Here is an example: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class JdbcActorDao implements ActorDao { + + private JdbcTemplate jdbcTemplate; + private SimpleJdbcInsert insertActor; + + public void setDataSource(DataSource dataSource) { + this.jdbcTemplate = new JdbcTemplate(dataSource); + this.insertActor = new SimpleJdbcInsert(dataSource) + .withTableName("t_actor") + .usingGeneratedKeyColumns("id"); + } + + public void add(Actor actor) { + SqlParameterSource parameters = new BeanPropertySqlParameterSource(actor); + Number newId = insertActor.executeAndReturnKey(parameters); + actor.setId(newId.longValue()); + } + + // ... additional methods + + } +---- + +Another option is the `MapSqlParameterSource` that resembles a Map but provides a more +convenient `addValue` method that can be chained. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class JdbcActorDao implements ActorDao { + + private JdbcTemplate jdbcTemplate; + private SimpleJdbcInsert insertActor; + + public void setDataSource(DataSource dataSource) { + this.jdbcTemplate = new JdbcTemplate(dataSource); + this.insertActor = new SimpleJdbcInsert(dataSource) + .withTableName("t_actor") + .usingGeneratedKeyColumns("id"); + } + + public void add(Actor actor) { + SqlParameterSource parameters = new MapSqlParameterSource() + .addValue("first_name", actor.getFirstName()) + .addValue("last_name", actor.getLastName()); + Number newId = insertActor.executeAndReturnKey(parameters); + actor.setId(newId.longValue()); + } + + // ... additional methods + + } +---- + +As you can see, the configuration is the same; only the executing code has to change to +use these alternative input classes. + + + +[[jdbc-simple-jdbc-call-1]] +==== Calling a stored procedure with SimpleJdbcCall +The `SimpleJdbcCall` class leverages metadata in the database to look up names of `in` +and `out` parameters, so that you do not have to declare them explicitly. You can +declare parameters if you prefer to do that, or if you have parameters such as `ARRAY` +or `STRUCT` that do not have an automatic mapping to a Java class. The first example +shows a simple procedure that returns only scalar values in `VARCHAR` and `DATE` format +from a MySQL database. The example procedure reads a specified actor entry and returns +`first_name`, `last_name`, and `birth_date` columns in the form of `out` parameters. + +[source,sql,indent=0] +[subs="verbatim,quotes"] +---- + CREATE PROCEDURE read_actor ( + IN in_id INTEGER, + OUT out_first_name VARCHAR(100), + OUT out_last_name VARCHAR(100), + OUT out_birth_date DATE) + BEGIN + SELECT first_name, last_name, birth_date + INTO out_first_name, out_last_name, out_birth_date + FROM t_actor where id = in_id; + END; +---- + +The `in_id` parameter contains the `id` of the actor you are looking up. The `out` +parameters return the data read from the table. + +The `SimpleJdbcCall` is declared in a similar manner to the `SimpleJdbcInsert`. You +should instantiate and configure the class in the initialization method of your data +access layer. Compared to the StoredProcedure class, you don't have to create a subclass +and you don't have to declare parameters that can be looked up in the database metadata. +Following is an example of a SimpleJdbcCall configuration using the above stored +procedure. The only configuration option, in addition to the `DataSource`, is the name +of the stored procedure. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class JdbcActorDao implements ActorDao { + + private JdbcTemplate jdbcTemplate; + private SimpleJdbcCall procReadActor; + + public void setDataSource(DataSource dataSource) { + this.jdbcTemplate = new JdbcTemplate(dataSource); + this.procReadActor = new SimpleJdbcCall(dataSource) + .withProcedureName("read_actor"); + } + + public Actor readActor(Long id) { + SqlParameterSource in = new MapSqlParameterSource() + .addValue("in_id", id); + Map out = procReadActor.execute(in); + Actor actor = new Actor(); + actor.setId(id); + actor.setFirstName((String) out.get("out_first_name")); + actor.setLastName((String) out.get("out_last_name")); + actor.setBirthDate((Date) out.get("out_birth_date")); + return actor; + } + + // ... additional methods + + } +---- + +The code you write for the execution of the call involves creating an `SqlParameterSource` +containing the IN parameter. It's important to match the name provided for the input value +with that of the parameter name declared in the stored procedure. The case does not have +to match because you use metadata to determine how database objects should be referred to +in a stored procedure. What is specified in the source for the stored procedure is not +necessarily the way it is stored in the database. Some databases transform names to all +upper case while others use lower case or use the case as specified. + +The `execute` method takes the IN parameters and returns a Map containing any `out` +parameters keyed by the name as specified in the stored procedure. In this case they are +`out_first_name, out_last_name` and `out_birth_date`. + +The last part of the `execute` method creates an Actor instance to use to return the +data retrieved. Again, it is important to use the names of the `out` parameters as they +are declared in the stored procedure. Also, the case in the names of the `out` +parameters stored in the results map matches that of the `out` parameter names in the +database, which could vary between databases. To make your code more portable you should +do a case-insensitive lookup or instruct Spring to use a `CaseInsensitiveMap` from the +Jakarta Commons project. To do the latter, you create your own `JdbcTemplate` and set +the `setResultsMapCaseInsensitive` property to `true`. Then you pass this customized +`JdbcTemplate` instance into the constructor of your `SimpleJdbcCall`. You must include +the `commons-collections.jar` in your classpath for this to work. Here is an example of +this configuration: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class JdbcActorDao implements ActorDao { + + private SimpleJdbcCall procReadActor; + + public void setDataSource(DataSource dataSource) { + JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource); + jdbcTemplate.setResultsMapCaseInsensitive(true); + this.procReadActor = new SimpleJdbcCall(jdbcTemplate) + .withProcedureName("read_actor"); + } + + // ... additional methods + + } +---- + +By taking this action, you avoid conflicts in the case used for the names of your +returned `out` parameters. + + + +[[jdbc-simple-jdbc-call-2]] +==== Explicitly declaring parameters to use for a SimpleJdbcCall +You have seen how the parameters are deduced based on metadata, but you can declare then +explicitly if you wish. You do this by creating and configuring `SimpleJdbcCall` with +the `declareParameters` method, which takes a variable number of `SqlParameter` objects +as input. See the next section for details on how to define an `SqlParameter`. + +[NOTE] +==== +Explicit declarations are necessary if the database you use is not a Spring-supported +database. Currently Spring supports metadata lookup of stored procedure calls for the +following databases: Apache Derby, DB2, MySQL, Microsoft SQL Server, Oracle, and Sybase. +We also support metadata lookup of stored functions for: MySQL, Microsoft SQL Server, +and Oracle. +==== + +You can opt to declare one, some, or all the parameters explicitly. The parameter +metadata is still used where you do not declare parameters explicitly. To bypass all +processing of metadata lookups for potential parameters and only use the declared +parameters, you call the method `withoutProcedureColumnMetaDataAccess` as part of the +declaration. Suppose that you have two or more different call signatures declared for a +database function. In this case you call the `useInParameterNames` to specify the list +of IN parameter names to include for a given signature. + +The following example shows a fully declared procedure call, using the information from +the preceding example. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class JdbcActorDao implements ActorDao { + + private SimpleJdbcCall procReadActor; + + public void setDataSource(DataSource dataSource) { + JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource); + jdbcTemplate.setResultsMapCaseInsensitive(true); + this.procReadActor = new SimpleJdbcCall(jdbcTemplate) + .withProcedureName("read_actor") + .withoutProcedureColumnMetaDataAccess() + .useInParameterNames("in_id") + .declareParameters( + new SqlParameter("in_id", Types.NUMERIC), + new SqlOutParameter("out_first_name", Types.VARCHAR), + new SqlOutParameter("out_last_name", Types.VARCHAR), + new SqlOutParameter("out_birth_date", Types.DATE) + ); + } + + // ... additional methods + } +---- + +The execution and end results of the two examples are the same; this one specifies all +details explicitly rather than relying on metadata. + + + +[[jdbc-params]] +==== How to define SqlParameters +To define a parameter for the SimpleJdbc classes and also for the RDBMS operations +classes, covered in <>, you use an `SqlParameter` or one of its subclasses. +You typically specify the parameter name and SQL type in the constructor. The SQL type +is specified using the `java.sql.Types` constants. We have already seen declarations +like: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + new SqlParameter("in_id", Types.NUMERIC), + new SqlOutParameter("out_first_name", Types.VARCHAR), +---- + +The first line with the `SqlParameter` declares an IN parameter. IN parameters can be +used for both stored procedure calls and for queries using the `SqlQuery` and its +subclasses covered in the following section. + +The second line with the `SqlOutParameter` declares an `out` parameter to be used in a +stored procedure call. There is also an `SqlInOutParameter` for `InOut` parameters, +parameters that provide an `IN` value to the procedure and that also return a value. + +[NOTE] +==== +Only parameters declared as `SqlParameter` and `SqlInOutParameter` will be used to +provide input values. This is different from the `StoredProcedure` class, which for +backwards compatibility reasons allows input values to be provided for parameters +declared as `SqlOutParameter`. +==== + +For IN parameters, in addition to the name and the SQL type, you can specify a scale for +numeric data or a type name for custom database types. For `out` parameters, you can +provide a `RowMapper` to handle mapping of rows returned from a `REF` cursor. Another +option is to specify an `SqlReturnType` that provides an opportunity to define +customized handling of the return values. + + + +[[jdbc-simple-jdbc-call-3]] +==== Calling a stored function using SimpleJdbcCall +You call a stored function in almost the same way as you call a stored procedure, except +that you provide a function name rather than a procedure name. You use the +`withFunctionName` method as part of the configuration to indicate that we want to make +a call to a function, and the corresponding string for a function call is generated. A +specialized execute call, `executeFunction,` is used to execute the function and it +returns the function return value as an object of a specified type, which means you do +not have to retrieve the return value from the results map. A similar convenience method +named `executeObject` is also available for stored procedures that only have one `out` +parameter. The following example is based on a stored function named `get_actor_name` +that returns an actor's full name. Here is the MySQL source for this function: + +[source,sql,indent=0] +[subs="verbatim,quotes"] +---- + CREATE FUNCTION get_actor_name (in_id INTEGER) + RETURNS VARCHAR(200) READS SQL DATA + BEGIN + DECLARE out_name VARCHAR(200); + SELECT concat(first_name, ' ', last_name) + INTO out_name + FROM t_actor where id = in_id; + RETURN out_name; + END; +---- + +To call this function we again create a `SimpleJdbcCall` in the initialization method. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class JdbcActorDao implements ActorDao { + + private JdbcTemplate jdbcTemplate; + private SimpleJdbcCall funcGetActorName; + + public void setDataSource(DataSource dataSource) { + this.jdbcTemplate = new JdbcTemplate(dataSource); + JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource); + jdbcTemplate.setResultsMapCaseInsensitive(true); + this.funcGetActorName = new SimpleJdbcCall(jdbcTemplate) + .withFunctionName("get_actor_name"); + } + + public String getActorName(Long id) { + SqlParameterSource in = new MapSqlParameterSource() + .addValue("in_id", id); + String name = funcGetActorName.executeFunction(String.class, in); + return name; + } + + // ... additional methods + + } +---- + +The execute method used returns a `String` containing the return value from the function +call. + + + +[[jdbc-simple-jdbc-call-4]] +==== Returning ResultSet/REF Cursor from a SimpleJdbcCall +Calling a stored procedure or function that returns a result set is a bit tricky. Some +databases return result sets during the JDBC results processing while others require an +explicitly registered `out` parameter of a specific type. Both approaches need +additional processing to loop over the result set and process the returned rows. With +the `SimpleJdbcCall` you use the `returningResultSet` method and declare a `RowMapper` +implementation to be used for a specific parameter. In the case where the result set is +returned during the results processing, there are no names defined, so the returned +results will have to match the order in which you declare the `RowMapper` +implementations. The name specified is still used to store the processed list of results +in the results map that is returned from the execute statement. + +The next example uses a stored procedure that takes no IN parameters and returns all +rows from the t_actor table. Here is the MySQL source for this procedure: + +[source,sql,indent=0] +[subs="verbatim,quotes"] +---- + CREATE PROCEDURE read_all_actors() + BEGIN + SELECT a.id, a.first_name, a.last_name, a.birth_date FROM t_actor a; + END; +---- + +To call this procedure you declare the `RowMapper`. Because the class you want to map to +follows the JavaBean rules, you can use a `ParameterizedBeanPropertyRowMapper` that is +created by passing in the required class to map to in the `newInstance` method. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class JdbcActorDao implements ActorDao { + + private SimpleJdbcCall procReadAllActors; + + public void setDataSource(DataSource dataSource) { + JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource); + jdbcTemplate.setResultsMapCaseInsensitive(true); + this.procReadAllActors = new SimpleJdbcCall(jdbcTemplate) + .withProcedureName("read_all_actors") + .returningResultSet("actors", + ParameterizedBeanPropertyRowMapper.newInstance(Actor.class)); + } + + public List getActorsList() { + Map m = procReadAllActors.execute(new HashMap(0)); + return (List) m.get("actors"); + } + + // ... additional methods + + } +---- + +The execute call passes in an empty Map because this call does not take any parameters. +The list of Actors is then retrieved from the results map and returned to the caller. + + + + +[[jdbc-object]] +=== Modeling JDBC operations as Java objects +The `org.springframework.jdbc.object` package contains classes that allow you to access +the database in a more object-oriented manner. As an example, you can execute queries +and get the results back as a list containing business objects with the relational +column data mapped to the properties of the business object. You can also execute stored +procedures and run update, delete, and insert statements. + +[NOTE] +==== +Many Spring developers believe that the various RDBMS operation classes described below +(with the exception of the <> class) can often +be replaced with straight `JdbcTemplate` calls. Often it is simpler to write a DAO +method that simply calls a method on a `JdbcTemplate` directly (as opposed to +encapsulating a query as a full-blown class). + +However, if you are getting measurable value from using the RDBMS operation classes, +continue using these classes. +==== + + + +[[jdbc-SqlQuery]] +==== SqlQuery + +`SqlQuery` is a reusable, threadsafe class that encapsulates an SQL query. Subclasses +must implement the `newRowMapper(..)` method to provide a `RowMapper` instance that can +create one object per row obtained from iterating over the `ResultSet` that is created +during the execution of the query. The `SqlQuery` class is rarely used directly because +the `MappingSqlQuery` subclass provides a much more convenient implementation for +mapping rows to Java classes. Other implementations that extend `SqlQuery` are +`MappingSqlQueryWithParameters` and `UpdatableSqlQuery`. + + + +[[jdbc-MappingSqlQuery]] +==== MappingSqlQuery + +`MappingSqlQuery` is a reusable query in which concrete subclasses must implement the +abstract `mapRow(..)` method to convert each row of the supplied `ResultSet` into an +object of the type specified. The following example shows a custom query that maps the +data from the `t_actor` relation to an instance of the `Actor` class. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class ActorMappingQuery extends MappingSqlQuery { + + public ActorMappingQuery(DataSource ds) { + super(ds, "select id, first_name, last_name from t_actor where id = ?"); + super.declareParameter(new SqlParameter("id", Types.INTEGER)); + compile(); + } + + @Override + protected Actor mapRow(ResultSet rs, int rowNumber) throws SQLException { + Actor actor = new Actor(); + actor.setId(rs.getLong("id")); + actor.setFirstName(rs.getString("first_name")); + actor.setLastName(rs.getString("last_name")); + return actor; + } + + } +---- + +The class extends `MappingSqlQuery` parameterized with the `Actor` type. The constructor +for this customer query takes the `DataSource` as the only parameter. In this +constructor you call the constructor on the superclass with the `DataSource` and the SQL +that should be executed to retrieve the rows for this query. This SQL will be used to +create a `PreparedStatement` so it may contain place holders for any parameters to be +passed in during execution.You must declare each parameter using the `declareParameter` +method passing in an `SqlParameter`. The `SqlParameter` takes a name and the JDBC type +as defined in `java.sql.Types`. After you define all parameters, you call the +`compile()` method so the statement can be prepared and later executed. This class is +thread-safe after it is compiled, so as long as these instances are created when the DAO +is initialized they can be kept as instance variables and be reused. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + private ActorMappingQuery actorMappingQuery; + + @Autowired + public void setDataSource(DataSource dataSource) { + this.actorMappingQuery = new ActorMappingQuery(dataSource); + } + + public Customer getCustomer(Long id) { + return actorMappingQuery.findObject(id); + } +---- + +The method in this example retrieves the customer with the id that is passed in as the +only parameter. Since we only want one object returned we simply call the convenience +method `findObject` with the id as parameter. If we had instead a query that returned a +list of objects and took additional parameters then we would use one of the execute +methods that takes an array of parameter values passed in as varargs. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public List searchForActors(int age, String namePattern) { + List actors = actorSearchMappingQuery.execute(age, namePattern); + return actors; + } +---- + + + +[[jdbc-SqlUpdate]] +==== SqlUpdate + +The `SqlUpdate` class encapsulates an SQL update. Like a query, an update object is +reusable, and like all `RdbmsOperation` classes, an update can have parameters and is +defined in SQL. This class provides a number of `update(..)` methods analogous to the +`execute(..)` methods of query objects. The `SQLUpdate` class is concrete. It can be +subclassed, for example, to add a custom update method, as in the following snippet +where it's simply called `execute`. However, you don't have to subclass the `SqlUpdate` +class since it can easily be parameterized by setting SQL and declaring parameters. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + import java.sql.Types; + + import javax.sql.DataSource; + + import org.springframework.jdbc.core.SqlParameter; + import org.springframework.jdbc.object.SqlUpdate; + + public class UpdateCreditRating extends SqlUpdate { + + public UpdateCreditRating(DataSource ds) { + setDataSource(ds); + setSql("update customer set credit_rating = ? where id = ?"); + declareParameter(new SqlParameter("creditRating", Types.NUMERIC)); + declareParameter(new SqlParameter("id", Types.NUMERIC)); + compile(); + } + + /** + * @param id for the Customer to be updated + * @param rating the new value for credit rating + * @return number of rows updated + */ + public int execute(int id, int rating) { + return update(rating, id); + } + } +---- + + + +[[jdbc-StoredProcedure]] +==== StoredProcedure + +The `StoredProcedure` class is a superclass for object abstractions of RDBMS stored +procedures. This class is `abstract`, and its various `execute(..)` methods have +`protected` access, preventing use other than through a subclass that offers tighter +typing. + +The inherited `sql` property will be the name of the stored procedure in the RDBMS. + +To define a parameter for the `StoredProcedure` class, you use an `SqlParameter` or one +of its subclasses. You must specify the parameter name and SQL type in the constructor +like in the following code snippet. The SQL type is specified using the `java.sql.Types` +constants. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + new SqlParameter("in_id", Types.NUMERIC), + new SqlOutParameter("out_first_name", Types.VARCHAR), +---- + +The first line with the `SqlParameter` declares an IN parameter. IN parameters can be +used for both stored procedure calls and for queries using the `SqlQuery` and its +subclasses covered in the following section. + +The second line with the `SqlOutParameter` declares an `out` parameter to be used in the +stored procedure call. There is also an `SqlInOutParameter` for `I` `nOut` parameters, +parameters that provide an `in` value to the procedure and that also return a value. + +For `i` `n` parameters, in addition to the name and the SQL type, you can specify a +scale for numeric data or a type name for custom database types. For `out` parameters +you can provide a `RowMapper` to handle mapping of rows returned from a REF cursor. +Another option is to specify an `SqlReturnType` that enables you to define customized +handling of the return values. + +Here is an example of a simple DAO that uses a `StoredProcedure` to call a function, +`sysdate()`,which comes with any Oracle database. To use the stored procedure +functionality you have to create a class that extends `StoredProcedure`. In this +example, the `StoredProcedure` class is an inner class, but if you need to reuse the +`StoredProcedure` you declare it as a top-level class. This example has no input +parameters, but an output parameter is declared as a date type using the class +`SqlOutParameter`. The `execute()` method executes the procedure and extracts the +returned date from the results `Map`. The results `Map` has an entry for each declared +output parameter, in this case only one, using the parameter name as the key. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + import java.sql.Types; + import java.util.Date; + import java.util.HashMap; + import java.util.Map; + + import javax.sql.DataSource; + + import org.springframework.beans.factory.annotation.Autowired; + import org.springframework.jdbc.core.SqlOutParameter; + import org.springframework.jdbc.object.StoredProcedure; + + public class StoredProcedureDao { + + private GetSysdateProcedure getSysdate; + + @Autowired + public void init(DataSource dataSource) { + this.getSysdate = new GetSysdateProcedure(dataSource); + } + + public Date getSysdate() { + return getSysdate.execute(); + } + + private class GetSysdateProcedure extends StoredProcedure { + + private static final String SQL = "sysdate"; + + public GetSysdateProcedure(DataSource dataSource) { + setDataSource(dataSource); + setFunction(true); + setSql(SQL); + declareParameter(new SqlOutParameter("date", Types.DATE)); + compile(); + } + + public Date execute() { + // the 'sysdate' sproc has no input parameters, so an empty Map is supplied... + Map results = execute(new HashMap()); + Date sysdate = (Date) results.get("date"); + return sysdate; + } + } + + } +---- + +The following example of a `StoredProcedure` has two output parameters (in this case, +Oracle REF cursors). + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + import oracle.jdbc.OracleTypes; + import org.springframework.jdbc.core.SqlOutParameter; + import org.springframework.jdbc.object.StoredProcedure; + + import javax.sql.DataSource; + import java.util.HashMap; + import java.util.Map; + + public class TitlesAndGenresStoredProcedure extends StoredProcedure { + + private static final String SPROC_NAME = "AllTitlesAndGenres"; + + public TitlesAndGenresStoredProcedure(DataSource dataSource) { + super(dataSource, SPROC_NAME); + declareParameter(new SqlOutParameter("titles", OracleTypes.CURSOR, new TitleMapper())); + declareParameter(new SqlOutParameter("genres", OracleTypes.CURSOR, new GenreMapper())); + compile(); + } + + public Map execute() { + // again, this sproc has no input parameters, so an empty Map is supplied + return super.execute(new HashMap()); + } + } +---- + +Notice how the overloaded variants of the `declareParameter(..)` method that have been +used in the `TitlesAndGenresStoredProcedure` constructor are passed `RowMapper` +implementation instances; this is a very convenient and powerful way to reuse existing +functionality. The code for the two `RowMapper` implementations is provided below. + +The `TitleMapper` class maps a `ResultSet` to a `Title` domain object for each row in +the supplied `ResultSet`: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + import org.springframework.jdbc.core.RowMapper; + + import java.sql.ResultSet; + import java.sql.SQLException; + + import com.foo.domain.Title; + + public final class TitleMapper implements RowMapper { + + public Title mapRow(ResultSet rs, int rowNum) throws SQLException { + Title title = new Title(); + title.setId(rs.getLong("id")); + title.setName(rs.getString("name")); + return title; + } + } +---- + +The `GenreMapper` class maps a `ResultSet` to a `Genre` domain object for each row in +the supplied `ResultSet`. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + import org.springframework.jdbc.core.RowMapper; + + import java.sql.ResultSet; + import java.sql.SQLException; + + import com.foo.domain.Genre; + + public final class GenreMapper implements RowMapper<Genre> { + + public Genre mapRow(ResultSet rs, int rowNum) throws SQLException { + return new Genre(rs.getString("name")); + } + } +---- + +To pass parameters to a stored procedure that has one or more input parameters in its +definition in the RDBMS, you can code a strongly typed `execute(..)` method that would +delegate to the superclass' untyped `execute(Map parameters)` method (which has +`protected` access); for example: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + import oracle.jdbc.OracleTypes; + import org.springframework.jdbc.core.SqlOutParameter; + import org.springframework.jdbc.core.SqlParameter; + import org.springframework.jdbc.object.StoredProcedure; + + import javax.sql.DataSource; + + import java.sql.Types; + import java.util.Date; + import java.util.HashMap; + import java.util.Map; + + public class TitlesAfterDateStoredProcedure extends StoredProcedure { + + private static final String SPROC_NAME = "TitlesAfterDate"; + private static final String CUTOFF_DATE_PARAM = "cutoffDate"; + + public TitlesAfterDateStoredProcedure(DataSource dataSource) { + super(dataSource, SPROC_NAME); + declareParameter(new SqlParameter(CUTOFF_DATE_PARAM, Types.DATE); + declareParameter(new SqlOutParameter("titles", OracleTypes.CURSOR, new TitleMapper())); + compile(); + } + + public Map<String, Object> execute(Date cutoffDate) { + Map<String, Object> inputs = new HashMap<String, Object>(); + inputs.put(CUTOFF_DATE_PARAM, cutoffDate); + return super.execute(inputs); + } + } +---- + + + + +[[jdbc-parameter-handling]] +=== Common problems with parameter and data value handling +Common problems with parameters and data values exist in the different approaches +provided by the Spring Framework JDBC. + + + +[[jdbc-type-information]] +==== Providing SQL type information for parameters +Usually Spring determines the SQL type of the parameters based on the type of parameter +passed in. It is possible to explicitly provide the SQL type to be used when setting +parameter values. This is sometimes necessary to correctly set NULL values. + +You can provide SQL type information in several ways: + +* Many update and query methods of the `JdbcTemplate` take an additional parameter in + the form of an `int` array. This array is used to indicate the SQL type of the + corresponding parameter using constant values from the `java.sql.Types` class. Provide + one entry for each parameter. +* You can use the `SqlParameterValue` class to wrap the parameter value that needs this + additional information.Create a new instance for each value and pass in the SQL type + and parameter value in the constructor. You can also provide an optional scale + parameter for numeric values. +* For methods working with named parameters, use the `SqlParameterSource` classes + `BeanPropertySqlParameterSource` or `MapSqlParameterSource`. They both have methods + for registering the SQL type for any of the named parameter values. + + + +[[jdbc-lob]] +==== Handling BLOB and CLOB objects +You can store images, other binary objects, and large chunks of text. These large object +are called BLOB for binary data and CLOB for character data. In Spring you can handle +these large objects by using the JdbcTemplate directly and also when using the higher +abstractions provided by RDBMS Objects and the `SimpleJdbc` classes. All of these +approaches use an implementation of the `LobHandler` interface for the actual management +of the LOB data. The `LobHandler` provides access to a `LobCreator` class, through the +`getLobCreator` method, used for creating new LOB objects to be inserted. + +The `LobCreator/LobHandler` provides the following support for LOB input and output: + +* BLOB +* byte[] -- getBlobAsBytes and setBlobAsBytes +* InputStream -- getBlobAsBinaryStream and setBlobAsBinaryStream +* CLOB +* String -- getClobAsString and setClobAsString +* InputStream -- getClobAsAsciiStream and setClobAsAsciiStream +* Reader -- getClobAsCharacterStream and setClobAsCharacterStream + +The next example shows how to create and insert a BLOB. Later you will see how to read +it back from the database. + +This example uses a `JdbcTemplate` and an implementation of the +`AbstractLobCreatingPreparedStatementCallbac` `k`. It implements one method, +`setValues`. This method provides a `LobCreator` that you use to set the values for the +LOB columns in your SQL insert statement. + +For this example we assume that there is a variable, `lobHandle` `r`, that already is +set to an instance of a `DefaultLobHandler`. You typically set this value through +dependency injection. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + final File blobIn = new File("spring2004.jpg"); + final InputStream blobIs = new FileInputStream(blobIn); + final File clobIn = new File("large.txt"); + final InputStream clobIs = new FileInputStream(clobIn); + final InputStreamReader clobReader = new InputStreamReader(clobIs); + jdbcTemplate.execute( + "INSERT INTO lob_table (id, a_clob, a_blob) VALUES (?, ?, ?)", + new AbstractLobCreatingPreparedStatementCallback(lobHandler) { # <1> + protected void setValues(PreparedStatement ps, LobCreator lobCreator) throws SQLException { + ps.setLong(1, 1L); + lobCreator.setClobAsCharacterStream(ps, 2, clobReader, (int)clobIn.length()); # <2> + lobCreator.setBlobAsBinaryStream(ps, 3, blobIs, (int)blobIn.length()); # <3> + } + } + ); + blobIs.close(); + clobReader.close(); +---- + +<1> Pass in the lobHandler that in this example is a plain `DefaultLobHandler` +<2> Using the method `setClobAsCharacterStream`, pass in the contents of the CLOB. +<3> Using the method `setBlobAsBinaryStream`, pass in the contents of the BLOB. + +Now it's time to read the LOB data from the database. Again, you use a `JdbcTemplate` +with the same instance variable `l` `obHandler` and a reference to a `DefaultLobHandler`. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + List<Map<String, Object>> l = jdbcTemplate.query("select id, a_clob, a_blob from lob_table", + new RowMapper<Map<String, Object>>() { + public Map<String, Object> mapRow(ResultSet rs, int i) throws SQLException { + Map<String, Object> results = new HashMap<String, Object>(); + String clobText = lobHandler.getClobAsString(rs, "a_clob"); # <1> + results.put("CLOB", clobText); byte[] blobBytes = lobHandler.getBlobAsBytes(rs, "a_blob"); # <2> + results.put("BLOB", blobBytes); return results; } }); +---- + +<1> Using the method `getClobAsString`, retrieve the contents of the CLOB. +<2> Using the method `getBlobAsBytes`, retrieve the contents of the BLOB. + + + +[[jdbc-in-clause]] +==== Passing in lists of values for IN clause +The SQL standard allows for selecting rows based on an expression that includes a +variable list of values. A typical example would be `select * from T_ACTOR where id in +(1, 2, 3)`. This variable list is not directly supported for prepared statements by the +JDBC standard; you cannot declare a variable number of placeholders. You need a number +of variations with the desired number of placeholders prepared, or you need to generate +the SQL string dynamically once you know how many placeholders are required. The named +parameter support provided in the `NamedParameterJdbcTemplate` and `JdbcTemplate` takes +the latter approach. Pass in the values as a `java.util.List` of primitive objects. This +list will be used to insert the required placeholders and pass in the values during the +statement execution. + +[NOTE] +==== +Be careful when passing in many values. The JDBC standard does not guarantee that you +can use more than 100 values for an `in` expression list. Various databases exceed this +number, but they usually have a hard limit for how many values are allowed. Oracle's +limit is 1000. +==== + +In addition to the primitive values in the value list, you can create a `java.util.List` +of object arrays. This list would support multiple expressions defined for the `in` +clause such as `select * from T_ACTOR where (id, last_name) in ((1, 'Johnson'), (2, +'Harrop'))`. This of course requires that your database supports this syntax. + + + +[[jdbc-complex-types]] +==== Handling complex types for stored procedure calls +When you call stored procedures you can sometimes use complex types specific to the +database. To accommodate these types, Spring provides a `SqlReturnType` for handling +them when they are returned from the stored procedure call and `SqlTypeValue` when they +are passed in as a parameter to the stored procedure. + +Here is an example of returning the value of an Oracle `STRUCT` object of the user +declared type `ITEM_TYPE`. The `SqlReturnType` interface has a single method named +`getTypeValue` that must be implemented. This interface is used as part of the +declaration of an `SqlOutParameter`. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + final TestItem = new TestItem(123L, "A test item", + new SimpleDateFormat("yyyy-M-d").parse("2010-12-31")); + + declareParameter(new SqlOutParameter("item", OracleTypes.STRUCT, "ITEM_TYPE", + new SqlReturnType() { + public Object getTypeValue(CallableStatement cs, int colIndx, int sqlType, String typeName) throws SQLException { + STRUCT struct = (STRUCT) cs.getObject(colIndx); + Object[] attr = struct.getAttributes(); + TestItem item = new TestItem(); + item.setId(((Number) attr[0]).longValue()); + item.setDescription((String) attr[1]); + item.setExpirationDate((java.util.Date) attr[2]); + return item; + } + })); +---- + +You use the `SqlTypeValue` to pass in the value of a Java object like `TestItem` into a +stored procedure. The `SqlTypeValue` interface has a single method named +`createTypeValue` that you must implement. The active connection is passed in, and you +can use it to create database-specific objects such as ++StructDescriptor++s, as shown in +the following example, or ++ArrayDescriptor++s. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + final TestItem = new TestItem(123L, "A test item", + new SimpleDateFormat("yyyy-M-d").parse("2010-12-31")); + + SqlTypeValue value = new AbstractSqlTypeValue() { + protected Object createTypeValue(Connection conn, int sqlType, String typeName) throws SQLException { + StructDescriptor itemDescriptor = new StructDescriptor(typeName, conn); + Struct item = new STRUCT(itemDescriptor, conn, + new Object[] { + testItem.getId(), + testItem.getDescription(), + new java.sql.Date(testItem.getExpirationDate().getTime()) + }); + return item; + } + }; +---- + +This `SqlTypeValue` can now be added to the Map containing the input parameters for the +execute call of the stored procedure. + +Another use for the `SqlTypeValue` is passing in an array of values to an Oracle stored +procedure. Oracle has its own internal `ARRAY` class that must be used in this case, and +you can use the `SqlTypeValue` to create an instance of the Oracle `ARRAY` and populate +it with values from the Java `ARRAY`. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + final Long[] ids = new Long[] {1L, 2L}; + + SqlTypeValue value = new AbstractSqlTypeValue() { + protected Object createTypeValue(Connection conn, int sqlType, String typeName) throws SQLException { + ArrayDescriptor arrayDescriptor = new ArrayDescriptor(typeName, conn); + ARRAY idArray = new ARRAY(arrayDescriptor, conn, ids); + return idArray; + } + }; +---- + + + + +[[jdbc-embedded-database-support]] +=== Embedded database support +The `org.springframework.jdbc.datasource.embedded` package provides support for embedded +Java database engines. Support for http://www.hsqldb.org[HSQL], +http://www.h2database.com[H2], and http://db.apache.org/derby[Derby] is provided +natively. You can also use an extensible API to plug in new embedded database types and +`DataSource` implementations. + + + +[[jdbc-why-embedded-database]] +==== Why use an embedded database? +An embedded database is useful during the development phase of a project because of its +lightweight nature. Benefits include ease of configuration, quick startup time, +testability, and the ability to rapidly evolve SQL during development. + + + +[[jdbc-embedded-database-xml]] +==== Creating an embedded database instance using Spring XML +If you want to expose an embedded database instance as a bean in a Spring +ApplicationContext, use the embedded-database tag in the spring-jdbc namespace: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + <jdbc:embedded-database id="dataSource"> + <jdbc:script location="classpath:schema.sql"/> + <jdbc:script location="classpath:test-data.sql"/> + </jdbc:embedded-database> +---- + +The preceding configuration creates an embedded HSQL database populated with SQL from +schema.sql and testdata.sql resources in the classpath. The database instance is made +available to the Spring container as a bean of type `javax.sql.DataSource`. This bean +can then be injected into data access objects as needed. + + + +[[jdbc-embedded-database-java]] +==== Creating an embedded database instance programmatically +The `EmbeddedDatabaseBuilder` class provides a fluent API for constructing an embedded +database programmatically. Use this when you need to create an embedded database +instance in a standalone environment, such as a data access object unit test: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder(); + EmbeddedDatabase db = builder.setType(H2).addScript("my-schema.sql").addScript("my-test-data.sql").build(); + // do stuff against the db (EmbeddedDatabase extends javax.sql.DataSource) + db.shutdown() +---- + + + +[[jdbc-embedded-database-extension]] +==== Extending the embedded database support +Spring JDBC embedded database support can be extended in two ways: + +* Implement `EmbeddedDatabaseConfigurer` to support a new embedded database type, such + as Apache Derby. +* Implement `DataSourceFactory` to support a new DataSource implementation, such as a + connection pool, to manage embedded database connections. + +You are encouraged to contribute back extensions to the Spring community at +https://jira.spring.io/browse/SPR[jira.spring.io]. + + + +[[jdbc-embedded-database-using-HSQL]] +==== Using HSQL +Spring supports HSQL 1.8.0 and above. HSQL is the default embedded database if no type +is specified explicitly. To specify HSQL explicitly, set the `type` attribute of the +`embedded-database` tag to `HSQL`. If you are using the builder API, call the +`setType(EmbeddedDatabaseType)` method with `EmbeddedDatabaseType.HSQL`. + + + +[[jdbc-embedded-database-using-H2]] +==== Using H2 +Spring supports the H2 database as well. To enable H2, set the `type` attribute of the +`embedded-database` tag to `H2`. If you are using the builder API, call the +`setType(EmbeddedDatabaseType)` method with `EmbeddedDatabaseType.H2`. + + + +[[jdbc-embedded-database-using-Derby]] +==== Using Derby +Spring also supports Apache Derby 10.5 and above. To enable Derby, set the `type` +attribute of the `embedded-database` tag to `Derby`. If using the builder API, call the +`setType(EmbeddedDatabaseType)` method with `EmbeddedDatabaseType.Derby`. + + + +[[jdbc-embedded-database-dao-testing]] +==== Testing data access logic with an embedded database +Embedded databases provide a lightweight way to test data access code. The following is +a data access unit test template that uses an embedded database: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class DataAccessUnitTestTemplate { + + private EmbeddedDatabase db; + + @Before + public void setUp() { + // creates an HSQL in-memory database populated from default scripts + // classpath:schema.sql and classpath:data.sql + db = new EmbeddedDatabaseBuilder().addDefaultScripts().build(); + } + + @Test + public void testDataAccess() { + JdbcTemplate template = new JdbcTemplate(db); + template.query(...); + } + + @After + public void tearDown() { + db.shutdown(); + } + + } +---- + + + + +[[jdbc-intializing-datasource]] +=== Initializing a DataSource +The `org.springframework.jdbc.datasource.init` package provides support for initializing +an existing `DataSource`. The embedded database support provides one option for creating +and initializing a `DataSource` for an application, but sometimes you need to initialize +an instance running on a server somewhere. + + + +[[jdbc-initializing-datasource-xml]] +==== Initializing a database instance using Spring XML +If you want to initialize a database and you can provide a reference to a DataSource +bean, use the `initialize-database` tag in the `spring-jdbc` namespace: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + <jdbc:initialize-database data-source="dataSource"> + <jdbc:script location="classpath:com/foo/sql/db-schema.sql"/> + <jdbc:script location="classpath:com/foo/sql/db-test-data.sql"/> + </jdbc:initialize-database> +---- + +The example above runs the two scripts specified against the database: the first script +is a schema creation, and the second is a test data set insert. The script locations can +also be patterns with wildcards in the usual ant style used for resources in Spring +(e.g. `classpath*:/com/foo/**/sql/*-data.sql`). If a pattern is used the scripts are +executed in lexical order of their URL or filename. + +The default behavior of the database initializer is to unconditionally execute the +scripts provided. This will not always be what you want, for instance if running against +an existing database that already has test data in it. The likelihood of accidentally +deleting data is reduced by the commonest pattern (as shown above) that creates the +tables first and then inserts the data - the first step will fail if the tables already +exist. + +However, to get more control over the creation and deletion of existing data, the XML +namespace provides a couple more options. The first is flag to switch the initialization +on and off. This can be set according to the environment (e.g. to pull a boolean value +from system properties or an environment bean), e.g. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + <jdbc:initialize-database data-source="dataSource" + **enabled="#{systemProperties.INITIALIZE_DATABASE}"**> + <jdbc:script location="..."/> + </jdbc:initialize-database> +---- + +The second option to control what happens with existing data is to be more tolerant of +failures. To this end you can control the ability of the initializer to ignore certain +errors in the SQL it executes from the scripts, e.g. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + <jdbc:initialize-database data-source="dataSource" **ignore-failures="DROPS"**> + <jdbc:script location="..."/> + </jdbc:initialize-database> +---- + +In this example we are saying we expect that sometimes the scripts will be run against +an empty database and there are some DROP statements in the scripts which would +therefore fail. So failed SQL `DROP` statements will be ignored, but other failures will +cause an exception. This is useful if your SQL dialect doesn't support `DROP ... IF +EXISTS` (or similar) but you want to unconditionally remove all test data before +re-creating it. In that case the first script is usually a set of drops, followed by a +set of `CREATE` statements. + +The `ignore-failures` option can be set to `NONE` (the default), `DROPS` (ignore failed +drops) or `ALL` (ignore all failures). + +If you need more control than you get from the XML namespace, you can simply use the +`DataSourceInitializer` directly, and define it as a component in your application. + + +[[jdbc-client-component-initialization]] +===== Initialization of Other Components that Depend on the Database +A large class of applications can just use the database initializer with no further +complications: those that do not use the database until after the Spring context has +started. If your application is __not__ one of those then you might need to read the +rest of this section. + +The database initializer depends on a data source instance and runs the scripts provided +in its initialization callback (c.f. `init-method` in an XML bean definition or +`InitializingBean`). If other beans depend on the same data source and also use the data +source in an initialization callback then there might be a problem because the data has +not yet been initialized. A common example of this is a cache that initializes eagerly +and loads up data from the database on application startup. + +To get round this issue you two options: change your cache initialization strategy to a +later phase, or ensure that the database initializer is initialized first. + +The first option might be easy if the application is in your control, and not otherwise. +Some suggestions for how to implement this are + +* Make the cache initialize lazily on first usage, which improves application startup time +* Have your cache or a separate component that initializes the cache implement + `Lifecycle` or `SmartLifecycle`. When the application context starts up a + `SmartLifecycle` can be automatically started if its `autoStartup` flag is set, and a + `Lifecycle` can be started manually by calling + `ConfigurableApplicationContext.start()` on the enclosing context. +* Use a Spring `ApplicationEvent` or similar custom observer mechanism to trigger the + cache initialization. `ContextRefreshedEvent` is always published by the context when + it is ready for use (after all beans have been initialized), so that is often a useful + hook (this is how the `SmartLifecycle` works by default). + +The second option can also be easy. Some suggestions on how to implement this are + +* Rely on Spring BeanFactory default behavior, which is that beans are initialized in + registration order. You can easily arrange that by adopting the common practice of a + set of <import/> elements that order your application modules, and ensure that the + database and database initialization are listed first +* Separate the datasource and the business components that use it and control their + startup order by putting them in separate ApplicationContext instances (e.g. parent + has the datasource and child has the business components). This structure is common in + Spring web applications, but can be more generally applied. diff --git a/src/asciidoc/jms.adoc b/src/asciidoc/jms.adoc new file mode 100644 index 000000000000..673e24b43b4f --- /dev/null +++ b/src/asciidoc/jms.adoc @@ -0,0 +1,1377 @@ +[[jms]] +== JMS (Java Message Service) + + + + +[[jms-introduction]] +=== Introduction +Spring provides a JMS integration framework that simplifies the use of the JMS API much +like Spring's integration does for the JDBC API. + +JMS can be roughly divided into two areas of functionality, namely the production and +consumption of messages. The `JmsTemplate` class is used for message production and +synchronous message reception. For asynchronous reception similar to Java EE's +message-driven bean style, Spring provides a number of message listener containers that +are used to create Message-Driven POJOs (MDPs). Spring also provides a declarative way +of creating message listeners. + +The package `org.springframework.jms.core` provides the core functionality for using +JMS. It contains JMS template classes that simplify the use of the JMS by handling the +creation and release of resources, much like the `JdbcTemplate` does for JDBC. The +design principle common to Spring template classes is to provide helper methods to +perform common operations and for more sophisticated usage, delegate the essence of the +processing task to user implemented callback interfaces. The JMS template follows the +same design. The classes offer various convenience methods for the sending of messages, +consuming a message synchronously, and exposing the JMS session and message producer to +the user. + +The package `org.springframework.jms.support` provides `JMSException` translation +functionality. The translation converts the checked `JMSException` hierarchy to a +mirrored hierarchy of unchecked exceptions. If there are any provider specific +subclasses of the checked `javax.jms.JMSException`, this exception is wrapped in the +unchecked `UncategorizedJmsException`. + +The package `org.springframework.jms.support.converter` provides a `MessageConverter` +abstraction to convert between Java objects and JMS messages. + +The package `org.springframework.jms.support.destination` provides various strategies +for managing JMS destinations, such as providing a service locator for destinations +stored in JNDI. + +The package `org.springframework.jms.annotation` provides the necessary infrastructure +to support annotation-driven listener endpoints using `@JmsListener`. + +The package `org.springframework.jms.config` provides the parser implementation for the +`jms` namespace as well the java config support to configure listener containers and +create listener endpoints. + +Finally, the package `org.springframework.jms.connection` provides an implementation of +the `ConnectionFactory` suitable for use in standalone applications. It also contains an +implementation of Spring's `PlatformTransactionManager` for JMS (the cunningly named +`JmsTransactionManager`). This allows for seamless integration of JMS as a transactional +resource into Spring's transaction management mechanisms. + + + + +[[jms-using]] +=== Using Spring JMS + + + +[[jms-jmstemplate]] +==== JmsTemplate + +The `JmsTemplate` class is the central class in the JMS core package. It simplifies the +use of JMS since it handles the creation and release of resources when sending or +synchronously receiving messages. + +Code that uses the `JmsTemplate` only needs to implement callback interfaces giving them +a clearly defined high level contract. The `MessageCreator` callback interface creates a +message given a `Session` provided by the calling code in `JmsTemplate`. In order to +allow for more complex usage of the JMS API, the callback `SessionCallback` provides the +user with the JMS session and the callback `ProducerCallback` exposes a `Session` and +`MessageProducer` pair. + +The JMS API exposes two types of send methods, one that takes delivery mode, priority, +and time-to-live as Quality of Service (QOS) parameters and one that takes no QOS +parameters which uses default values. Since there are many send methods in +`JmsTemplate`, the setting of the QOS parameters have been exposed as bean properties to +avoid duplication in the number of send methods. Similarly, the timeout value for +synchronous receive calls is set using the property `setReceiveTimeout`. + +Some JMS providers allow the setting of default QOS values administratively through the +configuration of the `ConnectionFactory`. This has the effect that a call to +`MessageProducer`'s send method `send(Destination destination, Message message)` will +use different QOS default values than those specified in the JMS specification. In order +to provide consistent management of QOS values, the `JmsTemplate` must therefore be +specifically enabled to use its own QOS values by setting the boolean property +`isExplicitQosEnabled` to `true`. + +For convenience, `JmsTemplate` also exposes a basic request-reply operation that allows +to send a message and wait for a reply on a temporary queue that is created as part of +the operation. + +[NOTE] +==== +Instances of the `JmsTemplate` class are __thread-safe once configured__. This is +important because it means that you can configure a single instance of a `JmsTemplate` +and then safely inject this __shared__ reference into multiple collaborators. To be +clear, the `JmsTemplate` is stateful, in that it maintains a reference to a +`ConnectionFactory`, but this state is __not__ conversational state. +==== + +As of Spring Framework 4.1, `JmsMessagingTemplate` is built on top of `JmsTemplate` +and provides an integration with the messaging abstraction, i.e. +`org.springframework.messaging.Message`. This allows you to create the message to +send in generic manner. + + +[[jms-connections]] +==== Connections +The `JmsTemplate` requires a reference to a `ConnectionFactory`. The `ConnectionFactory` +is part of the JMS specification and serves as the entry point for working with JMS. It +is used by the client application as a factory to create connections with the JMS +provider and encapsulates various configuration parameters, many of which are vendor +specific such as SSL configuration options. + +When using JMS inside an EJB, the vendor provides implementations of the JMS interfaces +so that they can participate in declarative transaction management and perform pooling +of connections and sessions. In order to use this implementation, Java EE containers +typically require that you declare a JMS connection factory as a `resource-ref` inside +the EJB or servlet deployment descriptors. To ensure the use of these features with the +`JmsTemplate` inside an EJB, the client application should ensure that it references the +managed implementation of the `ConnectionFactory`. + + +[[jms-caching-resources]] +===== Caching Messaging Resources +The standard API involves creating many intermediate objects. To send a message the +following 'API' walk is performed + +[literal] +[subs="verbatim,quotes"] +---- +ConnectionFactory->Connection->Session->MessageProducer->send +---- + +Between the ConnectionFactory and the Send operation there are three intermediate +objects that are created and destroyed. To optimise the resource usage and increase +performance two implementations of `ConnectionFactory` are provided. + + +[[jms-connection-factory]] +===== SingleConnectionFactory +Spring provides an implementation of the `ConnectionFactory` interface, +`SingleConnectionFactory`, that will return the same `Connection` on all +`createConnection()` calls and ignore calls to `close()`. This is useful for testing and +standalone environments so that the same connection can be used for multiple +`JmsTemplate` calls that may span any number of transactions. `SingleConnectionFactory` +takes a reference to a standard `ConnectionFactory` that would typically come from JNDI. + + +[[jdbc-connection-factory-caching]] +===== CachingConnectionFactory +The `CachingConnectionFactory` extends the functionality of `SingleConnectionFactory` +and adds the caching of Sessions, MessageProducers, and MessageConsumers. The initial +cache size is set to 1, use the property `SessionCacheSize` to increase the number of +cached sessions. Note that the number of actual cached sessions will be more than that +number as sessions are cached based on their acknowledgment mode, so there can be up to +4 cached session instances when `SessionCacheSize` is set to one, one for each +`AcknowledgementMode`. MessageProducers and MessageConsumers are cached within their +owning session and also take into account the unique properties of the producers and +consumers when caching. MessageProducers are cached based on their destination. +MessageConsumers are cached based on a key composed of the destination, selector, +noLocal delivery flag, and the durable subscription name (if creating durable consumers). + + + +[[jms-destinations]] +==== Destination Management +Destinations, like ConnectionFactories, are JMS administered objects that can be stored +and retrieved in JNDI. When configuring a Spring application context you can use the +JNDI factory class `JndiObjectFactoryBean` / `<jee:jndi-lookup>` to perform dependency +injection on your object's references to JMS destinations. However, often this strategy +is cumbersome if there are a large number of destinations in the application or if there +are advanced destination management features unique to the JMS provider. Examples of +such advanced destination management would be the creation of dynamic destinations or +support for a hierarchical namespace of destinations. The `JmsTemplate` delegates the +resolution of a destination name to a JMS destination object to an implementation of the +interface `DestinationResolver`. `DynamicDestinationResolver` is the default +implementation used by `JmsTemplate` and accommodates resolving dynamic destinations. A +`JndiDestinationResolver` is also provided that acts as a service locator for +destinations contained in JNDI and optionally falls back to the behavior contained in +`DynamicDestinationResolver`. + +Quite often the destinations used in a JMS application are only known at runtime and +therefore cannot be administratively created when the application is deployed. This is +often because there is shared application logic between interacting system components +that create destinations at runtime according to a well-known naming convention. Even +though the creation of dynamic destinations is not part of the JMS specification, most +vendors have provided this functionality. Dynamic destinations are created with a name +defined by the user which differentiates them from temporary destinations and are often +not registered in JNDI. The API used to create dynamic destinations varies from provider +to provider since the properties associated with the destination are vendor specific. +However, a simple implementation choice that is sometimes made by vendors is to +disregard the warnings in the JMS specification and to use the `TopicSession` method +`createTopic(String topicName)` or the `QueueSession` method `createQueue(String +queueName)` to create a new destination with default destination properties. Depending +on the vendor implementation, `DynamicDestinationResolver` may then also create a +physical destination instead of only resolving one. + +The boolean property `pubSubDomain` is used to configure the `JmsTemplate` with +knowledge of what JMS domain is being used. By default the value of this property is +false, indicating that the point-to-point domain, Queues, will be used. This property +used by `JmsTemplate` determines the behavior of dynamic destination resolution via +implementations of the `DestinationResolver` interface. + +You can also configure the `JmsTemplate` with a default destination via the property +`defaultDestination`. The default destination will be used with send and receive +operations that do not refer to a specific destination. + + + +[[jms-mdp]] +==== Message Listener Containers +One of the most common uses of JMS messages in the EJB world is to drive message-driven +beans (MDBs). Spring offers a solution to create message-driven POJOs (MDPs) in a way +that does not tie a user to an EJB container. (See <<jms-asynchronousMessageReception>> +for detailed coverage of Spring's MDP support.) As from Spring Framework 4.1, endpoint +methods can be simply annotated using `@JmsListener` see <<jms-annotated>> for more +details. + +A message listener container is used to receive messages from a JMS message queue and +drive the `MessageListener` that is injected into it. The listener container is +responsible for all threading of message reception and dispatches into the listener for +processing. A message listener container is the intermediary between an MDP and a +messaging provider, and takes care of registering to receive messages, participating in +transactions, resource acquisition and release, exception conversion and suchlike. This +allows you as an application developer to write the (possibly complex) business logic +associated with receiving a message (and possibly responding to it), and delegates +boilerplate JMS infrastructure concerns to the framework. + +There are two standard JMS message listener containers packaged with Spring, each with +its specialised feature set. + + +[[jms-mdp-simple]] +===== SimpleMessageListenerContainer +This message listener container is the simpler of the two standard flavors. It creates a +fixed number of JMS sessions and consumers at startup, registers the listener using the +standard JMS `MessageConsumer.setMessageListener()` method, and leaves it up the JMS +provider to perform listener callbacks. This variant does not allow for dynamic adaption +to runtime demands or for participation in externally managed transactions. +Compatibility-wise, it stays very close to the spirit of the standalone JMS +specification - but is generally not compatible with Java EE's JMS restrictions. + + +[[jms-mdp-default]] +===== DefaultMessageListenerContainer +This message listener container is the one used in most cases. In contrast to +`SimpleMessageListenerContainer`, this container variant does allow for dynamic adaption +to runtime demands and is able to participate in externally managed transactions. Each +received message is registered with an XA transaction when configured with a +`JtaTransactionManager`; so processing may take advantage of XA transaction semantics. +This listener container strikes a good balance between low requirements on the JMS +provider, advanced functionality such as transaction participation, and compatibility +with Java EE environments. + +The cache level of the container can be customized. Note that when no caching is enabled, +a new connection and a new session is created for each message reception. Combining this +with a non durable subscription with high loads may lead to message lost. Make sure to +use a proper cache level in such case. + +This container also has recoverable capabilities when the broker goes down. By default, +a simple `BackOff` implementation retries every 5 seconds. It is possible to specify +a custom `BackOff` implementation for more fine-grained recovery options, see +`ExponentialBackOff` for an example. + + +[[jms-tx]] +==== Transaction management +Spring provides a `JmsTransactionManager` that manages transactions for a single JMS +`ConnectionFactory`. This allows JMS applications to leverage the managed transaction +features of Spring as described in <<transaction>>. The `JmsTransactionManager` performs +local resource transactions, binding a JMS Connection/Session pair from the specified +`ConnectionFactory` to the thread. `JmsTemplate` automatically detects such +transactional resources and operates on them accordingly. + +In a Java EE environment, the `ConnectionFactory` will pool Connections and Sessions, so +those resources are efficiently reused across transactions. In a standalone environment, +using Spring's `SingleConnectionFactory` will result in a shared JMS `Connection`, with +each transaction having its own independent `Session`. Alternatively, consider the use +of a provider-specific pooling adapter such as ActiveMQ's `PooledConnectionFactory` +class. + +`JmsTemplate` can also be used with the `JtaTransactionManager` and an XA-capable JMS +`ConnectionFactory` for performing distributed transactions. Note that this requires the +use of a JTA transaction manager as well as a properly XA-configured ConnectionFactory! +(Check your Java EE server's / JMS provider's documentation.) + +Reusing code across a managed and unmanaged transactional environment can be confusing +when using the JMS API to create a `Session` from a `Connection`. This is because the +JMS API has only one factory method to create a `Session` and it requires values for the +transaction and acknowledgement modes. In a managed environment, setting these values is +the responsibility of the environment's transactional infrastructure, so these values +are ignored by the vendor's wrapper to the JMS Connection. When using the `JmsTemplate` +in an unmanaged environment you can specify these values through the use of the +properties `sessionTransacted` and `sessionAcknowledgeMode`. When using a +`PlatformTransactionManager` with `JmsTemplate`, the template will always be given a +transactional JMS `Session`. + + + + +[[jms-sending]] +=== Sending a Message + +The `JmsTemplate` contains many convenience methods to send a message. There are send +methods that specify the destination using a `javax.jms.Destination` object and those +that specify the destination using a string for use in a JNDI lookup. The send method +that takes no destination argument uses the default destination. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + import javax.jms.ConnectionFactory; + import javax.jms.JMSException; + import javax.jms.Message; + import javax.jms.Queue; + import javax.jms.Session; + + import org.springframework.jms.core.MessageCreator; + import org.springframework.jms.core.JmsTemplate; + + public class JmsQueueSender { + + private JmsTemplate jmsTemplate; + private Queue queue; + + public void setConnectionFactory(ConnectionFactory cf) { + this.jmsTemplate = new JmsTemplate(cf); + } + + public void setQueue(Queue queue) { + this.queue = queue; + } + + public void simpleSend() { + this.jmsTemplate.send(this.queue, new MessageCreator() { + public Message createMessage(Session session) throws JMSException { + return session.createTextMessage("hello queue world"); + } + }); + } + } +---- + +This example uses the `MessageCreator` callback to create a text message from the +supplied `Session` object. The `JmsTemplate` is constructed by passing a reference to a +`ConnectionFactory`. As an alternative, a zero argument constructor and +`connectionFactory` is provided and can be used for constructing the instance in +JavaBean style (using a BeanFactory or plain Java code). Alternatively, consider +deriving from Spring's `JmsGatewaySupport` convenience base class, which provides +pre-built bean properties for JMS configuration. + +The method `send(String destinationName, MessageCreator creator)` lets you send a +message using the string name of the destination. If these names are registered in JNDI, +you should set the `destinationResolver` property of the template to an instance of +`JndiDestinationResolver`. + +If you created the `JmsTemplate` and specified a default destination, the +`send(MessageCreator c)` sends a message to that destination. + + + +[[jms-msg-conversion]] +==== Using Message Converters +In order to facilitate the sending of domain model objects, the `JmsTemplate` has +various send methods that take a Java object as an argument for a message's data +content. The overloaded methods `convertAndSend()` and `receiveAndConvert()` in +`JmsTemplate` delegate the conversion process to an instance of the `MessageConverter` +interface. This interface defines a simple contract to convert between Java objects and +JMS messages. The default implementation `SimpleMessageConverter` supports conversion +between `String` and `TextMessage`, `byte[]` and `BytesMesssage`, and `java.util.Map` +and `MapMessage`. By using the converter, you and your application code can focus on the +business object that is being sent or received via JMS and not be concerned with the +details of how it is represented as a JMS message. + +The sandbox currently includes a `MapMessageConverter` which uses reflection to convert +between a JavaBean and a `MapMessage`. Other popular implementation choices you might +implement yourself are Converters that use an existing XML marshalling package, such as +JAXB, Castor, XMLBeans, or XStream, to create a `TextMessage` representing the object. + +To accommodate the setting of a message's properties, headers, and body that can not be +generically encapsulated inside a converter class, the `MessagePostProcessor` interface +gives you access to the message after it has been converted, but before it is sent. The +example below demonstrates how to modify a message header and a property after a +`java.util.Map` is converted to a message. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public void sendWithConversion() { + Map map = new HashMap(); + map.put("Name", "Mark"); + map.put("Age", new Integer(47)); + jmsTemplate.convertAndSend("testQueue", map, new MessagePostProcessor() { + public Message postProcessMessage(Message message) throws JMSException { + message.setIntProperty("AccountID", 1234); + message.setJMSCorrelationID("123-00001"); + return message; + } + }); + } +---- + +This results in a message of the form: + +[literal] +[subs="verbatim,quotes"] +---- +MapMessage={ + Header={ + ... standard headers ... + CorrelationID={123-00001} + } + Properties={ + AccountID={Integer:1234} + } + Fields={ + Name={String:Mark} + Age={Integer:47} + } +} +---- + + + +[[jms-callbacks]] +==== SessionCallback and ProducerCallback + +While the send operations cover many common usage scenarios, there are cases when you +want to perform multiple operations on a JMS `Session` or `MessageProducer`. The +`SessionCallback` and `ProducerCallback` expose the JMS `Session` and `Session` / +`MessageProducer` pair respectively. The `execute()` methods on `JmsTemplate` execute +these callback methods. + + + + +[[jms-receiving]] +=== Receiving a message + + + +[[jms-receiving-sync]] +==== Synchronous Reception +While JMS is typically associated with asynchronous processing, it is possible to +consume messages synchronously. The overloaded `receive(..)` methods provide this +functionality. During a synchronous receive, the calling thread blocks until a message +becomes available. This can be a dangerous operation since the calling thread can +potentially be blocked indefinitely. The property `receiveTimeout` specifies how long +the receiver should wait before giving up waiting for a message. + + + +[[jms-asynchronousMessageReception]] +==== Asynchronous Reception - Message-Driven POJOs + +[NOTE] +==== +Spring also supports annotated-listener endpoints through the use of the `@JmsListener` +and provides an open infrastructure to register endpoints programmatically. This +is by far the most convenient way to setup an asynchronous receiver, see +<<jms-annotated-support>> for more details. +==== + +In a fashion similar to a Message-Driven Bean (MDB) in the EJB world, the Message-Driven +POJO (MDP) acts as a receiver for JMS messages. The one restriction (but see also below +for the discussion of the `MessageListenerAdapter` class) on an MDP is that it must +implement the `javax.jms.MessageListener` interface. Please also be aware that in the +case where your POJO will be receiving messages on multiple threads, it is important to +ensure that your implementation is thread-safe. + +Below is a simple implementation of an MDP: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + import javax.jms.JMSException; + import javax.jms.Message; + import javax.jms.MessageListener; + import javax.jms.TextMessage; + + public class ExampleListener implements MessageListener { + + public void onMessage(Message message) { + if (message instanceof TextMessage) { + try { + System.out.println(((TextMessage) message).getText()); + } + catch (JMSException ex) { + throw new RuntimeException(ex); + } + } + else { + throw new IllegalArgumentException("Message must be of type TextMessage"); + } + } + + } +---- + +Once you've implemented your `MessageListener`, it's time to create a message listener +container. + +Find below an example of how to define and configure one of the message listener +containers that ships with Spring (in this case the `DefaultMessageListenerContainer`). + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + <!-- this is the Message Driven POJO (MDP) --> + <bean id="messageListener" class="jmsexample.ExampleListener" /> + + <!-- and this is the message listener container --> + <bean id="jmsContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer"> + <property name="connectionFactory" ref="connectionFactory"/> + <property name="destination" ref="destination"/> + **<property name="messageListener" ref="messageListener" />** + </bean> +---- + +Please refer to the Spring javadocs of the various message listener containers for a full +description of the features supported by each implementation. + + + +[[jms-receiving-async-session-aware-message-listener]] +==== the SessionAwareMessageListener interface + +The `SessionAwareMessageListener` interface is a Spring-specific interface that provides +a similar contract to the JMS `MessageListener` interface, but also provides the message +handling method with access to the JMS `Session` from which the `Message` was received. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + package org.springframework.jms.listener; + + public interface SessionAwareMessageListener { + + void onMessage(Message message, Session session) throws JMSException; + + } +---- + +You can choose to have your MDPs implement this interface (in preference to the standard +JMS `MessageListener` interface) if you want your MDPs to be able to respond to any +received messages (using the `Session` supplied in the `onMessage(Message, Session)` +method). All of the message listener container implementations that ship with Spring +have support for MDPs that implement either the `MessageListener` or +`SessionAwareMessageListener` interface. Classes that implement the +`SessionAwareMessageListener` come with the caveat that they are then tied to Spring +through the interface. The choice of whether or not to use it is left entirely up to you +as an application developer or architect. + +Please note that the `'onMessage(..)'` method of the `SessionAwareMessageListener` +interface throws `JMSException`. In contrast to the standard JMS `MessageListener` +interface, when using the `SessionAwareMessageListener` interface, it is the +responsibility of the client code to handle any exceptions thrown. + + + +[[jms-receiving-async-message-listener-adapter]] +==== the MessageListenerAdapter + +The `MessageListenerAdapter` class is the final component in Spring's asynchronous +messaging support: in a nutshell, it allows you to expose almost __any__ class as a MDP +(there are of course some constraints). + +Consider the following interface definition. Notice that although the interface extends +neither the `MessageListener` nor `SessionAwareMessageListener` interfaces, it can still +be used as a MDP via the use of the `MessageListenerAdapter` class. Notice also how the +various message handling methods are strongly typed according to the __contents__ of the +various `Message` types that they can receive and handle. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public interface MessageDelegate { + + void handleMessage(String message); + + void handleMessage(Map message); + + void handleMessage(byte[] message); + + void handleMessage(Serializable message); + + } +---- + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class DefaultMessageDelegate implements MessageDelegate { + // implementation elided for clarity... + } +---- + +In particular, note how the above implementation of the `MessageDelegate` interface (the +above `DefaultMessageDelegate` class) has __no__ JMS dependencies at all. It truly is a +POJO that we will make into an MDP via the following configuration. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + <!-- this is the Message Driven POJO (MDP) --> + **<bean id="messageListener" class="org.springframework.jms.listener.adapter.MessageListenerAdapter"> + <constructor-arg> + <bean class="jmsexample.DefaultMessageDelegate"/> + </constructor-arg> + </bean>** + + <!-- and this is the message listener container... --> + <bean id="jmsContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer"> + <property name="connectionFactory" ref="connectionFactory"/> + <property name="destination" ref="destination"/> + **<property name="messageListener" ref="messageListener" />** + </bean> +---- + +Below is an example of another MDP that can only handle the receiving of JMS +`TextMessage` messages. Notice how the message handling method is actually called +`'receive'` (the name of the message handling method in a `MessageListenerAdapter` +defaults to `'handleMessage'`), but it is configurable (as you will see below). Notice +also how the `'receive(..)'` method is strongly typed to receive and respond only to JMS +`TextMessage` messages. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public interface TextMessageDelegate { + + void receive(TextMessage message); + + } +---- + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class DefaultTextMessageDelegate implements TextMessageDelegate { + // implementation elided for clarity... + } +---- + +The configuration of the attendant `MessageListenerAdapter` would look like this: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + <bean id="messageListener" class="org.springframework.jms.listener.adapter.MessageListenerAdapter"> + <constructor-arg> + <bean class="jmsexample.DefaultTextMessageDelegate"/> + </constructor-arg> + <property name="defaultListenerMethod" value="receive"/> + <!-- we don't want automatic message context extraction --> + <property name="messageConverter"> + <null/> + </property> + </bean> +---- + +Please note that if the above `'messageListener'` receives a JMS `Message` of a type +other than `TextMessage`, an `IllegalStateException` will be thrown (and subsequently +swallowed). Another of the capabilities of the `MessageListenerAdapter` class is the +ability to automatically send back a response `Message` if a handler method returns a +non-void value. Consider the interface and class: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public interface ResponsiveTextMessageDelegate { + + // notice the return type... + String receive(TextMessage message); + + } +---- + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class DefaultResponsiveTextMessageDelegate implements ResponsiveTextMessageDelegate { + // implementation elided for clarity... + } +---- + +If the above `DefaultResponsiveTextMessageDelegate` is used in conjunction with a +`MessageListenerAdapter` then any non-null value that is returned from the execution of +the `'receive(..)'` method will (in the default configuration) be converted into a +`TextMessage`. The resulting `TextMessage` will then be sent to the `Destination` (if +one exists) defined in the JMS Reply-To property of the original `Message`, or the +default `Destination` set on the `MessageListenerAdapter` (if one has been configured); +if no `Destination` is found then an `InvalidDestinationException` will be thrown (and +please note that this exception __will not__ be swallowed and __will__ propagate up the +call stack). + + + +[[jms-tx-participation]] +==== Processing messages within transactions +Invoking a message listener within a transaction only requires reconfiguration of the +listener container. + +Local resource transactions can simply be activated through the `sessionTransacted` flag +on the listener container definition. Each message listener invocation will then operate +within an active JMS transaction, with message reception rolled back in case of listener +execution failure. Sending a response message (via `SessionAwareMessageListener`) will +be part of the same local transaction, but any other resource operations (such as +database access) will operate independently. This usually requires duplicate message +detection in the listener implementation, covering the case where database processing +has committed but message processing failed to commit. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + <bean id="jmsContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer"> + <property name="connectionFactory" ref="connectionFactory"/> + <property name="destination" ref="destination"/> + <property name="messageListener" ref="messageListener"/> + **<property name="sessionTransacted" value="true"/>** + </bean> +---- + +For participating in an externally managed transaction, you will need to configure a +transaction manager and use a listener container which supports externally managed +transactions: typically `DefaultMessageListenerContainer`. + +To configure a message listener container for XA transaction participation, you'll want +to configure a `JtaTransactionManager` (which, by default, delegates to the Java EE +server's transaction subsystem). Note that the underlying JMS ConnectionFactory needs to +be XA-capable and properly registered with your JTA transaction coordinator! (Check your +Java EE server's configuration of JNDI resources.) This allows message reception as well +as e.g. database access to be part of the same transaction (with unified commit +semantics, at the expense of XA transaction log overhead). + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + <bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager"/> +---- + +Then you just need to add it to our earlier container configuration. The container will +take care of the rest. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + <bean id="jmsContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer"> + <property name="connectionFactory" ref="connectionFactory"/> + <property name="destination" ref="destination"/> + <property name="messageListener" ref="messageListener"/> + **<property name="transactionManager" ref="transactionManager"/>** + </bean> +---- + + + + +[[jms-jca-message-endpoint-manager]] +=== Support for JCA Message Endpoints +Beginning with version 2.5, Spring also provides support for a JCA-based +`MessageListener` container. The `JmsMessageEndpointManager` will attempt to +automatically determine the `ActivationSpec` class name from the provider's +`ResourceAdapter` class name. Therefore, it is typically possible to just provide +Spring's generic `JmsActivationSpecConfig` as shown in the following example. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + <bean class="org.springframework.jms.listener.endpoint.JmsMessageEndpointManager"> + <property name="resourceAdapter" ref="resourceAdapter"/> + <property name="activationSpecConfig"> + <bean class="org.springframework.jms.listener.endpoint.JmsActivationSpecConfig"> + <property name="destinationName" value="myQueue"/> + </bean> + </property> + <property name="messageListener" ref="myMessageListener"/> + </bean> +---- + +Alternatively, you may set up a `JmsMessageEndpointManager` with a given +`ActivationSpec` object. The `ActivationSpec` object may also come from a JNDI lookup +(using `<jee:jndi-lookup>`). + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + <bean class="org.springframework.jms.listener.endpoint.JmsMessageEndpointManager"> + <property name="resourceAdapter" ref="resourceAdapter"/> + <property name="activationSpec"> + <bean class="org.apache.activemq.ra.ActiveMQActivationSpec"> + <property name="destination" value="myQueue"/> + <property name="destinationType" value="javax.jms.Queue"/> + </bean> + </property> + <property name="messageListener" ref="myMessageListener"/> + </bean> +---- + +Using Spring's `ResourceAdapterFactoryBean`, the target `ResourceAdapter` may be +configured locally as depicted in the following example. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + <bean id="resourceAdapter" class="org.springframework.jca.support.ResourceAdapterFactoryBean"> + <property name="resourceAdapter"> + <bean class="org.apache.activemq.ra.ActiveMQResourceAdapter"> + <property name="serverUrl" value="tcp://localhost:61616"/> + </bean> + </property> + <property name="workManager"> + <bean class="org.springframework.jca.work.SimpleTaskWorkManager"/> + </property> + </bean> +---- + +The specified `WorkManager` may also point to an environment-specific thread pool - +typically through `SimpleTaskWorkManager's` "asyncTaskExecutor" property. Consider +defining a shared thread pool for all your `ResourceAdapter` instances if you happen to +use multiple adapters. + +In some environments (e.g. WebLogic 9 or above), the entire `ResourceAdapter` object may +be obtained from JNDI instead (using `<jee:jndi-lookup>`). The Spring-based message +listeners can then interact with the server-hosted `ResourceAdapter`, also using the +server's built-in `WorkManager`. + +Please consult the JavaDoc for `JmsMessageEndpointManager`, `JmsActivationSpecConfig`, +and `ResourceAdapterFactoryBean` for more details. + +Spring also provides a generic JCA message endpoint manager which is not tied to JMS: +`org.springframework.jca.endpoint.GenericMessageEndpointManager`. This component allows +for using any message listener type (e.g. a CCI MessageListener) and any +provider-specific ActivationSpec object. Check out your JCA provider's documentation to +find out about the actual capabilities of your connector, and consult +`GenericMessageEndpointManager`'s JavaDoc for the Spring-specific configuration details. + +[NOTE] +==== +JCA-based message endpoint management is very analogous to EJB 2.1 Message-Driven Beans; +it uses the same underlying resource provider contract. Like with EJB 2.1 MDBs, any +message listener interface supported by your JCA provider can be used in the Spring +context as well. Spring nevertheless provides explicit 'convenience' support for JMS, +simply because JMS is the most common endpoint API used with the JCA endpoint management +contract. +==== + + + +[[jms-annotated]] +=== Annotation-driven listener endpoints +The easiest way to receive a message asynchronously is to use the annotated listener +endpoint infrastructure. In a nutshell, it allows you to expose a method of a managed +bean as a JMS listener endpoint. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Component + public class MyService { + + @JmsListener(destination = "myDestination") + public void processOrder(String data) { ... } + } +---- + +The idea of the example above is that whenever a message is available on the +`javax.jms.Destination` "myDestination", the `processOrder` method is invoked +accordingly (in this case, with the content of the JMS message similarly to +what the <<jms-receiving-async-message-listener-adapter, `MessageListenerAdapter`>> +provides). + +The annotated endpoint infrastructure creates a message listener container +behind the scenes for each annotated method, using a `JmsListenerContainerFactory`. + +[[jms-annotated-support]] +==== Enable listener endpoint annotations + +To enable support for `@JmsListener` annotations add `@EnableJms` to one of +your `@Configuration` classes. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Configuration + @EnableJms + public class AppConfig { + + @Bean + public DefaultJmsListenerContainerFactory jmsListenerContainerFactory() { + DefaultJmsListenerContainerFactory factory = + new DefaultJmsListenerContainerFactory(); + factory.setConnectionFactory(connectionFactory()); + factory.setDestinationResolver(destinationResolver()); + factory.setConcurrency("3-10"); + return factory; + } + } +---- + +By default, the infrastructure looks for a bean named `jmsListenerContainerFactory` +as the source for the factory to use to create message listener containers. In this +case, and ignoring the JMS infrastructure setup, the `processOrder` method can be +invoked with a core poll size of 3 threads and a maximum pool size of 10 threads. + +It is possible to customize the listener container factory to use per annotation or +an explicit default can be configured by implementing the `JmsListenerConfigurer` +interface. The default is only required if at least one endpoint is registered +without a specific container factory. See the javadoc for full details and examples. + +If you prefer <<jms-namespace,XML configuration>> use the `<jms:annotation-driven>` +element. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + <jms:annotation-driven/> + + <bean id="jmsListenerContainerFactory" + class="org.springframework.jms.config.DefaultJmsListenerContainerFactory"> + <property name="connectionFactory" ref="connectionFactory"/> + <property name="destinationResolver" ref="destinationResolver"/> + <property name="concurrency" value="3-10"/> + </bean> +---- + +[[jms-annotated-programmatic-registration]] +==== Programmatic endpoints registration + +`JmsListenerEndpoint` provides a model of an JMS endpoint and is responsible for configuring +the container for that model. The infrastructure allows you to configure endpoints +programmatically in addition to the ones that are detected by the `JmsListener` annotation. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Configuration + @EnableJms + public class AppConfig implements JmsListenerConfigurer { + + @Override + public void configureJmsListeners(JmsListenerEndpointRegistrar registrar) { + SimpleJmsListenerEndpoint endpoint = new SimpleJmsListenerEndpoint(); + endpoint.setDestination("anotherQueue"); + endpoint.setMessageListener(message -> { + // processing + }); + registrar.registerEndpoint(endpoint); + } + } +---- + +In the example above, we used `SimpleJmsListenerEndpoint` which provides the actual +`MessageListener` to invoke but you could just as well build your own endpoint variant +describing a custom invocation mechanism. + +It should be noted that you could just as well skip the use of `@JmsListener` altogether +and only register your endpoints programmatically through `JmsListenerConfigurer`. + +[[jms-annotated-method-signature]] +==== Annotated endpoint method signature + +So far, we have been injecting a simple `String` in our endpoint but it can actually +have a very flexible method signature. Let's rewrite it to inject the `Order` with +a custom header: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Component + public class MyService { + + @JmsListener(destination = "myDestination") + public void processOrder(Order order, @Header("order_type") String orderType) { + ... + } + } +---- + +These are the main elements you can inject in JMS listener endpoints: + +* The raw `javax.jms.Message` or any of its subclasses (provided of course that it + matches the incoming message type). +* The `javax.jms.Session` for optional access to the native JMS API e.g. for sending + a custom reply. +* The `org.springframework.messaging.Message` representing the incoming JMS message. + Note that this message holds both the custom and the standard headers (as defined + by `JmsHeaders`). +* `@Header`-annotated method arguments to extract a specific header value, including + standard JMS headers. +* `@Headers`-annotated argument that must also be assignable to `java.util.Map` for + getting access to all headers. +* A non-annotated element that is not one of the supported types (i.e. `Message` and + `Session`) is considered to be the payload. You can make that explicit by annotating + the parameter with `@Payload`. You can also turn on validation by adding an extra + `@Validated`. + +The ability to inject Spring's `Message` abstraction is particularly useful to benefit +from all the information stored in the transport-specific message without relying on +transport-specific API. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @JmsListener(destination = "myDestination") + public void processOrder(Message<Order> order) { ... } +---- + +Handling of method arguments is provided by `DefaultJmsHandlerMethodFactory` which can be +further customized to support additional method arguments. The conversion and validation +support can be customized there as well. + +For instance, if we want to make sure our `Order` is valid before processing it, we can +annotate the payload with `@Valid` and configure the necessary validator as follows: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Configuration + @EnableJms + public class AppConfig implements JmsListenerConfigurer { + + @Override + public void configureJmsListeners(JmsListenerEndpointRegistrar registrar) { + registrar.setJmsHandlerMethodFactory(myJmsHandlerMethodFactory()); + } + + @Bean + public DefaultJmsHandlerMethodFactory myJmsHandlerMethodFactory() { + DefaultJmsHandlerMethodFactory factory = new DefaultJmsHandlerMethodFactory(); + factory.setValidator(myValidator()); + return factory; + } + } +---- + +[[jms-annotated-reply]] +==== Reply management + +The existing support in <<jms-receiving-async-message-listener-adapter,MessageListenerAdapter>> +already allows your method to have a non-`void` return type. When that's the case, the result of +the invocation is encapsulated in a `javax.jms.Message` sent either in the destination specified +in the `JMSReplyTo` header of the original message or in the default destination configured on +the listener. That default destination can now be set using the `@SendTo` annotation of the +messaging abstraction. + +Assuming our `processOrder` method should now return an `OrderStatus`, it is possible to write it +as follow to automatically send a reply: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @JmsListener(destination = "myDestination") + @SendTo("status") + public OrderStatus processOrder(Order order) { + // order processing + return status; + } +---- + +If you need to set additional headers in a transport-independent manner, you could return a +`Message` instead, something like: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @JmsListener(destination = "myDestination") + @SendTo("status") + public Message<OrderStatus> processOrder(Order order) { + // order processing + return MessageBuilder + .withPayload(status) + .setHeader("code", 1234) + .build(); + } +---- + +[[jms-namespace]] +=== JMS Namespace Support +Spring provides an XML namespace for simplifying JMS configuration. To use the JMS +namespace elements you will need to reference the JMS schema: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + <?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:jms="http://www.springframework.org/schema/jms"** + xsi:schemaLocation=" + http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd + **http://www.springframework.org/schema/jms http://www.springframework.org/schema/jms/spring-jms.xsd**"> + + <!-- bean definitions here --> + + </beans> +---- + +The namespace consists of three top-level elements: `<annotation-driven/>`, `<listener-container/>` +and `<jca-listener-container/>`. `<annotation-driven` enables the use of <<jms-annotated, +annotation-driven listener endpoints>>. `<listener-container/>` and `<jca-listener-container/>` +defines shared listener container configuration and may contain `<listener/>` child elements. Here +is an example of a basic configuration for two listeners. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + <jms:listener-container> + + <jms:listener destination="queue.orders" ref="orderService" method="placeOrder"/> + + <jms:listener destination="queue.confirmations" ref="confirmationLogger" method="log"/> + + </jms:listener-container> +---- + +The example above is equivalent to creating two distinct listener container bean +definitions and two distinct `MessageListenerAdapter` bean definitions as demonstrated +in <<jms-receiving-async-message-listener-adapter>>. In addition to the attributes shown +above, the `listener` element may contain several optional ones. The following table +describes all available attributes: + +[[jms-namespace-listener-tbl]] +.Attributes of the JMS <listener> element +[cols="1,6"] +|=== +| Attribute| Description + +| id +| A bean name for the hosting listener container. If not specified, a bean name will be + automatically generated. + +| destination __(required)__ +| The destination name for this listener, resolved through the `DestinationResolver` + strategy. + +| ref __(required)__ +| The bean name of the handler object. + +| method +| The name of the handler method to invoke. If the `ref` points to a `MessageListener` + or Spring `SessionAwareMessageListener`, this attribute may be omitted. + +| response-destination +| The name of the default response destination to send response messages to. This will + be applied in case of a request message that does not carry a "JMSReplyTo" field. The + type of this destination will be determined by the listener-container's + "destination-type" attribute. Note: This only applies to a listener method with a + return value, for which each result object will be converted into a response message. + +| subscription +| The name of the durable subscription, if any. + +| selector +| An optional message selector for this listener. + +| concurrency +| The number of concurrent sessions/consumers to start for this listener. Can either be + a simple number indicating the maximum number (e.g. "5") or a range indicating the lower + as well as the upper limit (e.g. "3-5"). Note that a specified minimum is just a hint + and might be ignored at runtime. Default is the value provided by the container +|=== + +The `<listener-container/>` element also accepts several optional attributes. This +allows for customization of the various strategies (for example, `taskExecutor` and +`destinationResolver`) as well as basic JMS settings and resource references. Using +these attributes, it is possible to define highly-customized listener containers while +still benefiting from the convenience of the namespace. + +Such settings can be automatically exposed as a `JmsListenerContainerFactory` by +specifying the id of the bean to expose through the `factory-id` attribute. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + <jms:listener-container connection-factory="myConnectionFactory" + task-executor="myTaskExecutor" + destination-resolver="myDestinationResolver" + transaction-manager="myTransactionManager" + concurrency="10"> + + <jms:listener destination="queue.orders" ref="orderService" method="placeOrder"/> + + <jms:listener destination="queue.confirmations" ref="confirmationLogger" method="log"/> + + </jms:listener-container> +---- + +The following table describes all available attributes. Consult the class-level javadocs +of the `AbstractMessageListenerContainer` and its concrete subclasses for more details +on the individual properties. The javadocs also provide a discussion of transaction +choices and message redelivery scenarios. + +[[jms-namespace-listener-container-tbl]] +.Attributes of the JMS <listener-container> element +[cols="1,6"] +|=== +| Attribute| Description + +| container-type +| The type of this listener container. Available options are: `default`, `simple`, + `default102`, or `simple102` (the default value is `'default'`). + +| container-class +| A custom listener container implementation class as fully qualified class name. + Default is Spring's standard `DefaultMessageListenerContainer` or + `SimpleMessageListenerContainer`, according to the "container-type" attribute. + +| factory-id +| Exposes the settings defined by this element as a `JmsListenerContainerFactory` + with the specified id so that they can be reused with other endpoints. + +| connection-factory +| A reference to the JMS `ConnectionFactory` bean (the default bean name is + `'connectionFactory'`). + +| task-executor +| A reference to the Spring `TaskExecutor` for the JMS listener invokers. + +| destination-resolver +| A reference to the `DestinationResolver` strategy for resolving JMS `Destinations`. + +| message-converter +| A reference to the `MessageConverter` strategy for converting JMS Messages to listener + method arguments. Default is a `SimpleMessageConverter`. + +| error-handler +| A reference to an `ErrorHandler` strategy for handling any uncaught Exceptions that + may occur during the execution of the `MessageListener`. + +| destination-type +| The JMS destination type for this listener: `queue`, `topic`, `durableTopic`, `sharedTopic` + or `sharedDurableTopic`. This enables potentially the `pubSubDomain`, `subscriptionDurable` + and `subscriptionShared` properties of the container. The default is `queue` (i.e. disabling + those 3 properties). + +| client-id +| The JMS client id for this listener container. Needs to be specified when using + durable subscriptions. + +| cache +| The cache level for JMS resources: `none`, `connection`, `session`, `consumer` or + `auto`. By default ( `auto`), the cache level will effectively be "consumer", unless + an external transaction manager has been specified - in which case the effective + default will be `none` (assuming Java EE-style transaction management where the given + ConnectionFactory is an XA-aware pool). + +| acknowledge +| The native JMS acknowledge mode: `auto`, `client`, `dups-ok` or `transacted`. A value + of `transacted` activates a locally transacted `Session`. As an alternative, specify + the `transaction-manager` attribute described below. Default is `auto`. + +| transaction-manager +| A reference to an external `PlatformTransactionManager` (typically an XA-based + transaction coordinator, e.g. Spring's `JtaTransactionManager`). If not specified, + native acknowledging will be used (see "acknowledge" attribute). + +| concurrency +| The number of concurrent sessions/consumers to start for each listener. Can either be + a simple number indicating the maximum number (e.g. "5") or a range indicating the + lower as well as the upper limit (e.g. "3-5"). Note that a specified minimum is just a + hint and might be ignored at runtime. Default is 1; keep concurrency limited to 1 in + case of a topic listener or if queue ordering is important; consider raising it for + general queues. + +| prefetch +| The maximum number of messages to load into a single session. Note that raising this + number might lead to starvation of concurrent consumers! + +| receive-timeout +| The timeout to use for receive calls (in milliseconds). The default is `1000` ms (1 + sec); `-1` indicates no timeout at all. + +| back-off +| Specify the `BackOff` instance to use to compute the interval between recovery + attempts. If the `BackOffExecution` implementation returns `BackOffExecution#STOP`, + the listener container will not further attempt to recover. The `recovery-interval` + value is ignored when this property is set. The default is a `FixedBackOff` with + an interval of 5000 ms, that is 5 seconds. + +| recovery-interval +| Specify the interval between recovery attempts, in milliseconds. Convenience + way to create a `FixedBackOff` with the specified interval. For more recovery + options, consider specifying a BackOff instance instead. The default is 5000 ms, + that is 5 seconds. + +| phase +| The lifecycle phase within which this container should start and stop. The lower the + value the earlier this container will start and the later it will stop. The default is + `Integer.MAX_VALUE` meaning the container will start as late as possible and stop as + soon as possible. +|=== + +Configuring a JCA-based listener container with the "jms" schema support is very similar. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + <jms:jca-listener-container resource-adapter="myResourceAdapter" + destination-resolver="myDestinationResolver" + transaction-manager="myTransactionManager" + concurrency="10"> + + <jms:listener destination="queue.orders" ref="myMessageListener"/> + + </jms:jca-listener-container> +---- + +The available configuration options for the JCA variant are described in the following +table: + +[[jms-namespace-jca-listener-container-tbl]] +.Attributes of the JMS <jca-listener-container/> element +[cols="1,6"] +|=== +| Attribute| Description + +| factory-id +| Exposes the settings defined by this element as a `JmsListenerContainerFactory` + with the specified id so that they can be reused with other endpoints. + +| resource-adapter +| A reference to the JCA `ResourceAdapter` bean (the default bean name is + `'resourceAdapter'`). + +| activation-spec-factory +| A reference to the `JmsActivationSpecFactory`. The default is to autodetect the JMS + provider and its `ActivationSpec` class (see `DefaultJmsActivationSpecFactory`) + +| destination-resolver +| A reference to the `DestinationResolver` strategy for resolving JMS `Destinations`. + +| message-converter +| A reference to the `MessageConverter` strategy for converting JMS Messages to listener + method arguments. Default is a `SimpleMessageConverter`. + +| destination-type +| The JMS destination type for this listener: `queue`, `topic`, `durableTopic`, `sharedTopic` + or `sharedDurableTopic`. This enables potentially the `pubSubDomain`, `subscriptionDurable` + and `subscriptionShared` properties of the container. The default is `queue` (i.e. disabling + those 3 properties). + +| client-id +| The JMS client id for this listener container. Needs to be specified when using + durable subscriptions. + +| acknowledge +| The native JMS acknowledge mode: `auto`, `client`, `dups-ok` or `transacted`. A value + of `transacted` activates a locally transacted `Session`. As an alternative, specify + the `transaction-manager` attribute described below. Default is `auto`. + +| transaction-manager +| A reference to a Spring `JtaTransactionManager` or a + `javax.transaction.TransactionManager` for kicking off an XA transaction for each + incoming message. If not specified, native acknowledging will be used (see the + "acknowledge" attribute). + +| concurrency +| The number of concurrent sessions/consumers to start for each listener. Can either be + a simple number indicating the maximum number (e.g. "5") or a range indicating the + lower as well as the upper limit (e.g. "3-5"). Note that a specified minimum is just a + hint and will typically be ignored at runtime when using a JCA listener container. + Default is 1. + +| prefetch +| The maximum number of messages to load into a single session. Note that raising this + number might lead to starvation of concurrent consumers! +|=== + + + + diff --git a/src/asciidoc/jmx.adoc b/src/asciidoc/jmx.adoc new file mode 100644 index 000000000000..eae906586513 --- /dev/null +++ b/src/asciidoc/jmx.adoc @@ -0,0 +1,1430 @@ +[[jmx]] +== JMX + + + + +[[jmx-introduction]] +=== Introduction +The JMX support in Spring provides you with the features to easily and transparently +integrate your Spring application into a JMX infrastructure. + +.JMX? +**** +This chapter is not an introduction to JMX... it doesn't try to explain the motivations +of why one might want to use JMX (or indeed what the letters JMX actually stand for). If +you are new to JMX, check out <<jmx-resources>> at the end of this chapter. +**** + +Specifically, Spring's JMX support provides four core features: + +* The automatic registration of __any__ Spring bean as a JMX MBean +* A flexible mechanism for controlling the management interface of your beans +* The declarative exposure of MBeans over remote, JSR-160 connectors +* The simple proxying of both local and remote MBean resources + +These features are designed to work without coupling your application components to +either Spring or JMX interfaces and classes. Indeed, for the most part your application +classes need not be aware of either Spring or JMX in order to take advantage of the +Spring JMX features. + + + + +[[jmx-exporting]] +=== Exporting your beans to JMX +The core class in Spring's JMX framework is the `MBeanExporter`. This class is +responsible for taking your Spring beans and registering them with a JMX `MBeanServer`. +For example, consider the following class: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + package org.springframework.jmx; + + public class JmxTestBean implements IJmxTestBean { + + private String name; + private int age; + private boolean isSuperman; + + public int getAge() { + return age; + } + + public void setAge(int age) { + this.age = age; + } + + public void setName(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + public int add(int x, int y) { + return x + y; + } + + public void dontExposeMe() { + throw new RuntimeException(); + } + } +---- + +To expose the properties and methods of this bean as attributes and operations of an +MBean you simply configure an instance of the `MBeanExporter` class in your +configuration file and pass in the bean as shown below: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + <beans> + <!-- this bean must not be lazily initialized if the exporting is to happen --> + <bean id="exporter" class="org.springframework.jmx.export.MBeanExporter" lazy-init="false"> + <property name="beans"> + <map> + <entry key="bean:name=testBean1" value-ref="testBean"/> + </map> + </property> + </bean> + <bean id="testBean" class="org.springframework.jmx.JmxTestBean"> + <property name="name" value="TEST"/> + <property name="age" value="100"/> + </bean> + </beans> +---- + +The pertinent bean definition from the above configuration snippet is the `exporter` +bean. The `beans` property tells the `MBeanExporter` exactly which of your beans must be +exported to the JMX `MBeanServer`. In the default configuration, the key of each entry +in the `beans` `Map` is used as the `ObjectName` for the bean referenced by the +corresponding entry value. This behavior can be changed as described in <<jmx-naming>>. + +With this configuration the `testBean` bean is exposed as an MBean under the +`ObjectName` `bean:name=testBean1`. By default, all __public__ properties of the bean +are exposed as attributes and all __public__ methods (bar those inherited from the +`Object` class) are exposed as operations. + +[NOTE] +==== +`MBeanExporter` is a `Lifecycle` bean (see <<beans-factory-lifecycle-processor>>) +and MBeans are exported as late as possible during the application lifecycle by default. It +is possible to configure the `phase` at which the export happens or disable automatic +registration by setting the `autoStartup` flag. +==== + + +[[jmx-exporting-mbeanserver]] +==== Creating an MBeanServer + +The above configuration assumes that the application is running in an environment that +has one (and only one) `MBeanServer` already running. In this case, Spring will attempt +to locate the running `MBeanServer` and register your beans with that server (if any). +This behavior is useful when your application is running inside a container such as +Tomcat or IBM WebSphere that has its own `MBeanServer`. + +However, this approach is of no use in a standalone environment, or when running inside +a container that does not provide an `MBeanServer`. To address this you can create an +`MBeanServer` instance declaratively by adding an instance of the +`org.springframework.jmx.support.MBeanServerFactoryBean` class to your configuration. +You can also ensure that a specific `MBeanServer` is used by setting the value of the +`MBeanExporter`'s `server` property to the `MBeanServer` value returned by an +`MBeanServerFactoryBean`; for example: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + <beans> + + <bean id="mbeanServer" class="org.springframework.jmx.support.MBeanServerFactoryBean"/> + + <!-- + this bean needs to be eagerly pre-instantiated in order for the exporting to occur; + this means that it must not be marked as lazily initialized + --> + <bean id="exporter" class="org.springframework.jmx.export.MBeanExporter"> + <property name="beans"> + <map> + <entry key="bean:name=testBean1" value-ref="testBean"/> + </map> + </property> + <property name="server" ref="mbeanServer"/> + </bean> + + <bean id="testBean" class="org.springframework.jmx.JmxTestBean"> + <property name="name" value="TEST"/> + <property name="age" value="100"/> + </bean> + + </beans> +---- + +Here an instance of `MBeanServer` is created by the `MBeanServerFactoryBean` and is +supplied to the `MBeanExporter` via the server property. When you supply your own +`MBeanServer` instance, the `MBeanExporter` will not attempt to locate a running +`MBeanServer` and will use the supplied `MBeanServer` instance. For this to work +correctly, you must (of course) have a JMX implementation on your classpath. + + + +[[jmx-mbean-server]] +==== Reusing an existing MBeanServer + +If no server is specified, the `MBeanExporter` tries to automatically detect a running +`MBeanServer`. This works in most environment where only one `MBeanServer` instance is +used, however when multiple instances exist, the exporter might pick the wrong server. +In such cases, one should use the `MBeanServer` `agentId` to indicate which instance to +be used: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + <beans> + <bean id="mbeanServer" class="org.springframework.jmx.support.MBeanServerFactoryBean"> + <!-- indicate to first look for a server --> + <property name="locateExistingServerIfPossible" value="true"/> + <!-- search for the MBeanServer instance with the given agentId --> + <property name="agentId" value="MBeanServer_instance_agentId>"/> + </bean> + <bean id="exporter" class="org.springframework.jmx.export.MBeanExporter"> + <property name="server" ref="mbeanServer"/> + ... + </bean> + </beans> +---- + +For platforms/cases where the existing `MBeanServer` has a dynamic (or unknown) +`agentId` which is retrieved through lookup methods, one should use +<<beans-factory-class-static-factory-method,factory-method>>: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + <beans> + <bean id="exporter" class="org.springframework.jmx.export.MBeanExporter"> + <property name="server"> + <!-- Custom MBeanServerLocator --> + <bean class="platform.package.MBeanServerLocator" factory-method="locateMBeanServer"/> + </property> + </bean> + + <!-- other beans here --> + + </beans> +---- + + + +[[jmx-exporting-lazy]] +==== Lazy-initialized MBeans +If you configure a bean with the `MBeanExporter` that is also configured for lazy +initialization, then the `MBeanExporter` will __not__ break this contract and will avoid +instantiating the bean. Instead, it will register a proxy with the `MBeanServer` and +will defer obtaining the bean from the container until the first invocation on the proxy +occurs. + + + +[[jmx-exporting-auto]] +==== Automatic registration of MBeans +Any beans that are exported through the `MBeanExporter` and are already valid MBeans are +registered as-is with the `MBeanServer` without further intervention from Spring. MBeans +can be automatically detected by the `MBeanExporter` by setting the `autodetect` +property to `true`: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + <bean id="exporter" class="org.springframework.jmx.export.MBeanExporter"> + <property name="autodetect" value="true"/> + </bean> + + <bean name="spring:mbean=true" class="org.springframework.jmx.export.TestDynamicMBean"/> +---- + +Here, the bean called `spring:mbean=true` is already a valid JMX MBean and will be +automatically registered by Spring. By default, beans that are autodetected for JMX +registration have their bean name used as the `ObjectName`. This behavior can be +overridden as detailed in <<jmx-naming>>. + + + +[[jmx-exporting-registration-behavior]] +==== Controlling the registration behavior +Consider the scenario where a Spring `MBeanExporter` attempts to register an `MBean` +with an `MBeanServer` using the `ObjectName` `'bean:name=testBean1'`. If an `MBean` +instance has already been registered under that same `ObjectName`, the default behavior +is to fail (and throw an `InstanceAlreadyExistsException`). + +It is possible to control the behavior of exactly what happens when an `MBean` is +registered with an `MBeanServer`. Spring's JMX support allows for three different +registration behaviors to control the registration behavior when the registration +process finds that an `MBean` has already been registered under the same `ObjectName`; +these registration behaviors are summarized on the following table: + +[[jmx-registration-behaviors]] +.Registration Behaviors +[cols="1,4"] +|=== +| Registration behavior| Explanation + +| `REGISTRATION_FAIL_ON_EXISTING` +| This is the default registration behavior. If an `MBean` instance has already been + registered under the same `ObjectName`, the `MBean` that is being registered will not + be registered and an `InstanceAlreadyExistsException` will be thrown. The existing + `MBean` is unaffected. + +| `REGISTRATION_IGNORE_EXISTING` +| If an `MBean` instance has already been registered under the same `ObjectName`, the + `MBean` that is being registered will __not__ be registered. The existing `MBean` is + unaffected, and no `Exception` will be thrown. This is useful in settings where + multiple applications want to share a common `MBean` in a shared `MBeanServer`. + +| `REGISTRATION_REPLACE_EXISTING` +| If an `MBean` instance has already been registered under the same `ObjectName`, the + existing `MBean` that was previously registered will be unregistered and the new + `MBean` will be registered in its place (the new `MBean` effectively replaces the + previous instance). +|=== + +The above values are defined as constants on the `MBeanRegistrationSupport` class (the +`MBeanExporter` class derives from this superclass). If you want to change the default +registration behavior, you simply need to set the value of the +`registrationBehaviorName` property on your `MBeanExporter` definition to one of those +values. + +The following example illustrates how to effect a change from the default registration +behavior to the `REGISTRATION_REPLACE_EXISTING` behavior: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + <beans> + + <bean id="exporter" class="org.springframework.jmx.export.MBeanExporter"> + <property name="beans"> + <map> + <entry key="bean:name=testBean1" value-ref="testBean"/> + </map> + </property> + <property name="registrationBehaviorName" value="REGISTRATION_REPLACE_EXISTING"/> + </bean> + + <bean id="testBean" class="org.springframework.jmx.JmxTestBean"> + <property name="name" value="TEST"/> + <property name="age" value="100"/> + </bean> + + </beans> +---- + + + + +[[jmx-interface]] +=== Controlling the management interface of your beans +In the previous example, you had little control over the management interface of your +bean; __all__ of the __public__ properties and methods of each exported bean was exposed +as JMX attributes and operations respectively. To exercise finer-grained control over +exactly which properties and methods of your exported beans are actually exposed as JMX +attributes and operations, Spring JMX provides a comprehensive and extensible mechanism +for controlling the management interfaces of your beans. + + + +[[jmx-interface-assembler]] +==== the MBeanInfoAssembler Interface + +Behind the scenes, the `MBeanExporter` delegates to an implementation of the +`org.springframework.jmx.export.assembler.MBeanInfoAssembler` interface which is +responsible for defining the management interface of each bean that is being exposed. +The default implementation, +`org.springframework.jmx.export.assembler.SimpleReflectiveMBeanInfoAssembler`, simply +defines a management interface that exposes all public properties and methods (as you +saw in the previous examples). Spring provides two additional implementations of the +`MBeanInfoAssembler` interface that allow you to control the generated management +interface using either source-level metadata or any arbitrary interface. + + + +[[jmx-interface-metadata]] +==== Using Source-Level Metadata (Java annotations) +Using the `MetadataMBeanInfoAssembler` you can define the management interfaces for your +beans using source level metadata. The reading of metadata is encapsulated by the +`org.springframework.jmx.export.metadata.JmxAttributeSource` interface. Spring JMX +provides a default implementation which uses Java annotations, namely +`org.springframework.jmx.export.annotation.AnnotationJmxAttributeSource`. The +`MetadataMBeanInfoAssembler` __must__ be configured with an implementation instance of +the `JmxAttributeSource` interface for it to function correctly (there is __no__ +default). + +To mark a bean for export to JMX, you should annotate the bean class with the +`ManagedResource` annotation. Each method you wish to expose as an operation must be +marked with the `ManagedOperation` annotation and each property you wish to expose must +be marked with the `ManagedAttribute` annotation. When marking properties you can omit +either the annotation of the getter or the setter to create a write-only or read-only +attribute respectively. + +The example below shows the annotated version of the `JmxTestBean` class that you saw +earlier: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + package org.springframework.jmx; + + import org.springframework.jmx.export.annotation.ManagedResource; + import org.springframework.jmx.export.annotation.ManagedOperation; + import org.springframework.jmx.export.annotation.ManagedAttribute; + + @ManagedResource( + objectName="bean:name=testBean4", + description="My Managed Bean", + log=true, + logFile="jmx.log", + currencyTimeLimit=15, + persistPolicy="OnUpdate", + persistPeriod=200, + persistLocation="foo", + persistName="bar") + public class AnnotationTestBean implements IJmxTestBean { + + private String name; + private int age; + + @ManagedAttribute(description="The Age Attribute", currencyTimeLimit=15) + public int getAge() { + return age; + } + + public void setAge(int age) { + this.age = age; + } + + @ManagedAttribute(description="The Name Attribute", + currencyTimeLimit=20, + defaultValue="bar", + persistPolicy="OnUpdate") + public void setName(String name) { + this.name = name; + } + + @ManagedAttribute(defaultValue="foo", persistPeriod=300) + public String getName() { + return name; + } + + @ManagedOperation(description="Add two numbers") + @ManagedOperationParameters({ + @ManagedOperationParameter(name = "x", description = "The first number"), + @ManagedOperationParameter(name = "y", description = "The second number")}) + public int add(int x, int y) { + return x + y; + } + + public void dontExposeMe() { + throw new RuntimeException(); + } + + } +---- + +Here you can see that the `JmxTestBean` class is marked with the `ManagedResource` +annotation and that this `ManagedResource` annotation is configured with a set of +properties. These properties can be used to configure various aspects of the MBean that +is generated by the `MBeanExporter`, and are explained in greater detail later in +section entitled <<jmx-interface-metadata-types>>. + +You will also notice that both the `age` and `name` properties are annotated with the +`ManagedAttribute` annotation, but in the case of the `age` property, only the getter is +marked. This will cause both of these properties to be included in the management +interface as attributes, but the `age` attribute will be read-only. + +Finally, you will notice that the `add(int, int)` method is marked with the +`ManagedOperation` attribute whereas the `dontExposeMe()` method is not. This will cause +the management interface to contain only one operation, `add(int, int)`, when using the +`MetadataMBeanInfoAssembler`. + +The configuration below shows how you configure the `MBeanExporter` to use the +`MetadataMBeanInfoAssembler`: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + <beans> + <bean id="exporter" class="org.springframework.jmx.export.MBeanExporter"> + <property name="assembler" ref="assembler"/> + <property name="namingStrategy" ref="namingStrategy"/> + <property name="autodetect" value="true"/> + </bean> + + <bean id="jmxAttributeSource" + class="org.springframework.jmx.export.annotation.AnnotationJmxAttributeSource"/> + + <!-- will create management interface using annotation metadata --> + <bean id="assembler" + class="org.springframework.jmx.export.assembler.MetadataMBeanInfoAssembler"> + <property name="attributeSource" ref="jmxAttributeSource"/> + </bean> + + <!-- will pick up the ObjectName from the annotation --> + <bean id="namingStrategy" + class="org.springframework.jmx.export.naming.MetadataNamingStrategy"> + <property name="attributeSource" ref="jmxAttributeSource"/> + </bean> + + <bean id="testBean" class="org.springframework.jmx.AnnotationTestBean"> + <property name="name" value="TEST"/> + <property name="age" value="100"/> + </bean> + </beans> +---- + +Here you can see that an `MetadataMBeanInfoAssembler` bean has been configured with an +instance of the `AnnotationJmxAttributeSource` class and passed to the `MBeanExporter` +through the assembler property. This is all that is required to take advantage of +metadata-driven management interfaces for your Spring-exposed MBeans. + + + +[[jmx-interface-metadata-types]] +==== Source-Level Metadata Types +The following source level metadata types are available for use in Spring JMX: + +[[jmx-metadata-types]] +.Source-Level Metadata Types +|=== +| Purpose| Annotation| Annotation Type + +| Mark all instances of a `Class` as JMX managed resources +| `@ManagedResource` +| Class + +| Mark a method as a JMX operation +| `@ManagedOperation` +| Method + +| Mark a getter or setter as one half of a JMX attribute +| `@ManagedAttribute` +| Method (only getters and setters) + +| Define descriptions for operation parameters +| `@ManagedOperationParameter` and `@ManagedOperationParameters` +| Method +|=== + +The following configuration parameters are available for use on these source-level +metadata types: + +[[jmx-metadata-parameters]] +.Source-Level Metadata Parameters +[cols="1,3,1"] +|=== +| Parameter| Description| Applies to + +| `ObjectName` +| Used by `MetadataNamingStrategy` to determine the `ObjectName` of a managed resource +| `ManagedResource` + +| `description` +| Sets the friendly description of the resource, attribute or operation +| `ManagedResource`, `ManagedAttribute`, `ManagedOperation`, `ManagedOperationParameter` + +| `currencyTimeLimit` +| Sets the value of the `currencyTimeLimit` descriptor field +| `ManagedResource`, `ManagedAttribute` + +| `defaultValue` +| Sets the value of the `defaultValue` descriptor field +| `ManagedAttribute` + +| `log` +| Sets the value of the `log` descriptor field +| `ManagedResource` + +| `logFile` +| Sets the value of the `logFile` descriptor field +| `ManagedResource` + +| `persistPolicy` +| Sets the value of the `persistPolicy` descriptor field +| `ManagedResource` + +| `persistPeriod` +| Sets the value of the `persistPeriod` descriptor field +| `ManagedResource` + +| `persistLocation` +| Sets the value of the `persistLocation` descriptor field +| `ManagedResource` + +| `persistName` +| Sets the value of the `persistName` descriptor field +| `ManagedResource` + +| `name` +| Sets the display name of an operation parameter +| `ManagedOperationParameter` + +| `index` +| Sets the index of an operation parameter +| `ManagedOperationParameter` +|=== + + + +[[jmx-interface-autodetect]] +==== the AutodetectCapableMBeanInfoAssembler interface + +To simplify configuration even further, Spring introduces the +`AutodetectCapableMBeanInfoAssembler` interface which extends the `MBeanInfoAssembler` +interface to add support for autodetection of MBean resources. If you configure the +`MBeanExporter` with an instance of `AutodetectCapableMBeanInfoAssembler` then it is +allowed to "vote" on the inclusion of beans for exposure to JMX. + +Out of the box, the only implementation of the `AutodetectCapableMBeanInfo` interface is +the `MetadataMBeanInfoAssembler` which will vote to include any bean which is marked +with the `ManagedResource` attribute. The default approach in this case is to use the +bean name as the `ObjectName` which results in a configuration like this: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + <beans> + + <bean id="exporter" class="org.springframework.jmx.export.MBeanExporter"> + <!-- notice how no 'beans' are explicitly configured here --> + <property name="autodetect" value="true"/> + <property name="assembler" ref="assembler"/> + </bean> + + <bean id="testBean" class="org.springframework.jmx.JmxTestBean"> + <property name="name" value="TEST"/> + <property name="age" value="100"/> + </bean> + + <bean id="assembler" class="org.springframework.jmx.export.assembler.MetadataMBeanInfoAssembler"> + <property name="attributeSource"> + <bean class="org.springframework.jmx.export.annotation.AnnotationJmxAttributeSource"/> + </property> + </bean> + + </beans> +---- + +Notice that in this configuration no beans are passed to the `MBeanExporter`; however, +the `JmxTestBean` will still be registered since it is marked with the `ManagedResource` +attribute and the `MetadataMBeanInfoAssembler` detects this and votes to include it. The +only problem with this approach is that the name of the `JmxTestBean` now has business +meaning. You can address this issue by changing the default behavior for `ObjectName` +creation as defined in <<jmx-naming>>. + + + +[[jmx-interface-java]] +==== Defining management interfaces using Java interfaces +In addition to the `MetadataMBeanInfoAssembler`, Spring also includes the +`InterfaceBasedMBeanInfoAssembler` which allows you to constrain the methods and +properties that are exposed based on the set of methods defined in a collection of +interfaces. + +Although the standard mechanism for exposing MBeans is to use interfaces and a simple +naming scheme, the `InterfaceBasedMBeanInfoAssembler` extends this functionality by +removing the need for naming conventions, allowing you to use more than one interface +and removing the need for your beans to implement the MBean interfaces. + +Consider this interface that is used to define a management interface for the +`JmxTestBean` class that you saw earlier: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public interface IJmxTestBean { + + public int add(int x, int y); + + public long myOperation(); + + public int getAge(); + + public void setAge(int age); + + public void setName(String name); + + public String getName(); + + } +---- + +This interface defines the methods and properties that will be exposed as operations and +attributes on the JMX MBean. The code below shows how to configure Spring JMX to use +this interface as the definition for the management interface: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + <beans> + + <bean id="exporter" class="org.springframework.jmx.export.MBeanExporter"> + <property name="beans"> + <map> + <entry key="bean:name=testBean5" value-ref="testBean"/> + </map> + </property> + <property name="assembler"> + <bean class="org.springframework.jmx.export.assembler.InterfaceBasedMBeanInfoAssembler"> + <property name="managedInterfaces"> + <value>org.springframework.jmx.IJmxTestBean</value> + </property> + </bean> + </property> + </bean> + + <bean id="testBean" class="org.springframework.jmx.JmxTestBean"> + <property name="name" value="TEST"/> + <property name="age" value="100"/> + </bean> + + </beans> +---- + +Here you can see that the `InterfaceBasedMBeanInfoAssembler` is configured to use the +`IJmxTestBean` interface when constructing the management interface for any bean. It is +important to understand that beans processed by the `InterfaceBasedMBeanInfoAssembler` +are __not__ required to implement the interface used to generate the JMX management +interface. + +In the case above, the `IJmxTestBean` interface is used to construct all management +interfaces for all beans. In many cases this is not the desired behavior and you may +want to use different interfaces for different beans. In this case, you can pass +`InterfaceBasedMBeanInfoAssembler` a `Properties` instance via the `interfaceMappings` +property, where the key of each entry is the bean name and the value of each entry is a +comma-separated list of interface names to use for that bean. + +If no management interface is specified through either the `managedInterfaces` or +`interfaceMappings` properties, then the `InterfaceBasedMBeanInfoAssembler` will reflect +on the bean and use all of the interfaces implemented by that bean to create the +management interface. + + + +[[jmx-interface-methodnames]] +==== Using MethodNameBasedMBeanInfoAssembler + +The `MethodNameBasedMBeanInfoAssembler` allows you to specify a list of method names +that will be exposed to JMX as attributes and operations. The code below shows a sample +configuration for this: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + <bean id="exporter" class="org.springframework.jmx.export.MBeanExporter"> + <property name="beans"> + <map> + <entry key="bean:name=testBean5" value-ref="testBean"/> + </map> + </property> + <property name="assembler"> + <bean class="org.springframework.jmx.export.assembler.MethodNameBasedMBeanInfoAssembler"> + <property name="managedMethods"> + <value>add,myOperation,getName,setName,getAge</value> + </property> + </bean> + </property> + </bean> +---- + +Here you can see that the methods `add` and `myOperation` will be exposed as JMX +operations and `getName()`, `setName(String)` and `getAge()` will be exposed as the +appropriate half of a JMX attribute. In the code above, the method mappings apply to +beans that are exposed to JMX. To control method exposure on a bean-by-bean basis, use +the `methodMappings` property of `MethodNameMBeanInfoAssembler` to map bean names to +lists of method names. + + + + +[[jmx-naming]] +=== Controlling the ObjectNames for your beans + +Behind the scenes, the `MBeanExporter` delegates to an implementation of the +`ObjectNamingStrategy` to obtain ++ObjectName++s for each of the beans it is registering. +The default implementation, `KeyNamingStrategy`, will, by default, use the key of the +`beans` `Map` as the `ObjectName`. In addition, the `KeyNamingStrategy` can map the key +of the `beans` `Map` to an entry in a `Properties` file (or files) to resolve the +`ObjectName`. In addition to the `KeyNamingStrategy`, Spring provides two additional +`ObjectNamingStrategy` implementations: the `IdentityNamingStrategy` that builds an +`ObjectName` based on the JVM identity of the bean and the `MetadataNamingStrategy` that +uses source level metadata to obtain the `ObjectName`. + + + +[[jmx-naming-properties]] +==== Reading ObjectNames from Properties + +You can configure your own `KeyNamingStrategy` instance and configure it to read +++ObjectName++s from a `Properties` instance rather than use bean key. The +`KeyNamingStrategy` will attempt to locate an entry in the `Properties` with a key +corresponding to the bean key. If no entry is found or if the `Properties` instance is +`null` then the bean key itself is used. + +The code below shows a sample configuration for the `KeyNamingStrategy`: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + <beans> + + <bean id="exporter" class="org.springframework.jmx.export.MBeanExporter"> + <property name="beans"> + <map> + <entry key="testBean" value-ref="testBean"/> + </map> + </property> + <property name="namingStrategy" ref="namingStrategy"/> + </bean> + + <bean id="testBean" class="org.springframework.jmx.JmxTestBean"> + <property name="name" value="TEST"/> + <property name="age" value="100"/> + </bean> + + <bean id="namingStrategy" class="org.springframework.jmx.export.naming.KeyNamingStrategy"> + <property name="mappings"> + <props> + <prop key="testBean">bean:name=testBean1</prop> + </props> + </property> + <property name="mappingLocations"> + <value>names1.properties,names2.properties</value> + </property> + </bean> + + </beans> +---- + +Here an instance of `KeyNamingStrategy` is configured with a `Properties` instance that +is merged from the `Properties` instance defined by the mapping property and the +properties files located in the paths defined by the mappings property. In this +configuration, the `testBean` bean will be given the `ObjectName` `bean:name=testBean1` +since this is the entry in the `Properties` instance that has a key corresponding to the +bean key. + +If no entry in the `Properties` instance can be found then the bean key name is used as +the `ObjectName`. + + + +[[jmx-naming-metadata]] +==== Using the MetadataNamingStrategy + +The `MetadataNamingStrategy` uses the `objectName` property of the `ManagedResource` +attribute on each bean to create the `ObjectName`. The code below shows the +configuration for the `MetadataNamingStrategy`: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + <beans> + + <bean id="exporter" class="org.springframework.jmx.export.MBeanExporter"> + <property name="beans"> + <map> + <entry key="testBean" value-ref="testBean"/> + </map> + </property> + <property name="namingStrategy" ref="namingStrategy"/> + </bean> + + <bean id="testBean" class="org.springframework.jmx.JmxTestBean"> + <property name="name" value="TEST"/> + <property name="age" value="100"/> + </bean> + + <bean id="namingStrategy" class="org.springframework.jmx.export.naming.MetadataNamingStrategy"> + <property name="attributeSource" ref="attributeSource"/> + </bean> + + <bean id="attributeSource" + class="org.springframework.jmx.export.annotation.AnnotationJmxAttributeSource"/> + + </beans> +---- + +If no `objectName` has been provided for the `ManagedResource` attribute, then an +`ObjectName` will be created with the following +format:__[fully-qualified-package-name]:type=[short-classname],name=[bean-name]__. For +example, the generated `ObjectName` for the following bean would be: +__com.foo:type=MyClass,name=myBean__. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + <bean id="myBean" class="com.foo.MyClass"/> +---- + + + +[[jmx-context-mbeanexport]] +==== Configuring annotation based MBean export +If you prefer using <<jmx-interface-metadata,the annotation based approach>> to define +your management interfaces, then a convenience subclass of `MBeanExporter` is available: +`AnnotationMBeanExporter`. When defining an instance of this subclass, the +`namingStrategy`, `assembler`, and `attributeSource` configuration is no longer needed, +since it will always use standard Java annotation-based metadata (autodetection is +always enabled as well). In fact, rather than defining an `MBeanExporter` bean, an even +simpler syntax is supported by the `@EnableMBeanExport` `@Configuration` annotation. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Configuration + @EnableMBeanExport + public class AppConfig { + + } +---- + +If you prefer XML based configuration the ' `context:mbean-export'` element serves the +same purpose. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + <context:mbean-export/> +---- + +You can provide a reference to a particular MBean `server` if necessary, and the +`defaultDomain` attribute (a property of `AnnotationMBeanExporter`) accepts an alternate +value for the generated MBean `ObjectNames`' domains. This would be used in place of the +fully qualified package name as described in the previous section on +<<jmx-naming-metadata, `MetadataNamingStrategy`>>. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @EnableMBeanExport(server="myMBeanServer", defaultDomain="myDomain") + @Configuration + ContextConfiguration { + + } +---- + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + <context:mbean-export server="myMBeanServer" default-domain="myDomain"/> +---- + +[NOTE] +==== +Do not use interface-based AOP proxies in combination with autodetection of JMX +annotations in your bean classes. Interface-based proxies 'hide' the target class, which +also hides the JMX managed resource annotations. Hence, use target-class proxies in that +case: through setting the 'proxy-target-class' flag on `<aop:config/>`, +`<tx:annotation-driven/>`, etc. Otherwise, your JMX beans might be silently ignored at +startup... +==== + + + + +[[jmx-jsr160]] +=== JSR-160 Connectors +For remote access, Spring JMX module offers two `FactoryBean` implementations inside the +`org.springframework.jmx.support` package for creating both server- and client-side +connectors. + + + +[[jmx-jsr160-server]] +==== Server-side Connectors +To have Spring JMX create, start and expose a JSR-160 `JMXConnectorServer` use the +following configuration: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + <bean id="serverConnector" class="org.springframework.jmx.support.ConnectorServerFactoryBean"/> +---- + +By default `ConnectorServerFactoryBean` creates a `JMXConnectorServer` bound to +`"service:jmx:jmxmp://localhost:9875"`. The `serverConnector` bean thus exposes the +local `MBeanServer` to clients through the JMXMP protocol on localhost, port 9875. Note +that the JMXMP protocol is marked as optional by the JSR 160 specification: currently, +the main open-source JMX implementation, MX4J, and the one provided with the JDK +do __not__ support JMXMP. + +To specify another URL and register the `JMXConnectorServer` itself with the +`MBeanServer` use the `serviceUrl` and `ObjectName` properties respectively: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + <bean id="serverConnector" + class="org.springframework.jmx.support.ConnectorServerFactoryBean"> + <property name="objectName" value="connector:name=rmi"/> + <property name="serviceUrl" + value="service:jmx:rmi://localhost/jndi/rmi://localhost:1099/myconnector"/> + </bean> +---- + +If the `ObjectName` property is set Spring will automatically register your connector +with the `MBeanServer` under that `ObjectName`. The example below shows the full set of +parameters which you can pass to the `ConnectorServerFactoryBean` when creating a +JMXConnector: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + <bean id="serverConnector" + class="org.springframework.jmx.support.ConnectorServerFactoryBean"> + <property name="objectName" value="connector:name=iiop"/> + <property name="serviceUrl" + value="service:jmx:iiop://localhost/jndi/iiop://localhost:900/myconnector"/> + <property name="threaded" value="true"/> + <property name="daemon" value="true"/> + <property name="environment"> + <map> + <entry key="someKey" value="someValue"/> + </map> + </property> + </bean> +---- + +Note that when using a RMI-based connector you need the lookup service (tnameserv or +rmiregistry) to be started in order for the name registration to complete. If you are +using Spring to export remote services for you via RMI, then Spring will already have +constructed an RMI registry. If not, you can easily start a registry using the following +snippet of configuration: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + <bean id="registry" class="org.springframework.remoting.rmi.RmiRegistryFactoryBean"> + <property name="port" value="1099"/> + </bean> +---- + + + +[[jmx-jsr160-client]] +==== Client-side Connectors +To create an `MBeanServerConnection` to a remote JSR-160 enabled `MBeanServer` use the +`MBeanServerConnectionFactoryBean` as shown below: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + <bean id="clientConnector" class="org.springframework.jmx.support.MBeanServerConnectionFactoryBean"> + <property name="serviceUrl" value="service:jmx:rmi://localhost/jndi/rmi://localhost:1099/jmxrmi"/> + </bean> +---- + + + +[[jmx-jsr160-protocols]] +==== JMX over Burlap/Hessian/SOAP +JSR-160 permits extensions to the way in which communication is done between the client +and the server. The examples above are using the mandatory RMI-based implementation +required by the JSR-160 specification (IIOP and JRMP) and the (optional) JMXMP. By using +other providers or JMX implementations (such as http://mx4j.sourceforge.net[MX4J]) you +can take advantage of protocols like SOAP, Hessian, Burlap over simple HTTP or SSL and +others: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + <bean id="serverConnector" class="org.springframework.jmx.support.ConnectorServerFactoryBean"> + <property name="objectName" value="connector:name=burlap"/> + <property name="serviceUrl" value="service:jmx:burlap://localhost:9874"/> + </bean> +---- + +In the case of the above example, MX4J 3.0.0 was used; see the official MX4J +documentation for more information. + + + + +[[jmx-proxy]] +=== Accessing MBeans via Proxies +Spring JMX allows you to create proxies that re-route calls to MBeans registered in a +local or remote `MBeanServer`. These proxies provide you with a standard Java interface +through which you can interact with your MBeans. The code below shows how to configure a +proxy for an MBean running in a local `MBeanServer`: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + <bean id="proxy" class="org.springframework.jmx.access.MBeanProxyFactoryBean"> + <property name="objectName" value="bean:name=testBean"/> + <property name="proxyInterface" value="org.springframework.jmx.IJmxTestBean"/> + </bean> +---- + +Here you can see that a proxy is created for the MBean registered under the +`ObjectName`: `bean:name=testBean`. The set of interfaces that the proxy will implement +is controlled by the `proxyInterfaces` property and the rules for mapping methods and +properties on these interfaces to operations and attributes on the MBean are the same +rules used by the `InterfaceBasedMBeanInfoAssembler`. + +The `MBeanProxyFactoryBean` can create a proxy to any MBean that is accessible via an +`MBeanServerConnection`. By default, the local `MBeanServer` is located and used, but +you can override this and provide an `MBeanServerConnection` pointing to a remote +`MBeanServer` to cater for proxies pointing to remote MBeans: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + <bean id="clientConnector" + class="org.springframework.jmx.support.MBeanServerConnectionFactoryBean"> + <property name="serviceUrl" value="service:jmx:rmi://remotehost:9875"/> + </bean> + + <bean id="proxy" class="org.springframework.jmx.access.MBeanProxyFactoryBean"> + <property name="objectName" value="bean:name=testBean"/> + <property name="proxyInterface" value="org.springframework.jmx.IJmxTestBean"/> + <property name="server" ref="clientConnector"/> + </bean> +---- + +Here you can see that we create an `MBeanServerConnection` pointing to a remote machine +using the `MBeanServerConnectionFactoryBean`. This `MBeanServerConnection` is then +passed to the `MBeanProxyFactoryBean` via the `server` property. The proxy that is +created will forward all invocations to the `MBeanServer` via this +`MBeanServerConnection`. + + + + +[[jmx-notifications]] +=== Notifications +Spring's JMX offering includes comprehensive support for JMX notifications. + + + +[[jmx-notifications-listeners]] +==== Registering Listeners for Notifications +Spring's JMX support makes it very easy to register any number of +`NotificationListeners` with any number of MBeans (this includes MBeans exported by +Spring's `MBeanExporter` and MBeans registered via some other mechanism). By way of an +example, consider the scenario where one would like to be informed (via a +`Notification`) each and every time an attribute of a target MBean changes. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + package com.example; + + import javax.management.AttributeChangeNotification; + import javax.management.Notification; + import javax.management.NotificationFilter; + import javax.management.NotificationListener; + + public class ConsoleLoggingNotificationListener + implements NotificationListener, NotificationFilter { + + public void handleNotification(Notification notification, Object handback) { + System.out.println(notification); + System.out.println(handback); + } + + public boolean isNotificationEnabled(Notification notification) { + return AttributeChangeNotification.class.isAssignableFrom(notification.getClass()); + } + + } +---- + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + <beans> + + <bean id="exporter" class="org.springframework.jmx.export.MBeanExporter"> + <property name="beans"> + <map> + <entry key="bean:name=testBean1" value-ref="testBean"/> + </map> + </property> + <property name="notificationListenerMappings"> + <map> + <entry key="bean:name=testBean1"> + <bean class="com.example.ConsoleLoggingNotificationListener"/> + </entry> + </map> + </property> + </bean> + + <bean id="testBean" class="org.springframework.jmx.JmxTestBean"> + <property name="name" value="TEST"/> + <property name="age" value="100"/> + </bean> + + </beans> +---- + +With the above configuration in place, every time a JMX `Notification` is broadcast from +the target MBean ( `bean:name=testBean1`), the `ConsoleLoggingNotificationListener` bean +that was registered as a listener via the `notificationListenerMappings` property will +be notified. The `ConsoleLoggingNotificationListener` bean can then take whatever action +it deems appropriate in response to the `Notification`. + +You can also use straight bean names as the link between exported beans and listeners: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + <beans> + + <bean id="exporter" class="org.springframework.jmx.export.MBeanExporter"> + <property name="beans"> + <map> + <entry key="bean:name=testBean1" value-ref="testBean"/> + </map> + </property> + <property name="notificationListenerMappings"> + <map> + <entry key="__testBean__"> + <bean class="com.example.ConsoleLoggingNotificationListener"/> + </entry> + </map> + </property> + </bean> + + <bean id="__testBean__" class="org.springframework.jmx.JmxTestBean"> + <property name="name" value="TEST"/> + <property name="age" value="100"/> + </bean> + + </beans> +---- + +If one wants to register a single `NotificationListener` instance for all of the beans +that the enclosing `MBeanExporter` is exporting, one can use the special wildcard `'*'` +(sans quotes) as the key for an entry in the `notificationListenerMappings` property +map; for example: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + <property name="notificationListenerMappings"> + <map> + <entry key="*"> + <bean class="com.example.ConsoleLoggingNotificationListener"/> + </entry> + </map> + </property> +---- + +If one needs to do the inverse (that is, register a number of distinct listeners against +an MBean), then one has to use the `notificationListeners` list property instead (and in +preference to the `notificationListenerMappings` property). This time, instead of +configuring simply a `NotificationListener` for a single MBean, one configures +`NotificationListenerBean` instances... a `NotificationListenerBean` encapsulates a +`NotificationListener` and the `ObjectName` (or `ObjectNames`) that it is to be +registered against in an `MBeanServer`. The `NotificationListenerBean` also encapsulates +a number of other properties such as a `NotificationFilter` and an arbitrary handback +object that can be used in advanced JMX notification scenarios. + +The configuration when using `NotificationListenerBean` instances is not wildly +different to what was presented previously: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + <beans> + + <bean id="exporter" class="org.springframework.jmx.export.MBeanExporter"> + <property name="beans"> + <map> + <entry key="bean:name=testBean1" value-ref="testBean"/> + </map> + </property> + <property name="notificationListeners"> + <list> + <bean class="org.springframework.jmx.export.NotificationListenerBean"> + <constructor-arg> + <bean class="com.example.ConsoleLoggingNotificationListener"/> + </constructor-arg> + <property name="mappedObjectNames"> + <list> + <value>bean:name=testBean1</value> + </list> + </property> + </bean> + </list> + </property> + </bean> + + <bean id="testBean" class="org.springframework.jmx.JmxTestBean"> + <property name="name" value="TEST"/> + <property name="age" value="100"/> + </bean> + + </beans> +---- + +The above example is equivalent to the first notification example. Lets assume then that +we want to be given a handback object every time a `Notification` is raised, and that +additionally we want to filter out extraneous `Notifications` by supplying a +`NotificationFilter`. (For a full discussion of just what a handback object is, and +indeed what a `NotificationFilter` is, please do consult that section of the JMX +specification (1.2) entitled 'The JMX Notification Model'.) + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + <beans> + + <bean id="exporter" class="org.springframework.jmx.export.MBeanExporter"> + <property name="beans"> + <map> + <entry key="bean:name=testBean1" value-ref="testBean1"/> + <entry key="bean:name=testBean2" value-ref="testBean2"/> + </map> + </property> + <property name="notificationListeners"> + <list> + <bean class="org.springframework.jmx.export.NotificationListenerBean"> + <constructor-arg ref="customerNotificationListener"/> + <property name="mappedObjectNames"> + <list> + <!-- handles notifications from two distinct MBeans --> + <value>bean:name=testBean1</value> + <value>bean:name=testBean2</value> + </list> + </property> + <property name="handback"> + <bean class="java.lang.String"> + <constructor-arg value="This could be anything..."/> + </bean> + </property> + <property name="notificationFilter" ref="customerNotificationListener"/> + </bean> + </list> + </property> + </bean> + + <!-- implements both the NotificationListener and NotificationFilter interfaces --> + <bean id="customerNotificationListener" class="com.example.ConsoleLoggingNotificationListener"/> + + <bean id="testBean1" class="org.springframework.jmx.JmxTestBean"> + <property name="name" value="TEST"/> + <property name="age" value="100"/> + </bean> + + <bean id="testBean2" class="org.springframework.jmx.JmxTestBean"> + <property name="name" value="ANOTHER TEST"/> + <property name="age" value="200"/> + </bean> + + </beans> +---- + + + +[[jmx-notifications-publishing]] +==== Publishing Notifications +Spring provides support not just for registering to receive `Notifications`, but also +for publishing `Notifications`. + +[NOTE] +==== +Please note that this section is really only relevant to Spring managed beans that have +been exposed as MBeans via an `MBeanExporter`; any existing, user-defined MBeans should +use the standard JMX APIs for notification publication. +==== + +The key interface in Spring's JMX notification publication support is the +`NotificationPublisher` interface (defined in the +`org.springframework.jmx.export.notification` package). Any bean that is going to be +exported as an MBean via an `MBeanExporter` instance can implement the related +`NotificationPublisherAware` interface to gain access to a `NotificationPublisher` +instance. The `NotificationPublisherAware` interface simply supplies an instance of a +`NotificationPublisher` to the implementing bean via a simple setter method, which the +bean can then use to publish `Notifications`. + +As stated in the javadocs of the `NotificationPublisher` class, managed beans that are +publishing events via the `NotificationPublisher` mechanism are __not__ responsible for +the state management of any notification listeners and the like ... Spring's JMX support +will take care of handling all the JMX infrastructure issues. All one need do as an +application developer is implement the `NotificationPublisherAware` interface and start +publishing events using the supplied `NotificationPublisher` instance. Note that the +`NotificationPublisher` will be set __after__ the managed bean has been registered with +an `MBeanServer`. + +Using a `NotificationPublisher` instance is quite straightforward... one simply creates +a JMX `Notification` instance (or an instance of an appropriate `Notification` +subclass), populates the notification with the data pertinent to the event that is to be +published, and one then invokes the `sendNotification(Notification)` on the +`NotificationPublisher` instance, passing in the `Notification`. + +Find below a simple example... in this scenario, exported instances of the `JmxTestBean` +are going to publish a `NotificationEvent` every time the `add(int, int)` operation is +invoked. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + package org.springframework.jmx; + + import org.springframework.jmx.export.notification.NotificationPublisherAware; + import org.springframework.jmx.export.notification.NotificationPublisher; + import javax.management.Notification; + + public class JmxTestBean implements IJmxTestBean, NotificationPublisherAware { + + private String name; + private int age; + private boolean isSuperman; + private NotificationPublisher publisher; + + // other getters and setters omitted for clarity + + public int add(int x, int y) { + int answer = x + y; + this.publisher.sendNotification(new Notification("add", this, 0)); + return answer; + } + + public void dontExposeMe() { + throw new RuntimeException(); + } + + public void setNotificationPublisher(NotificationPublisher notificationPublisher) { + this.publisher = notificationPublisher; + } + + } +---- + +The `NotificationPublisher` interface and the machinery to get it all working is one of +the nicer features of Spring's JMX support. It does however come with the price tag of +coupling your classes to both Spring and JMX; as always, the advice here is to be +pragmatic... if you need the functionality offered by the `NotificationPublisher` and +you can accept the coupling to both Spring and JMX, then do so. + + + + +[[jmx-resources]] +=== Further Resources +This section contains links to further resources about JMX. + +* The http://www.oracle.com/technetwork/java/javase/tech/javamanagement-140525.html[JMX +homepage] at Oracle +* The http://jcp.org/aboutJava/communityprocess/final/jsr003/index3.html[JMX + specification] (JSR-000003) +* The http://jcp.org/aboutJava/communityprocess/final/jsr160/index.html[JMX Remote API + specification] (JSR-000160) +* The http://mx4j.sourceforge.net/[MX4J homepage] (an Open Source implementation of + various JMX specs) + + + + diff --git a/src/asciidoc/mail.adoc b/src/asciidoc/mail.adoc new file mode 100644 index 000000000000..e39546229915 --- /dev/null +++ b/src/asciidoc/mail.adoc @@ -0,0 +1,440 @@ +[[mail]] +== Email + + + + +[[mail-introduction]] +=== Introduction + +.Library dependencies +**** +The following additional jars to be on the classpath of your application in order to be +able to use the Spring Framework's email library. + +* The https://java.net/projects/javamail/pages/Home[JavaMail] `mail.jar` library +* The http://www.oracle.com/technetwork/java/jaf11-139815.html[JAF] + `activation.jar` library + +All of these libraries are freely available on the web. +**** + +The Spring Framework provides a helpful utility library for sending email that shields +the user from the specifics of the underlying mailing system and is responsible for low +level resource handling on behalf of the client. + +The `org.springframework.mail` package is the root level package for the Spring +Framework's email support. The central interface for sending emails is the `MailSender` +interface; a simple value object encapsulating the properties of a simple mail such as +__from__ and __to__ (plus many others) is the `SimpleMailMessage` class. This package +also contains a hierarchy of checked exceptions which provide a higher level of +abstraction over the lower level mail system exceptions with the root exception being +`MailException`. Please refer to the javadocs for more information on the rich mail +exception hierarchy. + +The `org.springframework.mail.javamail.JavaMailSender` interface adds specialized +__JavaMail__ features such as MIME message support to the `MailSender` interface (from +which it inherits). `JavaMailSender` also provides a callback interface for preparation +of JavaMail MIME messages, called +`org.springframework.mail.javamail.MimeMessagePreparator` + + + + +[[mail-usage]] +=== Usage +Let's assume there is a business interface called `OrderManager`: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public interface OrderManager { + + void placeOrder(Order order); + + } +---- + +Let us also assume that there is a requirement stating that an email message with an +order number needs to be generated and sent to a customer placing the relevant order. + + + +[[mail-usage-simple]] +==== Basic MailSender and SimpleMailMessage usage + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + import org.springframework.mail.MailException; + import org.springframework.mail.MailSender; + import org.springframework.mail.SimpleMailMessage; + + public class SimpleOrderManager implements OrderManager { + + private MailSender mailSender; + private SimpleMailMessage templateMessage; + + public void setMailSender(MailSender mailSender) { + this.mailSender = mailSender; + } + + public void setTemplateMessage(SimpleMailMessage templateMessage) { + this.templateMessage = templateMessage; + } + + public void placeOrder(Order order) { + + // Do the business calculations... + + // Call the collaborators to persist the order... + + // Create a thread safe "copy" of the template message and customize it + SimpleMailMessage msg = new SimpleMailMessage(this.templateMessage); + msg.setTo(order.getCustomer().getEmailAddress()); + msg.setText( + "Dear " + order.getCustomer().getFirstName() + + order.getCustomer().getLastName() + + ", thank you for placing order. Your order number is " + + order.getOrderNumber()); + try{ + this.mailSender.send(msg); + } + catch (MailException ex) { + // simply log it and go on... + System.err.println(ex.getMessage()); + } + } + + } +---- + +Find below the bean definitions for the above code: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + <bean id="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl"> + <property name="host" value="mail.mycompany.com"/> + </bean> + + <!-- this is a template message that we can pre-load with default state --> + <bean id="templateMessage" class="org.springframework.mail.SimpleMailMessage"> + <property name="from" value="customerservice@mycompany.com"/> + <property name="subject" value="Your order"/> + </bean> + + <bean id="orderManager" class="com.mycompany.businessapp.support.SimpleOrderManager"> + <property name="mailSender" ref="mailSender"/> + <property name="templateMessage" ref="templateMessage"/> + </bean> +---- + + + +[[mail-usage-mime]] +==== Using the JavaMailSender and the MimeMessagePreparator + +Here is another implementation of `OrderManager` using the `MimeMessagePreparator` +callback interface. Please note in this case that the `mailSender` property is of type +`JavaMailSender` so that we are able to use the JavaMail `MimeMessage` class: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + import javax.mail.Message; + import javax.mail.MessagingException; + import javax.mail.internet.InternetAddress; + import javax.mail.internet.MimeMessage; + + import javax.mail.internet.MimeMessage; + import org.springframework.mail.MailException; + import org.springframework.mail.javamail.JavaMailSender; + import org.springframework.mail.javamail.MimeMessagePreparator; + + public class SimpleOrderManager implements OrderManager { + + private JavaMailSender mailSender; + + public void setMailSender(JavaMailSender mailSender) { + this.mailSender = mailSender; + } + + public void placeOrder(final Order order) { + + // Do the business calculations... + + // Call the collaborators to persist the order... + + MimeMessagePreparator preparator = new MimeMessagePreparator() { + + public void prepare(MimeMessage mimeMessage) throws Exception { + + mimeMessage.setRecipient(Message.RecipientType.TO, + new InternetAddress(order.getCustomer().getEmailAddress())); + mimeMessage.setFrom(new InternetAddress("mail@mycompany.com")); + mimeMessage.setText( + "Dear " + order.getCustomer().getFirstName() + " " + + order.getCustomer().getLastName() + + ", thank you for placing order. Your order number is " + + order.getOrderNumber()); + } + }; + + try { + this.mailSender.send(preparator); + } + catch (MailException ex) { + // simply log it and go on... + System.err.println(ex.getMessage()); + } + } + + } +---- + +[NOTE] +==== +The mail code is a crosscutting concern and could well be a candidate for refactoring +into a <<aop,custom Spring AOP aspect>>, which then could be executed at appropriate +joinpoints on the `OrderManager` target. +==== + +The Spring Framework's mail support ships with the standard JavaMail implementation. +Please refer to the relevant javadocs for more information. + + + + +[[mail-javamail-mime]] +=== Using the JavaMail MimeMessageHelper + +A class that comes in pretty handy when dealing with JavaMail messages is the +`org.springframework.mail.javamail.MimeMessageHelper` class, which shields you from +having to use the verbose JavaMail API. Using the `MimeMessageHelper` it is pretty easy +to create a `MimeMessage`: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + // of course you would use DI in any real-world cases + JavaMailSenderImpl sender = new JavaMailSenderImpl(); + sender.setHost("mail.host.com"); + + MimeMessage message = sender.createMimeMessage(); + MimeMessageHelper helper = new MimeMessageHelper(message); + helper.setTo("test@host.com"); + helper.setText("Thank you for ordering!"); + + sender.send(message); +---- + + + +[[mail-javamail-mime-attachments]] +==== Sending attachments and inline resources +Multipart email messages allow for both attachments and inline resources. Examples of +inline resources would be images or a stylesheet you want to use in your message, but +that you don't want displayed as an attachment. + + +[[mail-javamail-mime-attachments-attachment]] +===== Attachments +The following example shows you how to use the `MimeMessageHelper` to send an email +along with a single JPEG image attachment. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + JavaMailSenderImpl sender = new JavaMailSenderImpl(); + sender.setHost("mail.host.com"); + + MimeMessage message = sender.createMimeMessage(); + + // use the true flag to indicate you need a multipart message + MimeMessageHelper helper = new MimeMessageHelper(message, true); + helper.setTo("test@host.com"); + + helper.setText("Check out this image!"); + + // let's attach the infamous windows Sample file (this time copied to c:/) + FileSystemResource file = new FileSystemResource(new File("c:/Sample.jpg")); + helper.addAttachment("CoolImage.jpg", file); + + sender.send(message); +---- + + +[[mail-javamail-mime-attachments-inline]] +===== Inline resources +The following example shows you how to use the `MimeMessageHelper` to send an email +along with an inline image. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + JavaMailSenderImpl sender = new JavaMailSenderImpl(); + sender.setHost("mail.host.com"); + + MimeMessage message = sender.createMimeMessage(); + + // use the true flag to indicate you need a multipart message + MimeMessageHelper helper = new MimeMessageHelper(message, true); + helper.setTo("test@host.com"); + + // use the true flag to indicate the text included is HTML + helper.setText("<html><body><img src='cid:identifier1234'></body></html>", true); + + // let's include the infamous windows Sample file (this time copied to c:/) + FileSystemResource res = new FileSystemResource(new File("c:/Sample.jpg")); + helper.addInline("identifier1234", res); + + sender.send(message); +---- + +[WARNING] +==== + +Inline resources are added to the mime message using the specified `Content-ID` ( +`identifier1234` in the above example). The order in which you are adding the text and +the resource are __very__ important. Be sure to __first add the text__ and after that +the resources. If you are doing it the other way around, it won't work! +==== + + + +[[mail-templates]] +==== Creating email content using a templating library +The code in the previous examples explicitly created the content of the email message, +using methods calls such as `message.setText(..)`. This is fine for simple cases, and it +is okay in the context of the aforementioned examples, where the intent was to show you +the very basics of the API. + +In your typical enterprise application though, you are not going to create the content +of your emails using the above approach for a number of reasons. + +* Creating HTML-based email content in Java code is tedious and error prone +* There is no clear separation between display logic and business logic +* Changing the display structure of the email content requires writing Java code, + recompiling, redeploying... + +Typically the approach taken to address these issues is to use a template library such +as FreeMarker or Velocity to define the display structure of email content. This leaves +your code tasked only with creating the data that is to be rendered in the email +template and sending the email. It is definitely a best practice for when the content of +your emails becomes even moderately complex, and with the Spring Framework's support +classes for FreeMarker and Velocity becomes quite easy to do. Find below an example of +using the Velocity template library to create email content. + + +[[mail-templates-example]] +===== A Velocity-based example +To use http://velocity.apache.org[Velocity] to create your email template(s), you will +need to have the Velocity libraries available on your classpath. You will also need to +create one or more Velocity templates for the email content that your application needs. +Find below the Velocity template that this example will be using. As you can see it is +HTML-based, and since it is plain text it can be created using your favorite HTML or +text editor. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + # in the com/foo/package + <html> + <body> + <h3>Hi ${user.userName}, welcome to the Chipping Sodbury On-the-Hill message boards!</h3> + + <div> + Your email address is <a href="mailto:${user.emailAddress}">${user.emailAddress}</a>. + </div> + </body> + </html> +---- + +Find below some simple code and Spring XML configuration that makes use of the above +Velocity template to create email content and send email(s). + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + package com.foo; + + import org.apache.velocity.app.VelocityEngine; + import org.springframework.mail.javamail.JavaMailSender; + import org.springframework.mail.javamail.MimeMessageHelper; + import org.springframework.mail.javamail.MimeMessagePreparator; + import org.springframework.ui.velocity.VelocityEngineUtils; + + import javax.mail.internet.MimeMessage; + import java.util.HashMap; + import java.util.Map; + + public class SimpleRegistrationService implements RegistrationService { + + private JavaMailSender mailSender; + private VelocityEngine velocityEngine; + + public void setMailSender(JavaMailSender mailSender) { + this.mailSender = mailSender; + } + + public void setVelocityEngine(VelocityEngine velocityEngine) { + this.velocityEngine = velocityEngine; + } + + public void register(User user) { + + // Do the registration logic... + + sendConfirmationEmail(user); + } + + private void sendConfirmationEmail(final User user) { + MimeMessagePreparator preparator = new MimeMessagePreparator() { + public void prepare(MimeMessage mimeMessage) throws Exception { + MimeMessageHelper message = new MimeMessageHelper(mimeMessage); + message.setTo(user.getEmailAddress()); + message.setFrom("webmaster@csonth.gov.uk"); // could be parameterized... + Map model = new HashMap(); + model.put("user", user); + String text = VelocityEngineUtils.mergeTemplateIntoString( + velocityEngine, "com/dns/registration-confirmation.vm", model); + message.setText(text, true); + } + }; + this.mailSender.send(preparator); + } + + } +---- + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + <?xml version="1.0" encoding="UTF-8"?> + <beans xmlns="http://www.springframework.org/schema/beans" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://www.springframework.org/schema/beans + http://www.springframework.org/schema/beans/spring-beans.xsd"> + + <bean id="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl"> + <property name="host" value="mail.csonth.gov.uk"/> + </bean> + + <bean id="registrationService" class="com.foo.SimpleRegistrationService"> + <property name="mailSender" ref="mailSender"/> + <property name="velocityEngine" ref="velocityEngine"/> + </bean> + + <bean id="velocityEngine" class="org.springframework.ui.velocity.VelocityEngineFactoryBean"> + <property name="velocityProperties"> + <value> + resource.loader=class + class.resource.loader.class=org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader + </value> + </property> + </bean> + + </beans> +---- + diff --git a/src/asciidoc/mvc.adoc b/src/asciidoc/mvc.adoc new file mode 100644 index 000000000000..5f8de8fd8367 --- /dev/null +++ b/src/asciidoc/mvc.adoc @@ -0,0 +1,4867 @@ +[[mvc]] +== Web MVC framework + + + + +[[mvc-introduction]] +=== Introduction to Spring Web MVC framework +The Spring Web model-view-controller (MVC) framework is designed around a +`DispatcherServlet` that dispatches requests to handlers, with configurable handler +mappings, view resolution, locale, time zone and theme resolution as well as support for +uploading files. The default handler is based on the `@Controller` and `@RequestMapping` +annotations, offering a wide range of flexible handling methods. With the introduction +of Spring 3.0, the `@Controller` mechanism also allows you to create RESTful Web sites +and applications, through the `@PathVariable` annotation and other features. + +**** +"Open for extension..." +A key design principle in Spring Web MVC and in Spring in general is the "__Open for +extension, closed for modification__" principle. + +Some methods in the core classes of Spring Web MVC are marked `final`. As a developer +you cannot override these methods to supply your own behavior. This has not been done +arbitrarily, but specifically with this principle in mind. + +For an explanation of this principle, refer to __Expert Spring Web MVC and Web Flow__ by +Seth Ladd and others; specifically see the section "A Look At Design," on page 117 of +the first edition. Alternatively, see + +* http://www.objectmentor.com/resources/articles/ocp.pdf[Bob Martin, The Open-Closed + Principle (PDF)] + +You cannot add advice to final methods when you use Spring MVC. For example, you cannot +add advice to the `AbstractController.setSynchronizeOnSession()` method. Refer to +<<aop-understanding-aop-proxies>> for more information on AOP proxies and why you cannot +add advice to final methods. +**** + +In Spring Web MVC you can use any object as a command or form-backing object; you do not +need to implement a framework-specific interface or base class. Spring's data binding is +highly flexible: for example, it treats type mismatches as validation errors that can be +evaluated by the application, not as system errors. Thus you need not duplicate your +business objects' properties as simple, untyped strings in your form objects simply to +handle invalid submissions, or to convert the Strings properly. Instead, it is often +preferable to bind directly to your business objects. + +Spring's view resolution is extremely flexible. A `Controller` is typically responsible +for preparing a model `Map` with data and selecting a view name but it can also write +directly to the response stream and complete the request. View name resolution is highly +configurable through file extension or Accept header content type negotiation, through +bean names, a properties file, or even a custom `ViewResolver` implementation. The model +(the M in MVC) is a `Map` interface, which allows for the complete abstraction of the +view technology. You can integrate directly with template based rendering technologies +such as JSP, Velocity and Freemarker, or directly generate XML, JSON, Atom, and many +other types of content. The model `Map` is simply transformed into an appropriate +format, such as JSP request attributes, a Velocity template model. + + + +[[mvc-features]] +==== Features of Spring Web MVC + +.Spring Web Flow +**** +Spring Web Flow (SWF) aims to be the best solution for the management of web application +page flow. + +SWF integrates with existing frameworks like Spring MVC and JSF, in both Servlet and +Portlet environments. If you have a business process (or processes) that would benefit +from a conversational model as opposed to a purely request model, then SWF may be the +solution. + +SWF allows you to capture logical page flows as self-contained modules that are reusable +in different situations, and as such is ideal for building web application modules that +guide the user through controlled navigations that drive business processes. + +For more information about SWF, consult the +http://projects.spring.io/spring-webflow/[Spring Web Flow website]. +**** + +Spring's web module includes many unique web support features: + +* __Clear separation of roles__. Each role -- controller, validator, command object, + form object, model object, `DispatcherServlet`, handler mapping, view resolver, and so + on -- can be fulfilled by a specialized object. +* __Powerful and straightforward configuration of both framework and application classes + as JavaBeans__. This configuration capability includes easy referencing across + contexts, such as from web controllers to business objects and validators. +* __Adaptability, non-intrusiveness, and flexibility.__ Define any controller method + signature you need, possibly using one of the parameter annotations (such as + @RequestParam, @RequestHeader, @PathVariable, and more) for a given scenario. +* __Reusable business code, no need for duplication__. Use existing business objects + as command or form objects instead of mirroring them to extend a particular framework + base class. +* __Customizable binding and validation__. Type mismatches as application-level + validation errors that keep the offending value, localized date and number binding, + and so on instead of String-only form objects with manual parsing and conversion to + business objects. +* __Customizable handler mapping and view resolution__. Handler mapping and view + resolution strategies range from simple URL-based configuration, to sophisticated, + purpose-built resolution strategies. Spring is more flexible than web MVC frameworks + that mandate a particular technique. +* __Flexible model transfer__. Model transfer with a name/value `Map` supports easy + integration with any view technology. +* __Customizable locale, time zone and theme resolution, support for JSPs with or without + Spring tag library, support for JSTL, support for Velocity without the need for extra + bridges, and so on.__ +* __A simple yet powerful JSP tag library known as the Spring tag library that provides + support for features such as data binding and themes__. The custom tags allow for + maximum flexibility in terms of markup code. For information on the tag library + descriptor, see the appendix entitled <<spring.tld>> +* __A JSP form tag library, introduced in Spring 2.0, that makes writing forms in JSP + pages much easier.__ For information on the tag library descriptor, see the appendix + entitled <<spring-form.tld>> +* __Beans whose lifecycle is scoped to the current HTTP request or HTTP `Session`.__ + This is not a specific feature of Spring MVC itself, but rather of the + `WebApplicationContext` container(s) that Spring MVC uses. These bean scopes are + described in <<beans-factory-scopes-other>> + + + +[[mvc-introduction-pluggability]] +==== Pluggability of other MVC implementations +Non-Spring MVC implementations are preferable for some projects. Many teams expect to +leverage their existing investment in skills and tools, for example with JSF. + +If you do not want to use Spring's Web MVC, but intend to leverage other solutions that +Spring offers, you can integrate the web MVC framework of your choice with Spring +easily. Simply start up a Spring root application context through its +`ContextLoaderListener`, and access it through its `ServletContext` attribute (or +Spring's respective helper method) from within any action object. No "plug-ins" +are involved, so no dedicated integration is necessary. From the web layer's point of +view, you simply use Spring as a library, with the root application context instance as +the entry point. + +Your registered beans and Spring's services can be at your fingertips even without +Spring's Web MVC. Spring does not compete with other web frameworks in this scenario. +It simply addresses the many areas that the pure web MVC frameworks do not, from bean +configuration to data access and transaction handling. So you can enrich your +application with a Spring middle tier and/or data access tier, even if you just want +to use, for example, the transaction abstraction with JDBC or Hibernate. + + + + +[[mvc-servlet]] +=== The DispatcherServlet + +Spring's web MVC framework is, like many other web MVC frameworks, request-driven, +designed around a central Servlet that dispatches requests to controllers and offers +other functionality that facilitates the development of web applications. Spring's +`DispatcherServlet` however, does more than just that. It is completely integrated with +the Spring IoC container and as such allows you to use every other feature that Spring +has. + +The request processing workflow of the Spring Web MVC `DispatcherServlet` is illustrated +in the following diagram. The pattern-savvy reader will recognize that the +`DispatcherServlet` is an expression of the "Front Controller" design pattern (this is a +pattern that Spring Web MVC shares with many other leading web frameworks). + +image::images/mvc.png[width=400] + +The request processing workflow in Spring Web MVC (high level) + +The `DispatcherServlet` is an actual `Servlet` (it inherits from the `HttpServlet` base +class), and as such is declared in the `web.xml` of your web application. You need to +map requests that you want the `DispatcherServlet` to handle, by using a URL mapping in +the same `web.xml` file. This is standard Java EE Servlet configuration; the following +example shows such a `DispatcherServlet` declaration and mapping: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + <web-app> + <servlet> + <servlet-name>example</servlet-name> + <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> + <load-on-startup>1</load-on-startup> + </servlet> + + <servlet-mapping> + <servlet-name>example</servlet-name> + <url-pattern>/example/*</url-pattern> + </servlet-mapping> + + </web-app> +---- + +In the preceding example, all requests starting with `/example` will be handled by the +`DispatcherServlet` instance named `example`. In a Servlet 3.0+ environment, you also +have the option of configuring the Servlet container programmatically. Below is the code +based equivalent of the above `web.xml` example: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class MyWebApplicationInitializer implements WebApplicationInitializer { + + @Override + public void onStartup(ServletContext container) { + ServletRegistration.Dynamic registration = container.addServlet("dispatcher", new DispatcherServlet()); + registration.setLoadOnStartup(1); + registration.addMapping("/example/*"); + } + + } +---- + +`WebApplicationInitializer` is an interface provided by Spring MVC that ensures your +code-based configuration is detected and automatically used to initialize any Servlet 3 +container. An abstract base class implementation of this interace named +`AbstractDispatcherServletInitializer` makes it even easier to register the +`DispatcherServlet` by simply specifying its servlet mapping. +See <<mvc-container-config,Code-based Servlet container initialization>> for more details. + +The above is only the first step in setting up Spring Web MVC. You now need to configure +the various beans used by the Spring Web MVC framework (over and above the +`DispatcherServlet` itself). + +As detailed in <<context-introduction>>, `ApplicationContext` instances in Spring can be +scoped. In the Web MVC framework, each `DispatcherServlet` has its own +`WebApplicationContext`, which inherits all the beans already defined in the root +`WebApplicationContext`. These inherited beans can be overridden in the servlet-specific +scope, and you can define new scope-specific beans local to a given Servlet instance. + +.Context hierarchy in Spring Web MVC +image::images/mvc-contexts.gif[width=400] + +Upon initialization of a `DispatcherServlet`, Spring MVC looks for a file named +__[servlet-name]-servlet.xml__ in the `WEB-INF` directory of your web application and +creates the beans defined there, overriding the definitions of any beans defined with +the same name in the global scope. + +Consider the following `DispatcherServlet` Servlet configuration (in the `web.xml` file): + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + <web-app> + <servlet> + <servlet-name>**golfing**</servlet-name> + <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> + <load-on-startup>1</load-on-startup> + </servlet> + <servlet-mapping> + <servlet-name>**golfing**</servlet-name> + <url-pattern>/golfing/*</url-pattern> + </servlet-mapping> + </web-app> +---- + +With the above Servlet configuration in place, you will need to have a file called +`/WEB-INF/golfing-servlet.xml` in your application; this file will contain all of your +Spring Web MVC-specific components (beans). You can change the exact location of this +configuration file through a Servlet initialization parameter (see below for details). + +It is also possible to have just one root context for single DispatcherServlet scenarios +by setting an empty contextConfigLocation servlet init parameter, as shown below: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + <web-app> + <context-param> + <param-name>contextConfigLocation</param-name> + <param-value>/WEB-INF/root-context.xml</param-value> + </context-param> + <servlet> + <servlet-name>dispatcher</servlet-name> + <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> + <init-param> + <param-name>contextConfigLocation</param-name> + <param-value></param-value> + </init-param> + <load-on-startup>1</load-on-startup> + </servlet> + <servlet-mapping> + <servlet-name>dispatcher</servlet-name> + <url-pattern>/*</url-pattern> + </servlet-mapping> + <listener> + <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> + </listener> + </web-app> +---- + + +The `WebApplicationContext` is an extension of the plain `ApplicationContext` that has +some extra features necessary for web applications. It differs from a normal +`ApplicationContext` in that it is capable of resolving themes (see +<<mvc-themeresolver>>), and that it knows which Servlet it is associated with (by having +a link to the `ServletContext`). The `WebApplicationContext` is bound in the +`ServletContext`, and by using static methods on the `RequestContextUtils` class you can +always look up the `WebApplicationContext` if you need access to it. + + + +[[mvc-servlet-special-bean-types]] +==== Special Bean Types In the WebApplicationContext + +The Spring `DispatcherServlet` uses special beans to process requests and render the +appropriate views. These beans are part of Spring MVC. You can choose which special +beans to use by simply configuring one or more of them in the `WebApplicationContext`. +However, you don't need to do that initially since Spring MVC maintains a list of +default beans to use if you don't configure any. More on that in the next section. First +see the table below listing the special bean types the `DispatcherServlet` relies on. + +[[mvc-webappctx-special-beans-tbl]] +.Special bean types in the WebApplicationContext +|=== +| Bean type| Explanation + +| <<mvc-handlermapping,HandlerMapping>> +| Maps incoming requests to handlers and a list of pre- and post-processors (handler + interceptors) based on some criteria the details of which vary by `HandlerMapping` + implementation. The most popular implementation supports annotated controllers but + other implementations exists as well. + +| HandlerAdapter +| Helps the `DispatcherServlet` to invoke a handler mapped to a request regardless of + the handler is actually invoked. For example, invoking an annotated controller + requires resolving various annotations. Thus the main purpose of a `HandlerAdapter` is + to shield the `DispatcherServlet` from such details. + +| <<mvc-exceptionhandlers,HandlerExceptionResolver>> +| Maps exceptions to views also allowing for more complex exception handling code. + +| <<mvc-viewresolver,ViewResolver>> +| Resolves logical String-based view names to actual `View` types. + +| <<mvc-localeresolver,LocaleResolver>> & <<mvc-timezone,LocaleContextResolver>> +| Resolves the locale a client is using and possibly their time zone, in order to be able + to offer internationalized views + +| <<mvc-themeresolver,ThemeResolver>> +| Resolves themes your web application can use, for example, to offer personalized layouts + +| <<mvc-multipart,MultipartResolver>> +| Parses multi-part requests for example to support processing file uploads from HTML + forms. + +| <<mvc-flash-attributes,FlashMapManager>> +| Stores and retrieves the "input" and the "output" `FlashMap` that can be used to pass + attributes from one request to another, usually across a redirect. +|=== + + + +[[mvc-servlet-config]] +==== Default DispatcherServlet Configuration +As mentioned in the previous section for each special bean the `DispatcherServlet` +maintains a list of implementations to use by default. This information is kept in the +file `DispatcherServlet.properties` in the package `org.springframework.web.servlet`. + +All special beans have some reasonable defaults of their own. Sooner or later though +you'll need to customize one or more of the properties these beans provide. For example +it's quite common to configure an `InternalResourceViewResolver` settings its `prefix` +property to the parent location of view files. + +Regardless of the details, the important concept to understand here is that once +you configure a special bean such as an `InternalResourceViewResolver` in your +`WebApplicationContext`, you effectively override the list of default implementations +that would have been used otherwise for that special bean type. For example if you +configure an `InternalResourceViewResolver`, the default list of `ViewResolver` +implementations is ignored. + +In <<mvc-config>> you'll learn about other options for configuring Spring MVC including +MVC Java config and the MVC XML namespace both of which provide a simple starting point +and assume little knowledge of how Spring MVC works. Regardless of how you choose to +configure your application, the concepts explained in this section are fundamental +should be of help to you. + + + +[[mvc-servlet-sequence]] +==== DispatcherServlet Processing Sequence +After you set up a `DispatcherServlet`, and a request comes in for that specific +`DispatcherServlet`, the `DispatcherServlet` starts processing the request as follows: + +* The `WebApplicationContext` is searched for and bound in the request as an attribute + that the controller and other elements in the process can use. It is bound by default + under the key `DispatcherServlet.WEB_APPLICATION_CONTEXT_ATTRIBUTE`. +* The locale resolver is bound to the request to enable elements in the process to + resolve the locale to use when processing the request (rendering the view, preparing + data, and so on). If you do not need locale resolving, you do not need it. +* The theme resolver is bound to the request to let elements such as views determine + which theme to use. If you do not use themes, you can ignore it. +* If you specify a multipart file resolver, the request is inspected for multiparts; if + multiparts are found, the request is wrapped in a `MultipartHttpServletRequest` for + further processing by other elements in the process. See <<mvc-multipart>> for further + information about multipart handling. +* An appropriate handler is searched for. If a handler is found, the execution chain + associated with the handler (preprocessors, postprocessors, and controllers) is + executed in order to prepare a model or rendering. +* If a model is returned, the view is rendered. If no model is returned, (may be due to + a preprocessor or postprocessor intercepting the request, perhaps for security + reasons), no view is rendered, because the request could already have been fulfilled. + +Handler exception resolvers that are declared in the `WebApplicationContext` pick up +exceptions that are thrown during processing of the request. Using these exception +resolvers allows you to define custom behaviors to address exceptions. + +The Spring `DispatcherServlet` also supports the return of the +__last-modification-date__, as specified by the Servlet API. The process of determining +the last modification date for a specific request is straightforward: the +`DispatcherServlet` looks up an appropriate handler mapping and tests whether the +handler that is found implements the __LastModified__ interface. If so, the value of the +`long getLastModified(request)` method of the `LastModified` interface is returned to +the client. + +You can customize individual `DispatcherServlet` instances by adding Servlet +initialization parameters ( `init-param` elements) to the Servlet declaration in the +`web.xml` file. See the following table for the list of supported parameters. + +[[mvc-disp-servlet-init-params-tbl]] +.DispatcherServlet initialization parameters +|=== +| Parameter| Explanation + +| `contextClass` +| Class that implements `WebApplicationContext`, which instantiates the context used by + this Servlet. By default, the `XmlWebApplicationContext` is used. + +| `contextConfigLocation` +| String that is passed to the context instance (specified by `contextClass`) to + indicate where context(s) can be found. The string consists potentially of multiple + strings (using a comma as a delimiter) to support multiple contexts. In case of + multiple context locations with beans that are defined twice, the latest location + takes precedence. + +| `namespace` +| Namespace of the `WebApplicationContext`. Defaults to `[servlet-name]-servlet`. +|=== + + + + +[[mvc-controller]] +=== Implementing Controllers +Controllers provide access to the application behavior that you typically define through +a service interface. Controllers interpret user input and transform it into a model that +is represented to the user by the view. Spring implements a controller in a very +abstract way, which enables you to create a wide variety of controllers. + +Spring 2.5 introduced an annotation-based programming model for MVC controllers that +uses annotations such as `@RequestMapping`, `@RequestParam`, `@ModelAttribute`, and so +on. This annotation support is available for both Servlet MVC and Portlet MVC. +Controllers implemented in this style do not have to extend specific base classes or +implement specific interfaces. Furthermore, they do not usually have direct dependencies +on Servlet or Portlet APIs, although you can easily configure access to Servlet or +Portlet facilities. + +[TIP] +==== + +Available in the https://github.com/spring-projects/[spring-projects Org on Github], +a number of web applications leverage the annotation support described in this section +including __MvcShowcase__, __MvcAjax__, __MvcBasic__, __PetClinic__, __PetCare__, +and others. +==== + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Controller + public class HelloWorldController { + + @RequestMapping("/helloWorld") + public String helloWorld(Model model) { + model.addAttribute("message", "Hello World!"); + return "helloWorld"; + } + } +---- + +As you can see, the `@Controller` and `@RequestMapping` annotations allow flexible +method names and signatures. In this particular example the method accepts a `Model` and +returns a view name as a `String`, but various other method parameters and return values +can be used as explained later in this section. `@Controller` and `@RequestMapping` and +a number of other annotations form the basis for the Spring MVC implementation. This +section documents these annotations and how they are most commonly used in a Servlet +environment. + + + +[[mvc-ann-controller]] +==== Defining a controller with @Controller + +The `@Controller` annotation indicates that a particular class serves the role of +a __controller__. Spring does not require you to extend any controller base class or +reference the Servlet API. However, you can still reference Servlet-specific features if +you need to. + +The `@Controller` annotation acts as a stereotype for the annotated class, indicating +its role. The dispatcher scans such annotated classes for mapped methods and detects +`@RequestMapping` annotations (see the next section). + +You can define annotated controller beans explicitly, using a standard Spring bean +definition in the dispatcher's context. However, the `@Controller` stereotype also +allows for autodetection, aligned with Spring general support for detecting component +classes in the classpath and auto-registering bean definitions for them. + +To enable autodetection of such annotated controllers, you add component scanning to +your configuration. Use the __spring-context__ schema as shown in the following XML +snippet: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + <?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:p="http://www.springframework.org/schema/p" + 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"> + + <context:component-scan base-package="org.springframework.samples.petclinic.web"/> + + <!-- ... --> + + </beans> +---- + + + +[[mvc-ann-requestmapping]] +==== Mapping Requests With @RequestMapping + +You use the `@RequestMapping` annotation to map URLs such as `/appointments` onto an +entire class or a particular handler method. Typically the class-level annotation maps a +specific request path (or path pattern) onto a form controller, with additional +method-level annotations narrowing the primary mapping for a specific HTTP method +request method ("GET", "POST", etc.) or an HTTP request parameter condition. + +The following example from the __Petcare__ sample shows a controller in a Spring MVC +application that uses this annotation: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Controller + **@RequestMapping("/appointments")** + public class AppointmentsController { + + private final AppointmentBook appointmentBook; + + @Autowired + public AppointmentsController(AppointmentBook appointmentBook) { + this.appointmentBook = appointmentBook; + } + + **@RequestMapping(method = RequestMethod.GET)** + public Map<String, Appointment> get() { + return appointmentBook.getAppointmentsForToday(); + } + + **@RequestMapping(value="/{day}", method = RequestMethod.GET)** + public Map<String, Appointment> getForDay(@PathVariable @DateTimeFormat(iso=ISO.DATE) Date day, Model model) { + return appointmentBook.getAppointmentsForDay(day); + } + + **@RequestMapping(value="/new", method = RequestMethod.GET)** + public AppointmentForm getNewForm() { + return new AppointmentForm(); + } + + **@RequestMapping(method = RequestMethod.POST)** + public String add(@Valid AppointmentForm appointment, BindingResult result) { + if (result.hasErrors()) { + return "appointments/new"; + } + appointmentBook.addAppointment(appointment); + return "redirect:/appointments"; + } + } +---- + +In the example, the `@RequestMapping` is used in a number of places. The first usage is +on the type (class) level, which indicates that all handling methods on this controller +are relative to the `/appointments` path. The `get()` method has a further +`@RequestMapping` refinement: it only accepts GET requests, meaning that an HTTP GET for +`/appointments` invokes this method. The `post()` has a similar refinement, and the +`getNewForm()` combines the definition of HTTP method and path into one, so that GET +requests for `appointments/new` are handled by that method. + +The `getForDay()` method shows another usage of `@RequestMapping`: URI templates. (See +<<mvc-ann-requestmapping-uri-templates,the next section >>). + +A `@RequestMapping` on the class level is not required. Without it, all paths are simply +absolute, and not relative. The following example from the __PetClinic__ sample +application shows a multi-action controller using `@RequestMapping`: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Controller + public class ClinicController { + + private final Clinic clinic; + + @Autowired + public ClinicController(Clinic clinic) { + this.clinic = clinic; + } + + **@RequestMapping("/")** + public void welcomeHandler() { + } + + **@RequestMapping("/vets")** + public ModelMap vetsHandler() { + return new ModelMap(this.clinic.getVets()); + } + + } +---- + +[[mvc-ann-requestmapping-proxying]] +===== ++@Controller++'s and AOP Proxying + +In some cases a controller may need to be decorated with an AOP proxy at runtime. +One example is if you choose to have `@Transactional` annotations directly on the +controller. When this is the case, for controllers specifically, we recommend +using class-based proxying. This is typically the default choice with controllers. +However if a controller must implement an interface that is not a Spring Context +callback (e.g. `InitializingBean`, `*Aware`, etc), you may need to explicitly +configure class-based proxying. For example with `<tx:annotation-driven />`, +change to `<tx:annotation-driven proxy-target-class="true" />`. + +[[mvc-ann-requestmapping-31-vs-30]] +===== New Support Classes for @RequestMapping methods in Spring MVC 3.1 +Spring 3.1 introduced a new set of support classes for `@RequestMapping` methods called +`RequestMappingHandlerMapping` and `RequestMappingHandlerAdapter` respectively. They are +recommended for use and even required to take advantage of new features in Spring MVC +3.1 and going forward. The new support classes are enabled by default by the MVC +namespace and the MVC Java config but must be configured explicitly if using neither. +This section describes a few important differences between the old and the new support +classes. + +Prior to Spring 3.1, type and method-level request mappings were examined in two +separate stages -- a controller was selected first by the +`DefaultAnnotationHandlerMapping` and the actual method to invoke was narrowed down +second by the `AnnotationMethodHandlerAdapter`. + +With the new support classes in Spring 3.1, the `RequestMappingHandlerMapping` is the +only place where a decision is made about which method should process the request. Think +of controller methods as a collection of unique endpoints with mappings for each method +derived from type and method-level `@RequestMapping` information. + +This enables some new possibilities. For once a `HandlerInterceptor` or a +`HandlerExceptionResolver` can now expect the Object-based handler to be a +`HandlerMethod`, which allows them to examine the exact method, its parameters and +associated annotations. The processing for a URL no longer needs to be split across +different controllers. + +There are also several things no longer possible: + +* Select a controller first with a `SimpleUrlHandlerMapping` or + `BeanNameUrlHandlerMapping` and then narrow the method based on `@RequestMapping` + annotations. +* Rely on method names as a fall-back mechanism to disambiguate between two + `@RequestMapping` methods that don't have an explicit path mapping URL path but + otherwise match equally, e.g. by HTTP method. In the new support classes + `@RequestMapping` methods have to be mapped uniquely. +* Have a single default method (without an explicit path mapping) with which requests + are processed if no other controller method matches more concretely. In the new + support classes if a matching method is not found a 404 error is raised. + +The above features are still supported with the existing support classes. However to +take advantage of new Spring MVC 3.1 features you'll need to use the new support classes. + + +[[mvc-ann-requestmapping-uri-templates]] +===== URI Template Patterns +__URI templates__ can be used for convenient access to selected parts of a URL in a +`@RequestMapping` method. + +A URI Template is a URI-like string, containing one or more variable names. When you +substitute values for these variables, the template becomes a URI. The +http://bitworking.org/projects/URI-Templates/[proposed RFC] for URI Templates defines +how a URI is parameterized. For example, the URI Template +`http://www.example.com/users/{userId}` contains the variable __userId__. Assigning the +value __fred__ to the variable yields `http://www.example.com/users/fred`. + +In Spring MVC you can use the `@PathVariable` annotation on a method argument to bind it +to the value of a URI template variable: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @RequestMapping(value="/owners/{ownerId}", method=RequestMethod.GET) + public String findOwner(**@PathVariable** String ownerId, Model model) { + Owner owner = ownerService.findOwner(ownerId); + model.addAttribute("owner", owner); + return "displayOwner"; + } +---- + +The URI Template " `/owners/{ownerId}`" specifies the variable name `ownerId`. When the +controller handles this request, the value of `ownerId` is set to the value found in the +appropriate part of the URI. For example, when a request comes in for `/owners/fred`, +the value of `ownerId` is `fred`. + +[TIP] +==== + +To process the @PathVariable annotation, Spring MVC needs to find the matching URI +template variable by name. You can specify it in the annotation: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @RequestMapping(value="/owners/{ownerId}", method=RequestMethod.GET) + public String findOwner(**@PathVariable("ownerId")** String theOwner, Model model) { + // implementation omitted + } +---- + +Or if the URI template variable name matches the method argument name you can omit that +detail. As long as your code is not compiled without debugging information, Spring MVC +will match the method argument name to the URI template variable name: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @RequestMapping(value="/owners/{ownerId}", method=RequestMethod.GET) + public String findOwner(**@PathVariable** String ownerId, Model model) { + // implementation omitted + } +---- +==== + +A method can have any number of `@PathVariable` annotations: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @RequestMapping(value="/owners/{ownerId}/pets/{petId}", method=RequestMethod.GET) + public String findPet(**@PathVariable** String ownerId, **@PathVariable** String petId, Model model) { + Owner owner = ownerService.findOwner(ownerId); + Pet pet = owner.getPet(petId); + model.addAttribute("pet", pet); + return "displayPet"; + } +---- + +When a `@PathVariable` annotation is used on a `Map<String, String>` argument, the map +is populated with all URI template variables. + +A URI template can be assembled from type and path level __@RequestMapping__ +annotations. As a result the `findPet()` method can be invoked with a URL such as +`/owners/42/pets/21`. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Controller + @RequestMapping(**"/owners/{ownerId}"**) + public class RelativePathUriTemplateController { + + @RequestMapping(**"/pets/{petId}"**) + public void findPet(@PathVariable String ownerId, @PathVariable String petId, Model model) { + // implementation omitted + } + + } +---- + +A `@PathVariable` argument can be of __any simple type__ such as int, long, Date, etc. +Spring automatically converts to the appropriate type or throws a +`TypeMismatchException` if it fails to do so. You can also register support for parsing +additional data types. See <<mvc-ann-typeconversion>> and <<mvc-ann-webdatabinder>>. + + +[[mvc-ann-requestmapping-uri-templates-regex]] +===== URI Template Patterns with Regular Expressions +Sometimes you need more precision in defining URI template variables. Consider the URL +`"/spring-web/spring-web-3.0.5.jar"`. How do you break it down into multiple parts? + +The `@RequestMapping` annotation supports the use of regular expressions in URI template +variables. The syntax is `{varName:regex}` where the first part defines the variable +name and the second - the regular expression.For example: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @RequestMapping("/spring-web/{symbolicName:[a-z-]+}-{version:\\d\\.\\d\\.\\d}{extension:\\.[a-z]+}") + public void handle(@PathVariable String version, @PathVariable String extension) { + // ... + } + } +---- + + +[[mvc-ann-requestmapping-patterns]] +===== Path Patterns +In addition to URI templates, the `@RequestMapping` annotation also supports Ant-style +path patterns (for example, `/myPath/*.do`). A combination of URI template variables and +Ant-style globs is also supported (e.g. `/owners/*/pets/{petId}`). + + +[[mvc-ann-requestmapping-pattern-comparison]] +===== Path Pattern Comparison +When a URL matches multiple patterns, a sort is used to find the most specific match. + +A pattern with a lower count of URI variables and wild cards is considered more specific. +For example `/hotels/{hotel}/*` has 1 URI variable and 1 wild card and is considered +more specific than `/hotels/{hotel}/**` which as 1 URI variable and 2 wild cards. + +If two patterns have the same count, the one that is longer is considered more specific. +For example `/foo/bar*` is longer and considered more specific than `/foo/*`. + +When two patterns have the same count and length, the pattern with fewer wild cards is considered more specific. +For example `/hotels/{hotel}` is more specific than `/hotels/*`. + +There are also some additional special rules: + +* The *default mapping pattern* `/**` is less specific than any other pattern. +For example `/api/{a}/{b}/{c}` is more specific. +* A *prefix pattern* such as `/public/**` is less specific than any other pattern that doesn't contain double wildcards. +For example `/public/path3/{a}/{b}/{c}` is more specific. + +For the full details see `AntPatternComparator` in `AntPathMatcher`. Note that the PathMatcher +can be customized (see <<mvc-config-path-matching>> in the section on configuring Spring MVC). + + +[[mvc-ann-requestmapping-placeholders]] +===== Path Patterns with Placeholders +Patterns in `@RequestMapping` annotations support ${...} placeholders against local +properties and/or system properties and environment variables. This may be useful in +cases where the path a controller is mapped to may need to be customized through +configuration. For more information on placeholders, see the javadocs of the +`PropertyPlaceholderConfigurer` class. + + + +[[mvc-ann-requestmapping-suffix-pattern-match]] +===== Path Pattern Matching By Suffix +By default Spring MVC automatically performs `".*"` suffix pattern matching so +that a controller mapped to `/person` is also implicitly mapped to `/person.*`. +This allows indicating content types via file extensions, e.g. `/person.pdf`, +`/person.xml`, etc. A common pitfall however is when the last path segment of the +mapping is a URI variable, e.g. `/person/{id}`. While a request for `/person/1.json` +would correctly result in path variable id=1 and extension ".json", when the id +naturally contains a dot, e.g. `/person/joe@email.com` the result does not match +expectations. Clearly here ".com" is not a file extension. + +The proper way to address this is to configure Spring MVC to only do suffix pattern +matching against file extensions registered for content negotiation purposes. +For more on this, first see <<mvc-config-content-negotiation>> and then +<<mvc-config-path-matching>> showing how to enable suffix pattern matching +along with how to use registered suffix patterns only. + + + +[[mvc-ann-matrix-variables]] +===== Matrix Variables +The URI specification http://tools.ietf.org/html/rfc3986#section-3.3[RFC 3986] defines +the possibility of including name-value pairs within path segments. There is no specific +term used in the spec. The general "URI path parameters" could be applied although the +more unique http://www.w3.org/DesignIssues/MatrixURIs.html["Matrix URIs"], originating +from an old post by Tim Berners-Lee, is also frequently used and fairly well known. +Within Spring MVC these are referred to as matrix variables. + +Matrix variables can appear in any path segment, each matrix variable separated with a +";" (semicolon). For example: `"/cars;color=red;year=2012"`. Multiple values may be +either "," (comma) separated `"color=red,green,blue"` or the variable name may be +repeated `"color=red;color=green;color=blue"`. + +If a URL is expected to contain matrix variables, the request mapping pattern must +represent them with a URI template. This ensures the request can be matched correctly +regardless of whether matrix variables are present or not and in what order they are +provided. + +Below is an example of extracting the matrix variable "q": + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + // GET /pets/42;q=11;r=22 + + @RequestMapping(value = "/pets/{petId}", method = RequestMethod.GET) + public void findPet(@PathVariable String petId, @MatrixVariable int q) { + + // petId == 42 + // q == 11 + + } +---- + +Since all path segments may contain matrix variables, in some cases you need to be more +specific to identify where the variable is expected to be: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + // GET /owners/42;q=11/pets/21;q=22 + + @RequestMapping(value = "/owners/{ownerId}/pets/{petId}", method = RequestMethod.GET) + public void findPet( + @MatrixVariable(value="q", pathVar="ownerId") int q1, + @MatrixVariable(value="q", pathVar="petId") int q2) { + + // q1 == 11 + // q2 == 22 + + } +---- + +A matrix variable may be defined as optional and a default value specified: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + // GET /pets/42 + + @RequestMapping(value = "/pets/{petId}", method = RequestMethod.GET) + public void findPet(@MatrixVariable(required=false, defaultValue="1") int q) { + + // q == 1 + + } +---- + +All matrix variables may be obtained in a Map: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + // GET /owners/42;q=11;r=12/pets/21;q=22;s=23 + + @RequestMapping(value = "/owners/{ownerId}/pets/{petId}", method = RequestMethod.GET) + public void findPet( + @MatrixVariable Map<String, String> matrixVars, + @MatrixVariable(pathVar="petId"") Map<String, String> petMatrixVars) { + + // matrixVars: ["q" : [11,22], "r" : 12, "s" : 23] + // petMatrixVars: ["q" : 11, "s" : 23] + + } +---- + +Note that to enable the use of matrix variables, you must set the +`removeSemicolonContent` property of `RequestMappingHandlerMapping` to `false`. By +default it is set to `true`. + +[TIP] +==== + +The MVC Java config and the MVC namespace both provide options for enabling the use of +matrix variables. + +If you are using Java config, The <<mvc-config-advanced-java, Advanced Customizations +with MVC Java Config>> section describes how the `RequestMappingHandlerMapping` can +be customized. + +In the MVC namespace, the `<mvc:annotation-driven>` element has an +`enable-matrix-variables` attribute that should be set to `true`. By default it is set +to `false`. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + <?xml version="1.0" encoding="UTF-8"?> + <beans xmlns="http://www.springframework.org/schema/beans" + xmlns:mvc="http://www.springframework.org/schema/mvc" + 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.xsd + http://www.springframework.org/schema/mvc + http://www.springframework.org/schema/mvc/spring-mvc.xsd"> + + <mvc:annotation-driven enable-matrix-variables="true"/> + + </beans> +---- +==== + +[[mvc-ann-requestmapping-consumes]] +===== Consumable Media Types +You can narrow the primary mapping by specifying a list of consumable media types. The +request will be matched only if the __Content-Type__ request header matches the specified +media type. For example: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Controller + @RequestMapping(value = "/pets", method = RequestMethod.POST, **consumes="application/json"**) + public void addPet(@RequestBody Pet pet, Model model) { + // implementation omitted + } +---- + +Consumable media type expressions can also be negated as in __!text/plain__ to match to +all requests other than those with __Content-Type__ of __text/plain__. + +[TIP] +==== + +The __consumes__ condition is supported on the type and on the method level. Unlike most +other conditions, when used at the type level, method-level consumable types override +rather than extend type-level consumable types. +==== + + +[[mvc-ann-requestmapping-produces]] +===== Producible Media Types +You can narrow the primary mapping by specifying a list of producible media types. The +request will be matched only if the __Accept__ request header matches one of these +values. Furthermore, use of the __produces__ condition ensures the actual content type +used to generate the response respects the media types specified in the __produces__ +condition. For example: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Controller + @RequestMapping(value = "/pets/{petId}", method = RequestMethod.GET, **produces="application/json"**) + @ResponseBody + public Pet getPet(@PathVariable String petId, Model model) { + // implementation omitted + } +---- + +Just like with __consumes__, producible media type expressions can be negated as in +__!text/plain__ to match to all requests other than those with an __Accept__ header +value of __text/plain__. + +[TIP] +==== +The __produces__ condition is supported on the type and on the method level. Unlike most +other conditions, when used at the type level, method-level producible types override +rather than extend type-level producible types. +==== + + +[[mvc-ann-requestmapping-params-and-headers]] +===== Request Parameters and Header Values +You can narrow request matching through request parameter conditions such as +`"myParam"`, `"!myParam"`, or `"myParam=myValue"`. The first two test for request +parameter presence/absence and the third for a specific parameter value. Here is an +example with a request parameter value condition: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Controller + @RequestMapping("/owners/{ownerId}") + public class RelativePathUriTemplateController { + + @RequestMapping(value = "/pets/{petId}", method = RequestMethod.GET, **params="myParam=myValue"**) + public void findPet(@PathVariable String ownerId, @PathVariable String petId, Model model) { + // implementation omitted + } + + } +---- + +The same can be done to test for request header presence/absence or to match based on a +specific request header value: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Controller + @RequestMapping("/owners/{ownerId}") + public class RelativePathUriTemplateController { + + @RequestMapping(value = "/pets", method = RequestMethod.GET, **headers="myHeader=myValue"**) + public void findPet(@PathVariable String ownerId, @PathVariable String petId, Model model) { + // implementation omitted + } + + } +---- + +[TIP] +==== + +Although you can match to __Content-Type__ and __Accept__ header values using media type +wild cards (for example __"content-type=text/*"__ will match to __"text/plain"__ and +__"text/html"__), it is recommended to use the __consumes__ and __produces__ conditions +respectively instead. They are intended specifically for that purpose. +==== + + + +[[mvc-ann-methods]] +==== Defining @RequestMapping handler methods + +An `@RequestMapping` handler method can have a very flexible signatures. The supported +method arguments and return values are described in the following section. Most +arguments can be used in arbitrary order with the only exception of `BindingResult` +arguments. This is described in the next section. + +[NOTE] +==== +Spring 3.1 introduced a new set of support classes for `@RequestMapping` methods called +`RequestMappingHandlerMapping` and `RequestMappingHandlerAdapter` respectively. They are +recommended for use and even required to take advantage of new features in Spring MVC +3.1 and going forward. The new support classes are enabled by default from the MVC +namespace and with use of the MVC Java config but must be configured explicitly if using +neither. +==== + + +[[mvc-ann-arguments]] +===== Supported method argument types +The following are the supported method arguments: + +* Request or response objects (Servlet API). Choose any specific request or response + type, for example `ServletRequest` or `HttpServletRequest`. +* Session object (Servlet API): of type `HttpSession`. An argument of this type enforces + the presence of a corresponding session. As a consequence, such an argument is never + `null`. + +[NOTE] +==== +Session access may not be thread-safe, in particular in a Servlet environment. Consider +setting the ++RequestMappingHandlerAdapter++'s "synchronizeOnSession" flag to "true" if +multiple requests are allowed to access a session concurrently. +==== + +* `org.springframework.web.context.request.WebRequest` or + `org.springframework.web.context.request.NativeWebRequest`. Allows for generic request + parameter access as well as request/session attribute access, without ties to the + native Servlet/Portlet API. +* `java.util.Locale` for the current request locale, determined by the most specific + locale resolver available, in effect, the configured `LocaleResolver` in a Servlet + environment. +* `java.io.InputStream` / `java.io.Reader` for access to the request's content. This + value is the raw InputStream/Reader as exposed by the Servlet API. +* `java.io.OutputStream` / `java.io.Writer` for generating the response's content. This + value is the raw OutputStream/Writer as exposed by the Servlet API. +* `org.springframework.http.HttpMethod` for the HTTP request method. +* `java.security.Principal` containing the currently authenticated user. +* `@PathVariable` annotated parameters for access to URI template variables. See + <<mvc-ann-requestmapping-uri-templates>>. +* `@MatrixVariable` annotated parameters for access to name-value pairs located in URI + path segments. See <<mvc-ann-matrix-variables>>. +* `@RequestParam` annotated parameters for access to specific Servlet request + parameters. Parameter values are converted to the declared method argument type. See + <<mvc-ann-requestparam>>. +* `@RequestHeader` annotated parameters for access to specific Servlet request HTTP + headers. Parameter values are converted to the declared method argument type. +* `@RequestBody` annotated parameters for access to the HTTP request body. Parameter + values are converted to the declared method argument type using + ++HttpMessageConverter++s. See <<mvc-ann-requestbody>>. +* `@RequestPart` annotated parameters for access to the content of a + "multipart/form-data" request part. See <<mvc-multipart-forms-non-browsers>> and + <<mvc-multipart>>. +* `HttpEntity<?>` parameters for access to the Servlet request HTTP headers and + contents. The request stream will be converted to the entity body using + ++HttpMessageConverter++s. See <<mvc-ann-httpentity>>. +* `java.util.Map` / `org.springframework.ui.Model` / `org.springframework.ui.ModelMap` + for enriching the implicit model that is exposed to the web view. +* `org.springframework.web.servlet.mvc.support.RedirectAttributes` to specify the exact + set of attributes to use in case of a redirect and also to add flash attributes + (attributes stored temporarily on the server-side to make them available to the + request after the redirect). `RedirectAttributes` is used instead of the implicit + model if the method returns a "redirect:" prefixed view name or `RedirectView`. +* Command or form objects to bind request parameters to bean properties (via setters) or + directly to fields, with customizable type conversion, depending on `@InitBinder` + methods and/or the HandlerAdapter configuration. See the `webBindingInitializer` + property on `RequestMappingHandlerAdapter`. Such command objects along with their + validation results will be exposed as model attributes by default, using the command + class class name - e.g. model attribute "orderAddress" for a command object of type + "some.package.OrderAddress". The `ModelAttribute` annotation can be used on a method + argument to customize the model attribute name used. +* `org.springframework.validation.Errors` / + `org.springframework.validation.BindingResult` validation results for a preceding + command or form object (the immediately preceding method argument). +* `org.springframework.web.bind.support.SessionStatus` status handle for marking form + processing as complete, which triggers the cleanup of session attributes that have + been indicated by the `@SessionAttributes` annotation at the handler type level. +* `org.springframework.web.util.UriComponentsBuilder` a builder for preparing a URL + relative to the current request's host, port, scheme, context path, and the literal + part of the servlet mapping. + +The `Errors` or `BindingResult` parameters have to follow the model object that is being +bound immediately as the method signature might have more that one model object and +Spring will create a separate `BindingResult` instance for each of them so the following +sample won't work: + +.Invalid ordering of BindingResult and @ModelAttribute +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @RequestMapping(method = RequestMethod.POST) + public String processSubmit(**@ModelAttribute("pet") Pet pet**, Model model, **BindingResult result**) { ... } +---- + +Note, that there is a `Model` parameter in between `Pet` and `BindingResult`. To get +this working you have to reorder the parameters as follows: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @RequestMapping(method = RequestMethod.POST) + public String processSubmit(**@ModelAttribute("pet") Pet pet**, **BindingResult result**, Model model) { ... } +---- + + +[[mvc-ann-return-types]] +===== Supported method return types +The following are the supported return types: + +* A `ModelAndView` object, with the model implicitly enriched with command objects and + the results of `@ModelAttribute` annotated reference data accessor methods. +* A `Model` object, with the view name implicitly determined through a + `RequestToViewNameTranslator` and the model implicitly enriched with command objects + and the results of `@ModelAttribute` annotated reference data accessor methods. +* A `Map` object for exposing a model, with the view name implicitly determined through + a `RequestToViewNameTranslator` and the model implicitly enriched with command objects + and the results of `@ModelAttribute` annotated reference data accessor methods. +* A `View` object, with the model implicitly determined through command objects and + `@ModelAttribute` annotated reference data accessor methods. The handler method may + also programmatically enrich the model by declaring a `Model` argument (see above). +* A `String` value that is interpreted as the logical view name, with the model + implicitly determined through command objects and `@ModelAttribute` annotated + reference data accessor methods. The handler method may also programmatically enrich + the model by declaring a `Model` argument (see above). +* `void` if the method handles the response itself (by writing the response content + directly, declaring an argument of type `ServletResponse` / `HttpServletResponse` for + that purpose) or if the view name is supposed to be implicitly determined through a + `RequestToViewNameTranslator` (not declaring a response argument in the handler method + signature). +* If the method is annotated with `@ResponseBody`, the return type is written to the + response HTTP body. The return value will be converted to the declared method argument + type using ++HttpMessageConverter++s. See <<mvc-ann-responsebody>>. +* An `HttpEntity<?>` or `ResponseEntity<?>` object to provide access to the Servlet + response HTTP headers and contents. The entity body will be converted to the response + stream using ++HttpMessageConverter++s. See <<mvc-ann-httpentity>>. +* An `HttpHeaders` object to return a response with no body. +* A `Callable<?>` can be returned when the application wants to produce the return value + asynchronously in a thread managed by Spring MVC. +* A `DeferredResult<?>` can be returned when the application wants to produce the return + value from a thread of its own choosing. +* A `ListenableFuture<?>` can be returned when the application wants to produce the return + value from a thread of its own choosing. +* Any other return type is considered to be a single model attribute to be exposed to + the view, using the attribute name specified through `@ModelAttribute` at the method + level (or the default attribute name based on the return type class name). The model + is implicitly enriched with command objects and the results of `@ModelAttribute` + annotated reference data accessor methods. + + +[[mvc-ann-requestparam]] +===== Binding request parameters to method parameters with @RequestParam + +Use the `@RequestParam` annotation to bind request parameters to a method parameter in +your controller. + +The following code snippet shows the usage: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Controller + @RequestMapping("/pets") + @SessionAttributes("pet") + public class EditPetForm { + + // ... + + @RequestMapping(method = RequestMethod.GET) + public String setupForm(**@RequestParam("petId") int petId**, ModelMap model) { + Pet pet = this.clinic.loadPet(petId); + model.addAttribute("pet", pet); + return "petForm"; + } + + // ... + + } +---- + +Parameters using this annotation are required by default, but you can specify that a +parameter is optional by setting ++@RequestParam++'s `required` attribute to `false` +(e.g., `@RequestParam(value="id", required=false)`). + +Type conversion is applied automatically if the target method parameter type is not +`String`. See <<mvc-ann-typeconversion>>. + + +[[mvc-ann-requestbody]] +===== Mapping the request body with the @RequestBody annotation +The `@RequestBody` method parameter annotation indicates that a method parameter should +be bound to the value of the HTTP request body. For example: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @RequestMapping(value = "/something", method = RequestMethod.PUT) + public void handle(@RequestBody String body, Writer writer) throws IOException { + writer.write(body); + } +---- + +You convert the request body to the method argument by using an `HttpMessageConverter`. +`HttpMessageConverter` is responsible for converting from the HTTP request message to an +object and converting from an object to the HTTP response body. The +`RequestMappingHandlerAdapter` supports the `@RequestBody` annotation with the following +default `HttpMessageConverters`: + +* `ByteArrayHttpMessageConverter` converts byte arrays. +* `StringHttpMessageConverter` converts strings. +* `FormHttpMessageConverter` converts form data to/from a MultiValueMap<String, String>. +* `SourceHttpMessageConverter` converts to/from a javax.xml.transform.Source. + +For more information on these converters, see <<rest-message-conversion,Message +Converters>>. Also note that if using the MVC namespace or the MVC Java config, a wider +range of message converters are registered by default. See <<mvc-config-enable>> for more information. + +If you intend to read and write XML, you will need to configure the +`MarshallingHttpMessageConverter` with a specific `Marshaller` and an `Unmarshaller` +implementation from the `org.springframework.oxm` package. The example below shows how +to do that directly in your configuration but if your application is configured through +the MVC namespace or the MVC Java config see <<mvc-config-enable>> instead. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"> + <property name="messageConverters"> + <util:list id="beanList"> + <ref bean="stringHttpMessageConverter"/> + <ref bean="marshallingHttpMessageConverter"/> + </util:list> + </property + </bean> + + <bean id="stringHttpMessageConverter" + class="org.springframework.http.converter.StringHttpMessageConverter"/> + + <bean id="marshallingHttpMessageConverter" + class="org.springframework.http.converter.xml.MarshallingHttpMessageConverter"> + <property name="marshaller" ref="castorMarshaller" /> + <property name="unmarshaller" ref="castorMarshaller" /> + </bean> + + <bean id="castorMarshaller" class="org.springframework.oxm.castor.CastorMarshaller"/> +---- + +An `@RequestBody` method parameter can be annotated with `@Valid`, in which case it will +be validated using the configured `Validator` instance. When using the MVC namespace or +the MVC Java config, a JSR-303 validator is configured automatically assuming a JSR-303 +implementation is available on the classpath. + +Just like with `@ModelAttribute` parameters, an `Errors` argument can be used to examine +the errors. If such an argument is not declared, a `MethodArgumentNotValidException` +will be raised. The exception is handled in the `DefaultHandlerExceptionResolver`, which +sends a `400` error back to the client. + +[NOTE] +==== +Also see <<mvc-config-enable>> for +information on configuring message converters and a validator through the MVC namespace +or the MVC Java config. +==== + + +[[mvc-ann-responsebody]] +===== Mapping the response body with the @ResponseBody annotation + +The `@ResponseBody` annotation is similar to `@RequestBody`. This annotation can be put +on a method and indicates that the return type should be written straight to the HTTP +response body (and not placed in a Model, or interpreted as a view name). For example: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @RequestMapping(value = "/something", method = RequestMethod.PUT) + @ResponseBody + public String helloWorld() { + return "Hello World"; + } +---- + +The above example will result in the text `Hello World` being written to the HTTP +response stream. + +As with `@RequestBody`, Spring converts the returned object to a response body by using +an `HttpMessageConverter`. For more information on these converters, see the previous +section and <<rest-message-conversion,Message Converters>>. + +[[mvc-ann-restcontroller]] +===== Creating REST Controllers with the @RestController annotation + +It's a very common use case to have Controllers implement a REST API, thus serving only +JSON, XML or custom MediaType content. For convenience, instead of annotating all your +`@RequestMapping` methods with `@ResponseBody`, you can annotate your Controller Class +with `@RestController`. + +{javadoc-baseurl}/org/springframework/web/bind/annotation/RestController.html[`@RestController`] +is a stereotype annotation that combines `@ResponseBody` and `@Controller`. More than +that, it gives more meaning to your Controller and also may carry additional semantics +in future releases of the framework. + +As with regular ++@Controller++s, a `@RestController` may be assisted by a +`@ControllerAdvice` Bean. See the <<mvc-ann-controller-advice>> section for more details. + +[[mvc-ann-httpentity]] +===== Using HttpEntity + +The `HttpEntity` is similar to `@RequestBody` and `@ResponseBody`. Besides getting +access to the request and response body, `HttpEntity` (and the response-specific +subclass `ResponseEntity`) also allows access to the request and response headers, like +so: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @RequestMapping("/something") + public ResponseEntity<String> handle(HttpEntity<byte[]> requestEntity) throws UnsupportedEncodingException { + String requestHeader = requestEntity.getHeaders().getFirst("MyRequestHeader")); + byte[] requestBody = requestEntity.getBody(); + + // do something with request header and body + + HttpHeaders responseHeaders = new HttpHeaders(); + responseHeaders.set("MyResponseHeader", "MyValue"); + return new ResponseEntity<String>("Hello World", responseHeaders, HttpStatus.CREATED); + } +---- + +The above example gets the value of the `MyRequestHeader` request header, and reads the +body as a byte array. It adds the `MyResponseHeader` to the response, writes `Hello +World` to the response stream, and sets the response status code to 201 (Created). + +As with `@RequestBody` and `@ResponseBody`, Spring uses `HttpMessageConverter` to +convert from and to the request and response streams. For more information on these +converters, see the previous section and <<rest-message-conversion,Message Converters>>. + + +[[mvc-ann-modelattrib-methods]] +===== Using @ModelAttribute on a method + +The `@ModelAttribute` annotation can be used on methods or on method arguments. This +section explains its usage on methods while the next section explains its usage on +method arguments. + +An `@ModelAttribute` on a method indicates the purpose of that method is to add one or +more model attributes. Such methods support the same argument types as `@RequestMapping` +methods but cannot be mapped directly to requests. Instead `@ModelAttribute` methods in +a controller are invoked before `@RequestMapping` methods, within the same controller. A +couple of examples: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + // Add one attribute + // The return value of the method is added to the model under the name "account" + // You can customize the name via @ModelAttribute("myAccount") + + @ModelAttribute + public Account addAccount(@RequestParam String number) { + return accountManager.findAccount(number); + } + + // Add multiple attributes + + @ModelAttribute + public void populateModel(@RequestParam String number, Model model) { + model.addAttribute(accountManager.findAccount(number)); + // add more ... + } +---- + +`@ModelAttribute` methods are used to populate the model with commonly needed attributes +for example to fill a drop-down with states or with pet types, or to retrieve a command +object like Account in order to use it to represent the data on an HTML form. The latter +case is further discussed in the next section. + +Note the two styles of `@ModelAttribute` methods. In the first, the method adds an +attribute implicitly by returning it. In the second, the method accepts a `Model` and +adds any number of model attributes to it. You can choose between the two styles +depending on your needs. + +A controller can have any number of `@ModelAttribute` methods. All such methods are +invoked before `@RequestMapping` methods of the same controller. + +`@ModelAttribute` methods can also be defined in an ++@ControllerAdvice++-annotated class +and such methods apply to many controllers. See the <<mvc-ann-controller-advice>> section +for more details. + +[TIP] +==== + +What happens when a model attribute name is not explicitly specified? In such cases a +default name is assigned to the model attribute based on its type. For example if the +method returns an object of type `Account`, the default name used is "account". You can +change that through the value of the `@ModelAttribute` annotation. If adding attributes +directly to the `Model`, use the appropriate overloaded `addAttribute(..)` method - +i.e., with or without an attribute name. +==== + +The `@ModelAttribute` annotation can be used on `@RequestMapping` methods as well. In +that case the return value of the `@RequestMapping` method is interpreted as a model +attribute rather than as a view name. The view name is derived from view name +conventions instead much like for methods returning void -- see <<mvc-coc-r2vnt>>. + + +[[mvc-ann-modelattrib-method-args]] +===== Using @ModelAttribute on a method argument + +As explained in the previous section `@ModelAttribute` can be used on methods or on +method arguments. This section explains its usage on method arguments. + +An `@ModelAttribute` on a method argument indicates the argument should be retrieved +from the model. If not present in the model, the argument should be instantiated first +and then added to the model. Once present in the model, the argument's fields should be +populated from all request parameters that have matching names. This is known as data +binding in Spring MVC, a very useful mechanism that saves you from having to parse each +form field individually. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @RequestMapping(value="/owners/{ownerId}/pets/{petId}/edit", method = RequestMethod.POST) + public String processSubmit(**@ModelAttribute Pet pet**) { } +---- + +Given the above example where can the Pet instance come from? There are several options: + +* It may already be in the model due to use of `@SessionAttributes` -- see + <<mvc-ann-sessionattrib>>. +* It may already be in the model due to an `@ModelAttribute` method in the same + controller -- as explained in the previous section. +* It may be retrieved based on a URI template variable and type converter (explained in + more detail below). +* It may be instantiated using its default constructor. + +An `@ModelAttribute` method is a common way to to retrieve an attribute from the +database, which may optionally be stored between requests through the use of +`@SessionAttributes`. In some cases it may be convenient to retrieve the attribute by +using an URI template variable and a type converter. Here is an example: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @RequestMapping(value="/accounts/{account}", method = RequestMethod.PUT) + public String save(@ModelAttribute("account") Account account) { + + } +---- + +In this example the name of the model attribute (i.e. "account") matches the name of a +URI template variable. If you register `Converter<String, Account>` that can turn the +`String` account value into an `Account` instance, then the above example will work +without the need for an `@ModelAttribute` method. + +The next step is data binding. The `WebDataBinder` class matches request parameter names +-- including query string parameters and form fields -- to model attribute fields by +name. Matching fields are populated after type conversion (from String to the target +field type) has been applied where necessary. Data binding and validation are covered in +<<validation>>. Customizing the data binding process for a controller level is covered +in <<mvc-ann-webdatabinder>>. + +As a result of data binding there may be errors such as missing required fields or type +conversion errors. To check for such errors add a `BindingResult` argument immediately +following the `@ModelAttribute` argument: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @RequestMapping(value="/owners/{ownerId}/pets/{petId}/edit", method = RequestMethod.POST) + public String processSubmit(**@ModelAttribute("pet") Pet pet**, BindingResult result) { + + if (result.hasErrors()) { + return "petForm"; + } + + // ... + + } +---- + +With a `BindingResult` you can check if errors were found in which case it's common to +render the same form where the errors can be shown with the help of Spring's `<errors>` +form tag. + +In addition to data binding you can also invoke validation using your own custom +validator passing the same `BindingResult` that was used to record data binding errors. +That allows for data binding and validation errors to be accumulated in one place and +subsequently reported back to the user: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @RequestMapping(value="/owners/{ownerId}/pets/{petId}/edit", method = RequestMethod.POST) + public String processSubmit(**@ModelAttribute("pet") Pet pet**, BindingResult result) { + + new PetValidator().validate(pet, result); + if (result.hasErrors()) { + return "petForm"; + } + + // ... + + } +---- + +Or you can have validation invoked automatically by adding the JSR-303 `@Valid` +annotation: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @RequestMapping(value="/owners/{ownerId}/pets/{petId}/edit", method = RequestMethod.POST) + public String processSubmit(**@Valid @ModelAttribute("pet") Pet pet**, BindingResult result) { + + if (result.hasErrors()) { + return "petForm"; + } + + // ... + + } +---- + +See <<validation-beanvalidation>> and <<validation>> for details on how to configure and +use validation. + + +[[mvc-ann-sessionattrib]] +===== Using @SessionAttributes to store model attributes in the HTTP session between requests + +The type-level `@SessionAttributes` annotation declares session attributes used by a +specific handler. This will typically list the names of model attributes or types of +model attributes which should be transparently stored in the session or some +conversational storage, serving as form-backing beans between subsequent requests. + +The following code snippet shows the usage of this annotation, specifying the model +attribute name: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Controller + @RequestMapping("/editPet.do") + **@SessionAttributes("pet")** + public class EditPetForm { + // ... + } +---- + +[[mvc-ann-redirect-attributes]] +===== Specifying redirect and flash attributes +By default all model attributes are considered to be exposed as URI template variables +in the redirect URL. Of the remaining attributes those that are primitive types or +collections/arrays of primitive types are automatically appended as query parameters. + +In annotated controllers however the model may contain additional attributes originally +added for rendering purposes (e.g. drop-down field values). To gain precise control over +the attributes used in a redirect scenario, an `@RequestMapping` method can declare an +argument of type `RedirectAttributes` and use it to add attributes for use in +`RedirectView`. If the controller method does redirect, the content of +`RedirectAttributes` is used. Otherwise the content of the default `Model` is used. + +The `RequestMappingHandlerAdapter` provides a flag called +`"ignoreDefaultModelOnRedirect"` that can be used to indicate the content of the default +`Model` should never be used if a controller method redirects. Instead the controller +method should declare an attribute of type `RedirectAttributes` or if it doesn't do so +no attributes should be passed on to `RedirectView`. Both the MVC namespace and the MVC +Java config keep this flag set to `false` in order to maintain backwards compatibility. +However, for new applications we recommend setting it to `true` + +The `RedirectAttributes` interface can also be used to add flash attributes. Unlike +other redirect attributes, which end up in the target redirect URL, flash attributes are +saved in the HTTP session (and hence do not appear in the URL). The model of the +controller serving the target redirect URL automatically receives these flash attributes +after which they are removed from the session. See <<mvc-flash-attributes>> for an +overview of the general support for flash attributes in Spring MVC. + + +[[mvc-ann-form-urlencoded-data]] +===== Working with "application/x-www-form-urlencoded" data + +The previous sections covered use of `@ModelAttribute` to support form submission +requests from browser clients. The same annotation is recommended for use with requests +from non-browser clients as well. However there is one notable difference when it comes +to working with HTTP PUT requests. Browsers can submit form data via HTTP GET or HTTP +POST. Non-browser clients can also submit forms via HTTP PUT. This presents a challenge +because the Servlet specification requires the `ServletRequest.getParameter*()` family +of methods to support form field access only for HTTP POST, not for HTTP PUT. + +To support HTTP PUT and PATCH requests, the `spring-web` module provides the filter +`HttpPutFormContentFilter`, which can be configured in `web.xml`: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + <filter> + <filter-name>httpPutFormFilter</filter-name> + <filter-class>org.springframework.web.filter.HttpPutFormContentFilter</filter-class> + </filter> + + <filter-mapping> + <filter-name>httpPutFormFilter</filter-name> + <servlet-name>dispatcherServlet</servlet-name> + </filter-mapping> + + <servlet> + <servlet-name>dispatcherServlet</servlet-name> + <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> + </servlet> +---- + +The above filter intercepts HTTP PUT and PATCH requests with content type +`application/x-www-form-urlencoded`, reads the form data from the body of the request, +and wraps the `ServletRequest` in order to make the form data available through the +`ServletRequest.getParameter*()` family of methods. + +[NOTE] +==== +As `HttpPutFormContentFilter` consumes the body of the request, it should not be +configured for PUT or PATCH URLs that rely on other converters for +`application/x-www-form-urlencoded`. This includes `@RequestBody MultiValueMap<String, +String>` and `HttpEntity<MultiValueMap<String, String>>`. +==== + + +[[mvc-ann-cookievalue]] +===== Mapping cookie values with the @CookieValue annotation +The `@CookieValue` annotation allows a method parameter to be bound to the value of an +HTTP cookie. + +Let us consider that the following cookie has been received with an http request: + +[literal] +[subs="verbatim,quotes"] +---- +JSESSIONID=415A4AC178C59DACE0B2C9CA727CDD84 +---- + +The following code sample demonstrates how to get the value of the `JSESSIONID` cookie: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @RequestMapping("/displayHeaderInfo.do") + public void displayHeaderInfo(**@CookieValue("JSESSIONID")** String cookie) { + //... + } +---- + +Type conversion is applied automatically if the target method parameter type is not +`String`. See <<mvc-ann-typeconversion>>. + +This annotation is supported for annotated handler methods in Servlet and Portlet +environments. + + +[[mvc-ann-requestheader]] +===== Mapping request header attributes with the @RequestHeader annotation +The `@RequestHeader` annotation allows a method parameter to be bound to a request header. + +Here is a sample request header: + +[literal] +[subs="verbatim,quotes"] +---- +Host localhost:8080 +Accept text/html,application/xhtml+xml,application/xml;q=0.9 +Accept-Language fr,en-gb;q=0.7,en;q=0.3 +Accept-Encoding gzip,deflate +Accept-Charset ISO-8859-1,utf-8;q=0.7,*;q=0.7 +Keep-Alive 300 +---- + +The following code sample demonstrates how to get the value of the `Accept-Encoding` and +`Keep-Alive` headers: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @RequestMapping("/displayHeaderInfo.do") + public void displayHeaderInfo(**@RequestHeader("Accept-Encoding")** String encoding, + **@RequestHeader("Keep-Alive")** long keepAlive) { + //... + } +---- + +Type conversion is applied automatically if the method parameter is not `String`. See +<<mvc-ann-typeconversion>>. + +[TIP] +==== +Built-in support is available for converting a comma-separated string into an +array/collection of strings or other types known to the type conversion system. For +example a method parameter annotated with `@RequestHeader("Accept")` may be of type +`String` but also `String[]` or `List<String>`. +==== + +This annotation is supported for annotated handler methods in Servlet and Portlet +environments. + + +[[mvc-ann-typeconversion]] +===== Method Parameters And Type Conversion +String-based values extracted from the request including request parameters, path +variables, request headers, and cookie values may need to be converted to the target +type of the method parameter or field (e.g., binding a request parameter to a field in +an `@ModelAttribute` parameter) they're bound to. If the target type is not `String`, +Spring automatically converts to the appropriate type. All simple types such as int, +long, Date, etc. are supported. You can further customize the conversion process through +a `WebDataBinder` (see <<mvc-ann-webdatabinder>>) or by registering `Formatters` with +the `FormattingConversionService` (see <<format>>). + + +[[mvc-ann-webdatabinder]] +===== Customizing WebDataBinder initialization +To customize request parameter binding with PropertyEditors through Spring's +`WebDataBinder`, you can use `@InitBinder`-annotated methods within your controller, +`@InitBinder` methods within an `@ControllerAdvice` class, or provide a custom +`WebBindingInitializer`. See the <<mvc-ann-controller-advice>> section for more details. + +[[mvc-ann-initbinder]] +====== Customizing data binding with @InitBinder +Annotating controller methods with `@InitBinder` allows you to configure web data +binding directly within your controller class. `@InitBinder` identifies methods that +initialize the `WebDataBinder` that will be used to populate command and form object +arguments of annotated handler methods. + +Such init-binder methods support all arguments that `@RequestMapping` supports, except +for command/form objects and corresponding validation result objects. Init-binder +methods must not have a return value. Thus, they are usually declared as `void`. Typical +arguments include `WebDataBinder` in combination with `WebRequest` or +`java.util.Locale`, allowing code to register context-specific editors. + +The following example demonstrates the use of `@InitBinder` to configure a +`CustomDateEditor` for all `java.util.Date` form properties. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Controller + public class MyFormController { + + **@InitBinder** + public void initBinder(WebDataBinder binder) { + SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd"); + dateFormat.setLenient(false); + binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, false)); + } + + // ... + + } +---- + +[[mvc-ann-webbindinginitializer]] +====== Configuring a custom WebBindingInitializer + +To externalize data binding initialization, you can provide a custom implementation of +the `WebBindingInitializer` interface, which you then enable by supplying a custom bean +configuration for an `AnnotationMethodHandlerAdapter`, thus overriding the default +configuration. + +The following example from the PetClinic application shows a configuration using a +custom implementation of the `WebBindingInitializer` interface, +`org.springframework.samples.petclinic.web.ClinicBindingInitializer`, which configures +PropertyEditors required by several of the PetClinic controllers. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"> + <property name="cacheSeconds" value="0" /> + <property name="webBindingInitializer"> + <bean class="org.springframework.samples.petclinic.web.ClinicBindingInitializer" /> + </property> + </bean> +---- + +`@InitBinder` methods can also be defined in an ++@ControllerAdvice++-annotated class in +which case they apply to matching controllers. This provides an alternative to using a +`WebBindingInitializer`. See the <<mvc-ann-controller-advice>> section for more details. + + +[[mvc-ann-lastmodified]] +===== Support for the Last-Modified Response Header To Facilitate Content Caching +An `@RequestMapping` method may wish to support `'Last-Modified'` HTTP requests, as +defined in the contract for the Servlet API's `getLastModified` method, to facilitate +content caching. This involves calculating a lastModified `long` value for a given +request, comparing it against the `'If-Modified-Since'` request header value, and +potentially returning a response with status code 304 (Not Modified). An annotated +controller method can achieve that as follows: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @RequestMapping + public String myHandleMethod(WebRequest webRequest, Model model) { + + long lastModified = // 1. application-specific calculation + + if (request.checkNotModified(lastModified)) { + // 2. shortcut exit - no further processing necessary + return null; + } + + // 3. or otherwise further request processing, actually preparing content + model.addAttribute(...); + return "myViewName"; + } +---- + +There are two key elements to note: calling `request.checkNotModified(lastModified)` and +returning `null`. The former sets the response status to 304 before it returns `true`. +The latter, in combination with the former, causes Spring MVC to do no further +processing of the request. + +[[mvc-ann-controller-advice]] +===== Advising controllers with the `@ControllerAdvice` annotation +The `@ControllerAdvice` annotation is a component annotation allowing implementation +classes to be auto-detected through classpath scanning. It is automatically enabled when +using the MVC namespace or the MVC Java config. + +Classes annotated with `@ControllerAdvice` can contain `@ExceptionHandler`, +`@InitBinder`, and `@ModelAttribute` annotated methods, and these methods will apply to +`@RequestMapping` methods across all controller hierarchies as opposed to the controller +hierarchy within which they are declared. + +The `@ControllerAdvice` annotation can also target a subset of controllers with its +attributes: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + // Target all Controllers annotated with @RestController + @ControllerAdvice(annotations = RestController.class) + public class AnnotationAdvice {} + + // Target all Controllers within specific packages + @ControllerAdvice("org.example.controllers") + public class BasePackageAdvice {} + + // Target all Controllers assignable to specific classes + @ControllerAdvice(assignableTypes = {ControllerInterface.class, AbstractController.class}) + public class AssignableTypesAdvice {} +---- + +Check out the +{javadoc-baseurl}/org/springframework/web/bind/annotation/ControllerAdvice.html[`@ControllerAdvice` +documentation] for more details. + +[[mvc-ann-jsonview]] +===== Jackson Serialization View Support + +It can sometimes be useful to filter contextually the object that will be serialized to the +HTTP response body. In order to provide such capability, Spring MVC has built-in support for +rendering with http://wiki.fasterxml.com/JacksonJsonViews[Jackson's Serialization Views]. + +To use it with `@ResponseBody` controller method or methods return `ResponseEntity`, simply +add the `@JsonView` annotation: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @RestController + public class UserController { + + @RequestMapping(value = "/user", method = RequestMethod.GET) + @JsonView(User.WithoutPasswordView.class) + public User getUser() { + return new User("eric", "7!jd#h23"); + } + } + + public class User { + + public interface WithoutPasswordView {}; + public interface WithPasswordView extends WithoutPasswordView {}; + + private String username; + private String password; + + public User() { + } + + public User(String username, String password) { + this.username = username; + this.password = password; + } + + @JsonView(WithoutPasswordView.class) + public String getUsername() { + return this.username; + } + + @JsonView(WithPasswordView.class) + public String getPassword() { + return this.password; + } + } +---- + +For controllers relying on view resolution, simply add the serialization view class +to the model: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Controller + public class UserController extends AbstractController { + + @RequestMapping(value = "/user", method = RequestMethod.GET) + public String getUser(Model model) { + model.addAttribute("user", new User("eric", "7!jd#h23")); + model.addAttribute(JsonView.class.getName(), User.WithoutPasswordView.class); + return "userView"; + } + } + +---- + +[[mvc-ann-async]] +==== Asynchronous Request Processing +Spring MVC 3.2 introduced Servlet 3 based asynchronous request processing. Instead of +returning a value, as usual, a controller method can now return a +`java.util.concurrent.Callable` and produce the return value from a separate thread. +Meanwhile the main Servlet container thread is released and allowed to process other +requests. Spring MVC invokes the `Callable` in a separate thread with the help of a +`TaskExecutor` and when the `Callable` returns, the request is dispatched back to the +Servlet container to resume processing with the value returned by the `Callable`. Here +is an example controller method: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @RequestMapping(method=RequestMethod.POST) + public Callable<String> processUpload(final MultipartFile file) { + + return new Callable<String>() { + public String call() throws Exception { + // ... + return "someView"; + } + }; + + } +---- + +A second option is for the controller to return an instance of `DeferredResult`. In this +case the return value will also be produced from a separate thread. However, that thread +is not known to Spring MVC. For example the result may be produced in response to some +external event such as a JMS message, a scheduled task, etc. Here is an example +controller method: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @RequestMapping("/quotes") + @ResponseBody + public DeferredResult<String> quotes() { + DeferredResult<String> deferredResult = new DeferredResult<String>(); + // Save the deferredResult in in-memory queue ... + return deferredResult; + } + + // In some other thread... + deferredResult.setResult(data); +---- + +This may be difficult to understand without any knowledge of the Servlet 3 async +processing feature. It would certainly help to read up on it. At a very minimum consider +the following basic facts: + +* A `ServletRequest` can be put in asynchronous mode by calling `request.startAsync()`. + The main effect of doing so is that the Servlet, as well as any Filters, can exit but + the response will remain open allowing some other thread to complete processing. +* The call to `request.startAsync()` returns an `AsyncContext`, which can be used for + further control over async processing. For example it provides the method `dispatch`, + which can be called from an application thread in order to "dispatch" the request back + to the Servlet container. An async dispatch is similar to a forward except it is made + from one (application) thread to another (Servlet container) thread whereas a forward + occurs synchronously in the same (Servlet container) thread. +* `ServletRequest` provides access to the current `DispatcherType`, which can be used to + distinguish if a `Servlet` or a `Filter` is processing on the initial request + processing thread and when it is processing in an async dispatch. + +With the above in mind, the following is the sequence of events for async request +processing with a `Callable`: (1) Controller returns a `Callable`, (2) Spring MVC starts +async processing and submits the `Callable` to a `TaskExecutor` for processing in a +separate thread, (3) the `DispatcherServlet` and all Filter's exit the request +processing thread but the response remains open, (4) the `Callable` produces a result +and Spring MVC dispatches the request back to the Servlet container, (5) the +`DispatcherServlet` is invoked again and processing resumes with the asynchronously +produced result from the `Callable`. The exact sequencing of (2), (3), and (4) may vary +depending on the speed of execution of the concurrent threads. + +The sequence of events for async request processing with a `DeferredResult` is the same +in principal except it's up to the application to produce the asynchronous result from +some thread: (1) Controller returns a `DeferredResult` and saves it in some in-memory +queue or list where it can be accessed, (2) Spring MVC starts async processing, (3) the +`DispatcherServlet` and all configured Filter's exit the request processing thread but +the response remains open, (4) the application sets the `DeferredResult` from some +thread and Spring MVC dispatches the request back to the Servlet container, (5) the +`DispatcherServlet` is invoked again and processing resumes with the asynchronously +produced result. + +Explaining the motivation for async request processing and when or why to use it are +beyond the scope of this document. For further information you may wish to read +https://spring.io/blog/2012/05/07/spring-mvc-3-2-preview-introducing-servlet-3-async-support[this +blog post series]. + + +[[mvc-ann-async-exceptions]] +===== Exception Handling for Async Requests +What happens if a `Callable` returned from a controller method raises an Exception while +being executed? The effect is similar to what happens when any controller method raises +an exception. It is handled by a matching `@ExceptionHandler` method in the same +controller or by one of the configured `HandlerExceptionResolver` instances. + +[NOTE] +==== +Under the covers, when a `Callable` raises an Exception, Spring MVC still dispatches to +the Servlet container to resume processing. The only difference is that the result of +executing the `Callable` is an `Exception` that must be processed with the configured +`HandlerExceptionResolver` instances. +==== + +When using a `DeferredResult`, you have a choice of calling its `setErrorResult(Object)` +method and provide an `Exception` or any other Object you'd like to use as the result. +If the result is an `Exception`, it will be processed with a matching +`@ExceptionHandler` method in the same controller or with any configured +`HandlerExceptionResolver` instance. + + +[[mvc-ann-async-interception]] +===== Intercepting Async Requests +An existing `HandlerInterceptor` can implement `AsyncHandlerInterceptor`, which provides +one additional method `afterConcurrentHandlingStarted`. It is invoked after async +processing starts and when the initial request processing thread is being exited. See +the `AsyncHandlerInterceptor` javadocs for more details on that. + +Further options for async request lifecycle callbacks are provided directly on +`DeferredResult`, which has the methods `onTimeout(Runnable)` and +`onCompletion(Runnable)`. Those are called when the async request is about to time out +or has completed respectively. The timeout event can be handled by setting the +`DeferredResult` to some value. The completion callback however is final and the result +can no longer be set. + +Similar callbacks are also available with a `Callable`. However, you will need to wrap +the `Callable` in an instance of `WebAsyncTask` and then use that to register the +timeout and completion callbacks. Just like with `DeferredResult`, the timeout event can +be handled and a value can be returned while the completion event is final. + +You can also register a `CallableProcessingInterceptor` or a +`DeferredResultProcessingInterceptor` globally through the MVC Java config or the MVC +namespace. Those interceptors provide a full set of callbacks and apply every time a +`Callable` or a `DeferredResult` is used. + + +[[mvc-ann-async-configuration]] +===== Configuration for Async Request Processing + +[[mvc-ann-async-configuration-servlet3]] +====== Servlet 3 Async Config +To use Servlet 3 async request processing, you need to update `web.xml` to version 3.0: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + <web-app xmlns="http://java.sun.com/xml/ns/javaee" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + http://java.sun.com/xml/ns/javaee + http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" + version="3.0"> + + ... + + </web-app> +---- + +The `DispatcherServlet` and any `Filter` configuration need to have the +`<async-supported>true</async-supported>` sub-element. Additionally, any `Filter` that +also needs to get involved in async dispatches should also be configured to support the +ASYNC dispatcher type. Note that it is safe to enable the ASYNC dispatcher type for all +filters provided with the Spring Framework since they will not get involved in async +dispatches unless needed. + +[WARNING] +==== +Note that for some Filters it is absolutely critical to ensure they are mapped to +be invoked during asynchronous dispatches. For example if a filter such as the +`OpenEntityManagerInViewFilter` is responsible for releasing database connection +resources and must be invoked at the end of an async request. + +Below is an example of a propertly configured filter: +==== + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + <web-app xmlns="http://java.sun.com/xml/ns/javaee" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation=" + http://java.sun.com/xml/ns/javaee + http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" + version="3.0"> + + <filter> + <filter-name>Spring OpenEntityManagerInViewFilter</filter-name> + <filter-class>org.springframework.~.OpenEntityManagerInViewFilter</filter-class> + <async-supported>true</async-supported> + </filter> + + <filter-mapping> + <filter-name>Spring OpenEntityManagerInViewFilter</filter-name> + <url-pattern>/*</url-pattern> + <dispatcher>REQUEST</dispatcher> + <dispatcher>ASYNC</dispatcher> + </filter-mapping> + + </web-app> + +---- + +If using Servlet 3, Java based configuration, e.g. via `WebApplicationInitializer`, +you'll also need to set the "asyncSupported" flag as well as the ASYNC dispatcher type +just like with `web.xml`. To simplify all this configuration, consider extending +`AbstractDispatcherServletInitializer` or +`AbstractAnnotationConfigDispatcherServletInitializer`, which automatically set those +options and make it very easy to register `Filter` instances. + +[[mvc-ann-async-configuration-spring-mvc]] +====== Spring MVC Async Config +The MVC Java config and the MVC namespace both provide options for configuring async +request processing. `WebMvcConfigurer` has the method `configureAsyncSupport` while +<mvc:annotation-driven> has an <async-support> sub-element. + +Those allow you to configure the default timeout value to use for async requests, which +if not set depends on the underlying Servlet container (e.g. 10 seconds on Tomcat). You +can also configure an `AsyncTaskExecutor` to use for executing `Callable` instances +returned from controller methods. It is highly recommended to configure this property +since by default Spring MVC uses `SimpleAsyncTaskExecutor`. The MVC Java config and the +MVC namespace also allow you to register `CallableProcessingInterceptor` and +`DeferredResultProcessingInterceptor` instances. + +If you need to override the default timeout value for a specific `DeferredResult`, you +can do so by using the appropriate class constructor. Similarly, for a `Callable`, you +can wrap it in a `WebAsyncTask` and use the appropriate class constructor to customize +the timeout value. The class constructor of `WebAsyncTask` also allows providing an +`AsyncTaskExecutor`. + + + +[[mvc-ann-tests]] +==== Testing Controllers +The `spring-test` module offers first class support for testing annotated controllers. +See <<spring-mvc-test-framework>>. + + + + +[[mvc-handlermapping]] +=== Handler mappings +In previous versions of Spring, users were required to define one or more +`HandlerMapping` beans in the web application context to map incoming web requests to +appropriate handlers. With the introduction of annotated controllers, you generally +don't need to do that because the `RequestMappingHandlerMapping` automatically looks for +`@RequestMapping` annotations on all `@Controller` beans. However, do keep in mind that +all `HandlerMapping` classes extending from `AbstractHandlerMapping` have the following +properties that you can use to customize their behavior: + +* `interceptors` List of interceptors to use. ++HandlerInterceptor++s are discussed in + <<mvc-handlermapping-interceptor>>. +* `defaultHandler` Default handler to use, when this handler mapping does not result in + a matching handler. +* `order` Based on the value of the order property (see the + `org.springframework.core.Ordered` interface), Spring sorts all handler mappings + available in the context and applies the first matching handler. +* `alwaysUseFullPath` If `true` , Spring uses the full path within the current Servlet + context to find an appropriate handler. If `false` (the default), the path within the + current Servlet mapping is used. For example, if a Servlet is mapped using + `/testing/*` and the `alwaysUseFullPath` property is set to true, + `/testing/viewPage.html` is used, whereas if the property is set to false, + `/viewPage.html` is used. +* `urlDecode` Defaults to `true`, as of Spring 2.5. If you prefer to compare encoded + paths, set this flag to `false`. However, the `HttpServletRequest` always exposes the + Servlet path in decoded form. Be aware that the Servlet path will not match when + compared with encoded paths. + +The following example shows how to configure an interceptor: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + <beans> + <bean id="handlerMapping" class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"> + <property name="interceptors"> + <bean class="example.MyInterceptor"/> + </property> + </bean> + <beans> +---- + + + +[[mvc-handlermapping-interceptor]] +==== Intercepting requests with a HandlerInterceptor + +Spring's handler mapping mechanism includes handler interceptors, which are useful when +you want to apply specific functionality to certain requests, for example, checking for +a principal. + +Interceptors located in the handler mapping must implement `HandlerInterceptor` from the +`org.springframework.web.servlet` package. This interface defines three methods: +`preHandle(..)` is called __before__ the actual handler is executed; `postHandle(..)` is +called __after__ the handler is executed; and `afterCompletion(..)` is called __after +the complete request has finished__. These three methods should provide enough +flexibility to do all kinds of preprocessing and postprocessing. + +The `preHandle(..)` method returns a boolean value. You can use this method to break or +continue the processing of the execution chain. When this method returns `true`, the +handler execution chain will continue; when it returns false, the `DispatcherServlet` +assumes the interceptor itself has taken care of requests (and, for example, rendered an +appropriate view) and does not continue executing the other interceptors and the actual +handler in the execution chain. + +Interceptors can be configured using the `interceptors` property, which is present on +all `HandlerMapping` classes extending from `AbstractHandlerMapping`. This is shown in +the example below: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + <beans> + <bean id="handlerMapping" + class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"> + <property name="interceptors"> + <list> + <ref bean="officeHoursInterceptor"/> + </list> + </property> + </bean> + + <bean id="officeHoursInterceptor" + class="samples.TimeBasedAccessInterceptor"> + <property name="openingTime" value="9"/> + <property name="closingTime" value="18"/> + </bean> + <beans> +---- + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + package samples; + + public class TimeBasedAccessInterceptor extends HandlerInterceptorAdapter { + + private int openingTime; + private int closingTime; + + public void setOpeningTime(int openingTime) { + this.openingTime = openingTime; + } + + public void setClosingTime(int closingTime) { + this.closingTime = closingTime; + } + + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, + Object handler) throws Exception { + Calendar cal = Calendar.getInstance(); + int hour = cal.get(HOUR_OF_DAY); + if (openingTime <= hour && hour < closingTime) { + return true; + } + response.sendRedirect("http://host.com/outsideOfficeHours.html"); + return false; + } + } +---- + +Any request handled by this mapping is intercepted by the `TimeBasedAccessInterceptor`. +If the current time is outside office hours, the user is redirected to a static HTML +file that says, for example, you can only access the website during office hours. + +[NOTE] +==== +When using the `RequestMappingHandlerMapping` the actual handler is an instance of +`HandlerMethod` which identifies the specific controller method that will be invoked. +==== + +As you can see, the Spring adapter class `HandlerInterceptorAdapter` makes it easier to +extend the `HandlerInterceptor` interface. + +[TIP] +==== + +In the example above, the configured interceptor will apply to all requests handled with +annotated controller methods. If you want to narrow down the URL paths to which an +interceptor applies, you can use the MVC namespace or the MVC Java config, or declare +bean instances of type `MappedInterceptor` to do that. See <<mvc-config-enable>>. +==== + + + + +[[mvc-viewresolver]] +=== Resolving views +All MVC frameworks for web applications provide a way to address views. Spring provides +view resolvers, which enable you to render models in a browser without tying you to a +specific view technology. Out of the box, Spring enables you to use JSPs, Velocity +templates and XSLT views, for example. See <<view>> for a discussion of how to integrate +and use a number of disparate view technologies. + +The two interfaces that are important to the way Spring handles views are `ViewResolver` +and `View`. The `ViewResolver` provides a mapping between view names and actual views. +The `View` interface addresses the preparation of the request and hands the request over +to one of the view technologies. + + + +[[mvc-viewresolver-resolver]] +==== Resolving views with the ViewResolver interface + +As discussed in <<mvc-controller>>, all handler methods in the Spring Web MVC +controllers must resolve to a logical view name, either explicitly (e.g., by returning a +`String`, `View`, or `ModelAndView`) or implicitly (i.e., based on conventions). Views +in Spring are addressed by a logical view name and are resolved by a view resolver. +Spring comes with quite a few view resolvers. This table lists most of them; a couple of +examples follow. + +[[mvc-view-resolvers-tbl]] +.View resolvers +|=== +| ViewResolver| Description + +| `AbstractCachingViewResolver` +| Abstract view resolver that caches views. Often views need preparation before they can + be used; extending this view resolver provides caching. + +| `XmlViewResolver` +| Implementation of `ViewResolver` that accepts a configuration file written in XML with + the same DTD as Spring's XML bean factories. The default configuration file is + `/WEB-INF/views.xml`. + +| `ResourceBundleViewResolver` +| Implementation of `ViewResolver` that uses bean definitions in a `ResourceBundle`, + specified by the bundle base name. Typically you define the bundle in a properties + file, located in the classpath. The default file name is `views.properties`. + +| `UrlBasedViewResolver` +| Simple implementation of the `ViewResolver` interface that effects the direct + resolution of logical view names to URLs, without an explicit mapping definition. This + is appropriate if your logical names match the names of your view resources in a + straightforward manner, without the need for arbitrary mappings. + +| `InternalResourceViewResolver` +| Convenient subclass of `UrlBasedViewResolver` that supports `InternalResourceView` (in + effect, Servlets and JSPs) and subclasses such as `JstlView` and `TilesView`. You can + specify the view class for all views generated by this resolver by using + `setViewClass(..)`. See the `UrlBasedViewResolver` javadocs for details. + +| `VelocityViewResolver` / `FreeMarkerViewResolver` +| Convenient subclass of `UrlBasedViewResolver` that supports `VelocityView` (in effect, + Velocity templates) or `FreeMarkerView` ,respectively, and custom subclasses of them. + +| `ContentNegotiatingViewResolver` +| Implementation of the `ViewResolver` interface that resolves a view based on the + request file name or `Accept` header. See <<mvc-multiple-representations>>. +|=== + +As an example, with JSP as a view technology, you can use the `UrlBasedViewResolver`. +This view resolver translates a view name to a URL and hands the request over to the +RequestDispatcher to render the view. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + <bean id="viewResolver" + class="org.springframework.web.servlet.view.UrlBasedViewResolver"> + <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/> + <property name="prefix" value="/WEB-INF/jsp/"/> + <property name="suffix" value=".jsp"/> + </bean> +---- + +When returning `test` as a logical view name, this view resolver forwards the request to +the `RequestDispatcher` that will send the request to `/WEB-INF/jsp/test.jsp`. + +When you combine different view technologies in a web application, you can use the +`ResourceBundleViewResolver`: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + <bean id="viewResolver" + class="org.springframework.web.servlet.view.ResourceBundleViewResolver"> + <property name="basename" value="views"/> + <property name="defaultParentView" value="parentView"/> + </bean> +---- + +The `ResourceBundleViewResolver` inspects the `ResourceBundle` identified by the +basename, and for each view it is supposed to resolve, it uses the value of the property +`[viewname].(class)` as the view class and the value of the property `[viewname].url` as +the view url. Examples can be found in the next chapter which covers view technologies. +As you can see, you can identify a parent view, from which all views in the properties +file "extend". This way you can specify a default view class, for example. + +[NOTE] +==== +Subclasses of `AbstractCachingViewResolver` cache view instances that they resolve. +Caching improves performance of certain view technologies. It's possible to turn off the +cache by setting the `cache` property to `false`. Furthermore, if you must refresh a +certain view at runtime (for example when a Velocity template is modified), you can use +the `removeFromCache(String viewName, Locale loc)` method. +==== + + + +[[mvc-viewresolver-chaining]] +==== Chaining ViewResolvers +Spring supports multiple view resolvers. Thus you can chain resolvers and, for example, +override specific views in certain circumstances. You chain view resolvers by adding +more than one resolver to your application context and, if necessary, by setting the +`order` property to specify ordering. Remember, the higher the order property, the later +the view resolver is positioned in the chain. + +In the following example, the chain of view resolvers consists of two resolvers, an +`InternalResourceViewResolver`, which is always automatically positioned as the last +resolver in the chain, and an `XmlViewResolver` for specifying Excel views. Excel views +are not supported by the `InternalResourceViewResolver`. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + <bean id="jspViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> + <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/> + <property name="prefix" value="/WEB-INF/jsp/"/> + <property name="suffix" value=".jsp"/> + </bean> + + <bean id="excelViewResolver" class="org.springframework.web.servlet.view.XmlViewResolver"> + <property name="order" value="1"/> + <property name="location" value="/WEB-INF/views.xml"/> + </bean> + + <!-- in views.xml --> + + <beans> + <bean name="report" class="org.springframework.example.ReportExcelView"/> + </beans> +---- + +If a specific view resolver does not result in a view, Spring examines the context for +other view resolvers. If additional view resolvers exist, Spring continues to inspect +them until a view is resolved. If no view resolver returns a view, Spring throws a +`ServletException`. + +The contract of a view resolver specifies that a view resolver __can__ return null to +indicate the view could not be found. Not all view resolvers do this, however, because +in some cases, the resolver simply cannot detect whether or not the view exists. For +example, the `InternalResourceViewResolver` uses the `RequestDispatcher` internally, and +dispatching is the only way to figure out if a JSP exists, but this action can only +execute once. The same holds for the `VelocityViewResolver` and some others. Check the +javadocs of the specific view resolver to see whether it reports non-existing views. +Thus, putting an `InternalResourceViewResolver` in the chain in a place other than +the last results in the chain not being fully inspected, because the +`InternalResourceViewResolver` will __always__ return a view! + + + +[[mvc-redirecting]] +==== Redirecting to views +As mentioned previously, a controller typically returns a logical view name, which a +view resolver resolves to a particular view technology. For view technologies such as +JSPs that are processed through the Servlet or JSP engine, this resolution is usually +handled through the combination of `InternalResourceViewResolver` and +`InternalResourceView`, which issues an internal forward or include via the Servlet +API's `RequestDispatcher.forward(..)` method or `RequestDispatcher.include()` method. +For other view technologies, such as Velocity, XSLT, and so on, the view itself writes +the content directly to the response stream. + +It is sometimes desirable to issue an HTTP redirect back to the client, before the view +is rendered. This is desirable, for example, when one controller has been called with +`POST` data, and the response is actually a delegation to another controller (for +example on a successful form submission). In this case, a normal internal forward will +mean that the other controller will also see the same `POST` data, which is potentially +problematic if it can confuse it with other expected data. Another reason to perform a +redirect before displaying the result is to eliminate the possibility of the user +submitting the form data multiple times. In this scenario, the browser will first send +an initial `POST`; it will then receive a response to redirect to a different URL; and +finally the browser will perform a subsequent `GET` for the URL named in the redirect +response. Thus, from the perspective of the browser, the current page does not reflect +the result of a `POST` but rather of a `GET`. The end effect is that there is no way the +user can accidentally re- `POST` the same data by performing a refresh. The refresh +forces a `GET` of the result page, not a resend of the initial `POST` data. + + +[[mvc-redirecting-redirect-view]] +===== RedirectView + +One way to force a redirect as the result of a controller response is for the controller +to create and return an instance of Spring's `RedirectView`. In this case, +`DispatcherServlet` does not use the normal view resolution mechanism. Rather because it +has been given the (redirect) view already, the `DispatcherServlet` simply instructs the +view to do its work. + +The `RedirectView` issues an `HttpServletResponse.sendRedirect()` call that returns to +the client browser as an HTTP redirect. By default all model attributes are considered +to be exposed as URI template variables in the redirect URL. Of the remaining attributes +those that are primitive types or collections/arrays of primitive types are +automatically appended as query parameters. + +Appending primitive type attributes as query parameters may be the desired result if a +model instance was prepared specifically for the redirect. However, in annotated +controllers the model may contain additional attributes added for rendering purposes +(e.g. drop-down field values). To avoid the possibility of having such attributes appear +in the URL an annotated controller can declare an argument of type `RedirectAttributes` +and use it to specify the exact attributes to make available to `RedirectView`. If the +controller method decides to redirect, the content of `RedirectAttributes` is used. +Otherwise the content of the model is used. + +Note that URI template variables from the present request are automatically made +available when expanding a redirect URL and do not need to be added explicitly neither +through `Model` nor `RedirectAttributes`. For example: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @RequestMapping(value = "/files/{path}", method = RequestMethod.POST) + public String upload(...) { + // ... + return "redirect:files/{path}"; + } +---- + +If you use `RedirectView` and the view is created by the controller itself, it is +recommended that you configure the redirect URL to be injected into the controller so +that it is not baked into the controller but configured in the context along with the +view names. The next section discusses this process. + + +[[mvc-redirecting-redirect-prefix]] +===== The redirect: prefix + +While the use of `RedirectView` works fine, if the controller itself creates the +`RedirectView`, there is no avoiding the fact that the controller is aware that a +redirection is happening. This is really suboptimal and couples things too tightly. The +controller should not really care about how the response gets handled. In general it +should operate only in terms of view names that have been injected into it. + +The special `redirect:` prefix allows you to accomplish this. If a view name is returned +that has the prefix `redirect:`, the `UrlBasedViewResolver` (and all subclasses) will +recognize this as a special indication that a redirect is needed. The rest of the view +name will be treated as the redirect URL. + +The net effect is the same as if the controller had returned a `RedirectView`, but now +the controller itself can simply operate in terms of logical view names. A logical view +name such as `redirect:/myapp/some/resource` will redirect relative to the current +Servlet context, while a name such as `redirect:http://myhost.com/some/arbitrary/path` +will redirect to an absolute URL. + + +[[mvc-redirecting-forward-prefix]] +===== The forward: prefix + +It is also possible to use a special `forward:` prefix for view names that are +ultimately resolved by `UrlBasedViewResolver` and subclasses. This creates an +`InternalResourceView` (which ultimately does a `RequestDispatcher.forward()`) around +the rest of the view name, which is considered a URL. Therefore, this prefix is not +useful with `InternalResourceViewResolver` and `InternalResourceView` (for JSPs for +example). But the prefix can be helpful when you are primarily using another view +technology, but still want to force a forward of a resource to be handled by the +Servlet/JSP engine. (Note that you may also chain multiple view resolvers, instead.) + +As with the `redirect:` prefix, if the view name with the `forward:` prefix is injected +into the controller, the controller does not detect that anything special is happening +in terms of handling the response. + + + +[[mvc-multiple-representations]] +==== ContentNegotiatingViewResolver + +The `ContentNegotiatingViewResolver` does not resolve views itself but rather delegates +to other view resolvers, selecting the view that resembles the representation requested +by the client. Two strategies exist for a client to request a representation from the +server: + +* Use a distinct URI for each resource, typically by using a different file extension in + the URI. For example, the URI `http://www.example.com/users/fred.pdf` requests a PDF + representation of the user fred, and `http://www.example.com/users/fred.xml` requests + an XML representation. +* Use the same URI for the client to locate the resource, but set the `Accept` HTTP + request header to list the http://en.wikipedia.org/wiki/Internet_media_type[media + types] that it understands. For example, an HTTP request for + `http://www.example.com/users/fred` with an `Accept` header set to `application/pdf` + requests a PDF representation of the user fred, while + `http://www.example.com/users/fred` with an `Accept` header set to `text/xml` requests + an XML representation. This strategy is known as + http://en.wikipedia.org/wiki/Content_negotiation[content negotiation]. + +[NOTE] +==== +One issue with the `Accept` header is that it is impossible to set it in a web browser +within HTML. For example, in Firefox, it is fixed to: + +[literal] +[subs="verbatim,quotes"] +---- +Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 +---- + +For this reason it is common to see the use of a distinct URI for each representation +when developing browser based web applications. +==== + +To support multiple representations of a resource, Spring provides the +`ContentNegotiatingViewResolver` to resolve a view based on the file extension or +`Accept` header of the HTTP request. `ContentNegotiatingViewResolver` does not perform +the view resolution itself but instead delegates to a list of view resolvers that you +specify through the bean property `ViewResolvers`. + +The `ContentNegotiatingViewResolver` selects an appropriate `View` to handle the request +by comparing the request media type(s) with the media type (also known as +`Content-Type`) supported by the `View` associated with each of its `ViewResolvers`. The +first `View` in the list that has a compatible `Content-Type` returns the representation +to the client. If a compatible view cannot be supplied by the `ViewResolver` chain, then +the list of views specified through the `DefaultViews` property will be consulted. This +latter option is appropriate for singleton `Views` that can render an appropriate +representation of the current resource regardless of the logical view name. The `Accept` +header may include wild cards, for example `text/*`, in which case a `View` whose +Content-Type was `text/xml` is a compatible match. + +To support the resolution of a view based on a file extension, use the +`ContentNegotiatingViewResolver` bean property `mediaTypes` to specify a mapping of file +extensions to media types. For more information on the algorithm used to determine the +request media type, refer to the API documentation for `ContentNegotiatingViewResolver`. + +Here is an example configuration of a `ContentNegotiatingViewResolver:` + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + <bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver"> + <property name="mediaTypes"> + <map> + <entry key="atom" value="application/atom+xml"/> + <entry key="html" value="text/html"/> + <entry key="json" value="application/json"/> + </map> + </property> + <property name="viewResolvers"> + <list> + <bean class="org.springframework.web.servlet.view.BeanNameViewResolver"/> + <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> + <property name="prefix" value="/WEB-INF/jsp/"/> + <property name="suffix" value=".jsp"/> + </bean> + </list> + </property> + <property name="defaultViews"> + <list> + <bean class="org.springframework.web.servlet.view.json.MappingJackson2JsonView" /> + </list> + </property> + </bean> + + <bean id="content" class="com.foo.samples.rest.SampleContentAtomView"/> +---- + +The `InternalResourceViewResolver` handles the translation of view names and JSP pages, +while the `BeanNameViewResolver` returns a view based on the name of a bean. (See +"<<mvc-viewresolver-resolver,Resolving views with the ViewResolver interface>>" for more +details on how Spring looks up and instantiates a view.) In this example, the `content` +bean is a class that inherits from `AbstractAtomFeedView`, which returns an Atom RSS +feed. For more information on creating an Atom Feed representation, see the section Atom +Views. + +In the above configuration, if a request is made with an `.html` extension, the view +resolver looks for a view that matches the `text/html` media type. The +`InternalResourceViewResolver` provides the matching view for `text/html`. If the +request is made with the file extension `.atom`, the view resolver looks for a view that +matches the `application/atom+xml` media type. This view is provided by the +`BeanNameViewResolver` that maps to the `SampleContentAtomView` if the view name +returned is `content`. If the request is made with the file extension `.json`, the +`MappingJackson2JsonView` instance from the `DefaultViews` list will be selected +regardless of the view name. Alternatively, client requests can be made without a file +extension but with the `Accept` header set to the preferred media-type, and the same +resolution of request to views would occur. + +[NOTE] +==== +If `ContentNegotiatingViewResolver`'s list of ViewResolvers is not configured +explicitly, it automatically uses any ViewResolvers defined in the application context. +==== + +The corresponding controller code that returns an Atom RSS feed for a URI of the form +`http://localhost/content.atom` or `http://localhost/content` with an `Accept` header of +application/atom+xml is shown below. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Controller + public class ContentController { + + private List<SampleContent> contentList = new ArrayList<SampleContent>(); + + @RequestMapping(value="/content", method=RequestMethod.GET) + public ModelAndView getContent() { + ModelAndView mav = new ModelAndView(); + mav.setViewName("content"); + mav.addObject("sampleContentList", contentList); + return mav; + } + + } +---- + + + + +[[mvc-flash-attributes]] +=== Using flash attributes +Flash attributes provide a way for one request to store attributes intended for use in +another. This is most commonly needed when redirecting -- for example, the +__Post/Redirect/Get__ pattern. Flash attributes are saved temporarily before the +redirect (typically in the session) to be made available to the request after the +redirect and removed immediately. + +Spring MVC has two main abstractions in support of flash attributes. `FlashMap` is used +to hold flash attributes while `FlashMapManager` is used to store, retrieve, and manage +`FlashMap` instances. + +Flash attribute support is always "on" and does not need to enabled explicitly although +if not used, it never causes HTTP session creation. On each request there is an "input" +`FlashMap` with attributes passed from a previous request (if any) and an "output" +`FlashMap` with attributes to save for a subsequent request. Both `FlashMap` instances +are accessible from anywhere in Spring MVC through static methods in +`RequestContextUtils`. + +Annotated controllers typically do not need to work with `FlashMap` directly. Instead an +`@RequestMapping` method can accept an argument of type `RedirectAttributes` and use it +to add flash attributes for a redirect scenario. Flash attributes added via +`RedirectAttributes` are automatically propagated to the "output" FlashMap. Similarly +after the redirect attributes from the "input" `FlashMap` are automatically added to the +`Model` of the controller serving the target URL. + +.Matching requests to flash attributes +**** +The concept of flash attributes exists in many other Web frameworks and has proven to be +exposed sometimes to concurrency issues. This is because by definition flash attributes +are to be stored until the next request. However the very "next" request may not be the +intended recipient but another asynchronous request (e.g. polling or resource requests) +in which case the flash attributes are removed too early. + +To reduce the possibility of such issues, `RedirectView` automatically "stamps" +`FlashMap` instances with the path and query parameters of the target redirect URL. In +turn the default `FlashMapManager` matches that information to incoming requests when +looking up the "input" `FlashMap`. + +This does not eliminate the possibility of a concurrency issue entirely but nevertheless +reduces it greatly with information that is already available in the redirect URL. +Therefore the use of flash attributes is recommended mainly for redirect scenarios . +**** + + + + +[[mvc-construct-encode-uri]] +=== Building URIs + +Spring MVC provides a mechanism for building and encoding a URI using +`UriComponentsBuilder` and `UriComponents`. + +For example you can expand and encode a URI template string: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + UriComponents uriComponents = UriComponentsBuilder.fromUriString( + "http://example.com/hotels/{hotel}/bookings/{booking}").build(); + + URI uri = uriComponents.expand("42", "21").encode().toUri(); +---- + +Note that `UriComponents` is immutable and the `expand()` and `encode()` operations +return new instances if necessary. + +You can also expand and encode using individual URI components: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + UriComponents uriComponents = UriComponentsBuilder.newInstance() + .scheme("http").host("example.com").path("/hotels/{hotel}/bookings/{booking}").build() + .expand("42", "21") + .encode(); +---- + +In a Servlet environment the `ServletUriComponentsBuilder` sub-class provides static +factory methods to copy available URL information from a Servlet requests: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + HttpServletRequest request = ... + + // Re-use host, scheme, port, path and query string + // Replace the "accountId" query param + + ServletUriComponentsBuilder ucb = ServletUriComponentsBuilder.fromRequest(request) + .replaceQueryParam("accountId", "{id}").build() + .expand("123") + .encode(); +---- + +Alternatively, you may choose to copy a subset of the available information up to and +including the context path: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + // Re-use host, port and context path + // Append "/accounts" to the path + + ServletUriComponentsBuilder ucb = ServletUriComponentsBuilder.fromContextPath(request) + .path("/accounts").build() +---- + +Or in cases where the `DispatcherServlet` is mapped by name (e.g. `/main/*`), you can +also have the literal part of the servlet mapping included: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + // Re-use host, port, context path + // Append the literal part of the servlet mapping to the path + // Append "/accounts" to the path + + ServletUriComponentsBuilder ucb = ServletUriComponentsBuilder.fromServletMapping(request) + .path("/accounts").build() +---- + +[[mvc-construct-uri-controllers]] +=== Building URIs to Controllers and methods + +Spring MVC provides another mechanism for building and encoding URIs that link to +Controllers and methods defined within an application. +{javadoc-baseurl}/org/springframework/web/servlet/mvc/method/annotation/MvcUriComponentsBuilder.html[`MvcUriComponentsBuilder`] +extends `UriComponentsBuilder` and provides such possibilities. + +Given this Controller: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Controller + @RequestMapping("/hotels/{hotel}") + public class BookingController { + + @RequestMapping("/bookings/{booking}") + public String getBooking(@PathVariable Long booking) { + + // ... + + } +---- + +and using the `MvcUriComponentsBuilder`, the previous example is now: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + UriComponents uriComponents = MvcUriComponentsBuilder + .fromMethodName(BookingController.class, "getBooking",21).buildAndExpand(42); + + URI uri = uriComponents.encode().toUri(); +---- + +The `MvcUriComponentsBuilder` can also create "mock Controllers", thus enabling to create +URIs by coding against the actual Controller's API: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + UriComponents uriComponents = MvcUriComponentsBuilder + .fromMethodCall(on(BookingController.class).getBooking(21)).buildAndExpand(42); + + URI uri = uriComponents.encode().toUri(); +---- + + +[[mvc-localeresolver]] +=== Using locales +Most parts of Spring's architecture support internationalization, just as the Spring web +MVC framework does. `DispatcherServlet` enables you to automatically resolve messages +using the client's locale. This is done with `LocaleResolver` objects. + +When a request comes in, the `DispatcherServlet` looks for a locale resolver, and if it +finds one it tries to use it to set the locale. Using the `RequestContext.getLocale()` +method, you can always retrieve the locale that was resolved by the locale resolver. + +In addition to automatic locale resolution, you can also attach an interceptor to the +handler mapping (see <<mvc-handlermapping-interceptor>> for more information on handler +mapping interceptors) to change the locale under specific circumstances, for example, +based on a parameter in the request. + +Locale resolvers and interceptors are defined in the +`org.springframework.web.servlet.i18n` package and are configured in your application +context in the normal way. Here is a selection of the locale resolvers included in +Spring. + + + +[[mvc-timezone]] +==== Obtaining Time Zone Information +In addition to obtaining the client's locale, it is often useful to know their time zone. +The `LocaleContextResolver` interface offers an extension to `LocaleResolver` that allows +resolvers to provide a richer `LocaleContext`, which may include time zone information. + +When available, the user's `TimeZone` can be obtained using the +`RequestContext.getTimeZone()` method. Time zone information will automatically be used +by Date/Time `Converter` and `Formatter` objects registered with Spring's +`ConversionService`. + + + +[[mvc-localeresolver-acceptheader]] +==== AcceptHeaderLocaleResolver +This locale resolver inspects the `accept-language` header in the request that was sent +by the client (e.g., a web browser). Usually this header field contains the locale of +the client's operating system. __Note that this resolver does not support time zone +information.__ + + + +[[mvc-localeresolver-cookie]] +==== CookieLocaleResolver + +This locale resolver inspects a `Cookie` that might exist on the client to see if a +`Locale` or `TimeZone` is specified. If so, it uses the specified details. Using the +properties of this locale resolver, you can specify the name of the cookie as well as the +maximum age. Find below an example of defining a `CookieLocaleResolver`. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + <bean id="localeResolver" class="org.springframework.web.servlet.i18n.CookieLocaleResolver"> + + <property name="cookieName" value="clientlanguage"/> + + <!-- in seconds. If set to -1, the cookie is not persisted (deleted when browser shuts down) --> + <property name="cookieMaxAge" value="100000"> + + </bean> +---- + +[[mvc-cookie-locale-resolver-props-tbl]] +.CookieLocaleResolver properties +[cols="1,1,4"] +|=== +| Property| Default| Description + +| cookieName +| classname + LOCALE +| The name of the cookie + +| cookieMaxAge +| Integer.MAX_INT +| The maximum time a cookie will stay persistent on the client. If -1 is specified, the + cookie will not be persisted; it will only be available until the client shuts down + their browser. + +| cookiePath +| / +| Limits the visibility of the cookie to a certain part of your site. When cookiePath is + specified, the cookie will only be visible to that path and the paths below it. +|=== + + + +[[mvc-localeresolver-session]] +==== SessionLocaleResolver + +The `SessionLocaleResolver` allows you to retrieve `Locale` and `TimeZone` from the +session that might be associated with the user's request. + + + +[[mvc-localeresolver-interceptor]] +==== LocaleChangeInterceptor + +You can enable changing of locales by adding the `LocaleChangeInterceptor` to one of the +handler mappings (see <<mvc-handlermapping>>). It will detect a parameter in the request +and change the locale. It calls `setLocale()` on the `LocaleResolver` that also exists +in the context. The following example shows that calls to all `*.view` resources +containing a parameter named `siteLanguage` will now change the locale. So, for example, +a request for the following URL, `http://www.sf.net/home.view?siteLanguage=nl` will +change the site language to Dutch. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + <bean id="localeChangeInterceptor" + class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor"> + <property name="paramName" value="siteLanguage"/> + </bean> + + <bean id="localeResolver" + class="org.springframework.web.servlet.i18n.CookieLocaleResolver"/> + + <bean id="urlMapping" + class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping"> + <property name="interceptors"> + <list> + <ref bean="localeChangeInterceptor"/> + </list> + </property> + <property name="mappings"> + <value>/**/*.view=someController</value> + </property> + </bean> +---- + + + + +[[mvc-themeresolver]] +=== Using themes + + + +[[mvc-themeresolver-introduction]] +==== Overview of themes +You can apply Spring Web MVC framework themes to set the overall look-and-feel of your +application, thereby enhancing user experience. A theme is a collection of static +resources, typically style sheets and images, that affect the visual style of the +application. + + + +[[mvc-themeresolver-defining]] +==== Defining themes +To use themes in your web application, you must set up an implementation of the +`org.springframework.ui.context.ThemeSource` interface. The `WebApplicationContext` +interface extends `ThemeSource` but delegates its responsibilities to a dedicated +implementation. By default the delegate will be an +`org.springframework.ui.context.support.ResourceBundleThemeSource` implementation that +loads properties files from the root of the classpath. To use a custom `ThemeSource` +implementation or to configure the base name prefix of the `ResourceBundleThemeSource`, +you can register a bean in the application context with the reserved name `themeSource`. +The web application context automatically detects a bean with that name and uses it. + +When using the `ResourceBundleThemeSource`, a theme is defined in a simple properties +file. The properties file lists the resources that make up the theme. Here is an example: + +[literal] +[subs="verbatim,quotes"] +---- +styleSheet=/themes/cool/style.css +background=/themes/cool/img/coolBg.jpg +---- + +The keys of the properties are the names that refer to the themed elements from view +code. For a JSP, you typically do this using the `spring:theme` custom tag, which is +very similar to the `spring:message` tag. The following JSP fragment uses the theme +defined in the previous example to customize the look and feel: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + <%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%> + <html> + <head> + <link rel="stylesheet" href="<spring:theme code='styleSheet'/>" type="text/css"/> + </head> + <body style="background=<spring:theme code='background'/>"> + ... + </body> + </html> +---- + +By default, the `ResourceBundleThemeSource` uses an empty base name prefix. As a result, +the properties files are loaded from the root of the classpath. Thus you would put the +`cool.properties` theme definition in a directory at the root of the classpath, for +example, in `/WEB-INF/classes`. The `ResourceBundleThemeSource` uses the standard Java +resource bundle loading mechanism, allowing for full internationalization of themes. For +example, we could have a `/WEB-INF/classes/cool_nl.properties` that references a special +background image with Dutch text on it. + + + +[[mvc-themeresolver-resolving]] +==== Theme resolvers +After you define themes, as in the preceding section, you decide which theme to use. The +`DispatcherServlet` will look for a bean named `themeResolver` to find out which +`ThemeResolver` implementation to use. A theme resolver works in much the same way as a +`LocaleResolver`. It detects the theme to use for a particular request and can also +alter the request's theme. The following theme resolvers are provided by Spring: + +[[mvc-theme-resolver-impls-tbl]] +.ThemeResolver implementations +[cols="1,4"] +|=== +| Class| Description + +| `FixedThemeResolver` +| Selects a fixed theme, set using the `defaultThemeName` property. + +| `SessionThemeResolver` +| The theme is maintained in the user's HTTP session. It only needs to be set once for + each session, but is not persisted between sessions. + +| `CookieThemeResolver` +| The selected theme is stored in a cookie on the client. +|=== + +Spring also provides a `ThemeChangeInterceptor` that allows theme changes on every +request with a simple request parameter. + + + + +[[mvc-multipart]] +=== Spring's multipart (file upload) support + + + +[[mvc-multipart-introduction]] +==== Introduction +Spring's built-in multipart support handles file uploads in web applications. You enable +this multipart support with pluggable `MultipartResolver` objects, defined in the +`org.springframework.web.multipart` package. Spring provides one `MultipartResolver` +implementation for use with http://jakarta.apache.org/commons/fileupload[__Commons +FileUpload__] and another for use with Servlet 3.0 multipart request parsing. + +By default, Spring does no multipart handling, because some developers want to handle +multiparts themselves. You enable Spring multipart handling by adding a multipart +resolver to the web application's context. Each request is inspected to see if it +contains a multipart. If no multipart is found, the request continues as expected. If a +multipart is found in the request, the `MultipartResolver` that has been declared in +your context is used. After that, the multipart attribute in your request is treated +like any other attribute. + + + +[[mvc-multipart-resolver-commons]] +==== Using a MultipartResolver with __Commons FileUpload__ + +The following example shows how to use the `CommonsMultipartResolver`: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + <bean id="multipartResolver" + class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> + + <!-- one of the properties available; the maximum file size in bytes --> + <property name="maxUploadSize" value="100000"/> + + </bean> +---- + +Of course you also need to put the appropriate jars in your classpath for the multipart +resolver to work. In the case of the `CommonsMultipartResolver`, you need to use +`commons-fileupload.jar`. + +When the Spring `DispatcherServlet` detects a multi-part request, it activates the +resolver that has been declared in your context and hands over the request. The resolver +then wraps the current `HttpServletRequest` into a `MultipartHttpServletRequest` that +supports multipart file uploads. Using the `MultipartHttpServletRequest`, you can get +information about the multiparts contained by this request and actually get access to +the multipart files themselves in your controllers. + + + +[[mvc-multipart-resolver-standard]] +==== Using a MultipartResolver with __Servlet 3.0__ + +In order to use Servlet 3.0 based multipart parsing, you need to mark the +`DispatcherServlet` with a `"multipart-config"` section in `web.xml`, or with a +`javax.servlet.MultipartConfigElement` in programmatic Servlet registration, or in case +of a custom Servlet class possibly with a `javax.servlet.annotation.MultipartConfig` +annotation on your Servlet class. Configuration settings such as maximum sizes or +storage locations need to be applied at that Servlet registration level as Servlet 3.0 +does not allow for those settings to be done from the MultipartResolver. + +Once Servlet 3.0 multipart parsing has been enabled in one of the above mentioned ways +you can add the `StandardServletMultipartResolver` to your Spring configuration: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + <bean id="multipartResolver" + class="org.springframework.web.multipart.support.StandardServletMultipartResolver"> + </bean> +---- + + + +[[mvc-multipart-forms]] +==== Handling a file upload in a form +After the `MultipartResolver` completes its job, the request is processed like any +other. First, create a form with a file input that will allow the user to upload a form. +The encoding attribute ( `enctype="multipart/form-data"`) lets the browser know how to +encode the form as multipart request: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + <html> + <head> + <title>Upload a file please + + +

Please upload a file

+
+ + + + + + +---- + +The next step is to create a controller that handles the file upload. This controller is +very similar to a <>, except that we +use `MultipartHttpServletRequest` or `MultipartFile` in the method parameters: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Controller + public class FileUploadController { + + @RequestMapping(value = "/form", method = RequestMethod.POST) + public String handleFormUpload(@RequestParam("name") String name, + @RequestParam("file") MultipartFile file) { + + if (!file.isEmpty()) { + byte[] bytes = file.getBytes(); + // store the bytes somewhere + return "redirect:uploadSuccess"; + } + + return "redirect:uploadFailure"; + } + + } +---- + +Note how the `@RequestParam` method parameters map to the input elements declared in the +form. In this example, nothing is done with the `byte[]`, but in practice you can save +it in a database, store it on the file system, and so on. + +When using Servlet 3.0 multipart parsing you can also use `javax.servlet.http.Part` for +the method parameter: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Controller + public class FileUploadController { + + @RequestMapping(value = "/form", method = RequestMethod.POST) + public String handleFormUpload(@RequestParam("name") String name, + @RequestParam("file") Part file) { + + InputStream inputStream = file.getInputStream(); + // store bytes from uploaded file somewhere + + return "redirect:uploadSuccess"; + } + + } +---- + + + +[[mvc-multipart-forms-non-browsers]] +==== Handling a file upload request from programmatic clients +Multipart requests can also be submitted from non-browser clients in a RESTful service +scenario. All of the above examples and configuration apply here as well. However, +unlike browsers that typically submit files and simple form fields, a programmatic +client can also send more complex data of a specific content type -- for example a +multipart request with a file and second part with JSON formatted data: + +[literal] +[subs="verbatim,quotes"] +---- +POST /someUrl +Content-Type: multipart/mixed + +--edt7Tfrdusa7r3lNQc79vXuhIIMlatb7PQg7Vp +Content-Disposition: form-data; name="meta-data" +Content-Type: application/json; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +{ + "name": "value" +} +--edt7Tfrdusa7r3lNQc79vXuhIIMlatb7PQg7Vp +Content-Disposition: form-data; name="file-data"; filename="file.properties" +Content-Type: text/xml +Content-Transfer-Encoding: 8bit +... File Data ... +---- + +You could access the part named "meta-data" with a `@RequestParam("meta-data") String +metadata` controller method argument. However, you would probably prefer to accept a +strongly typed object initialized from the JSON formatted data in the body of the +request part, very similar to the way `@RequestBody` converts the body of a +non-multipart request to a target object with the help of an `HttpMessageConverter`. + +You can use the `@RequestPart` annotation instead of the `@RequestParam` annotation for +this purpose. It allows you to have the content of a specific multipart passed through +an `HttpMessageConverter` taking into consideration the `'Content-Type'` header of the +multipart: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @RequestMapping(value="/someUrl", method = RequestMethod.POST) + public String onSubmit(**@RequestPart("meta-data") MetaData metadata, + @RequestPart("file-data") MultipartFile file**) { + + // ... + + } +---- + +Notice how `MultipartFile` method arguments can be accessed with `@RequestParam` or with +`@RequestPart` interchangeably. However, the `@RequestPart("meta-data") MetaData` method +argument in this case is read as JSON content based on its `'Content-Type'` header and +converted with the help of the `MappingJackson2HttpMessageConverter`. + + + + +[[mvc-exceptionhandlers]] +=== Handling exceptions + + + +[[mvc-exceptionhandlers-resolver]] +==== HandlerExceptionResolver + +Spring `HandlerExceptionResolver` implementations deal with unexpected exceptions that +occur during controller execution. A `HandlerExceptionResolver` somewhat resembles the +exception mappings you can define in the web application descriptor `web.xml`. However, +they provide a more flexible way to do so. For example they provide information about +which handler was executing when the exception was thrown. Furthermore, a programmatic +way of handling exceptions gives you more options for responding appropriately before +the request is forwarded to another URL (the same end result as when you use the Servlet +specific exception mappings). + +Besides implementing the `HandlerExceptionResolver` interface, which is only a matter of +implementing the `resolveException(Exception, Handler)` method and returning a +`ModelAndView`, you may also use the provided `SimpleMappingExceptionResolver` or create +`@ExceptionHandler` methods. The `SimpleMappingExceptionResolver` enables you to take +the class name of any exception that might be thrown and map it to a view name. This is +functionally equivalent to the exception mapping feature from the Servlet API, but it is +also possible to implement more finely grained mappings of exceptions from different +handlers. The `@ExceptionHandler` annotation on the other hand can be used on methods +that should be invoked to handle an exception. Such methods may be defined locally +within an `@Controller` or may apply to many `@Controller` classes when defined within an +`@ControllerAdvice` class. The following sections explain this in more detail. + + + +[[mvc-ann-exceptionhandler]] +==== @ExceptionHandler + +The `HandlerExceptionResolver` interface and the `SimpleMappingExceptionResolver` +implementations allow you to map Exceptions to specific views declaratively along with +some optional Java logic before forwarding to those views. However, in some cases, +especially when relying on `@ResponseBody` methods rather than on view resolution, it +may be more convenient to directly set the status of the response and optionally write +error content to the body of the response. + +You can do that with `@ExceptionHandler` methods. When declared within a controller such +methods apply to exceptions raised by `@RequestMapping` methods of that contoroller (or +any of its sub-classes). You can also declare an `@ExceptionHandler` method within an +`@ControllerAdvice` class in which case it handles exceptions from `@RequestMapping` +methods from many controllers. Below is an example of a controller-local +`@ExceptionHandler` method: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Controller + public class SimpleController { + + // @RequestMapping methods omitted ... + + @ExceptionHandler(IOException.class) + public ResponseEntity handleIOException(IOException ex) { + // prepare responseEntity + return responseEntity; + } + + } +---- + +The `@ExceptionHandler` value can be set to an array of Exception types. If an exception +is thrown that matches one of the types in the list, then the method annotated with the +matching `@ExceptionHandler` will be invoked. If the annotation value is not set then +the exception types listed as method arguments are used. + +Much like standard controller methods annotated with a `@RequestMapping` annotation, the +method arguments and return values of `@ExceptionHandler` methods can be flexible. For +example, the `HttpServletRequest` can be accessed in Servlet environments and the +`PortletRequest` in Portlet environments. The return type can be a `String`, which is +interpreted as a view name, a `ModelAndView` object, a `ResponseEntity`, or you can also +add the `@ResponseBody` to have the method return value converted with message +converters and written to the response stream. + + + +[[mvc-ann-rest-spring-mvc-exceptions]] +==== Handling Standard Spring MVC Exceptions +Spring MVC may raise a number of exceptions while processing a request. The +`SimpleMappingExceptionResolver` can easily map any exception to a default error view as +needed. However, when working with clients that interpret responses in an automated way +you will want to set specific status code on the response. Depending on the exception +raised the status code may indicate a client error (4xx) or a server error (5xx). + +The `DefaultHandlerExceptionResolver` translates Spring MVC exceptions to specific error +status codes. It is registered by default with the MVC namespace, the MVC Java config, +and also by the the `DispatcherServlet` (i.e. when not using the MVC namespace or Java +config). Listed below are some of the exceptions handled by this resolver and the +corresponding status codes: + +|=== +| Exception| HTTP Status Code + +| `BindException` +| 400 (Bad Request) + +| `ConversionNotSupportedException` +| 500 (Internal Server Error) + +| `HttpMediaTypeNotAcceptableException` +| 406 (Not Acceptable) + +| `HttpMediaTypeNotSupportedException` +| 415 (Unsupported Media Type) + +| `HttpMessageNotReadableException` +| 400 (Bad Request) + +| `HttpMessageNotWritableException` +| 500 (Internal Server Error) + +| `HttpRequestMethodNotSupportedException` +| 405 (Method Not Allowed) + +| `MethodArgumentNotValidException` +| 400 (Bad Request) + +| `MissingServletRequestParameterException` +| 400 (Bad Request) + +| `MissingServletRequestPartException` +| 400 (Bad Request) + +| `NoHandlerFoundException` +| 404 (Not Found) + +| `NoSuchRequestHandlingMethodException` +| 404 (Not Found) + +| `TypeMismatchException` +| 400 (Bad Request) +|=== + +The `DefaultHandlerExceptionResolver` works transparently by setting the status of the +response. However, it stops short of writing any error content to the body of the +response while your application may need to add developer-friendly content to every +error response for example when providing a REST API. You can prepare a `ModelAndView` +and render error content through view resolution -- i.e. by configuring a +`ContentNegotiatingViewResolver`, `MappingJackson2JsonView`, and so on. However, you may +prefer to use `@ExceptionHandler` methods instead. + +If you prefer to write error content via `@ExceptionHandler` methods you can extend +`ResponseEntityExceptionHandler` instead. This is a convenient base for +`@ControllerAdvice` classes providing an `@ExceptionHandler` method to handle standard +Spring MVC exceptions and return `ResponseEntity`. That allows you to customize the +response and write error content with message converters. See the +`ResponseEntityExceptionHandler` javadocs for more details. + + + +[[mvc-ann-annotated-exceptions]] +==== Annotating Business Exceptions With @ResponseStatus + +A business exception can be annotated with `@ResponseStatus`. When the exception is +raised, the `ResponseStatusExceptionResolver` handles it by setting the status of the +response accordingly. By default the `DispatcherServlet` registers the +`ResponseStatusExceptionResolver` and it is available for use. + + + +[[mvc-ann-customer-servlet-container-error-page]] +==== Customizing the Default Servlet Container Error Page +When the status of the response is set to an error status code and the body of the +response is empty, Servlet containers commonly render an HTML formatted error page. To +customize the default error page of the container, you can declare an `` +element in `web.xml`. Up until Servlet 3, that element had to be mapped to a specific +status code or exception type. Starting with Servlet 3 an error page does not need to be +mapped, which effectively means the specified location customizes the default Servlet +container error page. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + /error + +---- + +Note that the actual location for the error page can be a JSP page or some other URL +within the container including one handled through an `@Controller` method: + +When writing error information, the status code and the error message set on the +`HttpServletResponse` can be accessed through request attributes in a controller: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Controller + public class ErrorController { + + @RequestMapping(value="/error", produces="application/json") + @ResponseBody + public Map handle(HttpServletRequest request) { + + Map map = new HashMap(); + map.put("status", request.getAttribute("javax.servlet.error.status_code")); + map.put("reason", request.getAttribute("javax.servlet.error.message")); + + return map; + } + + } +---- + +or in a JSP: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + <%@ page contentType="application/json" pageEncoding="UTF-8"%> + { + status:<%=request.getAttribute("javax.servlet.error.status_code") %>, + reason:<%=request.getAttribute("javax.servlet.error.message") %> + } +---- + + +[[mvc-web-security]] +=== Web Security + +The http://projects.spring.io/spring-security/[Spring Security] project provides features +to protect web applications from malicious exploits. Check out the reference documentation in the sections on +http://docs.spring.io/spring-security/site/docs/current/reference/htmlsingle/#csrf["CSRF protection"], +http://docs.spring.io/spring-security/site/docs/current/reference/htmlsingle/#headers["Security Response Headers"], and also +http://docs.spring.io/spring-security/site/docs/current/reference/htmlsingle/#mvc["Spring MVC Integration"]. +Note that using Spring Security to secure the application is not necessarily required for all features. +For example CSRF protection can be added simply by adding the `CsrfFilter` and +`CsrfRequestDataValueProcessor` to your configuration. See the +https://github.com/spring-projects/spring-mvc-showcase/commit/361adc124c05a8187b84f25e8a57550bb7d9f8e4[Spring MVC Showcase] +for an example. + +Another option is to use a framework dedicated to Web Security. +http://hdiv.org/[HDIV] is one such framework and integrates with Spring MVC. + + + + +[[mvc-coc]] +=== Convention over configuration support +For a lot of projects, sticking to established conventions and having reasonable +defaults is just what they (the projects) need, and Spring Web MVC now has explicit +support for __convention over configuration__. What this means is that if you establish +a set of naming conventions and suchlike, you can __substantially__ cut down on the +amount of configuration that is required to set up handler mappings, view resolvers, +`ModelAndView` instances, etc. This is a great boon with regards to rapid prototyping, +and can also lend a degree of (always good-to-have) consistency across a codebase should +you choose to move forward with it into production. + +Convention-over-configuration support addresses the three core areas of MVC: models, +views, and controllers. + + + +[[mvc-coc-ccnhm]] +==== The Controller ControllerClassNameHandlerMapping + +The `ControllerClassNameHandlerMapping` class is a `HandlerMapping` implementation that +uses a convention to determine the mapping between request URLs and the `Controller` +instances that are to handle those requests. + +Consider the following simple `Controller` implementation. Take special notice of the +__name__ of the class. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class **ViewShoppingCartController** implements Controller { + + public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) { + // the implementation is not hugely important for this example... + } + + } +---- + +Here is a snippet from the corresponding Spring Web MVC configuration file: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + +---- + +The `ControllerClassNameHandlerMapping` finds all of the various handler (or +`Controller`) beans defined in its application context and strips `Controller` off the +name to define its handler mappings. Thus, `ViewShoppingCartController` maps to the +`/viewshoppingcart*` request URL. + +Let's look at some more examples so that the central idea becomes immediately familiar. +(Notice all lowercase in the URLs, in contrast to camel-cased `Controller` class names.) + +* `WelcomeController` maps to the `/welcome*` request URL +* `HomeController` maps to the `/home*` request URL +* `IndexController` maps to the `/index*` request URL +* `RegisterController` maps to the `/register*` request URL + +In the case of `MultiActionController` handler classes, the mappings generated are +slightly more complex. The `Controller` names in the following examples are assumed to +be `MultiActionController` implementations: + +* `AdminController` maps to the `/admin/*` request URL +* `CatalogController` maps to the `/catalog/*` request URL + +If you follow the convention of naming your `Controller` implementations as +`xxxController`, the `ControllerClassNameHandlerMapping` saves you the tedium of +defining and maintaining a potentially __looooong__ `SimpleUrlHandlerMapping` (or +suchlike). + +The `ControllerClassNameHandlerMapping` class extends the `AbstractHandlerMapping` base +class so you can define `HandlerInterceptor` instances and everything else just as you +would with many other `HandlerMapping` implementations. + + + +[[mvc-coc-modelmap]] +==== The Model ModelMap (ModelAndView) + +The `ModelMap` class is essentially a glorified `Map` that can make adding objects that +are to be displayed in (or on) a `View` adhere to a common naming convention. Consider +the following `Controller` implementation; notice that objects are added to the +`ModelAndView` without any associated name specified. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class DisplayShoppingCartController implements Controller { + + public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) { + + List cartItems = // get a List of CartItem objects + User user = // get the User doing the shopping + + ModelAndView mav = new ModelAndView("displayShoppingCart"); <-- the logical view name + + mav.addObject(cartItems); <-- look ma, no name, just the object + mav.addObject(user); <-- and again ma! + + return mav; + } + } +---- + +The `ModelAndView` class uses a `ModelMap` class that is a custom `Map` implementation +that automatically generates a key for an object when an object is added to it. The +strategy for determining the name for an added object is, in the case of a scalar object +such as `User`, to use the short class name of the object's class. The following +examples are names that are generated for scalar objects put into a `ModelMap` instance. + +* An `x.y.User` instance added will have the name `user` generated. +* An `x.y.Registration` instance added will have the name `registration` generated. +* An `x.y.Foo` instance added will have the name `foo` generated. +* A `java.util.HashMap` instance added will have the name `hashMap` generated. You + probably want to be explicit about the name in this case because `hashMap` is less + than intuitive. +* Adding `null` will result in an `IllegalArgumentException` being thrown. If the object + (or objects) that you are adding could be `null`, then you will also want to be + explicit about the name. + +.What, no automatic pluralization? +**** +Spring Web MVC's convention-over-configuration support does not support automatic +pluralization. That is, you cannot add a `List` of `Person` objects to a `ModelAndView` +and have the generated name be `people`. + +This decision was made after some debate, with the "Principle of Least Surprise" winning +out in the end. +**** + +The strategy for generating a name after adding a `Set` or a `List` is to peek into the +collection, take the short class name of the first object in the collection, and use +that with `List` appended to the name. The same applies to arrays although with arrays +it is not necessary to peek into the array contents. A few examples will make the +semantics of name generation for collections clearer: + +* An `x.y.User[]` array with zero or more `x.y.User` elements added will have the name + `userList` generated. +* An `x.y.Foo[]` array with zero or more `x.y.User` elements added will have the name + `fooList` generated. +* A `java.util.ArrayList` with one or more `x.y.User` elements added will have the name + `userList` generated. +* A `java.util.HashSet` with one or more `x.y.Foo` elements added will have the name + `fooList` generated. +* An __empty__ `java.util.ArrayList` will not be added at all (in effect, the + `addObject(..)` call will essentially be a no-op). + + + +[[mvc-coc-r2vnt]] +==== The View - RequestToViewNameTranslator + +The `RequestToViewNameTranslator` interface determines a logical `View` name when no +such logical view name is explicitly supplied. It has just one implementation, the +`DefaultRequestToViewNameTranslator` class. + +The `DefaultRequestToViewNameTranslator` maps request URLs to logical view names, as +with this example: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class RegistrationController implements Controller { + + public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) { + // process the request... + ModelAndView mav = new ModelAndView(); + // add data as necessary to the model... + return mav; + // notice that no View or logical view name has been set + } + + } +---- + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + + + + + + + + + + + + +---- + +Notice how in the implementation of the `handleRequest(..)` method no `View` or logical +view name is ever set on the `ModelAndView` that is returned. The +`DefaultRequestToViewNameTranslator` is tasked with generating a __logical view name__ +from the URL of the request. In the case of the above `RegistrationController`, which is +used in conjunction with the `ControllerClassNameHandlerMapping`, a request URL of +`http://localhost/registration.html` results in a logical view name of `registration` +being generated by the `DefaultRequestToViewNameTranslator`. This logical view name is +then resolved into the `/WEB-INF/jsp/registration.jsp` view by the +`InternalResourceViewResolver` bean. + +[TIP] +==== + +You do not need to define a `DefaultRequestToViewNameTranslator` bean explicitly. If you +like the default settings of the `DefaultRequestToViewNameTranslator`, you can rely on +the Spring Web MVC `DispatcherServlet` to instantiate an instance of this class if one +is not explicitly configured. +==== + +Of course, if you need to change the default settings, then you do need to configure +your own `DefaultRequestToViewNameTranslator` bean explicitly. Consult the comprehensive +`DefaultRequestToViewNameTranslator` javadocs for details on the various properties +that can be configured. + + + + +[[mvc-etag]] +=== ETag support +An http://en.wikipedia.org/wiki/HTTP_ETag[ETag] (entity tag) is an HTTP response header +returned by an HTTP/1.1 compliant web server used to determine change in content at a +given URL. It can be considered to be the more sophisticated successor to the +`Last-Modified` header. When a server returns a representation with an ETag header, the +client can use this header in subsequent GETs, in an `If-None-Match` header. If the +content has not changed, the server returns `304: Not Modified`. + +Support for ETags is provided by the Servlet filter `ShallowEtagHeaderFilter`. It is a +plain Servlet Filter, and thus can be used in combination with any web framework. The +`ShallowEtagHeaderFilter` filter creates so-called shallow ETags (as opposed to deep +ETags, more about that later).The filter caches the content of the rendered JSP (or +other content), generates an MD5 hash over that, and returns that as an ETag header in +the response. The next time a client sends a request for the same resource, it uses that +hash as the `If-None-Match` value. The filter detects this, renders the view again, and +compares the two hashes. If they are equal, a `304` is returned. This filter will not +save processing power, as the view is still rendered. The only thing it saves is +bandwidth, as the rendered response is not sent back over the wire. + +You configure the `ShallowEtagHeaderFilter` in `web.xml`: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + etagFilter + org.springframework.web.filter.ShallowEtagHeaderFilter + + + + etagFilter + petclinic + +---- + + + + +[[mvc-container-config]] +=== Code-based Servlet container initialization +In a Servlet 3.0+ environment, you have the option of configuring the Servlet container +programmatically as an alternative or in combination with a `web.xml` file. Below is an +example of registering a `DispatcherServlet`: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + import org.springframework.web.WebApplicationInitializer; + + public class MyWebApplicationInitializer implements WebApplicationInitializer { + + @Override + public void onStartup(ServletContext container) { + XmlWebApplicationContext appContext = new XmlWebApplicationContext(); + appContext.setConfigLocation("/WEB-INF/spring/dispatcher-config.xml"); + + ServletRegistration.Dynamic registration = container.addServlet("dispatcher", new DispatcherServlet(appContext)); + registration.setLoadOnStartup(1); + registration.addMapping("/"); + } + + } +---- + +`WebApplicationInitializer` is an interface provided by Spring MVC that ensures your +implementation is detected and automatically used to initialize any Servlet 3 container. +An abstract base class implementation of `WebApplicationInitializer` named +`AbstractDispatcherServletInitializer` makes it even easier to register the +`DispatcherServlet` by simply overriding methods to specify the servlet mapping and the +location of the `DispatcherServlet` configuration: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class MyWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer { + + @Override + protected Class[] getRootConfigClasses() { + return null; + } + + @Override + protected Class[] getServletConfigClasses() { + return new Class[] { MyWebConfig.class }; + } + + @Override + protected String[] getServletMappings() { + return new String[] { "/" }; + } + + } +---- + +The above example is for an application that uses Java-based Spring configuration. If +using XML-based Spring configuration, extend directly from +`AbstractDispatcherServletInitializer`: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class MyWebAppInitializer extends AbstractDispatcherServletInitializer { + + @Override + protected WebApplicationContext createRootApplicationContext() { + return null; + } + + @Override + protected WebApplicationContext createServletApplicationContext() { + XmlWebApplicationContext cxt = new XmlWebApplicationContext(); + cxt.setConfigLocation("/WEB-INF/spring/dispatcher-config.xml"); + return cxt; + } + + @Override + protected String[] getServletMappings() { + return new String[] { "/" }; + } + + } +---- + +`AbstractDispatcherServletInitializer` also provides a convenient way to add `Filter` +instances and have them automatically mapped to the `DispatcherServlet`: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class MyWebAppInitializer extends AbstractDispatcherServletInitializer { + + // ... + + @Override + protected Filter[] getServletFilters() { + return new Filter[] { new HiddenHttpMethodFilter(), new CharacterEncodingFilter() }; + } + + } +---- + +Each filter is added with a default name based on its concrete type and automatically +mapped to the `DispatcherServlet`. + +The `isAsyncSupported` protected method of `AbstractDispatcherServletInitializer` +provides a single place to enable async support on the `DispatcherServlet` and all +filters mapped to it. By default this flag is set to `true`. + + + + +[[mvc-config]] +=== Configuring Spring MVC +<> and <> explained about Spring +MVC's special beans and the default implementations used by the `DispatcherServlet`. In +this section you'll learn about two additional ways of configuring Spring MVC. Namely +the MVC Java config and the MVC XML namespace. + +The MVC Java config and the MVC namespace provide similar default configuration that +overrides the `DispatcherServlet` defaults. The goal is to spare most applications from +having to having to create the same configuration and also to provide higher-level +constructs for configuring Spring MVC that serve as a simple starting point and require +little or no prior knowledge of the underlying configuration. + +You can choose either the MVC Java config or the MVC namespace depending on your +preference. Also as you will see further below, with the MVC Java config it is easier to +see the underlying configuration as well as to make fine-grained customizations directly +to the created Spring MVC beans. But let's start from the beginning. + + + +[[mvc-config-enable]] +==== Enabling the MVC Java Config or the MVC XML Namespace +To enable MVC Java config add the annotation `@EnableWebMvc` to one of your +`@Configuration` classes: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Configuration + @EnableWebMvc + public class WebConfig { + + } +---- + +To achieve the same in XML use the `mvc:annotation-driven` element in your +DispatcherServlet context (or in your root context if you have no DispatcherServlet +context defined): + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + +---- + +The above registers a `RequestMappingHandlerMapping`, a `RequestMappingHandlerAdapter`, +and an `ExceptionHandlerExceptionResolver` (among others) in support of processing +requests with annotated controller methods using annotations such as `@RequestMapping`, +`@ExceptionHandler`, and others. + +It also enables the following: + +. Spring 3 style type conversion through a <> instance +in addition to the JavaBeans PropertyEditors used for Data Binding. +. Support for <> Number fields using the `@NumberFormat` annotation +through the `ConversionService`. +. Support for <> Date, Calendar, Long, and Joda Time fields using the +`@DateTimeFormat` annotation. +. Support for <> `@Controller` inputs with `@Valid`, if +a JSR-303 Provider is present on the classpath. +. HttpMessageConverter support for `@RequestBody` method parameters and `@ResponseBody` +method return values from `@RequestMapping` or `@ExceptionHandler` methods. + ++ + +This is the complete list of HttpMessageConverters set up by mvc:annotation-driven: + ++ + +.. `ByteArrayHttpMessageConverter` converts byte arrays. +.. `StringHttpMessageConverter` converts strings. +.. `ResourceHttpMessageConverter` converts to/from +`org.springframework.core.io.Resource` for all media types. +.. `SourceHttpMessageConverter` converts to/from a `javax.xml.transform.Source`. +.. `FormHttpMessageConverter` converts form data to/from a `MultiValueMap`. +.. `Jaxb2RootElementHttpMessageConverter` converts Java objects to/from XML -- added if +JAXB2 is present and Jackson 2 XML extension is not present on the classpath. +.. `MappingJackson2HttpMessageConverter` converts to/from JSON -- added if Jackson 2 +is present on the classpath. +.. `MappingJackson2XmlHttpMessageConverter` converts to/from XML -- added if +https://github.com/FasterXML/jackson-dataformat-xml[Jackson 2 XML extension] is present +on the classpath. +.. `AtomFeedHttpMessageConverter` converts Atom feeds -- added if Rome is present on the +classpath. +.. `RssChannelHttpMessageConverter` converts RSS feeds -- added if Rome is present on +the classpath. + + + +[[mvc-config-customize]] +==== Customizing the Provided Configuration +To customize the default configuration in Java you simply implement the +`WebMvcConfigurer` interface or more likely extend the class `WebMvcConfigurerAdapter` +and override the methods you need. Below is an example of some of the available methods +to override. See +{javadoc-baseurl}/org/springframework/web/servlet/config/annotation/WebMvcConfigurer.html[`WebMvcConfigurer`] +for a list of all methods and the javadocs for further details: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Configuration + @EnableWebMvc + public class WebConfig extends WebMvcConfigurerAdapter { + + @Override + protected void addFormatters(FormatterRegistry registry) { + // Add formatters and/or converters + } + + @Override + public void configureMessageConverters(List> converters) { + // Configure the list of HttpMessageConverters to use + } + + } +---- + +To customize the default configuration of `` check what +attributes and sub-elements it supports. You can view the +http://schema.spring.io/mvc/spring-mvc.xsd[Spring MVC XML schema] or use the code +completion feature of your IDE to discover what attributes and sub-elements are +available. The sample below shows a subset of what is available: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + + + + + + + + +---- + + + +[[mvc-config-interceptors]] +==== Interceptors +You can configure `HandlerInterceptors` or `WebRequestInterceptors` to be applied to all +incoming requests or restricted to specific URL path patterns. + +An example of registering interceptors in Java: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Configuration + @EnableWebMvc + public class WebConfig extends WebMvcConfigurerAdapter { + + @Override + public void addInterceptors(InterceptorRegistry registry) { + registry.addInterceptor(new LocaleInterceptor()); + registry.addInterceptor(new ThemeInterceptor()).addPathPatterns("/**").excludePathPatterns("/admin/**"); + registry.addInterceptor(new SecurityInterceptor()).addPathPatterns("/secure/*"); + } + + } +---- + +And in XML use the `` element: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + + + + + +---- + + + +[[mvc-config-content-negotiation]] +==== Content Negotiation +You can configure how Spring MVC determines the requested media types from the client +for request mapping as well as for content negotiation purposes. The available options +are to check the file extension in the request URI, the "Accept" header, a request +parameter, as well as to fall back on a default content type. By default, file extension +in the request URI is checked first and the "Accept" header is checked next. + +For file extensions in the request URI, the MVC Java config and the MVC namespace, +automatically register extensions such as `.json`, `.xml`, `.rss`, and `.atom` if the +corresponding dependencies such as Jackson, JAXB2, or Rome are present on the classpath. +Additional extensions may be not need to be registered explicitly if they can be +discovered via `ServletContext.getMimeType(String)` or the __Java Activation Framework__ +(see `javax.activation.MimetypesFileTypeMap`). You can register more extensions with the +{javadoc-baseurl}/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerMapping.html#setUseRegisteredSuffixPatternMatch(boolean)[setUseRegisteredSuffixPatternMatch +method]. + +The introduction of `ContentNegotiationManager` also enables selective suffix pattern +matching for incoming requests. For more details, see its javadocs. + +Below is an example of customizing content negotiation options through the MVC Java +config: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Configuration + @EnableWebMvc + public class WebConfig extends WebMvcConfigurerAdapter { + + @Override + public void configureContentNegotiation(ContentNegotiationConfigurer configurer) { + configurer.favorPathExtension(false).favorParameter(true); + } + } +---- + +In the MVC namespace, the `` element has a +`content-negotiation-manager` attribute, which expects a `ContentNegotiationManager` +that in turn can be created with a `ContentNegotiationManagerFactoryBean`: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + json=application/json + xml=application/xml + + + +---- + +If not using the MVC Java config or the MVC namespace, you'll need to create an instance +of `ContentNegotiationManager` and use it to configure `RequestMappingHandlerMapping` +for request mapping purposes, and `RequestMappingHandlerAdapter` and +`ExceptionHandlerExceptionResolver` for content negotiation purposes. + +Note that `ContentNegotiatingViewResolver` now can also be configured with a +`ContentNegotiatingViewResolver`, so you can use one instance throughout Spring MVC. + +In more advanced cases, it may be useful to configure multiple +`ContentNegotiationManager` instances that in turn may contain custom +`ContentNegotiationStrategy` implementations. For example you could configure +`ExceptionHandlerExceptionResolver` with a `ContentNegotiationManager` that always +resolves the requested media type to `"application/json"`. Or you may want to plug a +custom strategy that has some logic to select a default content type (e.g. either XML or +JSON) if no content types were requested. + + + +[[mvc-config-view-controller]] +==== View Controllers +This is a shortcut for defining a `ParameterizableViewController` that immediately +forwards to a view when invoked. Use it in static cases when there is no Java controller +logic to execute before the view generates the response. + +An example of forwarding a request for `"/"` to a view called `"home"` in Java: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Configuration + @EnableWebMvc + public class WebConfig extends WebMvcConfigurerAdapter { + + @Override + public void addViewControllers(ViewControllerRegistry registry) { + registry.addViewController("/").setViewName("home"); + } + + } +---- + +And the same in XML use the `` element: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + +---- + + +[[mvc-config-view-resolvers]] +==== View Resolvers +The MVC config simplifies the registration of view resolvers. + +The following is a Java config example that configures content negotiation view +resolution using FreeMarker HTML templates and Jackson as a default `View` for +JSON rendering: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Configuration + @EnableWebMvc + public class WebConfig extends WebMvcConfigurerAdapter { + + @Override + public void configureViewResolvers(ViewResolverRegistry registry) { + registry.enableContentNegotiation(new MappingJackson2JsonView()); + registry.jsp(); + } + + } +---- + +And the same in XML: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + +---- + +Note however that FreeMarker, Velocity, Tiles, and Groovy Markup also require +configuration of the underlying view technology. + +The MVC namespace provides dedicated elements. For example with FreeMarker: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + + + + + + + +---- + +In Java config simply add the respective "Configurer" bean: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Configuration + @EnableWebMvc + public class WebConfig extends WebMvcConfigurerAdapter { + + @Override + public void configureViewResolvers(ViewResolverRegistry registry) { + registry.enableContentNegotiation(new MappingJackson2JsonView()); + registry.freeMarker().cache(false); + } + + @Bean + public FreeMarkerConfigurer freeMarkerConfigurer() { + FreeMarkerConfigurer configurer = new FreeMarkerConfigurer(); + configurer.setTemplateLoaderPath("/WEB-INF/"); + return configurer; + } + + } +---- + + + +[[mvc-config-static-resources]] +==== Serving of Resources +This option allows static resource requests following a particular URL pattern to be +served by a `ResourceHttpRequestHandler` from any of a list of `Resource` locations. +This provides a convenient way to serve static resources from locations other than the +web application root, including locations on the classpath. The `cache-period` property +may be used to set far future expiration headers (1 year is the recommendation of +optimization tools such as Page Speed and YSlow) so that they will be more efficiently +utilized by the client. The handler also properly evaluates the `Last-Modified` header +(if present) so that a `304` status code will be returned as appropriate, avoiding +unnecessary overhead for resources that are already cached by the client. For example, +to serve resource requests with a URL pattern of `/resources/**` from a +`public-resources` directory within the web application root you would use: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Configuration + @EnableWebMvc + public class WebConfig extends WebMvcConfigurerAdapter { + + @Override + public void addResourceHandlers(ResourceHandlerRegistry registry) { + registry.addResourceHandler("/resources/**").addResourceLocations("/public-resources/"); + } + + } +---- + +And the same in XML: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + +---- + +To serve these resources with a 1-year future expiration to ensure maximum use of the +browser cache and a reduction in HTTP requests made by the browser: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Configuration + @EnableWebMvc + public class WebConfig extends WebMvcConfigurerAdapter { + + @Override + public void addResourceHandlers(ResourceHandlerRegistry registry) { + registry.addResourceHandler("/resources/**").addResourceLocations("/public-resources/").setCachePeriod(31556926); + } + + } +---- + +And in XML: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + +---- + +The `mapping` attribute must be an Ant pattern that can be used by +`SimpleUrlHandlerMapping`, and the `location` attribute must specify one or more valid +resource directory locations. Multiple resource locations may be specified using a +comma-separated list of values. The locations specified will be checked in the specified +order for the presence of the resource for any given request. For example, to enable the +serving of resources from both the web application root and from a known path of +`/META-INF/public-web-resources/` in any jar on the classpath use: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @EnableWebMvc + @Configuration + public class WebConfig extends WebMvcConfigurerAdapter { + + @Override + public void addResourceHandlers(ResourceHandlerRegistry registry) { + registry.addResourceHandler("/resources/**") + .addResourceLocations("/", "classpath:/META-INF/public-web-resources/"); + } + + } +---- + +And in XML: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + +---- + +When serving resources that may change when a new version of the application is +deployed, it is recommended that you incorporate a version string into the mapping +pattern used to request the resources, so that you may force clients to request the +newly deployed version of your application's resources. Such a version string can be +parameterized and accessed using SpEL so that it may be easily managed in a single place +when deploying new versions. + +As an example, let's consider an application that uses a performance-optimized custom +build (as recommended) of the Dojo JavaScript library in production, and that the build +is generally deployed within the web application at a path of +`/public-resources/dojo/dojo.js`. Since different parts of Dojo may be incorporated into +the custom build for each new version of the application, the client web browsers need +to be forced to re-download that custom-built `dojo.js` resource any time a new version +of the application is deployed. A simple way to achieve this would be to manage the +version of the application in a properties file, such as: + +[literal] +[subs="verbatim,quotes"] +---- +application.version=1.0.0 +---- + +and then to make the properties file's values accessible to SpEL as a bean using the +`util:properties` tag: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + +---- + +With the application version now accessible via SpEL, we can incorporate this into the +use of the `resources` tag: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + +---- + +In Java, you can use the `@PropertySouce` annotation and then inject the `Environment` +abstraction for access to all defined properties: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Configuration + @EnableWebMvc + @PropertySource("/WEB-INF/spring/application.properties") + public class WebConfig extends WebMvcConfigurerAdapter { + + @Inject Environment env; + + @Override + public void addResourceHandlers(ResourceHandlerRegistry registry) { + registry.addResourceHandler( + "/resources-" + env.getProperty("application.version") + "/**") + .addResourceLocations("/public-resources/"); + } + + } +---- + +and finally, to request the resource with the proper URL, we can take advantage of the +Spring JSP tags: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + +---- + + +[[mvc-default-servlet-handler]] +==== Falling Back On the "Default" Servlet To Serve Resources +This allows for mapping the `DispatcherServlet` to "/" (thus overriding the mapping +of the container's default Servlet), while still allowing static resource requests to be +handled by the container's default Servlet. It configures a +`DefaultServletHttpRequestHandler` with a URL mapping of "/**" and the lowest priority +relative to other URL mappings. + +This handler will forward all requests to the default Servlet. Therefore it is important +that it remains last in the order of all other URL `HandlerMappings`. That will be the +case if you use `` or alternatively if you are setting up your +own customized `HandlerMapping` instance be sure to set its `order` property to a value +lower than that of the `DefaultServletHttpRequestHandler`, which is `Integer.MAX_VALUE`. + +To enable the feature using the default setup use: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Configuration + @EnableWebMvc + public class WebConfig extends WebMvcConfigurerAdapter { + + @Override + public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) { + configurer.enable(); + } + + } +---- + +Or in XML: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + +---- + +The caveat to overriding the "/" Servlet mapping is that the `RequestDispatcher` for the +default Servlet must be retrieved by name rather than by path. The +`DefaultServletHttpRequestHandler` will attempt to auto-detect the default Servlet for +the container at startup time, using a list of known names for most of the major Servlet +containers (including Tomcat, Jetty, GlassFish, JBoss, Resin, WebLogic, and WebSphere). +If the default Servlet has been custom configured with a different name, or if a +different Servlet container is being used where the default Servlet name is unknown, +then the default Servlet's name must be explicitly provided as in the following example: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Configuration + @EnableWebMvc + public class WebConfig extends WebMvcConfigurerAdapter { + + @Override + public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) { + configurer.enable("myCustomDefaultServlet"); + } + + } +---- + +Or in XML: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + +---- + + + +[[mvc-config-path-matching]] +==== Path Matching +This allows customizing various settings related to URL mapping and path matching. +For details on the individual options check out the +{javadoc-baseurl}/org/springframework/web/servlet/config/annotation/PathMatchConfigurer.html[PathMatchConfigurer] API. + +Below is an example in Java config: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Configuration + @EnableWebMvc + public class WebConfig extends WebMvcConfigurerAdapter { + + @Override + public void configurePathMatch(PathMatchConfigurer configurer) { + configurer + .setUseSuffixPatternMatch(true) + .setUseTrailingSlashMatch(false) + .setUseRegisteredSuffixPatternMatch(true) + .setPathMatcher(antPathMatcher()) + .setUrlPathHelper(urlPathHelper()); + } + + @Bean + public UrlPathHelper urlPathHelper() { + //... + } + + @Bean + public PathMatcher antPathMatcher() { + //... + } + + } +---- + +And the same in XML, use the `` element: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + +---- + + + +[[mvc-config-advanced-java]] +==== Advanced Customizations with MVC Java Config +As you can see from the above examples, MVC Java config and the MVC namespace provide +higher level constructs that do not require deep knowledge of the underlying beans +created for you. Instead it helps you to focus on your application needs. However, at +some point you may need more fine-grained control or you may simply wish to understand +the underlying configuration. + +The first step towards more fine-grained control is to see the underlying beans created +for you. In MVC Java config you can see the javadocs and the `@Bean` methods in +`WebMvcConfigurationSupport`. The configuration in this class is automatically imported +through the `@EnableWebMvc` annotation. In fact if you open `@EnableWebMvc` you can see +the `@Import` statement. + +The next step towards more fine-grained control is to customize a property on one of the +beans created in `WebMvcConfigurationSupport` or perhaps to provide your own instance. +This requires two things -- remove the `@EnableWebMvc` annotation in order to prevent +the import and then extend from `DelegatingWebMvcConfiguration`, a subclass of +`WebMvcConfigurationSupport`. +Here is an example: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Configuration + public class WebConfig extends DelegatingWebMvcConfiguration { + + @Override + public void addInterceptors(InterceptorRegistry registry){ + // ... + } + + @Override + @Bean + public RequestMappingHandlerAdapter requestMappingHandlerAdapter() { + // Create or let "super" create the adapter + // Then customize one of its properties + } + + } +---- + +[NOTE] +==== +An application should have only one configuration extending `DelegatingWebMvcConfiguration` +or a single `@EnableWebMvc` annotated class, since they both register the same underlying +beans. + +Modifying beans in this way does not prevent you from using any of the higher-level +constructs shown earlier in this section. `WebMvcConfigurerAdapter` subclasses and +`WebMvcConfigurer` implementations are still being used. +==== + + + +[[mvc-config-advanced-xml]] +==== Advanced Customizations with the MVC Namespace +Fine-grained control over the configuration created for you is a bit harder with the MVC +namespace. + +If you do need to do that, rather than replicating the configuration it provides, +consider configuring a `BeanPostProcessor` that detects the bean you want to customize +by type and then modifying its properties as necessary. For example: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Component + public class MyPostProcessor implements BeanPostProcessor { + + public Object postProcessBeforeInitialization(Object bean, String name) throws BeansException { + if (bean instanceof RequestMappingHandlerAdapter) { + // Modify properties of the adapter + } + } + + } +---- + +Note that `MyPostProcessor` needs to be included in an `` in order for +it to be detected or if you prefer you can declare it explicitly with an XML bean +declaration. + + + diff --git a/src/asciidoc/new-in-3.adoc b/src/asciidoc/new-in-3.adoc new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/src/asciidoc/new-in-4.adoc b/src/asciidoc/new-in-4.adoc new file mode 100644 index 000000000000..34a89dc05e9c --- /dev/null +++ b/src/asciidoc/new-in-4.adoc @@ -0,0 +1,302 @@ +[[new-in-4.0]] +== New Features and Enhancements in Spring Framework 4.0 +The Spring Framework was first released in 2004; since then there have been significant +major revisions: Spring 2.0 provided XML namespaces and AspectJ support; Spring 2.5 +embraced annotation-driven configuration; Spring 3.0 introduced a strong Java 5+ foundation +across the framework codebase, and features such as the Java-based `@Configuration` model. + +Version 4.0 is the latest major release of the Spring Framework and the first to fully +support Java 8 features. You can still use Spring with older versions of Java, however, +the minimum requirement has now been raised to Java SE 6. We have also taken the +opportunity of a major release to remove many deprecated classes and methods. + +A https://github.com/spring-projects/spring-framework/wiki/Migrating-from-earlier-versions-of-the-spring-framework[migration guide for upgrading to Spring 4.0] +is available on the https://github.com/spring-projects/spring-framework/wiki[Spring Framework GitHub Wiki]. + + + + +=== Improved Getting Started Experience +The new https://spring.io[spring.io] website provides a whole series of +https://spring.io/guides["Getting Started"] guides to help you learn Spring. You +can read more about the guides in the <> section +in this document. The new website also provides a comprehensive overview of the many +additional projects that are released under the Spring umbrella. + +If you are a Maven user you may also be interested in the helpful +<> POM file that is now published with each Spring +Framework release. + + + + +=== Removed Deprecated Packages and Methods +All deprecated packages, and many deprecated classes and methods have been removed with +version 4.0. If you are upgrading from a previous release of Spring, you should ensure +that you have fixed any deprecated calls that you were making to outdated APIs. + +For a complete set of changes, check out the +http://docs.spring.io/spring-framework/docs/3.2.4.RELEASE_to_4.0.0.RELEASE/[API +Differences Report]. + +Note that optional third-party dependencies have been raised to a 2010/2011 minimum +(i.e. Spring 4 generally only supports versions released in late 2010 or later now): +notably, Hibernate 3.6+, EhCache 2.1+, Quartz 1.8+, Groovy 1.8+, and Joda-Time 2.0+. +As an exception to the rule, Spring 4 requires the recent Hibernate Validator 4.3+, +and support for Jackson has been focused on 2.0+ now (with Jackson 1.8/1.9 support +retained for the time being where Spring 3.2 had it; now just in deprecated form). + + + + +=== Java 8 (as well as 6 and 7) +Spring Framework 4.0 provides support for several Java 8 features. You can make use of +__lambda expressions__ and __method references__ with Spring's callback interfaces. There +is first-class support for `java.time` (http://jcp.org/en/jsr/detail?id=310[JSR-310]), +and several existing annotations have been retrofitted as `@Repeatable`. You can also +use Java 8's parameter name discovery (based on the `-parameters` compiler flag) as an +alternative to compiling your code with debug information enabled. + +Spring remains compatible with older versions of Java and the JDK: concretely, Java SE 6 +(specifically, a minimum level equivalent to JDK 6 update 18, as released in January 2010) +and above are still fully supported. However, for newly started development projects +based on Spring 4, we recommend the use of Java 7 or 8. + + + + +=== Java EE 6 and 7 +Java EE version 6 or above is now considered the baseline for Spring Framework 4, with +the JPA 2.0 and Servlet 3.0 specifications being of particular relevance. In order to +remain compatible with Google App Engine and older application servers, it is possible +to deploy a Spring 4 application into a Servlet 2.5 environment. However, Servlet 3.0+ +is strongly recommended and a prerequisite in Spring's test and mock packages for test +setups in development environments. + +[NOTE] +==== +If you are a WebSphere 7 user, be sure to install the JPA 2.0 feature pack. On +WebLogic 10.3.4 or higher, install the JPA 2.0 patch that comes with it. This turns +both of those server generations into Spring 4 compatible deployment environments. +==== + +On a more forward-looking note, Spring Framework 4.0 supports the Java EE 7 level of +applicable specifications now: in particular, JMS 2.0, JTA 1.2, JPA 2.1, Bean Validation +1.1, and JSR-236 Concurrency Utilities. As usual, this support focuses on individual +use of those specifications, e.g. on Tomcat or in standalone environments. However, +it works equally well when a Spring application is deployed to a Java EE 7 server. + +Note that Hibernate 4.3 is a JPA 2.1 provider and therefore only supported as of +Spring Framework 4.0. The same applies to Hibernate Validator 5.0 as a Bean Validation +1.1 provider. Neither of the two are officially supported with Spring Framework 3.2. + + + +[[groovy-bean-definition-dsl]] +=== Groovy Bean Definition DSL +With Spring Framework 4.0 it is now possible to define external bean configuration using +a Groovy DSL. This is similar in concept to using XML bean definitions, but allows for +a more concise syntax. Using Groovy also allows you to easily embed bean definitions +directly in your bootstrap code. For example: + +[source,groovy,indent=0] +[subs="verbatim,quotes"] +---- + def reader = new GroovyBeanDefinitionReader(myApplicationContext) + reader.beans { + dataSource(BasicDataSource) { + driverClassName = "org.hsqldb.jdbcDriver" + url = "jdbc:hsqldb:mem:grailsDB" + username = "sa" + password = "" + settings = [mynew:"setting"] + } + sessionFactory(SessionFactory) { + dataSource = dataSource + } + myService(MyService) { + nestedBean = { AnotherBean bean -> + dataSource = dataSource + } + } + } +---- + +For more information consult the `GroovyBeanDefinitionReader` +{javadoc-baseurl}/org/springframework/beans/factory/groovy/GroovyBeanDefinitionReader.html[javadocs]. + + + + +=== Core Container Improvements +There have been several general improvements to the core container: + +* Spring now treats <> when injecting Beans. For example, if you are using a Spring Data + `Repository` you can now easily inject a specific implementation: + `@Autowired Repository customerRepository`. +* If you use Spring's meta-annotation support, you can now develop custom annotations that + <>. +* Beans can now be __ordered__ when they are <>. Both the `@Order` annotation and `Ordered` interface are + supported. +* The `@Lazy` annotation can now be used on injection points, as well as on `@Bean` + definitions. +* The <> for + developers using Java-based configuration. +* A generalized model for <> has + been added via the `@Conditional` annotation. This is similar to `@Profile` support but + allows for user-defined strategies to be developed programmatically. +* <> no longer require a default + constructor. Support is provided via the http://code.google.com/p/objenesis/[objenesis] + library which is repackaged __inline__ and distributed as part of the Spring Framework. + With this strategy, no constructor at all is being invoked for proxy instances anymore. +* There is managed time zone support across the framework now, e.g. on `LocaleContext`. + + + + +=== General Web Improvements +Deployment to Servlet 2.5 servers remains an option, but Spring Framework 4.0 is now +focused primarily on Servlet 3.0+ environments. If you are using the +<> you +will need to ensure that a Servlet 3.0 compatible JAR is in your __test classpath__. + +In addition to the WebSocket support mentioned later, the following general improvements +have been made to Spring's Web modules: + +* You can use the <> with Spring + MVC applications, removing the need to add `@ResponseBody` to each of your + `@RequestMapping` methods. +* The `AsyncRestTemplate` class has been added, <> when developing REST clients. +* Spring now offers <> when developing + Spring MVC applications. + + + + +=== WebSocket, SockJS, and STOMP Messaging +A new `spring-websocket` module provides comprehensive support for WebSocket-based, +two-way communication between client and server in web applications. It is compatible with +http://jcp.org/en/jsr/detail?id=356[JSR-356], the Java WebSocket API, and in addition +provides SockJS-based fallback options (i.e. WebSocket emulation) for use in browsers +that don't yet support the WebSocket protocol (e.g. Internet Explorer < 10). + +A new `spring-messaging` module adds support for STOMP as the WebSocket sub-protocol +to use in applications along with an annotation programming model for routing and +processing STOMP messages from WebSocket clients. As a result an `@Controller` +can now contain both `@RequestMapping` and `@MessageMapping` methods for handling +HTTP requests and messages from WebSocket-connected clients. The new `spring-messaging` +module also contains key abstractions formerly from the +http://projects.spring.io/spring-integration/[Spring Integration] project such as +`Message`, `MessageChannel`, `MessageHandler`, and others to serve as a foundation +for messaging-based applications. + +For further details, including a more thorough introduction, see the <> section. + + + + +=== Testing Improvements +In addition to pruning of deprecated code within the `spring-test` module, Spring +Framework 4.0 introduces several new features for use in unit and integration testing. + +* Almost all annotations in the `spring-test` module (e.g., `@ContextConfiguration`, + `@WebAppConfiguration`, `@ContextHierarchy`, `@ActiveProfiles`, etc.) can now be used + as <> to create custom + _composed annotations_ and reduce configuration duplication across a test suite. +* Active bean definition profiles can now be resolved programmatically, simply by + implementing a custom <> + and registering it via the `resolver` attribute of `@ActiveProfiles`. +* A new `SocketUtils` class has been introduced in the `spring-core` module + which enables you to scan for free TCP and UDP server ports on localhost. This + functionality is not specific to testing but can prove very useful when writing + integration tests that require the use of sockets, for example tests that start + an in-memory SMTP server, FTP server, Servlet container, etc. +* As of Spring 4.0, the set of mocks in the `org.springframework.mock.web` package is + now based on the Servlet 3.0 API. Furthermore, several of the Servlet API mocks + (e.g., `MockHttpServletRequest`, `MockServletContext`, etc.) have been updated with + minor enhancements and improved configurability. + + + + +[[new-in-4.1]] +== New Features and Enhancements in Spring Framework 4.1 + +=== JMS Improvements +Spring 4.1 introduces a much simpler infrastructure <> by annotating bean methods with +{javadoc-baseurl}/org/springframework/jms/annotation/JmsListener.html[`@JmsListener`]. +The XML namespace has been enhanced to support this new style (`jms:annotation-driven`) +and it is also possible to fully configure the infrastructure using Java config ( +{javadoc-baseurl}/org/springframework/jms/annotation/EnableJms.html[`@EnableJms`], +`JmsListenerContainerFactory`). It is also possible to register listener endpoints +programmatically using +{javadoc-baseurl}/org/springframework/jms/annotation/JmsListenerConfigurer.html[`JmsListenerConfigurer`]. + +Spring 4.1 also aligns its JMS support to allow you to benefit from the `spring-messaging` +abstraction introduced in 4.0, that is: + +* Message listener endpoints can have a more flexible signature and benefit from + standard messaging annotations such as `@Payload`, `@Header`, `@Headers` and `@SendTo`. It + is also possible to use a standard `Message` in lieu of `javax.jms.Message` as method + argument +* A new {javadoc-baseurl}/org/springframework/jms/core/JmsMessageOperations.html[`JmsMessageOperations`] + interface is available and permits `JmsTemplate` like operations using the `Message` + abstraction + +Finally, Spring 4.1 provides additional miscellaneous improvements: + +* Synchronous request-reply operations support in `JmsTemplate` +* Listener priority can be specified per `` element +* Recovery options for the message listener container is configurable using a + {javadoc-baseurl}/org/springframework/util/backoff/BackOff.html[`BackOff`] implementation +* JMS 2.0 shared consumers are supported + +=== Caching Improvements + +Spring 4.1 supports <> using Spring's +existing cache configuration and infrastructure abstraction; no changes are required +to use the standard annotations. + +Spring 4.1 also improves its own abstraction significantly: + +* Caches can be resolved at runtime using a + <>. As a result the + `value` argument defining the cache name(s) to use is no longer mandatory +* More operation-level customizations: cache resolver, cache manager, key + generator +* A new <> allows + to share common settings at class level **without** enabling any cache operation +* Better exception handling of cached methods using `CacheErrorHandler` + +Spring 4.1 also has a breaking change in the `CacheInterface` as a new +`putIfAbsent` method has been added. + +=== Testing Improvements + +* Groovy scripts can now be used to configure the `ApplicationContext` loaded for + integration tests in the TestContext framework. +** See <> for details. +* Test-managed transactions can now be programmatically started and ended within + transactional test methods via the new `TestTransaction` API. +** See <> for details. +* SQL script execution can now be configured declaratively via the new `@Sql` and + `@SqlConfig` annotations on a per-class or per-method basis. +** See <> for details. +* Test property sources which automatically override system and application property + sources can be configured via the new `@TestPropertySource` annotation. +** See <> for details. +* Default ++TestExecutionListener++s can now be automatically discovered. +** See <> for details. +* Custom ++TestExecutionListener++s can now be automatically merged with the default + listeners. +** See <> for details. +* The documentation for transactional testing support in the TestContext framework has + been improved with more thorough explanations and additional examples. +** See <> for details. +* Various improvements to `MockServletContext`, `MockHttpServletRequest`, and other + Servlet API mocks. +* `AssertThrows` has been refactored to support `Throwable` instead of `Exception`. diff --git a/src/asciidoc/orm.adoc b/src/asciidoc/orm.adoc new file mode 100644 index 000000000000..47c0c939de9f --- /dev/null +++ b/src/asciidoc/orm.adoc @@ -0,0 +1,1561 @@ +[[orm]] +== Object Relational Mapping (ORM) Data Access + + + + +[[orm-introduction]] +=== Introduction to ORM with Spring +The Spring Framework supports integration with Hibernate, Java Persistence API (JPA) +and Java Data Objects (JDO) for resource management, data access object +(DAO) implementations, and transaction strategies. For example, for Hibernate there is +first-class support with several convenient IoC features that address many typical +Hibernate integration issues. You can configure all of the supported features for O/R +(object relational) mapping tools through Dependency Injection. They can participate in +Spring's resource and transaction management, and they comply with Spring's generic +transaction and DAO exception hierarchies. The recommended integration style is to code +DAOs against plain Hibernate, JPA, and JDO APIs. The older style of using Spring's DAO +templates is no longer recommended; however, coverage of this style can be found in the +<> in the appendices. + +Spring adds significant enhancements to the ORM layer of your choice when you create +data access applications. You can leverage as much of the integration support as you +wish, and you should compare this integration effort with the cost and risk of building +a similar infrastructure in-house. You can use much of the ORM support as you would a +library, regardless of technology, because everything is designed as a set of reusable +JavaBeans. ORM in a Spring IoC container facilitates configuration and deployment. Thus +most examples in this section show configuration inside a Spring container. + +Benefits of using the Spring Framework to create your ORM DAOs include: + +* __Easier testing.__ Spring's IoC approach makes it easy to swap the implementations + and configuration locations of Hibernate `SessionFactory` instances, JDBC `DataSource` + instances, transaction managers, and mapped object implementations (if needed). This + in turn makes it much easier to test each piece of persistence-related code in + isolation. +* __Common data access exceptions.__ Spring can wrap exceptions from your ORM tool, + converting them from proprietary (potentially checked) exceptions to a common runtime + DataAccessException hierarchy. This feature allows you to handle most persistence + exceptions, which are non-recoverable, only in the appropriate layers, without + annoying boilerplate catches, throws, and exception declarations. You can still trap + and handle exceptions as necessary. Remember that JDBC exceptions (including + DB-specific dialects) are also converted to the same hierarchy, meaning that you can + perform some operations with JDBC within a consistent programming model. +* __General resource management.__ Spring application contexts can handle the location + and configuration of Hibernate `SessionFactory` instances, JPA `EntityManagerFactory` + instances, JDBC `DataSource` instances, and other related resources. This makes these + values easy to manage and change. Spring offers efficient, easy, and safe handling of + persistence resources. For example, related code that uses Hibernate generally needs to + use the same Hibernate `Session` to ensure efficiency and proper transaction handling. + Spring makes it easy to create and bind a `Session` to the current thread transparently, + by exposing a current `Session` through the Hibernate `SessionFactory`. Thus Spring + solves many chronic problems of typical Hibernate usage, for any local or JTA + transaction environment. +* __Integrated transaction management.__ You can wrap your ORM code with a declarative, + aspect-oriented programming (AOP) style method interceptor either through the + `@Transactional` annotation or by explicitly configuring the transaction AOP advice in + an XML configuration file. In both cases, transaction semantics and exception handling + (rollback, and so on) are handled for you. As discussed below, in + <>, you can also swap various + transaction managers, without affecting your ORM-related code. For example, you can + swap between local transactions and JTA, with the same full services (such as + declarative transactions) available in both scenarios. Additionally, JDBC-related code + can fully integrate transactionally with the code you use to do ORM. This is useful + for data access that is not suitable for ORM, such as batch processing and BLOB + streaming, which still need to share common transactions with ORM operations. + +[TIP] +==== +For more comprehensive ORM support, including support for alternative database +technologies such as MongoDB, you might want to check out the +http://projects.spring.io/spring-data/[Spring Data] suite of projects. If you are +a JPA user, the https://spring.io/guides/gs/accessing-data-jpa/[Getting Started Accessing +Data with JPA] guide from https://spring.io provides a great introduction. +==== + + + +[[orm-general]] +=== General ORM integration considerations +This section highlights considerations that apply to all ORM technologies. The +<> section provides more details and also show these features and +configurations in a concrete context. + +The major goal of Spring's ORM integration is clear application layering, with any data +access and transaction technology, and for loose coupling of application objects. No +more business service dependencies on the data access or transaction strategy, no more +hard-coded resource lookups, no more hard-to-replace singletons, no more custom service +registries. One simple and consistent approach to wiring up application objects, keeping +them as reusable and free from container dependencies as possible. All the individual +data access features are usable on their own but integrate nicely with Spring's +application context concept, providing XML-based configuration and cross-referencing of +plain JavaBean instances that need not be Spring-aware. In a typical Spring application, +many important objects are JavaBeans: data access templates, data access objects, +transaction managers, business services that use the data access objects and transaction +managers, web view resolvers, web controllers that use the business services,and so on. + + + +[[orm-resource-mngmnt]] +==== Resource and transaction management +Typical business applications are cluttered with repetitive resource management code. +Many projects try to invent their own solutions, sometimes sacrificing proper handling +of failures for programming convenience. Spring advocates simple solutions for proper +resource handling, namely IoC through templating in the case of JDBC and applying AOP +interceptors for the ORM technologies. + +The infrastructure provides proper resource handling and appropriate conversion of +specific API exceptions to an unchecked infrastructure exception hierarchy. Spring +introduces a DAO exception hierarchy, applicable to any data access strategy. For direct +JDBC, the `JdbcTemplate` class mentioned in a previous section provides connection +handling and proper conversion of `SQLException` to the `DataAccessException` hierarchy, +including translation of database-specific SQL error codes to meaningful exception +classes. For ORM technologies, see the next section for how to get the same exception +translation benefits. + +When it comes to transaction management, the `JdbcTemplate` class hooks in to the Spring +transaction support and supports both JTA and JDBC transactions, through respective +Spring transaction managers. For the supported ORM technologies Spring offers Hibernate, +JPA and JDO support through the Hibernate, JPA, and JDO transaction managers as well as +JTA support. For details on transaction support, see the <> chapter. + + + +[[orm-exception-translation]] +==== Exception translation +When you use Hibernate, JPA, or JDO in a DAO, you must decide how to handle the +persistence technology's native exception classes. The DAO throws a subclass of a +`HibernateException`, `PersistenceException` or `JDOException` depending on the +technology. These exceptions are all run-time exceptions and do not have to be declared +or caught. You may also have to deal with `IllegalArgumentException` and +`IllegalStateException`. This means that callers can only treat exceptions as generally +fatal, unless they want to depend on the persistence technology's own exception +structure. Catching specific causes such as an optimistic locking failure is not +possible without tying the caller to the implementation strategy. This trade off might +be acceptable to applications that are strongly ORM-based and/or do not need any special +exception treatment. However, Spring enables exception translation to be applied +transparently through the `@Repository` annotation: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Repository + public class ProductDaoImpl implements ProductDao { + + // class body here... + + } +---- + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + +---- + +The postprocessor automatically looks for all exception translators (implementations of +the `PersistenceExceptionTranslator` interface) and advises all beans marked with the +`@Repository` annotation so that the discovered translators can intercept and apply the +appropriate translation on the thrown exceptions. + +In summary: you can implement DAOs based on the plain persistence technology's API and +annotations, while still benefiting from Spring-managed transactions, dependency +injection, and transparent exception conversion (if desired) to Spring's custom +exception hierarchies. + + + + +[[orm-hibernate]] +=== Hibernate +We will start with a coverage of http://www.hibernate.org/[Hibernate 3] in a Spring +environment, using it to demonstrate the approach that Spring takes towards integrating +O/R mappers. This section will cover many issues in detail and show different variations +of DAO implementations and transaction demarcation. Most of these patterns can be +directly translated to all other supported ORM tools. The following sections in this +chapter will then cover the other ORM technologies, showing briefer examples there. + +[NOTE] +==== +As of Spring 4.0, Spring requires Hibernate 3.6 or later. +==== + + + +[[orm-session-factory-setup]] +==== SessionFactory setup in a Spring container + +To avoid tying application objects to hard-coded resource lookups, you can define +resources such as a JDBC `DataSource` or a Hibernate `SessionFactory` as beans in the +Spring container. Application objects that need to access resources receive references +to such predefined instances through bean references, as illustrated in the DAO +definition in the next section. + +The following excerpt from an XML application context definition shows how to set up a +JDBC `DataSource` and a Hibernate `SessionFactory` on top of it: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + + + + + + + product.hbm.xml + + + + + hibernate.dialect=org.hibernate.dialect.HSQLDialect + + + + + +---- + +Switching from a local Jakarta Commons DBCP `BasicDataSource` to a JNDI-located +`DataSource` (usually managed by an application server) is just a matter of +configuration: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + +---- + +You can also access a JNDI-located `SessionFactory`, using Spring's +`JndiObjectFactoryBean` / `` to retrieve and expose it. However, that +is typically not common outside of an EJB context. + + + +[[orm-hibernate-straight]] +==== Implementing DAOs based on plain Hibernate 3 API +Hibernate 3 has a feature called contextual sessions, wherein Hibernate itself manages +one current `Session` per transaction. This is roughly equivalent to Spring's +synchronization of one Hibernate `Session` per transaction. A corresponding DAO +implementation resembles the following example, based on the plain Hibernate API: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class ProductDaoImpl implements ProductDao { + + private SessionFactory sessionFactory; + + public void setSessionFactory(SessionFactory sessionFactory) { + this.sessionFactory = sessionFactory; + } + + public Collection loadProductsByCategory(String category) { + return this.sessionFactory.getCurrentSession() + .createQuery("from test.Product product where product.category=?") + .setParameter(0, category) + .list(); + } + } +---- + +This style is similar to that of the Hibernate reference documentation and examples, +except for holding the `SessionFactory` in an instance variable. We strongly recommend +such an instance-based setup over the old-school `static` `HibernateUtil` class from +Hibernate's CaveatEmptor sample application. (In general, do not keep any resources in +`static` variables unless __absolutely__ necessary.) + +The above DAO follows the dependency injection pattern: it fits nicely into a Spring IoC +container, just as it would if coded against Spring's `HibernateTemplate`. Of course, +such a DAO can also be set up in plain Java (for example, in unit tests). Simply +instantiate it and call `setSessionFactory(..)` with the desired factory reference. As a +Spring bean definition, the DAO would resemble the following: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + +---- + +The main advantage of this DAO style is that it depends on Hibernate API only; no import +of any Spring class is required. This is of course appealing from a non-invasiveness +perspective, and will no doubt feel more natural to Hibernate developers. + +However, the DAO throws plain `HibernateException` (which is unchecked, so does not have +to be declared or caught), which means that callers can only treat exceptions as +generally fatal - unless they want to depend on Hibernate's own exception hierarchy. +Catching specific causes such as an optimistic locking failure is not possible without +tying the caller to the implementation strategy. This trade off might be acceptable to +applications that are strongly Hibernate-based and/or do not need any special exception +treatment. + +Fortunately, Spring's `LocalSessionFactoryBean` supports Hibernate's +`SessionFactory.getCurrentSession()` method for any Spring transaction strategy, +returning the current Spring-managed transactional `Session` even with +`HibernateTransactionManager`. Of course, the standard behavior of that method remains +the return of the current `Session` associated with the ongoing JTA transaction, if any. +This behavior applies regardless of whether you are using Spring's +`JtaTransactionManager`, EJB container managed transactions (CMTs), or JTA. + +In summary: you can implement DAOs based on the plain Hibernate 3 API, while still being +able to participate in Spring-managed transactions. + + + +[[orm-hibernate-tx-declarative]] +==== Declarative transaction demarcation +We recommend that you use Spring's declarative transaction support, which enables you to +replace explicit transaction demarcation API calls in your Java code with an AOP +transaction interceptor. This transaction interceptor can be configured in a Spring +container using either Java annotations or XML.This declarative transaction capability +allows you to keep business services free of repetitive transaction demarcation code and +to focus on adding business logic, which is the real value of your application. + +[NOTE] +==== +Prior to continuing, you are __strongly__ encouraged to read <> +if you have not done so. +==== + +Furthermore, transaction semantics like propagation behavior and isolation level can be +changed in a configuration file and do not affect the business service implementations. + +The following example shows how you can configure an AOP transaction interceptor, using +XML, for a simple service class: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + + + + + + + + + + + + + + + + + + + + +---- + +This is the service class that is advised: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class ProductServiceImpl implements ProductService { + + private ProductDao productDao; + + public void setProductDao(ProductDao productDao) { + this.productDao = productDao; + } + + // notice the absence of transaction demarcation code in this method + // Spring's declarative transaction infrastructure will be demarcating + // transactions on your behalf + public void increasePriceOfAllProductsInCategory(final String category) { + List productsToChange = this.productDao.loadProductsByCategory(category); + // ... + } + } +---- + +We also show an attribute-support based configuration, in the following example. You +annotate the service layer with @Transactional annotations and instruct the Spring +container to find these annotations and provide transactional semantics for these +annotated methods. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class ProductServiceImpl implements ProductService { + + private ProductDao productDao; + + public void setProductDao(ProductDao productDao) { + this.productDao = productDao; + } + + @Transactional + public void increasePriceOfAllProductsInCategory(final String category) { + List productsToChange = this.productDao.loadProductsByCategory(category); + // ... + } + + @Transactional(readOnly = true) + public List findAllProducts() { + return this.productDao.findAllProducts(); + } + + } +---- + +As you can see from the following configuration example, the configuration is much +simplified, compared to the XML example above, while still providing the same +functionality driven by the annotations in the service layer code. All you need to +provide is the TransactionManager implementation and a "" entry. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + + + + + + + + + +---- + + + +[[orm-hibernate-tx-programmatic]] +==== Programmatic transaction demarcation +You can demarcate transactions in a higher level of the application, on top of such +lower-level data access services spanning any number of operations. Nor do restrictions +exist on the implementation of the surrounding business service; it just needs a Spring +`PlatformTransactionManager`. Again, the latter can come from anywhere, but preferably +as a bean reference through a `setTransactionManager(..)` method, just as the +`productDAO` should be set by a `setProductDao(..)` method. The following snippets show +a transaction manager and a business service definition in a Spring application context, +and an example for a business method implementation: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + + + + + +---- + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class ProductServiceImpl implements ProductService { + + private TransactionTemplate transactionTemplate; + private ProductDao productDao; + + public void setTransactionManager(PlatformTransactionManager transactionManager) { + this.transactionTemplate = new TransactionTemplate(transactionManager); + } + + public void setProductDao(ProductDao productDao) { + this.productDao = productDao; + } + + public void increasePriceOfAllProductsInCategory(final String category) { + this.transactionTemplate.execute(new TransactionCallbackWithoutResult() { + public void doInTransactionWithoutResult(TransactionStatus status) { + List productsToChange = this.productDao.loadProductsByCategory(category); + // do the price increase... + } + }); + } + } +---- + +Spring's `TransactionInterceptor` allows any checked application exception to be thrown +with the callback code, while `TransactionTemplate` is restricted to unchecked +exceptions within the callback. `TransactionTemplate` triggers a rollback in case of an +unchecked application exception, or if the transaction is marked rollback-only by the +application (via `TransactionStatus`). `TransactionInterceptor` behaves the same way by +default but allows configurable rollback policies per method. + + + +[[orm-hibernate-tx-strategies]] +==== Transaction management strategies +Both `TransactionTemplate` and `TransactionInterceptor` delegate the actual transaction +handling to a `PlatformTransactionManager` instance, which can be a +`HibernateTransactionManager` (for a single Hibernate `SessionFactory`, using a +`ThreadLocal` `Session` under the hood) or a `JtaTransactionManager` (delegating to the +JTA subsystem of the container) for Hibernate applications. You can even use a custom +`PlatformTransactionManager` implementation. Switching from native Hibernate transaction +management to JTA, such as when facing distributed transaction requirements for certain +deployments of your application, is just a matter of configuration. Simply replace +the Hibernate transaction manager with Spring's JTA transaction implementation. Both +transaction demarcation and data access code will work without changes, because they +just use the generic transaction management APIs. + +For distributed transactions across multiple Hibernate session factories, simply combine +`JtaTransactionManager` as a transaction strategy with multiple +`LocalSessionFactoryBean` definitions. Each DAO then gets one specific `SessionFactory` +reference passed into its corresponding bean property. If all underlying JDBC data +sources are transactional container ones, a business service can demarcate transactions +across any number of DAOs and any number of session factories without special regard, as +long as it is using `JtaTransactionManager` as the strategy. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + + + + product.hbm.xml + + + + + hibernate.dialect=org.hibernate.dialect.MySQLDialect + hibernate.show_sql=true + + + + + + + + + inventory.hbm.xml + + + + + hibernate.dialect=org.hibernate.dialect.OracleDialect + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +---- + +Both `HibernateTransactionManager` and `JtaTransactionManager` allow for proper +JVM-level cache handling with Hibernate, without container-specific transaction manager +lookup or a JCA connector (if you are not using EJB to initiate transactions). + +`HibernateTransactionManager` can export the Hibernate JDBC `Connection` to plain JDBC +access code, for a specific `DataSource`. This capability allows for high-level +transaction demarcation with mixed Hibernate and JDBC data access completely without +JTA, if you are accessing only one database. `HibernateTransactionManager` automatically +exposes the Hibernate transaction as a JDBC transaction if you have set up the passed-in +`SessionFactory` with a `DataSource` through the `dataSource` property of the +`LocalSessionFactoryBean` class. Alternatively, you can specify explicitly the +`DataSource` for which the transactions are supposed to be exposed through the +`dataSource` property of the `HibernateTransactionManager` class. + + + +[[orm-hibernate-resources]] +==== Comparing container-managed and locally defined resources +You can switch between a container-managed JNDI `SessionFactory` and a locally defined +one, without having to change a single line of application code. Whether to keep +resource definitions in the container or locally within the application is mainly a +matter of the transaction strategy that you use. Compared to a Spring-defined local +`SessionFactory`, a manually registered JNDI `SessionFactory` does not provide any +benefits. Deploying a `SessionFactory` through Hibernate's JCA connector provides the +added value of participating in the Java EE server's management infrastructure, but does +not add actual value beyond that. + +Spring's transaction support is not bound to a container. Configured with any strategy +other than JTA, transaction support also works in a stand-alone or test environment. +Especially in the typical case of single-database transactions, Spring's single-resource +local transaction support is a lightweight and powerful alternative to JTA. When you use +local EJB stateless session beans to drive transactions, you depend both on an EJB +container and JTA, even if you access only a single database, and only use stateless +session beans to provide declarative transactions through container-managed +transactions. Also, direct use of JTA programmatically requires a Java EE environment as +well. JTA does not involve only container dependencies in terms of JTA itself and of +JNDI `DataSource` instances. For non-Spring, JTA-driven Hibernate transactions, you have +to use the Hibernate JCA connector, or extra Hibernate transaction code with the +`TransactionManagerLookup` configured for proper JVM-level caching. + +Spring-driven transactions can work as well with a locally defined Hibernate +`SessionFactory` as they do with a local JDBC `DataSource` if they are accessing a +single database. Thus you only have to use Spring's JTA transaction strategy when you +have distributed transaction requirements. A JCA connector requires container-specific +deployment steps, and obviously JCA support in the first place. This configuration +requires more work than deploying a simple web application with local resource +definitions and Spring-driven transactions. Also, you often need the Enterprise Edition +of your container if you are using, for example, WebLogic Express, which does not +provide JCA. A Spring application with local resources and transactions spanning one +single database works in any Java EE web container (without JTA, JCA, or EJB) such as +Tomcat, Resin, or even plain Jetty. Additionally, you can easily reuse such a middle +tier in desktop applications or test suites. + +All things considered, if you do not use EJBs, stick with local `SessionFactory` setup +and Spring's `HibernateTransactionManager` or `JtaTransactionManager`. You get all of +the benefits, including proper transactional JVM-level caching and distributed +transactions, without the inconvenience of container deployment. JNDI registration of a +Hibernate `SessionFactory` through the JCA connector only adds value when used in +conjunction with EJBs. + + + +[[orm-hibernate-invalid-jdbc-access-error]] +==== Spurious application server warnings with Hibernate +In some JTA environments with very strict `XADataSource` implementations -- currently +only some WebLogic Server and WebSphere versions -- when Hibernate is configured without +regard to the JTA `PlatformTransactionManager` object for that environment, it is +possible for spurious warning or exceptions to show up in the application server log. +These warnings or exceptions indicate that the connection being accessed is no longer +valid, or JDBC access is no longer valid, possibly because the transaction is no longer +active. As an example, here is an actual exception from WebLogic: + +[literal] +[subs="verbatim,quotes"] +---- +java.sql.SQLException: The transaction is no longer active - status: 'Committed'. No +further JDBC access is allowed within this transaction. +---- + +You resolve this warning by simply making Hibernate aware of the JTA +`PlatformTransactionManager` instance, to which it will synchronize (along with Spring). +You have two options for doing this: + +* If in your application context you are already directly obtaining the JTA + `PlatformTransactionManager` object (presumably from JNDI through + `JndiObjectFactoryBean` or ``) and feeding it, for example, to + Spring's `JtaTransactionManager`, then the easiest way is to specify a reference to + the bean defining this JTA `PlatformTransactionManager` instance as the value of the + `jtaTransactionManager` property for `LocalSessionFactoryBean.` Spring then makes the + object available to Hibernate. +* More likely you do not already have the JTA `PlatformTransactionManager` instance, + because Spring's `JtaTransactionManager` can find it itself. Thus you need to + configure Hibernate to look up JTA `PlatformTransactionManager` directly. You do this + by configuring an application server- specific `TransactionManagerLookup` class in the + Hibernate configuration, as described in the Hibernate manual. + +The remainder of this section describes the sequence of events that occur with and +without Hibernate's awareness of the JTA `PlatformTransactionManager`. + +When Hibernate is not configured with any awareness of the JTA +`PlatformTransactionManager`, the following events occur when a JTA transaction commits: + +* The JTA transaction commits. +* Spring's `JtaTransactionManager` is synchronized to the JTA transaction, so it is + called back through an __afterCompletion__ callback by the JTA transaction manager. +* Among other activities, this synchronization can trigger a callback by Spring to + Hibernate, through Hibernate's `afterTransactionCompletion` callback (used to clear + the Hibernate cache), followed by an explicit `close()` call on the Hibernate Session, + which causes Hibernate to attempt to `close()` the JDBC Connection. +* In some environments, this `Connection.close()` call then triggers the warning or + error, as the application server no longer considers the `Connection` usable at all, + because the transaction has already been committed. + +When Hibernate is configured with awareness of the JTA `PlatformTransactionManager`, the +following events occur when a JTA transaction commits: + +* the JTA transaction is ready to commit. +* Spring's `JtaTransactionManager` is synchronized to the JTA transaction, so the + transaction is called back through a __beforeCompletion__ callback by the JTA + transaction manager. +* Spring is aware that Hibernate itself is synchronized to the JTA transaction, and + behaves differently than in the previous scenario. Assuming the Hibernate `Session` + needs to be closed at all, Spring will close it now. +* The JTA transaction commits. +* Hibernate is synchronized to the JTA transaction, so the transaction is called back + through an __afterCompletion__ callback by the JTA transaction manager, and can + properly clear its cache. + + + + +[[orm-jdo]] +=== JDO +Spring supports the standard JDO 2.0 and 2.1 APIs as data access strategy, following the +same style as the Hibernate support. The corresponding integration classes reside in the +`org.springframework.orm.jdo` package. + + + +[[orm-jdo-setup]] +==== PersistenceManagerFactory setup + +Spring provides a `LocalPersistenceManagerFactoryBean` class that allows you to define a +local JDO `PersistenceManagerFactory` within a Spring application context: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + +---- + +Alternatively, you can set up a `PersistenceManagerFactory` through direct instantiation +of a `PersistenceManagerFactory` implementation class. A JDO `PersistenceManagerFactory` +implementation class follows the JavaBeans pattern, just like a JDBC `DataSource` +implementation class, which is a natural fit for a configuration that uses Spring. This +setup style usually supports a Spring-defined JDBC `DataSource`, passed into the +`connectionFactory` property. For example, for the open source JDO implementation +DataNucleus (formerly JPOX) ( http://www.datanucleus.org/[http://www.datanucleus.org/]), +this is the XML configuration of the `PersistenceManagerFactory` implementation: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + + + + + + + + +---- + +You can also set up JDO `PersistenceManagerFactory` in the JNDI environment of a Java EE +application server, usually through the JCA connector provided by the particular JDO +implementation. Spring's standard `JndiObjectFactoryBean` or `` can be +used to retrieve and expose such a `PersistenceManagerFactory`. However, outside an EJB +context, no real benefit exists in holding the `PersistenceManagerFactory` in JNDI: only +choose such a setup for a good reason. See <> for a discussion; +the arguments there apply to JDO as well. + + + +[[orm-jdo-daos-straight]] +==== Implementing DAOs based on the plain JDO API +DAOs can also be written directly against plain JDO API, without any Spring +dependencies, by using an injected `PersistenceManagerFactory`. The following is an +example of a corresponding DAO implementation: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class ProductDaoImpl implements ProductDao { + + private PersistenceManagerFactory persistenceManagerFactory; + + public void setPersistenceManagerFactory(PersistenceManagerFactory pmf) { + this.persistenceManagerFactory = pmf; + } + + public Collection loadProductsByCategory(String category) { + PersistenceManager pm = this.persistenceManagerFactory.getPersistenceManager(); + try { + Query query = pm.newQuery(Product.class, "category = pCategory"); + query.declareParameters("String pCategory"); + return query.execute(category); + } + finally { + pm.close(); + } + } + } +---- + +Because the above DAO follows the dependency injection pattern, it fits nicely into a +Spring container, just as it would if coded against Spring's `JdoTemplate`: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + +---- + +The main problem with such DAOs is that they always get a new `PersistenceManager` from +the factory. To access a Spring-managed transactional `PersistenceManager`, define a +`TransactionAwarePersistenceManagerFactoryProxy` (as included in Spring) in front of +your target `PersistenceManagerFactory`, then passing a reference to that proxy into +your DAOs as in the following example: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + + + + +---- + +Your data access code will receive a transactional `PersistenceManager` (if any) from +the `PersistenceManagerFactory.getPersistenceManager()` method that it calls. The latter +method call goes through the proxy, which first checks for a current transactional +`PersistenceManager` before getting a new one from the factory. Any `close()` calls on +the `PersistenceManager` are ignored in case of a transactional `PersistenceManager`. + +If your data access code always runs within an active transaction (or at least within +active transaction synchronization), it is safe to omit the `PersistenceManager.close()` +call and thus the entire `finally` block, which you might do to keep your DAO +implementations concise: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class ProductDaoImpl implements ProductDao { + + private PersistenceManagerFactory persistenceManagerFactory; + + public void setPersistenceManagerFactory(PersistenceManagerFactory pmf) { + this.persistenceManagerFactory = pmf; + } + + public Collection loadProductsByCategory(String category) { + PersistenceManager pm = this.persistenceManagerFactory.getPersistenceManager(); + Query query = pm.newQuery(Product.class, "category = pCategory"); + query.declareParameters("String pCategory"); + return query.execute(category); + } + } +---- + +With such DAOs that rely on active transactions, it is recommended that you enforce +active transactions through turning off +`TransactionAwarePersistenceManagerFactoryProxy`'s `allowCreate` flag: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + + + + + +---- + +The main advantage of this DAO style is that it depends on JDO API only; no import of +any Spring class is required. This is of course appealing from a non-invasiveness +perspective, and might feel more natural to JDO developers. + +However, the DAO throws plain `JDOException` (which is unchecked, so does not have to be +declared or caught), which means that callers can only treat exceptions as fatal, unless +you want to depend on JDO's own exception structure. Catching specific causes such as an +optimistic locking failure is not possible without tying the caller to the +implementation strategy. This trade off might be acceptable to applications that are +strongly JDO-based and/or do not need any special exception treatment. + +In summary, you can DAOs based on the plain JDO API, and they can still participate in +Spring-managed transactions. This strategy might appeal to you if you are already +familiar with JDO. However, such DAOs throw plain `JDOException`, and you would have to +convert explicitly to Spring's `DataAccessException` (if desired). + + + +[[orm-jdo-tx]] +==== Transaction management +[NOTE] +==== +You are __strongly__ encouraged to read <> if you have not done +so, to get a more detailed coverage of Spring's declarative transaction support. +==== + +To execute service operations within transactions, you can use Spring's common +declarative transaction facilities. For example: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + + + + + + + + + + + + + + + + + + +---- + +JDO requires an active transaction to modify a persistent object. The non-transactional +flush concept does not exist in JDO, in contrast to Hibernate. For this reason, you need +to set up the chosen JDO implementation for a specific environment. Specifically, you +need to set it up explicitly for JTA synchronization, to detect an active JTA +transaction itself. This is not necessary for local transactions as performed by +Spring's `JdoTransactionManager`, but it is necessary to participate in JTA +transactions, whether driven by Spring's `JtaTransactionManager` or by EJB CMT and plain +JTA. + +`JdoTransactionManager` is capable of exposing a JDO transaction to JDBC access code +that accesses the same JDBC `DataSource`, provided that the registered `JdoDialect` +supports retrieval of the underlying JDBC `Connection`. This is the case for JDBC-based +JDO 2.0 implementations by default. + + + +[[orm-jdo-dialect]] +==== JdoDialect + +As an advanced feature, both `JdoTemplate` and `JdoTransactionManager` support a custom +`JdoDialect` that can be passed into the `jdoDialect` bean property. In this scenario, +the DAOs will not receive a `PersistenceManagerFactory` reference but rather a full +`JdoTemplate` instance (for example, passed into the `jdoTemplate` property of +`JdoDaoSupport`). Using a `JdoDialect` implementation, you can enable advanced features +supported by Spring, usually in a vendor-specific manner: + +* Applying specific transaction semantics such as custom isolation level or transaction + timeout +* Retrieving the transactional JDBC `Connection` for exposure to JDBC-based DAOs +* Applying query timeouts, which are automatically calculated from Spring-managed + transaction timeouts +* Eagerly flushing a `PersistenceManager,` to make transactional changes visible to + JDBC-based data access code +* Advanced translation of `JDOExceptions` to Spring `DataAccessExceptions` + +See the `JdoDialect` javadocs for more details on its operations and how to use them +within Spring's JDO support. + + + + +[[orm-jpa]] +=== JPA +The Spring JPA, available under the `org.springframework.orm.jpa` package, offers +comprehensive support for the +http://www.oracle.com/technetwork/articles/javaee/jpa-137156.html[Java Persistence +API] in a similar manner to the integration with Hibernate or JDO, while being aware of +the underlying implementation in order to provide additional features. + + + +[[orm-jpa-setup]] +==== Three options for JPA setup in a Spring environment +The Spring JPA support offers three ways of setting up the JPA `EntityManagerFactory` +that will be used by the application to obtain an entity manager. + + +[[orm-jpa-setup-lemfb]] +===== LocalEntityManagerFactoryBean + +[NOTE] +==== +Only use this option in simple deployment environments such as stand-alone applications +and integration tests. +==== + +The `LocalEntityManagerFactoryBean` creates an `EntityManagerFactory` suitable for +simple deployment environments where the application uses only JPA for data access. The +factory bean uses the JPA `PersistenceProvider` autodetection mechanism (according to +JPA's Java SE bootstrapping) and, in most cases, requires you to specify only the +persistence unit name: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + +---- + +This form of JPA deployment is the simplest and the most limited. You cannot refer to an +existing JDBC `DataSource` bean definition and no support for global transactions +exists. Furthermore, weaving (byte-code transformation) of persistent classes is +provider-specific, often requiring a specific JVM agent to specified on startup. This +option is sufficient only for stand-alone applications and test environments, for which +the JPA specification is designed. + + +[[orm-jpa-setup-jndi]] +===== Obtaining an EntityManagerFactory from JNDI + +[NOTE] +==== +Use this option when deploying to a Java EE 5 server. Check your server's documentation +on how to deploy a custom JPA provider into your server, allowing for a different +provider than the server's default. +==== + +Obtaining an `EntityManagerFactory` from JNDI (for example in a Java EE 5 environment), +is simply a matter of changing the XML configuration: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + +---- + +This action assumes standard Java EE 5 bootstrapping: the Java EE server autodetects +persistence units (in effect, `META-INF/persistence.xml` files in application jars) and +`persistence-unit-ref` entries in the Java EE deployment descriptor (for example, +`web.xml`) and defines environment naming context locations for those persistence units. + +In such a scenario, the entire persistence unit deployment, including the weaving +(byte-code transformation) of persistent classes, is up to the Java EE server. The JDBC +`DataSource` is defined through a JNDI location in the `META-INF/persistence.xml` file; +EntityManager transactions are integrated with the server's JTA subsystem. Spring merely +uses the obtained `EntityManagerFactory`, passing it on to application objects through +dependency injection, and managing transactions for the persistence unit, typically +through `JtaTransactionManager`. + +If multiple persistence units are used in the same application, the bean names of such +JNDI-retrieved persistence units should match the persistence unit names that the +application uses to refer to them, for example, in `@PersistenceUnit` and +`@PersistenceContext` annotations. + + +[[orm-jpa-setup-lcemfb]] +===== LocalContainerEntityManagerFactoryBean + +[NOTE] +==== +Use this option for full JPA capabilities in a Spring-based application environment. +This includes web containers such as Tomcat as well as stand-alone applications and +integration tests with sophisticated persistence requirements. +==== + +The `LocalContainerEntityManagerFactoryBean` gives full control over +`EntityManagerFactory` configuration and is appropriate for environments where +fine-grained customization is required. The `LocalContainerEntityManagerFactoryBean` +creates a `PersistenceUnitInfo` instance based on the `persistence.xml` file, the +supplied `dataSourceLookup` strategy, and the specified `loadTimeWeaver`. It is thus +possible to work with custom data sources outside of JNDI and to control the weaving +process. The following example shows a typical bean definition for a +`LocalContainerEntityManagerFactoryBean`: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + +---- + +The following example shows a typical `persistence.xml` file: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + META-INF/orm.xml + + + +---- + +[NOTE] +==== +The `exclude-unlisted-classes` element always indicates that __no__ scanning for +annotated entity classes is supposed to occur, in order to support the +`` shortcut. This is in line with the JPA specification, +which suggests that shortcut, but unfortunately is in conflict with the JPA XSD, which +implies `false` for that shortcut. Consequently, ` false +` is not supported. Simply omit the +`exclude-unlisted-classes` element if you want entity class scanning to occur. +==== + +Using the `LocalContainerEntityManagerFactoryBean` is the most powerful JPA setup +option, allowing for flexible local configuration within the application. It supports +links to an existing JDBC `DataSource`, supports both local and global transactions, and +so on. However, it also imposes requirements on the runtime environment, such as the +availability of a weaving-capable class loader if the persistence provider demands +byte-code transformation. + +This option may conflict with the built-in JPA capabilities of a Java EE 5 server. In a +full Java EE 5 environment, consider obtaining your `EntityManagerFactory` from JNDI. +Alternatively, specify a custom `persistenceXmlLocation` on your +`LocalContainerEntityManagerFactoryBean` definition, for example, +META-INF/my-persistence.xml, and only include a descriptor with that name in your +application jar files. Because the Java EE 5 server only looks for default +`META-INF/persistence.xml` files, it ignores such custom persistence units and hence +avoid conflicts with a Spring-driven JPA setup upfront. (This applies to Resin 3.1, for +example.) + +.When is load-time weaving required? +**** +Not all JPA providers require a JVM agent ; Hibernate is an example of one that does +not. If your provider does not require an agent or you have other alternatives, such as +applying enhancements at build time through a custom compiler or an ant task, the +load-time weaver __should not__ be used. +**** + +The `LoadTimeWeaver` interface is a Spring-provided class that allows JPA +`ClassTransformer` instances to be plugged in a specific manner, depending whether the +environment is a web container or application server. Hooking `ClassTransformers` +through an +http://docs.oracle.com/javase/6/docs/api/java/lang/instrument/package-summary.html[agent] +typically is not efficient. The agents work against the __entire virtual machine__ and +inspect __every__ class that is loaded, which is usually undesirable in a production +server environment. + +Spring provides a number of `LoadTimeWeaver` implementations for various environments, +allowing `ClassTransformer` instances to be applied only __per class loader__ and not +per VM. + +Refer to <> in the AOP chapter for more insight regarding the +`LoadTimeWeaver` implementations and their setup, either generic or customized to +various platforms (such as Tomcat, WebLogic, GlassFish, Resin and JBoss). + +As described in the aforementioned section, you can configure a context-wide +`LoadTimeWeaver` using the `@EnableLoadTimeWeaving` annotation of +`context:load-time-weaver` XML element. Such a global weaver is picked up by all JPA +`LocalContainerEntityManagerFactoryBeans` automatically. This is the preferred way of +setting up a load-time weaver, delivering autodetection of the platform (WebLogic, +GlassFish, Tomcat, Resin, JBoss or VM agent) and automatic propagation of the weaver to +all weaver-aware beans: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + ... + +---- + +However, if needed, one can manually specify a dedicated weaver through the +`loadTimeWeaver` property: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + +---- + +No matter how the LTW is configured, using this technique, JPA applications relying on +instrumentation can run in the target platform (ex: Tomcat) without needing an agent. +This is important especially when the hosting applications rely on different JPA +implementations because the JPA transformers are applied only at class loader level and +thus are isolated from each other. + + +[[orm-jpa-multiple-pu]] +===== Dealing with multiple persistence units +For applications that rely on multiple persistence units locations, stored in various +JARS in the classpath, for example, Spring offers the `PersistenceUnitManager` to act as +a central repository and to avoid the persistence units discovery process, which can be +expensive. The default implementation allows multiple locations to be specified that are +parsed and later retrieved through the persistence unit name. (By default, the classpath +is searched for `META-INF/persistence.xml` files.) + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + org/springframework/orm/jpa/domain/persistence-multi.xml + classpath:/my/package/**/custom-persistence.xml + classpath*:META-INF/persistence.xml + + + + + + + + + + + + + + + + +---- + +The default implementation allows customization of the `PersistenceUnitInfo` instances, +before they are fed to the JPA provider, declaratively through its properties, which +affect __all__ hosted units, or programmatically, through the +`PersistenceUnitPostProcessor`, which allows persistence unit selection. If no +`PersistenceUnitManager` is specified, one is created and used internally by +`LocalContainerEntityManagerFactoryBean`. + + + +[[orm-jpa-straight]] +==== Implementing DAOs based on plain JPA +[NOTE] +==== +Although `EntityManagerFactory` instances are thread-safe, `EntityManager` instances are +not. The injected JPA `EntityManager` behaves like an `EntityManager` fetched from an +application server's JNDI environment, as defined by the JPA specification. It delegates +all calls to the current transactional `EntityManager`, if any; otherwise, it falls back +to a newly created `EntityManager` per operation, in effect making its usage thread-safe. +==== + +It is possible to write code against the plain JPA without any Spring dependencies, by +using an injected `EntityManagerFactory` or `EntityManager`. Spring can understand +`@PersistenceUnit` and `@PersistenceContext` annotations both at field and method level +if a `PersistenceAnnotationBeanPostProcessor` is enabled. A plain JPA DAO implementation +using the `@PersistenceUnit` annotation might look like this: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class ProductDaoImpl implements ProductDao { + + private EntityManagerFactory emf; + + @PersistenceUnit + public void setEntityManagerFactory(EntityManagerFactory emf) { + this.emf = emf; + } + + public Collection loadProductsByCategory(String category) { + EntityManager em = this.emf.createEntityManager(); + try { + Query query = em.createQuery("from Product as p where p.category = ?1"); + query.setParameter(1, category); + return query.getResultList(); + } + finally { + if (em != null) { + em.close(); + } + } + } + } +---- + +The DAO above has no dependency on Spring and still fits nicely into a Spring +application context. Moreover, the DAO takes advantage of annotations to require the +injection of the default `EntityManagerFactory`: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + +---- + +As an alternative to defining a `PersistenceAnnotationBeanPostProcessor` explicitly, +consider using the Spring `context:annotation-config` XML element in your application +context configuration. Doing so automatically registers all Spring standard +post-processors for annotation-based configuration, including +`CommonAnnotationBeanPostProcessor` and so on. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + +---- + +The main problem with such a DAO is that it always creates a new `EntityManager` through +the factory. You can avoid this by requesting a transactional `EntityManager` (also +called "shared EntityManager" because it is a shared, thread-safe proxy for the actual +transactional EntityManager) to be injected instead of the factory: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class ProductDaoImpl implements ProductDao { + + @PersistenceContext + private EntityManager em; + + public Collection loadProductsByCategory(String category) { + Query query = em.createQuery("from Product as p where p.category = :category"); + query.setParameter("category", category); + return query.getResultList(); + } + } +---- + +The `@PersistenceContext` annotation has an optional attribute `type`, which defaults to +`PersistenceContextType.TRANSACTION`. This default is what you need to receive a shared +EntityManager proxy. The alternative, `PersistenceContextType.EXTENDED`, is a completely +different affair: This results in a so-called extended EntityManager, which is __not +thread-safe__ and hence must not be used in a concurrently accessed component such as a +Spring-managed singleton bean. Extended EntityManagers are only supposed to be used in +stateful components that, for example, reside in a session, with the lifecycle of the +EntityManager not tied to a current transaction but rather being completely up to the +application. + +.Method- and field-level Injection +**** +Annotations that indicate dependency injections (such as `@PersistenceUnit` and +`@PersistenceContext`) can be applied on field or methods inside a class, hence the +expressions __method-level injection__ and __field-level injection__. Field-level +annotations are concise and easier to use while method-level allows for further +processing of the injected dependency. In both cases the member visibility (public, +protected, private) does not matter. + +What about class-level annotations? + +On the Java EE 5 platform, they are used for dependency declaration and not for resource +injection. +**** + +The injected `EntityManager` is Spring-managed (aware of the ongoing transaction). It is +important to note that even though the new DAO implementation uses method level +injection of an `EntityManager` instead of an `EntityManagerFactory`, no change is +required in the application context XML due to annotation usage. + +The main advantage of this DAO style is that it only depends on Java Persistence API; no +import of any Spring class is required. Moreover, as the JPA annotations are understood, +the injections are applied automatically by the Spring container. This is appealing from +a non-invasiveness perspective, and might feel more natural to JPA developers. + + + +[[orm-jpa-tx]] +==== Transaction Management +[NOTE] +==== +You are __strongly__ encouraged to read <> if you have not done +so, to get a more detailed coverage of Spring's declarative transaction support. +==== + +To execute service operations within transactions, you can use Spring's common +declarative transaction facilities. For example: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + + + + + + + + + + + + + + + + + + +---- + +Spring JPA allows a configured `JpaTransactionManager` to expose a JPA transaction to +JDBC access code that accesses the same JDBC `DataSource`, provided that the registered +`JpaDialect` supports retrieval of the underlying JDBC `Connection`. Out of the box, +Spring provides dialects for the Toplink, Hibernate and OpenJPA JPA implementations. See +the next section for details on the `JpaDialect` mechanism. + + + +[[orm-jpa-dialect]] +==== JpaDialect + +As an advanced feature `JpaTemplate`, `JpaTransactionManager` and subclasses of +`AbstractEntityManagerFactoryBean` support a custom `JpaDialect`, to be passed into the +`jpaDialect` bean property. In such a scenario, the DAOs do not receive an +`EntityManagerFactory` reference but rather a full `JpaTemplate` instance (for example, +passed into the `jpaTemplate` property of `JpaDaoSupport`). A `JpaDialect` +implementation can enable some advanced features supported by Spring, usually in a +vendor-specific manner: + +* Applying specific transaction semantics such as custom isolation level or transaction + timeout) +* Retrieving the transactional JDBC `Connection` for exposure to JDBC-based DAOs) +* Advanced translation of `PersistenceExceptions` to Spring `DataAccessExceptions` + +This is particularly valuable for special transaction semantics and for advanced +translation of exception. The default implementation used ( `DefaultJpaDialect`) does +not provide any special capabilities and if the above features are required, you have to +specify the appropriate dialect. + +See the `JpaDialect` javadocs for more details of its operations and how they are used +within Spring's JPA support. + diff --git a/src/asciidoc/overview.adoc b/src/asciidoc/overview.adoc new file mode 100644 index 000000000000..e9d2d85f8efa --- /dev/null +++ b/src/asciidoc/overview.adoc @@ -0,0 +1,693 @@ +[[overview]] +== Introduction to Spring Framework +Spring Framework is a Java platform that provides comprehensive infrastructure support +for developing Java applications. Spring handles the infrastructure so you can focus on +your application. + +Spring enables you to build applications from "plain old Java objects" (POJOs) and to +apply enterprise services non-invasively to POJOs. This capability applies to the Java +SE programming model and to full and partial Java EE. + +Examples of how you, as an application developer, can use the Spring platform advantage: + +* Make a Java method execute in a database transaction without having to deal with + transaction APIs. +* Make a local Java method a remote procedure without having to deal with remote APIs. +* Make a local Java method a management operation without having to deal with JMX APIs. +* Make a local Java method a message handler without having to deal with JMS APIs. + + + + +[[overview-dependency-injection]] +=== Dependency Injection and Inversion of Control + +[[background-ioc]] +.Background +**** +"__The question is, what aspect of control are [they] inverting?__" Martin Fowler posed +this question about Inversion of Control (IoC) on his site in 2004. Fowler suggested +renaming the principle to make it more self-explanatory and came up with __Dependency +Injection__. + +For insight into IoC and DI, refer to Fowler's article at +http://martinfowler.com/articles/injection.html[http://martinfowler.com/articles/injection.html]. +**** + +Java applications -- a loose term that runs the gamut from constrained applets to n-tier +server-side enterprise applications -- typically consist of objects that collaborate to +form the application proper. Thus the objects in an application have __dependencies__ on +each other. + +Although the Java platform provides a wealth of application development functionality, +it lacks the means to organize the basic building blocks into a coherent whole, leaving +that task to architects and developers. True, you can use design patterns such +as __Factory__, __Abstract Factory__, __Builder__, __Decorator__, and __Service Locator__ +to compose the various classes and object instances that make up an application. +However, these patterns are simply that: best practices given a name, with a description +of what the pattern does, where to apply it, the problems it addresses, and so forth. +Patterns are formalized best practices that __you must implement yourself__ in your +application. + +The Spring Framework __Inversion of Control__ (IoC) component addresses this concern by +providing a formalized means of composing disparate components into a fully working +application ready for use. The Spring Framework codifies formalized design patterns as +first-class objects that you can integrate into your own application(s). Numerous +organizations and institutions use the Spring Framework in this manner to engineer +robust, __maintainable__ applications. + + + + +[[overview-modules]] +=== Modules +The Spring Framework consists of features organized into about 20 modules. These modules +are grouped into Core Container, Data Access/Integration, Web, AOP (Aspect Oriented +Programming), Instrumentation, and Test, as shown in the following diagram. + +.Overview of the Spring Framework +image::images/spring-overview.png[width=400] + + + +[[overview-core-container]] +==== Core Container +The <> consists of the Core, Beans, Context, and +Expression Language modules. + +The <> 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 <> module builds on the solid base provided by the +<> 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. + +The <> 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 context 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. + +[[overview-aop-instrumentation]] +==== AOP and Instrumentation +Spring's <> module provides an __AOP Alliance__-compliant +aspect-oriented programming implementation allowing you to define, for example, +method-interceptors and pointcuts to cleanly decouple code that implements functionality +that should be separated. Using source-level metadata functionality, you can also +incorporate behavioral information into your code, in a manner similar to that of .NET +attributes. + +The separate __Aspects__ module provides integration with AspectJ. + +The __Instrumentation__ module provides class instrumentation support and classloader +implementations to be used in certain application servers. + +[[overview-messaging]] +==== Messaging +Spring Framework 4 includes a new `spring-messaging` module with key abstractions from +the _Spring Integration_ project such as `Message`, `MessageChannel`, +`MessageHandler` and others to serve as a foundation for messaging-based applications. The +module also includes a set of annotations for mapping messages to methods, similar to the +Spring MVC annotation based programming model. + +[[overview-data-access]] +==== Data Access/Integration +The __Data Access/Integration__ layer consists of the JDBC, ORM, OXM, JMS and +Transaction modules. + +The <> module provides a JDBC-abstraction layer that removes the +need to do tedious JDBC coding and parsing of database-vendor specific error codes. + +The <> module provides integration layers for popular +object-relational mapping APIs, including <>, <>, and +<>. Using the ORM package you can use all of these O/R-mapping +frameworks in combination with all of the other features Spring offers, such as the simple +declarative transaction management feature mentioned previously. + +The <> module provides an abstraction layer that supports Object/XML mapping +implementations for JAXB, Castor, XMLBeans, JiBX and XStream. + +The Java Messaging Service (<>) module contains features for producing and +consuming messages. Since Spring Framework 4.1, it provides an integration with the +`spring-messaging` module. + +The <> module supports programmatic and declarative transaction +management for classes that implement special interfaces and for __all your POJOs (plain +old Java objects)__. + + + +[[overview-web]] +==== Web +The __Web__ layer consists of the Web, Web-Servlet, WebSocket and Web-Portlet modules. + +Spring's __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. It also contains the +web-related parts of Spring's remoting support. + +The __Web-Servlet__ module contains Spring's model-view-controller +(<>) implementation for web applications. Spring's MVC +framework provides a clean separation between domain model code and web forms, and +integrates with all the other features of the Spring Framework. + +The __Web-Portlet__ module provides the MVC implementation to be used in a portlet +environment and mirrors the functionality of Web-Servlet module. + + + + + + + +[[overview-testing]] +==== Test +The __Test__ module supports the testing of Spring components with JUnit or TestNG. It +provides consistent loading of Spring ApplicationContexts and caching of those contexts. +It also provides mock objects that you can use to test your code in isolation. + + + + +[[overview-usagescenarios]] +=== Usage scenarios +The building blocks described previously make Spring a logical choice in many scenarios, +from applets to full-fledged enterprise applications that use Spring's transaction +management functionality and web framework integration. + +.Typical full-fledged Spring web application +image::images/overview-full.png[width=400] + +Spring's <> make +the web application fully transactional, just as it would be if you used EJB +container-managed transactions. All your custom business logic can be implemented with +simple POJOs and managed by Spring's IoC container. Additional services include support +for sending email and validation that is independent of the web layer, which lets you +choose where to execute validation rules. Spring's ORM support is integrated with JPA, +Hibernate and and JDO; for example, when using Hibernate, you can continue to use +your existing mapping files and standard Hibernate `SessionFactory` configuration. Form +controllers seamlessly integrate the web-layer with the domain model, removing the need +for `ActionForms` or other classes that transform HTTP parameters to values for your +domain model. + +.Spring middle-tier using a third-party web framework +image::images/overview-thirdparty-web.png[width=400] + +Sometimes circumstances do not allow you to completely switch to a different framework. +The Spring Framework does __not__ force you to use everything within it; it is not an +__all-or-nothing__ solution. Existing front-ends built with Struts, Tapestry, JSF +or other UI frameworks can be integrated with a Spring-based middle-tier, which allows +you to use Spring transaction features. You simply need to wire up your business logic +using an `ApplicationContext` and use a `WebApplicationContext` to integrate your web +layer. + +.Remoting usage scenario +image::images/overview-remoting.png[width=400] + +When you need to access existing code through web services, you can use Spring's +`Hessian-`, `Burlap-`, `Rmi-` or `JaxRpcProxyFactory` classes. Enabling remote access to +existing applications is not difficult. + +.EJBs - Wrapping existing POJOs +image::images/overview-ejb.png[width=400] + +The Spring Framework also provides an <> for +Enterprise JavaBeans, enabling you to reuse your existing POJOs and wrap them in +stateless session beans for use in scalable, fail-safe web applications that might need +declarative security. + + + +[[dependency-management]] +==== Dependency Management and Naming Conventions +Dependency management and dependency injection are different things. To get those nice +features of Spring into your application (like dependency injection) you need to +assemble all the libraries needed (jar files) and get them onto your classpath at +runtime, and possibly at compile time. These dependencies are not virtual components +that are injected, but physical resources in a file system (typically). The process of +dependency management involves locating those resources, storing them and adding them to +classpaths. Dependencies can be direct (e.g. my application depends on Spring at +runtime), or indirect (e.g. my application depends on `commons-dbcp` which depends on +`commons-pool`). The indirect dependencies are also known as "transitive" and it is +those dependencies that are hardest to identify and manage. + +If you are going to use Spring you need to get a copy of the jar libraries that comprise +the pieces of Spring that you need. To make this easier Spring is packaged as a set of +modules that separate the dependencies as much as possible, so for example if you don't +want to write a web application you don't need the spring-web modules. To refer to +Spring library modules in this guide we use a shorthand naming convention `spring-*` or +`spring-*.jar,` where `*` represents the short name for the module (e.g. `spring-core`, +`spring-webmvc`, `spring-jms`, etc.). The actual jar file name that you use is normally +the module name concatenated with the version number +(e.g. __spring-core-{spring-version}.jar__). + +Each release of the Spring Framework will publish artifacts to the following places: + +* Maven Central, which is the default repository that Maven queries, and does not + require any special configuration to use. Many of the common libraries that Spring + depends on also are available from Maven Central and a large section of the Spring + community uses Maven for dependency management, so this is convenient for them. The + names of the jars here are in the form `spring-*-.jar` and the Maven groupId + is `org.springframework`. +* In a public Maven repository hosted specifically for Spring. In addition to the final + GA releases, this repository also hosts development snapshots and milestones. The jar + file names are in the same form as Maven Central, so this is a useful place to get + development versions of Spring to use with other libraries deployed in Maven Central. + This repository also contains a bundle distribution zip file that contains all Spring + jars bundled together for easy download. + +So the first thing you need to decide is how to manage your dependencies: we generally +recommend the use of an automated system like Maven, Gradle or Ivy, but you can also do +it manually by downloading all the jars yourself. We provide detailed instructions later +in this chapter. + + +[[overview-spring-dependencies]] +===== Spring Dependencies and Depending on Spring +Although Spring provides integration and support for a huge range of enterprise and +other external tools, it intentionally keeps its mandatory dependencies to an absolute +minimum: you shouldn't have to locate and download (even automatically) a large number +of jar libraries in order to use Spring for simple use cases. For basic dependency +injection there is only one mandatory external dependency, and that is for logging (see +below for a more detailed description of logging options). + +Next we outline the basic steps needed to configure an application that depends on +Spring, first with Maven and then with Gradle and finally using Ivy. In all cases, if +anything is unclear, refer to the documentation of your dependency management system, or +look at some sample code - Spring itself uses Gradle to manage dependencies when it is +building, and our samples mostly use Gradle or Maven. + + +[[overview-maven-dependency-management]] +===== Maven Dependency Management +If you are using http://maven.apache.org/[Maven] for dependency management you don't even +need to supply the logging dependency explicitly. For example, to create an application +context and use dependency injection to configure an application, your Maven dependencies +will look like this: + +[source,xml,indent=0] +[subs="verbatim,quotes,attributes"] +---- + + + org.springframework + spring-context + {spring-version} + runtime + + +---- + +That's it. Note the scope can be declared as runtime if you don't need to compile +against Spring APIs, which is typically the case for basic dependency injection use +cases. + +The example above works with the Maven Central repository. To use the Spring Maven +repository (e.g. for milestones or developer snapshots), you need to specify the +repository location in your Maven configuration. For full releases: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + io.spring.repo.maven.release + http://repo.spring.io/release/ + false + + +---- + +For milestones: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + io.spring.repo.maven.milestone + http://repo.spring.io/milestone/ + false + + +---- + +And for snapshots: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + io.spring.repo.maven.snapshot + http://repo.spring.io/snapshot/ + true + + +---- + + +[[overview-maven-bom]] +===== Maven "Bill Of Materials" Dependency ===== +It is possible to accidentally mix different versions of Spring JARs when using Maven. +For example, you may find that a third-party library, or another Spring project, +pulls in a transitive dependency to an older release. If you forget to explicitly declare +a direct dependency yourself, all sorts of unexpected issues can arise. + +To overcome such problems Maven supports the concept of a "bill of materials" (BOM) +dependency. You can import the `spring-framework-bom` in your `dependencyManagement` +section to ensure that all spring dependencies (both direct and transitive) are at +the same version. + +[source,xml,indent=0] +[subs="verbatim,quotes,attributes"] +---- + + + + org.springframework + spring-framework-bom + {spring-version} + pom + import + + + +---- + +An added benefit of using the BOM is that you no longer need to specify the `` +attribute when depending on Spring Framework artifacts: + +[source,xml,indent=0] +[subs="verbatim,quotes,attributes"] +---- + + + org.springframework + spring-context + + + org.springframework + spring-web + + +---- + + +[[overview-gradle-dependency-management]] +===== Gradle Dependency Management +To use the Spring repository with the http://www.gradle.org/[Gradle] build system, +include the appropriate URL in the `repositories` section: + +[source,groovy,indent=0] +[subs="verbatim,quotes"] +---- + repositories { + mavenCentral() + // and optionally... + maven { url "http://repo.spring.io/release" } + } +---- + +You can change the `repositories` URL from `/release` to `/milestone` or `/snapshot` as +appropriate. Once a repository has been configured, you can declare dependencies in the +usual Gradle way: + +[source,groovy,indent=0] +[subs="verbatim,quotes,attributes"] +---- + dependencies { + compile("org.springframework:spring-context:{spring-version}") + testCompile("org.springframework:spring-test:{spring-version}") + } +---- + + +[[overview-ivy-dependency-management]] +===== Ivy Dependency Management +If you prefer to use http://ant.apache.org/ivy[Ivy] to manage dependencies then there +are similar configuration options. + +To configure Ivy to point to the Spring repository add the following resolver to your +`ivysettings.xml`: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + +---- + +You can change the `root` URL from `/release/` to `/milestone/` or `/snapshot/` as +appropriate. + +Once configured, you can add dependencies in the usual way. For example (in `ivy.xml`): + +[source,xml,indent=0] +[subs="verbatim,quotes,attributes"] +---- + +---- + + +[[overview-distribution-zip]] +===== Distribution Zip Files +Although using a build system that supports dependency management is the recommended +way to obtain the Spring Framework, it is still possible to download a distribution +zip file. + +Distribution zips are published to the Spring Maven Repository (this is just for our +convenience, you don't need Maven or any other build system in order to download them). + +To download a distribution zip open a web browser to +http://repo.spring.io/release/org/springframework/spring and select the appropriate +subfolder for the version that you want. Distribution files end `-dist.zip`, for example ++spring-framework-{spring-version}-RELEASE-dist.zip+. Distributions are also published +for http://repo.spring.io/milestone/org/springframework/spring[milestones] and +http://repo.spring.io/snapshot/org/springframework/spring[snapshots]. + + + +[[overview-logging]] +==== Logging +Logging is a very important dependency for Spring because __a)__ it is the only mandatory +external dependency, __b)__ everyone likes to see some output from the tools they are +using, and __c)__ Spring integrates with lots of other tools all of which have also made +a choice of logging dependency. One of the goals of an application developer is often to +have unified logging configured in a central place for the whole application, including +all external components. This is more difficult than it might have been since there are so +many choices of logging framework. + +The mandatory logging dependency in Spring is the Jakarta Commons Logging API (JCL). We +compile against JCL and we also make JCL `Log` objects visible for classes that extend +the Spring Framework. It's important to users that all versions of Spring use the same +logging library: migration is easy because backwards compatibility is preserved even +with applications that extend Spring. The way we do this is to make one of the modules +in Spring depend explicitly on `commons-logging` (the canonical implementation of JCL), +and then make all the other modules depend on that at compile time. If you are using +Maven for example, and wondering where you picked up the dependency on +`commons-logging`, then it is from Spring and specifically from the central module +called `spring-core`. + +The nice thing about `commons-logging` is that you don't need anything else to make your +application work. It has a runtime discovery algorithm that looks for other logging +frameworks in well known places on the classpath and uses one that it thinks is +appropriate (or you can tell it which one if you need to). If nothing else is available +you get pretty nice looking logs just from the JDK (java.util.logging or JUL for short). +You should find that your Spring application works and logs happily to the console out +of the box in most situations, and that's important. + + +[[overview-not-using-commons-logging]] +===== Not Using Commons Logging +Unfortunately, the runtime discovery algorithm in `commons-logging`, while convenient +for the end-user, is problematic. If we could turn back the clock and start Spring now +as a new project it would use a different logging dependency. The first choice would +probably be the Simple Logging Facade for Java ( http://www.slf4j.org[SLF4J]), which is +also used by a lot of other tools that people use with Spring inside their applications. + +There are basically two ways to switch off `commons-logging`: + +. Exclude the dependency from the `spring-core` module (as it is the only module that + explicitly depends on `commons-logging`) +. Depend on a special `commons-logging` dependency that replaces the library with + an empty jar (more details can be found in the + http://slf4j.org/faq.html#excludingJCL[SLF4J FAQ]) + +To exclude commons-logging, add the following to your `dependencyManagement` section: + +[source,xml,indent=0] +[subs="verbatim,quotes,attributes"] +---- + + + org.springframework + spring-core + {spring-version} + + + commons-logging + commons-logging + + + + +---- + +Now this application is probably broken because there is no implementation of the JCL +API on the classpath, so to fix it a new one has to be provided. In the next section we +show you how to provide an alternative implementation of JCL using SLF4J as an example. + + +[[overview-logging-slf4j]] +===== Using SLF4J +SLF4J is a cleaner dependency and more efficient at runtime than `commons-logging` +because it uses compile-time bindings instead of runtime discovery of the other logging +frameworks it integrates. This also means that you have to be more explicit about what +you want to happen at runtime, and declare it or configure it accordingly. SLF4J +provides bindings to many common logging frameworks, so you can usually choose one that +you already use, and bind to that for configuration and management. + +SLF4J provides bindings to many common logging frameworks, including JCL, and it also +does the reverse: bridges between other logging frameworks and itself. So to use SLF4J +with Spring you need to replace the `commons-logging` dependency with the SLF4J-JCL +bridge. Once you have done that then logging calls from within Spring will be translated +into logging calls to the SLF4J API, so if other libraries in your application use that +API, then you have a single place to configure and manage logging. + +A common choice might be to bridge Spring to SLF4J, and then provide explicit binding +from SLF4J to Log4J. You need to supply 4 dependencies (and exclude the existing +`commons-logging`): the bridge, the SLF4J API, the binding to Log4J, and the Log4J +implementation itself. In Maven you would do that like this + +[source,xml,indent=0] +[subs="verbatim,quotes,attributes"] +---- + + + org.springframework + spring-core + {spring-version} + + + commons-logging + commons-logging + + + + + org.slf4j + jcl-over-slf4j + 1.5.8 + + + org.slf4j + slf4j-api + 1.5.8 + + + org.slf4j + slf4j-log4j12 + 1.5.8 + + + log4j + log4j + 1.2.14 + + +---- + +That might seem like a lot of dependencies just to get some logging. Well it is, but it +__is__ optional, and it should behave better than the vanilla `commons-logging` with +respect to classloader issues, notably if you are in a strict container like an OSGi +platform. Allegedly there is also a performance benefit because the bindings are at +compile-time not runtime. + +A more common choice amongst SLF4J users, which uses fewer steps and generates fewer +dependencies, is to bind directly to http://logback.qos.ch[Logback]. This removes the +extra binding step because Logback implements SLF4J directly, so you only need to depend +on two libraries not four ( `jcl-over-slf4j` and `logback`). If you do that you might +also need to exclude the slf4j-api dependency from other external dependencies (not +Spring), because you only want one version of that API on the classpath. + + +[[overview-logging-log4j]] +===== Using Log4J +Many people use http://logging.apache.org/log4j[Log4j] as a logging framework for +configuration and management purposes. It's efficient and well-established, and in fact +it's what we use at runtime when we build and test Spring. Spring also provides some +utilities for configuring and initializing Log4j, so it has an optional compile-time +dependency on Log4j in some modules. + +To make Log4j work with the default JCL dependency ( `commons-logging`) all you need to +do is put Log4j on the classpath, and provide it with a configuration file ( +`log4j.properties` or `log4j.xml` in the root of the classpath). So for Maven users this +is your dependency declaration: + +[source,xml,indent=0] +[subs="verbatim,quotes,attributes"] +---- + + + org.springframework + spring-core + {spring-version} + + + log4j + log4j + 1.2.14 + + +---- + +And here's a sample log4j.properties for logging to the console: + +[literal] +[subs="verbatim,quotes"] +---- +log4j.rootCategory=INFO, stdout + +log4j.appender.stdout=org.apache.log4j.ConsoleAppender +log4j.appender.stdout.layout=org.apache.log4j.PatternLayout +log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %t %c{2}:%L - %m%n + +log4j.category.org.springframework.beans.factory=DEBUG +---- + +[[overview-native-jcl]] +====== Runtime Containers with Native JCL +Many people run their Spring applications in a container that itself provides an +implementation of JCL. IBM Websphere Application Server (WAS) is the archetype. This +often causes problems, and unfortunately there is no silver bullet solution; simply +excluding `commons-logging` from your application is not enough in most situations. + +To be clear about this: the problems reported are usually not with JCL per se, or even +with `commons-logging`: rather they are to do with binding `commons-logging` to another +framework (often Log4J). This can fail because `commons-logging` changed the way they do +the runtime discovery in between the older versions (1.0) found in some containers and +the modern versions that most people use now (1.1). Spring does not use any unusual +parts of the JCL API, so nothing breaks there, but as soon as Spring or your application +tries to do any logging you can find that the bindings to Log4J are not working. + +In such cases with WAS the easiest thing to do is to invert the class loader hierarchy +(IBM calls it "parent last") so that the application controls the JCL dependency, not +the container. That option isn't always open, but there are plenty of other suggestions +in the public domain for alternative approaches, and your mileage may vary depending on +the exact version and feature set of the container. diff --git a/src/asciidoc/oxm.adoc b/src/asciidoc/oxm.adoc new file mode 100644 index 000000000000..7f6c37f7c818 --- /dev/null +++ b/src/asciidoc/oxm.adoc @@ -0,0 +1,708 @@ +[[oxm]] +== Marshalling XML using O/X Mappers + + + + +[[oxm-introduction]] +=== Introduction +In this chapter, we will describe Spring's Object/XML Mapping support. Object/XML +Mapping, or O/X mapping for short, is the act of converting an XML document to and from +an object. This conversion process is also known as XML Marshalling, or XML +Serialization. This chapter uses these terms interchangeably. + +Within the field of O/X mapping, a __marshaller__ is responsible for serializing an +object (graph) to XML. In similar fashion, an __unmarshaller__ deserializes the XML to +an object graph. This XML can take the form of a DOM document, an input or output +stream, or a SAX handler. + +Some of the benefits of using Spring for your O/X mapping needs are: + + + +==== Ease of configuration +Spring's bean factory makes it easy to configure marshallers, without needing to +construct JAXB context, JiBX binding factories, etc. The marshallers can be configured +as any other bean in your application context. Additionally, XML Schema-based +configuration is available for a number of marshallers, making the configuration even +simpler. + + + +==== Consistent Interfaces +Spring's O/X mapping operates through two global interfaces: the `Marshaller` and +`Unmarshaller` interface. These abstractions allow you to switch O/X mapping frameworks +with relative ease, with little or no changes required on the classes that do the +marshalling. This approach has the additional benefit of making it possible to do XML +marshalling with a mix-and-match approach (e.g. some marshalling performed using JAXB, +other using XMLBeans) in a non-intrusive fashion, leveraging the strength of each +technology. + + + +==== Consistent Exception Hierarchy +Spring provides a conversion from exceptions from the underlying O/X mapping tool to its +own exception hierarchy with the `XmlMappingException` as the root exception. As can be +expected, these runtime exceptions wrap the original exception so no information is lost. + + + + +[[oxm-marshaller-unmarshaller]] +=== Marshaller and Unmarshaller +As stated in the introduction, a __marshaller__ serializes an object to XML, and an +__unmarshaller__ deserializes XML stream to an object. In this section, we will describe +the two Spring interfaces used for this purpose. + + + +[[oxm-marshaller]] +==== Marshaller +Spring abstracts all marshalling operations behind the +`org.springframework.oxm.Marshaller` interface, the main methods of which is listed +below. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public interface Marshaller { + + /** + * Marshals the object graph with the given root into the provided Result. + */ + void marshal(Object graph, Result result) throws XmlMappingException, IOException; + + } +---- + +The `Marshaller` interface has one main method, which marshals the given object to a +given `javax.xml.transform.Result`. Result is a tagging interface that basically +represents an XML output abstraction: concrete implementations wrap various XML +representations, as indicated in the table below. + +[[oxm-marshller-tbl]] +|=== +| Result implementation| Wraps XML representation + +| `DOMResult` +| `org.w3c.dom.Node` + +| `SAXResult` +| `org.xml.sax.ContentHandler` + +| `StreamResult` +| `java.io.File`, `java.io.OutputStream`, or `java.io.Writer` +|=== + +[NOTE] +==== +Although the `marshal()` method accepts a plain object as its first parameter, most +`Marshaller` implementations cannot handle arbitrary objects. Instead, an object class +must be mapped in a mapping file, marked with an annotation, registered with the +marshaller, or have a common base class. Refer to the further sections in this chapter +to determine how your O/X technology of choice manages this. +==== + + + +[[oxm-unmarshaller]] +==== Unmarshaller +Similar to the `Marshaller`, there is the `org.springframework.oxm.Unmarshaller` +interface. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public interface Unmarshaller { + + /** + * Unmarshals the given provided Source into an object graph. + */ + Object unmarshal(Source source) throws XmlMappingException, IOException; + } +---- + +This interface also has one method, which reads from the given +`javax.xml.transform.Source` (an XML input abstraction), and returns the object read. As +with Result, Source is a tagging interface that has three concrete implementations. Each +wraps a different XML representation, as indicated in the table below. + +[[oxm-unmarshller-tbl]] +|=== +| Source implementation| Wraps XML representation + +| `DOMSource` +| `org.w3c.dom.Node` + +| `SAXSource` +| `org.xml.sax.InputSource`, and `org.xml.sax.XMLReader` + +| `StreamSource` +| `java.io.File`, `java.io.InputStream`, or `java.io.Reader` +|=== + +Even though there are two separate marshalling interfaces ( `Marshaller` and +`Unmarshaller`), all implementations found in Spring-WS implement both in one class. +This means that you can wire up one marshaller class and refer to it both as a +marshaller and an unmarshaller in your `applicationContext.xml`. + + + +[[oxm-xmlmappingexception]] +==== XmlMappingException +Spring converts exceptions from the underlying O/X mapping tool to its own exception +hierarchy with the `XmlMappingException` as the root exception. As can be expected, +these runtime exceptions wrap the original exception so no information will be lost. + +Additionally, the `MarshallingFailureException` and `UnmarshallingFailureException` +provide a distinction between marshalling and unmarshalling operations, even though the +underlying O/X mapping tool does not do so. + +The O/X Mapping exception hierarchy is shown in the following figure: +image::images/oxm-exceptions.png[width=400] + +O/X Mapping exception hierarchy + + + + +[[oxm-usage]] +=== Using Marshaller and Unmarshaller +Spring's OXM can be used for a wide variety of situations. In the following example, we +will use it to marshal the settings of a Spring-managed application as an XML file. We +will use a simple JavaBean to represent the settings: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class Settings { + + private boolean fooEnabled; + + public boolean isFooEnabled() { + return fooEnabled; + } + + public void setFooEnabled(boolean fooEnabled) { + this.fooEnabled = fooEnabled; + } + } +---- + +The application class uses this bean to store its settings. Besides a main method, the +class has two methods: `saveSettings()` saves the settings bean to a file named +`settings.xml`, and `loadSettings()` loads these settings again. A `main()` method +constructs a Spring application context, and calls these two methods. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + import java.io.FileInputStream; + import java.io.FileOutputStream; + import java.io.IOException; + import javax.xml.transform.stream.StreamResult; + import javax.xml.transform.stream.StreamSource; + + import org.springframework.context.ApplicationContext; + import org.springframework.context.support.ClassPathXmlApplicationContext; + import org.springframework.oxm.Marshaller; + import org.springframework.oxm.Unmarshaller; + + public class Application { + + private static final String FILE_NAME = "settings.xml"; + private Settings settings = new Settings(); + private Marshaller marshaller; + private Unmarshaller unmarshaller; + + public void setMarshaller(Marshaller marshaller) { + this.marshaller = marshaller; + } + + public void setUnmarshaller(Unmarshaller unmarshaller) { + this.unmarshaller = unmarshaller; + } + + public void saveSettings() throws IOException { + FileOutputStream os = null; + try { + os = new FileOutputStream(FILE_NAME); + this.marshaller.marshal(settings, new StreamResult(os)); + } finally { + if (os != null) { + os.close(); + } + } + } + + public void loadSettings() throws IOException { + FileInputStream is = null; + try { + is = new FileInputStream(FILE_NAME); + this.settings = (Settings) this.unmarshaller.unmarshal(new StreamSource(is)); + } finally { + if (is != null) { + is.close(); + } + } + } + + public static void main(String[] args) throws IOException { + ApplicationContext appContext = + new ClassPathXmlApplicationContext("applicationContext.xml"); + Application application = (Application) appContext.getBean("application"); + application.saveSettings(); + application.loadSettings(); + } + } +---- + +The `Application` requires both a `marshaller` and `unmarshaller` property to be set. We +can do so using the following `applicationContext.xml`: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + +---- + +This application context uses Castor, but we could have used any of the other marshaller +instances described later in this chapter. Note that Castor does not require any further +configuration by default, so the bean definition is rather simple. Also note that the +`CastorMarshaller` implements both `Marshaller` and `Unmarshaller`, so we can refer to the +`castorMarshaller` bean in both the `marshaller` and `unmarshaller` property of the +application. + +This sample application produces the following `settings.xml` file: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + +---- + + + + +[[oxm-schema-based-config]] +=== XML Schema-based Configuration +Marshallers could be configured more concisely using tags from the OXM namespace. To +make these tags available, the appropriate schema has to be referenced first in the +preamble of the XML configuration file. Note the 'oxm' related text below: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + +---- + +Currently, the following tags are available: + +* <> +* <> +* <> +* <> + +Each tag will be explained in its respective marshaller's section. As an example though, +here is how the configuration of a JAXB2 marshaller might look like: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + +---- + + + + +[[oxm-jaxb]] +=== JAXB +The JAXB binding compiler translates a W3C XML Schema into one or more Java classes, a +`jaxb.properties` file, and possibly some resource files. JAXB also offers a way to +generate a schema from annotated Java classes. + +Spring supports the JAXB 2.0 API as XML marshalling strategies, following the +`Marshaller` and `Unmarshaller` interfaces described in <>. +The corresponding integration classes reside in the `org.springframework.oxm.jaxb` +package. + + + +[[oxm-jaxb2]] +==== Jaxb2Marshaller +The `Jaxb2Marshaller` class implements both the Spring `Marshaller` and `Unmarshaller` +interface. It requires a context path to operate, which you can set using the +`contextPath` property. The context path is a list of colon (:) separated Java package +names that contain schema derived classes. It also offers a `classesToBeBound` property, +which allows you to set an array of classes to be supported by the marshaller. Schema +validation is performed by specifying one or more schema resource to the bean, like so: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + org.springframework.oxm.jaxb.Flight + org.springframework.oxm.jaxb.Flights + + + + + + ... + + +---- + + +[[oxm-jaxb2-xsd]] +===== XML Schema-based Configuration +The `jaxb2-marshaller` tag configures a `org.springframework.oxm.jaxb.Jaxb2Marshaller`. +Here is an example: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + +---- + +Alternatively, the list of classes to bind can be provided to the marshaller via the +`class-to-be-bound` child tag: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + ... + +---- + +Available attributes are: + +|=== +| Attribute| Description| Required + +| `id` +| the id of the marshaller +| no + +| `contextPath` +| the JAXB Context path +| no +|=== + + + + +[[oxm-castor]] +=== Castor +Castor XML mapping is an open source XML binding framework. It allows you to transform +the data contained in a java object model into/from an XML document. By default, it does +not require any further configuration, though a mapping file can be used to have more +control over the behavior of Castor. + +For more information on Castor, refer to the +http://castor.codehaus.org/xml-framework.html[__Castor web site__]. The Spring +integration classes reside in the `org.springframework.oxm.castor` package. + + + +[[oxm-castor-marshaller]] +==== CastorMarshaller +As with JAXB, the `CastorMarshaller` implements both the `Marshaller` and `Unmarshaller` +interface. It can be wired up as follows: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + ... + +---- + + + +[[oxm-castor-mapping]] +==== Mapping +Although it is possible to rely on Castor's default marshalling behavior, it might be +necessary to have more control over it. This can be accomplished using a Castor mapping +file. For more information, refer to http://castor.codehaus.org/xml-mapping.html[Castor +XML Mapping]. + +The mapping can be set using the `mappingLocation` resource property, indicated below +with a classpath resource. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + +---- + + +[[oxm-castor-xsd]] +===== XML Schema-based Configuration +The `castor-marshaller` tag configures a +`org.springframework.oxm.castor.CastorMarshaller`. Here is an example: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + +---- + +The marshaller instance can be configured in two ways, by specifying either the location +of a mapping file (through the `mapping-location` property), or by identifying Java +POJOs (through the `target-class` or `target-package` properties) for which there exist +corresponding XML descriptor classes. The latter way is usually used in conjunction with +XML code generation from XML schemas. + +Available attributes are: + +|=== +| Attribute| Description| Required + +| `id` +| the id of the marshaller +| no + +| `encoding` +| the encoding to use for unmarshalling from XML +| no + +| `target-class` +| a Java class name for a POJO for which an XML class descriptor is available (as + generated through code generation) +| no + +| `target-package` +| a Java package name that identifies a package that contains POJOs and their + corresponding Castor XML descriptor classes (as generated through code generation from + XML schemas) +| no + +| `mapping-location` +| location of a Castor XML mapping file +| no +|=== + + + + +[[oxm-xmlbeans]] +=== XMLBeans +XMLBeans is an XML binding tool that has full XML Schema support, and offers full XML +Infoset fidelity. It takes a different approach to that of most other O/X mapping +frameworks, in that all classes that are generated from an XML Schema are all derived +from `XmlObject`, and contain XML binding information in them. + +For more information on XMLBeans, refer to the http://xmlbeans.apache.org/[__XMLBeans +web site __]. The Spring-WS integration classes reside in the +`org.springframework.oxm.xmlbeans` package. + + + +[[oxm-xmlbeans-marshaller]] +==== XmlBeansMarshaller +The `XmlBeansMarshaller` implements both the `Marshaller` and `Unmarshaller` interfaces. +It can be configured as follows: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + ... + + +---- + +[NOTE] +==== +Note that the `XmlBeansMarshaller` can only marshal objects of type `XmlObject`, and not +every `java.lang.Object`. +==== + + +[[oxm-xmlbeans-xsd]] +===== XML Schema-based Configuration +The `xmlbeans-marshaller` tag configures a +`org.springframework.oxm.xmlbeans.XmlBeansMarshaller`. Here is an example: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + +---- + +Available attributes are: + +|=== +| Attribute| Description| Required + +| `id` +| the id of the marshaller +| no + +| `options` +| the bean name of the XmlOptions that is to be used for this marshaller. Typically a + `XmlOptionsFactoryBean` definition +| no +|=== + + + + +[[oxm-jibx]] +=== JiBX +The JiBX framework offers a solution similar to that which JDO provides for ORM: a +binding definition defines the rules for how your Java objects are converted to or from +XML. After preparing the binding and compiling the classes, a JiBX binding compiler +enhances the class files, and adds code to handle converting instances of the classes +from or to XML. + +For more information on JiBX, refer to the http://jibx.sourceforge.net/[__JiBX web +site__]. The Spring integration classes reside in the `org.springframework.oxm.jibx` +package. + + + +[[oxm-jibx-marshaller]] +==== JibxMarshaller +The `JibxMarshaller` class implements both the `Marshaller` and `Unmarshaller` +interface. To operate, it requires the name of the class to marshal in, which you can +set using the `targetClass` property. Optionally, you can set the binding name using the +`bindingName` property. In the next sample, we bind the `Flights` class: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + org.springframework.oxm.jibx.Flights + + ... + +---- + +A `JibxMarshaller` is configured for a single class. If you want to marshal multiple +classes, you have to configure multiple ++JibxMarshaller++s with different `targetClass` +property values. + + +[[oxm-jibx-xsd]] +===== XML Schema-based Configuration +The `jibx-marshaller` tag configures a `org.springframework.oxm.jibx.JibxMarshaller`. +Here is an example: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + +---- + +Available attributes are: + +|=== +| Attribute| Description| Required + +| `id` +| the id of the marshaller +| no + +| `target-class` +| the target class for this marshaller +| yes + +| `bindingName` +| the binding name used by this marshaller +| no +|=== + + + + +[[oxm-xstream]] +=== XStream +XStream is a simple library to serialize objects to XML and back again. It does not +require any mapping, and generates clean XML. + +For more information on XStream, refer to the http://xstream.codehaus.org/[__XStream +web site__]. The Spring integration classes reside in the +`org.springframework.oxm.xstream` package. + + + +[[oxm-xstream-marshaller]] +==== XStreamMarshaller +The `XStreamMarshaller` does not require any configuration, and can be configured in an +application context directly. To further customize the XML, you can set an__alias map__, +which consists of string aliases mapped to classes: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + org.springframework.oxm.xstream.Flight + + + + ... + +---- + +[WARNING] +==== + +By default, XStream allows for arbitrary classes to be unmarshalled, which can result in +security vulnerabilities. As such, it is __not recommended to use the +`XStreamMarshaller` to unmarshal XML from external sources__ (i.e. the Web), as this can +result in __security vulnerabilities__. If you do use the `XStreamMarshaller` to +unmarshal XML from an external source, set the `supportedClasses` property on the +`XStreamMarshaller`, like so: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + ... + +---- + +This will make sure that only the registered classes are eligible for unmarshalling. + +Additionally, you can register +{javadoc-baseurl}/org/springframework/oxm/xstream/XStreamMarshaller.html#setConverters(com.thoughtworks.xstream.converters.ConverterMatcher...)[custom +converters] to make sure that only your supported classes can be unmarshalled. You might +want to add a `CatchAllConverter` as the last converter in the list, in addition to +converters that explicitly support the domain classes that should be supported. As a +result, default XStream converters with lower priorities and possible security +vulnerabilities do not get invoked. +==== + +NOTE: Note that XStream is an XML serialization library, not a data binding library. +Therefore, it has limited namespace support. As such, it is rather unsuitable for usage +within Web services. diff --git a/src/asciidoc/portlet.adoc b/src/asciidoc/portlet.adoc new file mode 100644 index 000000000000..79a0cc29a77a --- /dev/null +++ b/src/asciidoc/portlet.adoc @@ -0,0 +1,1471 @@ +[[portlet]] +== Portlet MVC Framework + + + + +[[portlet-introduction]] +=== Introduction + +.JSR-168 The Java Portlet Specification +**** +For more general information about portlet development, please review a whitepaper from +Oracle entitled +http://www.oracle.com/technetwork/java/index-raji-test-141933.html["Introduction +to JSR 168"], and of course the +http://jcp.org/aboutJava/communityprocess/final/jsr168/[JSR-168 Specification] itself. +**** + +In addition to supporting conventional (servlet-based) Web development, Spring also +supports JSR-168 Portlet development. As much as possible, the Portlet MVC framework is +a mirror image of the Web MVC framework, and also uses the same underlying view +abstractions and integration technology. So, be sure to review the chapters entitled +<> and <> before continuing with this chapter. + +[NOTE] +==== +Bear in mind that while the concepts of Spring MVC are the same in Spring Portlet MVC, +there are some notable differences created by the unique workflow of JSR-168 portlets. +==== + +The main way in which portlet workflow differs from servlet workflow is that the request +to the portlet can have two distinct phases: the action phase and the render phase. The +action phase is executed only once and is where any 'backend' changes or actions occur, +such as making changes in a database. The render phase then produces what is displayed +to the user each time the display is refreshed. The critical point here is that for a +single overall request, the action phase is executed only once, but the render phase may +be executed multiple times. This provides (and requires) a clean separation between the +activities that modify the persistent state of your system and the activities that +generate what is displayed to the user. + +.Spring Web Flow +**** +Spring Web Flow (SWF) aims to be the best solution for the management of web application +page flow. + +SWF integrates with existing frameworks like Spring MVC and JSF, in both Servlet and +Portlet environments. If you have a business process (or processes) that would benefit +from a conversational model as opposed to a purely request model, then SWF may be the +solution. + +SWF allows you to capture logical page flows as self-contained modules that are reusable +in different situations, and as such is ideal for building web application modules that +guide the user through controlled navigations that drive business processes. + +For more information about SWF, consult the Spring Web Flow website. +**** + +The dual phases of portlet requests are one of the real strengths of the JSR-168 +specification. For example, dynamic search results can be updated routinely on the +display without the user explicitly rerunning the search. Most other portlet MVC +frameworks attempt to completely hide the two phases from the developer and make it look +as much like traditional servlet development as possible - we think this approach +removes one of the main benefits of using portlets. So, the separation of the two phases +is preserved throughout the Spring Portlet MVC framework. The primary manifestation of +this approach is that where the servlet version of the MVC classes will have one method +that deals with the request, the portlet version of the MVC classes will have two +methods that deal with the request: one for the action phase and one for the render +phase. For example, where the servlet version of `AbstractController` has the +`handleRequestInternal(..)` method, the portlet version of `AbstractController` has +`handleActionRequestInternal(..)` and `handleRenderRequestInternal(..)` methods. + +The framework is designed around a `DispatcherPortlet` that dispatches requests to +handlers, with configurable handler mappings and view resolution, just as the +`DispatcherServlet` in the web framework does. File upload is also supported in the same +way. + +Locale resolution and theme resolution are not supported in Portlet MVC - these areas +are in the purview of the portal/portlet container and are not appropriate at the Spring +level. However, all mechanisms in Spring that depend on the locale (such as +internationalization of messages) will still function properly because +`DispatcherPortlet` exposes the current locale in the same way as `DispatcherServlet`. + + + +[[portlet-introduction-controller]] +==== Controllers - The C in MVC +The default handler is still a very simple `Controller` interface, offering just two +methods: + +* `void handleActionRequest(request,response)` +* `ModelAndView handleRenderRequest(request,response)` + +The framework also includes most of the same controller implementation hierarchy, such +as `AbstractController`, `SimpleFormController`, and so on. Data binding, command object +usage, model handling, and view resolution are all the same as in the servlet framework. + + + +[[portlet-introduction-view]] +==== Views - The V in MVC +All the view rendering capabilities of the servlet framework are used directly via a +special bridge servlet named `ViewRendererServlet`. By using this servlet, the portlet +request is converted into a servlet request and the view can be rendered using the +entire normal servlet infrastructure. This means all the existing renderers, such as +JSP, Velocity, etc., can still be used within the portlet. + + + +[[portlet-introduction-scope]] +==== Web-scoped beans +Spring Portlet MVC supports beans whose lifecycle is scoped to the current HTTP request +or HTTP `Session` (both normal and global). This is not a specific feature of Spring +Portlet MVC itself, but rather of the `WebApplicationContext` container(s) that Spring +Portlet MVC uses. These bean scopes are described in detail in +<> + + + + +[[portlet-dispatcher]] +=== The DispatcherPortlet + +Portlet MVC is a request-driven web MVC framework, designed around a portlet that +dispatches requests to controllers and offers other functionality facilitating the +development of portlet applications. Spring's `DispatcherPortlet` however, does more +than just that. It is completely integrated with the Spring `ApplicationContext` and +allows you to use every other feature Spring has. + +Like ordinary portlets, the `DispatcherPortlet` is declared in the `portlet.xml` file of +your web application: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + sample + org.springframework.web.portlet.DispatcherPortlet + + text/html + view + + + Sample Portlet + + +---- + +The `DispatcherPortlet` now needs to be configured. + +In the Portlet MVC framework, each `DispatcherPortlet` has its own +`WebApplicationContext`, which inherits all the beans already defined in the Root +`WebApplicationContext`. These inherited beans can be overridden in the portlet-specific +scope, and new scope-specific beans can be defined local to a given portlet instance. + +The framework will, on initialization of a `DispatcherPortlet`, look for a file named +`[portlet-name]-portlet.xml` in the `WEB-INF` directory of your web application and +create the beans defined there (overriding the definitions of any beans defined with the +same name in the global scope). + +The config location used by the `DispatcherPortlet` can be modified through a portlet +initialization parameter (see below for details). + +The Spring `DispatcherPortlet` has a few special beans it uses, in order to be able to +process requests and render the appropriate views. These beans are included in the +Spring framework and can be configured in the `WebApplicationContext`, just as any other +bean would be configured. Each of those beans is described in more detail below. Right +now, we'll just mention them, just to let you know they exist and to enable us to go on +talking about the `DispatcherPortlet`. For most of the beans, defaults are provided so +you don't have to worry about configuring them. + +[[portlet-webappctx-special-beans-tbl]] +.Special beans in the WebApplicationContext +[cols="1,4"] +|=== +| Expression| Explanation + +| handler mapping(s) +| (<>) a list of pre- and post-processors and controllers that + will be executed if they match certain criteria (for instance a matching portlet mode + specified with the controller) + +| controller(s) +| (<>) the beans providing the actual functionality (or at least, + access to the functionality) as part of the MVC triad + +| view resolver +| (<>) capable of resolving view names to view definitions + +| multipart resolver +| (<>) offers functionality to process file uploads from HTML forms + +| handler exception resolver +| (<>) offers functionality to map exceptions to views or + implement other more complex exception handling code +|=== + +When a `DispatcherPortlet` is setup for use and a request comes in for that specific +`DispatcherPortlet`, it starts processing the request. The list below describes the +complete process a request goes through if handled by a `DispatcherPortlet`: + +. The locale returned by `PortletRequest.getLocale()` is bound to the request to let +elements in the process resolve the locale to use when processing the request (rendering +the view, preparing data, etc.). +. If a multipart resolver is specified and this is an `ActionRequest`, the request is +inspected for multiparts and if they are found, it is wrapped in a +`MultipartActionRequest` for further processing by other elements in the process. (See +<> for further information about multipart handling). +. An appropriate handler is searched for. If a handler is found, the execution chain +associated with the handler (pre-processors, post-processors, controllers) will be +executed in order to prepare a model. +. If a model is returned, the view is rendered, using the view resolver that has been +configured with the `WebApplicationContext`. If no model is returned (which could be due +to a pre- or post-processor intercepting the request, for example, for security +reasons), no view is rendered, since the request could already have been fulfilled. + +Exceptions that are thrown during processing of the request get picked up by any of the +handler exception resolvers that are declared in the `WebApplicationContext`. Using +these exception resolvers you can define custom behavior in case such exceptions get +thrown. + +You can customize Spring's `DispatcherPortlet` by adding context parameters in the +`portlet.xml` file or portlet init-parameters. The possibilities are listed below. + +[[portlet-dpp-init-params]] +.DispatcherPortlet initialization parameters +[cols="1,4"] +|=== +| Parameter| Explanation + +| `contextClass` +| Class that implements `WebApplicationContext`, which will be used to instantiate the + context used by this portlet. If this parameter isn't specified, the + `XmlPortletApplicationContext` will be used. + +| `contextConfigLocation` +| String which is passed to the context instance (specified by `contextClass`) to + indicate where context(s) can be found. The String is potentially split up into + multiple Strings (using a comma as a delimiter) to support multiple contexts (in case + of multiple context locations, for beans that are defined twice, the latest takes + precedence). + +| `namespace` +| The namespace of the `WebApplicationContext`. Defaults to `[portlet-name]-portlet`. + +| `viewRendererUrl` +| The URL at which `DispatcherPortlet` can access an instance of `ViewRendererServlet` + (see <>). +|=== + + + + +[[portlet-viewservlet]] +=== The ViewRendererServlet + +The rendering process in Portlet MVC is a bit more complex than in Web MVC. In order to +reuse all the <> from Spring Web MVC, we must convert the +`PortletRequest` / `PortletResponse` to `HttpServletRequest` / `HttpServletResponse` and +then call the `render` method of the `View`. To do this, `DispatcherPortlet` uses a +special servlet that exists for just this purpose: the `ViewRendererServlet`. + +In order for `DispatcherPortlet` rendering to work, you must declare an instance of the +`ViewRendererServlet` in the `web.xml` file for your web application as follows: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + ViewRendererServlet + org.springframework.web.servlet.ViewRendererServlet + + + + ViewRendererServlet + /WEB-INF/servlet/view + +---- + +To perform the actual rendering, `DispatcherPortlet` does the following: + +. Binds the `WebApplicationContext` to the request as an attribute under the same +`WEB_APPLICATION_CONTEXT_ATTRIBUTE` key that `DispatcherServlet` uses. +. Binds the `Model` and `View` objects to the request to make them available to the +`ViewRendererServlet`. +. Constructs a `PortletRequestDispatcher` and performs an `include` using the `/WEB- +INF/servlet/view` URL that is mapped to the `ViewRendererServlet`. + +The `ViewRendererServlet` is then able to call the `render` method on the `View` with +the appropriate arguments. + +The actual URL for the `ViewRendererServlet` can be changed using `DispatcherPortlet`'s +`viewRendererUrl` configuration parameter. + + + + +[[portlet-controller]] +=== Controllers +The controllers in Portlet MVC are very similar to the Web MVC Controllers, and porting +code from one to the other should be simple. + +The basis for the Portlet MVC controller architecture is the +`org.springframework.web.portlet.mvc.Controller` interface, which is listed below. + +[source,java,indent=0] +---- + public interface Controller { + + /** + * Process the render request and return a ModelAndView object which the + * DispatcherPortlet will render. + */ + ModelAndView handleRenderRequest(RenderRequest request, + RenderResponse response) throws Exception; + + /** + * Process the action request. There is nothing to return. + */ + void handleActionRequest(ActionRequest request, + ActionResponse response) throws Exception; + + } +---- + +As you can see, the Portlet `Controller` interface requires two methods that handle the +two phases of a portlet request: the action request and the render request. The action +phase should be capable of handling an action request, and the render phase should be +capable of handling a render request and returning an appropriate model and view. While +the `Controller` interface is quite abstract, Spring Portlet MVC offers several +controllers that already contain a lot of the functionality you might need; most of +these are very similar to controllers from Spring Web MVC. The `Controller` interface +just defines the most common functionality required of every controller: handling an +action request, handling a render request, and returning a model and a view. + + + +[[portlet-controller-abstractcontroller]] +==== AbstractController and PortletContentGenerator + +Of course, just a `Controller` interface isn't enough. To provide a basic +infrastructure, all of Spring Portlet MVC's ++Controller++s inherit from +`AbstractController`, a class offering access to Spring's `ApplicationContext` and +control over caching. + +[[portlet-ac-features]] +.Features offered by the AbstractController +[cols="1,4"] +|=== +| Parameter| Explanation + +| `requireSession` +| Indicates whether or not this `Controller` requires a session to do its work. This + feature is offered to all controllers. If a session is not present when such a + controller receives a request, the user is informed using a `SessionRequiredException`. + +| `synchronizeSession` +| Use this if you want handling by this controller to be synchronized on the user's + session. To be more specific, the extending controller will override the + `handleRenderRequestInternal(..)` and `handleActionRequestInternal(..)` methods, which + will be synchronized on the user's session if you specify this variable. + +| `renderWhenMinimized` +| If you want your controller to actually render the view when the portlet is in a + minimized state, set this to true. By default, this is set to false so that portlets + that are in a minimized state don't display any content. + +| `cacheSeconds` +| When you want a controller to override the default cache expiration defined for the + portlet, specify a positive integer here. By default it is set to `-1`, which does not + change the default caching. Setting it to `0` will ensure the result is never cached. +|=== + +The `requireSession` and `cacheSeconds` properties are declared on the +`PortletContentGenerator` class, which is the superclass of `AbstractController`) but +are included here for completeness. + +When using the `AbstractController` as a base class for your controllers (which is not +recommended since there are a lot of other controllers that might already do the job for +you) you only have to override either the `handleActionRequestInternal(ActionRequest, +ActionResponse)` method or the `handleRenderRequestInternal(RenderRequest, +RenderResponse)` method (or both), implement your logic, and return a `ModelAndView` +object (in the case of `handleRenderRequestInternal`). + +The default implementations of both `handleActionRequestInternal(..)` and +`handleRenderRequestInternal(..)` throw a `PortletException`. This is consistent with +the behavior of `GenericPortlet` from the JSR- 168 Specification API. So you only need +to override the method that your controller is intended to handle. + +Here is short example consisting of a class and a declaration in the web application +context. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + package samples; + + import javax.portlet.RenderRequest; + import javax.portlet.RenderResponse; + + import org.springframework.web.portlet.mvc.AbstractController; + import org.springframework.web.portlet.ModelAndView; + + public class SampleController extends AbstractController { + + public ModelAndView handleRenderRequestInternal(RenderRequest request, RenderResponse response) { + ModelAndView mav = new ModelAndView("foo"); + mav.addObject("message", "Hello World!"); + return mav; + } + + } +---- + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + +---- + +The class above and the declaration in the web application context is all you need +besides setting up a handler mapping (see <>) to get this very +simple controller working. + + + +[[portlet-controller-simple]] +==== Other simple controllers +Although you can extend `AbstractController`, Spring Portlet MVC provides a number of +concrete implementations which offer functionality that is commonly used in simple MVC +applications. + +The `ParameterizableViewController` is basically the same as the example above, except +for the fact that you can specify the view name that it will return in the web +application context (no need to hard-code the view name). + +The `PortletModeNameViewController` uses the current mode of the portlet as the view +name. So, if your portlet is in View mode (i.e. `PortletMode.VIEW`) then it uses "view" +as the view name. + + + +[[portlet-controller-command]] +==== Command Controllers +Spring Portlet MVC has the exact same hierarchy of __command controllers__ as Spring Web +MVC. They provide a way to interact with data objects and dynamically bind parameters +from the `PortletRequest` to the data object specified. Your data objects don't have to +implement a framework-specific interface, so you can directly manipulate your persistent +objects if you desire. Let's examine what command controllers are available, to get an +overview of what you can do with them: + +* `AbstractCommandController` - a command controller you can use to create your own + command controller, capable of binding request parameters to a data object you + specify. This class does not offer form functionality, it does however offer + validation features and lets you specify in the controller itself what to do with the + command object that has been filled with the parameters from the request. +* `AbstractFormController` - an abstract controller offering form submission support. + Using this controller you can model forms and populate them using a command object you + retrieve in the controller. After a user has filled the form, `AbstractFormController` + binds the fields, validates, and hands the object back to the controller to take + appropriate action. Supported features are: invalid form submission (resubmission), + validation, and normal form workflow. You implement methods to determine which views + are used for form presentation and success. Use this controller if you need forms, but + don't want to specify what views you're going to show the user in the application + context. +* `SimpleFormController` - a concrete `AbstractFormController` that provides even more + support when creating a form with a corresponding command object. The + `SimpleFormController` lets you specify a command object, a viewname for the form, a + viewname for the page you want to show the user when form submission has succeeded, + and more. +* `AbstractWizardFormController` -- a concrete `AbstractFormController` that provides a + wizard-style interface for editing the contents of a command object across multiple + display pages. Supports multiple user actions: finish, cancel, or page change, all of + which are easily specified in request parameters from the view. + +These command controllers are quite powerful, but they do require a detailed +understanding of how they operate in order to use them efficiently. Carefully review the +javadocs for this entire hierarchy and then look at some sample implementations before +you start using them. + + + +[[portlet-controller-wrapping]] +==== PortletWrappingController + +Instead of developing new controllers, it is possible to use existing portlets and map +requests to them from a `DispatcherPortlet`. Using the `PortletWrappingController`, you +can instantiate an existing `Portlet` as a `Controller` as follows: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + config=/WEB-INF/my-portlet-config.xml + + +---- + +This can be very valuable since you can then use interceptors to pre-process and +post-process requests going to these portlets. Since JSR-168 does not support any kind +of filter mechanism, this is quite handy. For example, this can be used to wrap the +Hibernate `OpenSessionInViewInterceptor` around a MyFaces JSF Portlet. + + + + +[[portlet-handlermapping]] +=== Handler mappings +Using a handler mapping you can map incoming portlet requests to appropriate handlers. +There are some handler mappings you can use out of the box, for example, the +`PortletModeHandlerMapping`, but let's first examine the general concept of a +`HandlerMapping`. + +Note: We are intentionally using the term "Handler" here instead of "Controller". +`DispatcherPortlet` is designed to be used with other ways to process requests than just +Spring Portlet MVC's own Controllers. A Handler is any Object that can handle portlet +requests. Controllers are an example of Handlers, and they are of course the default. To +use some other framework with `DispatcherPortlet`, a corresponding implementation of +`HandlerAdapter` is all that is needed. + +The functionality a basic `HandlerMapping` provides is the delivering of a +`HandlerExecutionChain`, which must contain the handler that matches the incoming +request, and may also contain a list of handler interceptors that are applied to the +request. When a request comes in, the `DispatcherPortlet` will hand it over to the +handler mapping to let it inspect the request and come up with an appropriate +`HandlerExecutionChain`. Then the `DispatcherPortlet` will execute the handler and +interceptors in the chain (if any). These concepts are all exactly the same as in Spring +Web MVC. + +The concept of configurable handler mappings that can optionally contain interceptors +(executed before or after the actual handler was executed, or both) is extremely +powerful. A lot of supporting functionality can be built into a custom `HandlerMapping`. +Think of a custom handler mapping that chooses a handler not only based on the portlet +mode of the request coming in, but also on a specific state of the session associated +with the request. + +In Spring Web MVC, handler mappings are commonly based on URLs. Since there is really no +such thing as a URL within a Portlet, we must use other mechanisms to control mappings. +The two most common are the portlet mode and a request parameter, but anything available +to the portlet request can be used in a custom handler mapping. + +The rest of this section describes three of Spring Portlet MVC's most commonly used +handler mappings. They all extend `AbstractHandlerMapping` and share the following +properties: + +* `interceptors`: The list of interceptors to use. ++HandlerInterceptor++s are discussed + in <>. +* `defaultHandler`: The default handler to use, when this handler mapping does not + result in a matching handler. +* `order`: Based on the value of the order property (see the + `org.springframework.core.Ordered` interface), Spring will sort all handler mappings + available in the context and apply the first matching handler. +* `lazyInitHandlers`: Allows for lazy initialization of singleton handlers (prototype + handlers are always lazily initialized). Default value is false. This property is + directly implemented in the three concrete Handlers. + + + +[[portlet-handlermapping-portletmode]] +==== PortletModeHandlerMapping + +This is a simple handler mapping that maps incoming requests based on the current mode +of the portlet (e.g. 'view', 'edit', 'help'). An example: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + + +---- + + + +[[portlet-handlermapping-parameter]] +==== ParameterHandlerMapping + +If we need to navigate around to multiple controllers without changing portlet mode, the +simplest way to do this is with a request parameter that is used as the key to control +the mapping. + +`ParameterHandlerMapping` uses the value of a specific request parameter to control the +mapping. The default name of the parameter is `'action'`, but can be changed using the +`'parameterName'` property. + +The bean configuration for this mapping will look something like this: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + + +---- + + + +[[portlet-handlermapping-portletmodeparameter]] +==== PortletModeParameterHandlerMapping + +The most powerful built-in handler mapping, `PortletModeParameterHandlerMapping` +combines the capabilities of the two previous ones to allow different navigation within +each portlet mode. + +Again the default name of the parameter is "action", but can be changed using the +`parameterName` property. + +By default, the same parameter value may not be used in two different portlet modes. +This is so that if the portal itself changes the portlet mode, the request will no +longer be valid in the mapping. This behavior can be changed by setting the +`allowDupParameters` property to true. However, this is not recommended. + +The bean configuration for this mapping will look something like this: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + + + + + + + + + + + + +---- + +This mapping can be chained ahead of a `PortletModeHandlerMapping`, which can then +provide defaults for each mode and an overall default as well. + + + +[[portlet-handlermapping-interceptor]] +==== Adding HandlerInterceptors + +Spring's handler mapping mechanism has a notion of handler interceptors, which can be +extremely useful when you want to apply specific functionality to certain requests, for +example, checking for a principal. Again Spring Portlet MVC implements these concepts in +the same way as Web MVC. + +Interceptors located in the handler mapping must implement `HandlerInterceptor` from the +`org.springframework.web.portlet` package. Just like the servlet version, this interface +defines three methods: one that will be called before the actual handler will be +executed ( `preHandle`), one that will be called after the handler is executed ( +`postHandle`), and one that is called after the complete request has finished ( +`afterCompletion`). These three methods should provide enough flexibility to do all +kinds of pre- and post- processing. + +The `preHandle` method returns a boolean value. You can use this method to break or +continue the processing of the execution chain. When this method returns `true`, the +handler execution chain will continue. When it returns `false`, the `DispatcherPortlet` +assumes the interceptor itself has taken care of requests (and, for example, rendered an +appropriate view) and does not continue executing the other interceptors and the actual +handler in the execution chain. + +The `postHandle` method is only called on a `RenderRequest`. The `preHandle` and +`afterCompletion` methods are called on both an `ActionRequest` and a `RenderRequest`. +If you need to execute logic in these methods for just one type of request, be sure to +check what kind of request it is before processing it. + + + +[[portlet-handlermapping-interceptoradapter]] +==== HandlerInterceptorAdapter + +As with the servlet package, the portlet package has a concrete implementation of +`HandlerInterceptor` called `HandlerInterceptorAdapter`. This class has empty versions +of all the methods so that you can inherit from this class and implement just one or two +methods when that is all you need. + + + +[[portlet-handlermapping-parameterinterceptor]] +==== ParameterMappingInterceptor + +The portlet package also has a concrete interceptor named `ParameterMappingInterceptor` +that is meant to be used directly with `ParameterHandlerMapping` and +`PortletModeParameterHandlerMapping`. This interceptor will cause the parameter that is +being used to control the mapping to be forwarded from an `ActionRequest` to the +subsequent `RenderRequest`. This will help ensure that the `RenderRequest` is mapped to +the same Handler as the `ActionRequest`. This is done in the `preHandle` method of the +interceptor, so you can still modify the parameter value in your handler to change where +the `RenderRequest` will be mapped. + +Be aware that this interceptor is calling `setRenderParameter` on the `ActionResponse`, +which means that you cannot call `sendRedirect` in your handler when using this +interceptor. If you need to do external redirects then you will either need to forward +the mapping parameter manually or write a different interceptor to handle this for you. + + + + +[[portlet-viewresolver]] +=== Views and resolving them +As mentioned previously, Spring Portlet MVC directly reuses all the view technologies +from Spring Web MVC. This includes not only the various `View` implementations +themselves, but also the `ViewResolver` implementations. For more information, refer to +<> and <> respectively. + +A few items on using the existing `View` and `ViewResolver` implementations are worth +mentioning: + +* Most portals expect the result of rendering a portlet to be an HTML fragment. So, + things like JSP/JSTL, Velocity, FreeMarker, and XSLT all make sense. But it is + unlikely that views that return other document types will make any sense in a portlet + context. +* There is no such thing as an HTTP redirect from within a portlet (the + `sendRedirect(..)` method of `ActionResponse` cannot be used to stay within the + portal). So, `RedirectView` and use of the `'redirect:'` prefix will __not__ work + correctly from within Portlet MVC. +* It may be possible to use the `'forward:'` prefix from within Portlet MVC. However, + remember that since you are in a portlet, you have no idea what the current URL looks + like. This means you cannot use a relative URL to access other resources in your web + application and that you will have to use an absolute URL. + +Also, for JSP development, the new Spring Taglib and the new Spring Form Taglib both +work in portlet views in exactly the same way that they work in servlet views. + + + + +[[portlet-multipart]] +=== Multipart (file upload) support +Spring Portlet MVC has built-in multipart support to handle file uploads in portlet +applications, just like Web MVC does. The design for the multipart support is done with +pluggable `PortletMultipartResolver` objects, defined in the +`org.springframework.web.portlet.multipart` package. Spring provides a +`PortletMultipartResolver` for use with +http://jakarta.apache.org/commons/fileupload[Commons FileUpload]. How uploading files is +supported will be described in the rest of this section. + +By default, no multipart handling will be done by Spring Portlet MVC, as some developers +will want to handle multiparts themselves. You will have to enable it yourself by adding +a multipart resolver to the web application's context. After you have done that, +`DispatcherPortlet` will inspect each request to see if it contains a multipart. If no +multipart is found, the request will continue as expected. However, if a multipart is +found in the request, the `PortletMultipartResolver` that has been declared in your +context will be used. After that, the multipart attribute in your request will be +treated like any other attribute. + +[NOTE] +==== +Any configured `PortletMultipartResolver` bean __must__ have the following id (or name): +" `portletMultipartResolver`". If you have defined your `PortletMultipartResolver` with +any other name, then the `DispatcherPortlet` will __not__ find your +`PortletMultipartResolver`, and consequently no multipart support will be in effect. +==== + + + +[[portlet-multipart-resolver]] +==== Using the PortletMultipartResolver + +The following example shows how to use the `CommonsPortletMultipartResolver`: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + +---- + +Of course you also need to put the appropriate jars in your classpath for the multipart +resolver to work. In the case of the `CommonsMultipartResolver`, you need to use +`commons-fileupload.jar`. Be sure to use at least version 1.1 of Commons FileUpload as +previous versions do not support JSR-168 Portlet applications. + +Now that you have seen how to set Portlet MVC up to handle multipart requests, let's +talk about how to actually use it. When `DispatcherPortlet` detects a multipart request, +it activates the resolver that has been declared in your context and hands over the +request. What the resolver then does is wrap the current `ActionRequest` in a +`MultipartActionRequest` that has support for multipart file uploads. Using the +`MultipartActionRequest` you can get information about the multiparts contained by this +request and actually get access to the multipart files themselves in your controllers. + +Note that you can only receive multipart file uploads as part of an `ActionRequest`, not +as part of a `RenderRequest`. + + + +[[portlet-multipart-forms]] +==== Handling a file upload in a form +After the `PortletMultipartResolver` has finished doing its job, the request will be +processed like any other. To use the `PortletMultipartResolver`, create a form with an +upload field (see example below), then let Spring bind the file onto your form (backing +object). To actually let the user upload a file, we have to create a (JSP/HTML) form: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- +

Please upload a file

+
+ + + +---- + +As you can see, we've created a field named "file" that matches the property of the bean +that holds the `byte[]` array. Furthermore we've added the encoding attribute ( +`enctype="multipart/form-data"`), which is necessary to let the browser know how to +encode the multipart fields (do not forget this!). + +Just as with any other property that's not automagically convertible to a string or +primitive type, to be able to put binary data in your objects you have to register a +custom editor with the `PortletRequestDataBinder`. There are a couple of editors +available for handling files and setting the results on an object. There's a +`StringMultipartFileEditor` capable of converting files to Strings (using a user-defined +character set), and there is a `ByteArrayMultipartFileEditor` which converts files to +byte arrays. They function analogous to the `CustomDateEditor`. + +So, to be able to upload files using a form, declare the resolver, a mapping to a +controller that will process the bean, and the controller itself. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + + + + + + + + +---- + +After that, create the controller and the actual class to hold the file property. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class FileUploadController extends SimpleFormController { + + public void onSubmitAction(ActionRequest request, ActionResponse response, + Object command, BindException errors) throws Exception { + + // cast the bean + FileUploadBean bean = (FileUploadBean) command; + + // let's see if there's content there + byte[] file = bean.getFile(); + if (file == null) { + // hmm, that's strange, the user did not upload anything + } + + // do something with the file here + } + + protected void initBinder(PortletRequest request, + PortletRequestDataBinder binder) throws Exception { + // to actually be able to convert Multipart instance to byte[] + // we have to register a custom editor + binder.registerCustomEditor(byte[].class, new ByteArrayMultipartFileEditor()); + // now Spring knows how to handle multipart object and convert + } + + } + + public class FileUploadBean { + + private byte[] file; + + public void setFile(byte[] file) { + this.file = file; + } + + public byte[] getFile() { + return file; + } + + } +---- + +As you can see, the `FileUploadBean` has a property of type `byte[]` that holds the +file. The controller registers a custom editor to let Spring know how to actually +convert the multipart objects the resolver has found to properties specified by the +bean. In this example, nothing is done with the `byte[]` property of the bean itself, +but in practice you can do whatever you want (save it in a database, mail it to +somebody, etc). + +An equivalent example in which a file is bound straight to a String-typed property on a +form backing object might look like this: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class FileUploadController extends SimpleFormController { + + public void onSubmitAction(ActionRequest request, ActionResponse response, + Object command, BindException errors) throws Exception { + + // cast the bean + FileUploadBean bean = (FileUploadBean) command; + + // let's see if there's content there + String file = bean.getFile(); + if (file == null) { + // hmm, that's strange, the user did not upload anything + } + + // do something with the file here + } + + protected void initBinder(PortletRequest request, + PortletRequestDataBinder binder) throws Exception { + + // to actually be able to convert Multipart instance to a String + // we have to register a custom editor + binder.registerCustomEditor(String.class, new StringMultipartFileEditor()); + // now Spring knows how to handle multipart objects and convert + } + } + + public class FileUploadBean { + + private String file; + + public void setFile(String file) { + this.file = file; + } + + public String getFile() { + return file; + } + } +---- + +Of course, this last example only makes (logical) sense in the context of uploading a +plain text file (it wouldn't work so well in the case of uploading an image file). + +The third (and final) option is where one binds directly to a `MultipartFile` property +declared on the (form backing) object's class. In this case one does not need to +register any custom property editor because there is no type conversion to be performed. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class FileUploadController extends SimpleFormController { + + public void onSubmitAction(ActionRequest request, ActionResponse response, + Object command, BindException errors) throws Exception { + + // cast the bean + FileUploadBean bean = (FileUploadBean) command; + + // let's see if there's content there + MultipartFile file = bean.getFile(); + if (file == null) { + // hmm, that's strange, the user did not upload anything + } + + // do something with the file here + } + } + + public class FileUploadBean { + + private MultipartFile file; + + public void setFile(MultipartFile file) { + this.file = file; + } + + public MultipartFile getFile() { + return file; + } + + } +---- + + + + +[[portlet-exceptionresolver]] +=== Handling exceptions +Just like Servlet MVC, Portlet MVC provides ++HandlerExceptionResolver++s to ease the +pain of unexpected exceptions that occur while your request is being processed by a +handler that matched the request. Portlet MVC also provides a portlet-specific, concrete +`SimpleMappingExceptionResolver` that enables you to take the class name of any +exception that might be thrown and map it to a view name. + + + + +[[portlet-annotation]] +=== Annotation-based controller configuration +Spring 2.5 introduced an annotation-based programming model for MVC controllers, using +annotations such as `@RequestMapping`, `@RequestParam`, `@ModelAttribute`, etc. This +annotation support is available for both Servlet MVC and Portlet MVC. Controllers +implemented in this style do not have to extend specific base classes or implement +specific interfaces. Furthermore, they do not usually have direct dependencies on +Servlet or Portlet API's, although they can easily get access to Servlet or Portlet +facilities if desired. + +The following sections document these annotations and how they are most commonly used in +a Portlet environment. + + + +[[portlet-ann-setup]] +==== Setting up the dispatcher for annotation support +__`@RequestMapping` will only be processed if a corresponding `HandlerMapping` (for +type level annotations) and/or `HandlerAdapter` (for method level annotations) is +present in the dispatcher.__ This is the case by default in both `DispatcherServlet` and +`DispatcherPortlet`. + +However, if you are defining custom `HandlerMappings` or `HandlerAdapters`, then you +need to make sure that a corresponding custom `DefaultAnnotationHandlerMapping` and/or +`AnnotationMethodHandlerAdapter` is defined as well - provided that you intend to use +`@RequestMapping`. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + // ... (controller bean definitions) ... + + +---- + +Defining a `DefaultAnnotationHandlerMapping` and/or `AnnotationMethodHandlerAdapter` +explicitly also makes sense if you would like to customize the mapping strategy, e.g. +specifying a custom `WebBindingInitializer` (see below). + + + +[[portlet-ann-controller]] +==== Defining a controller with @Controller + +The `@Controller` annotation indicates that a particular class serves the role of a +__controller__. There is no need to extend any controller base class or reference the +Portlet API. You are of course still able to reference Portlet-specific features if you +need to. + +The basic purpose of the `@Controller` annotation is to act as a stereotype for the +annotated class, indicating its role. The dispatcher will scan such annotated classes +for mapped methods, detecting `@RequestMapping` annotations (see the next section). + +Annotated controller beans may be defined explicitly, using a standard Spring bean +definition in the dispatcher's context. However, the `@Controller` stereotype also +allows for autodetection, aligned with Spring 2.5's general support for detecting +component classes in the classpath and auto-registering bean definitions for them. + +To enable autodetection of such annotated controllers, you have to add component +scanning to your configuration. This is easily achieved by using the __spring-context__ +schema as shown in the following XML snippet: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + // ... + + +---- + + + +[[portlet-ann-requestmapping]] +==== Mapping requests with @RequestMapping + +The `@RequestMapping` annotation is used to map portlet modes like 'VIEW'/'EDIT' onto an +entire class or a particular handler method. Typically the type-level annotation maps a +specific mode (or mode plus parameter condition) onto a form controller, with additional +method-level annotations 'narrowing' the primary mapping for specific portlet request +parameters. + +[TIP] +==== + +`@RequestMapping` at the type level may be used for plain implementations of the +`Controller` interface as well. In this case, the request processing code would follow +the traditional `handle(Action|Render)Request` signature, while the controller's mapping +would be expressed through an `@RequestMapping` annotation. This works for pre-built +`Controller` base classes, such as `SimpleFormController`, too. + +In the following discussion, we'll focus on controllers that are based on annotated +handler methods. +==== + +The following is an example of a form controller from the PetPortal sample application +using this annotation: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Controller + @RequestMapping("EDIT") + @SessionAttributes("site") + public class PetSitesEditController { + + private Properties petSites; + + public void setPetSites(Properties petSites) { + this.petSites = petSites; + } + + @ModelAttribute("petSites") + public Properties getPetSites() { + return this.petSites; + } + + @RequestMapping // default (action=list) + public String showPetSites() { + return "petSitesEdit"; + } + + @RequestMapping(params = "action=add") // render phase + public String showSiteForm(Model model) { + // Used for the initial form as well as for redisplaying with errors. + if (!model.containsAttribute("site")) { + model.addAttribute("site", new PetSite()); + } + + return "petSitesAdd"; + } + + @RequestMapping(params = "action=add") // action phase + public void populateSite(@ModelAttribute("site") PetSite petSite, + BindingResult result, SessionStatus status, ActionResponse response) { + new PetSiteValidator().validate(petSite, result); + if (!result.hasErrors()) { + this.petSites.put(petSite.getName(), petSite.getUrl()); + status.setComplete(); + response.setRenderParameter("action", "list"); + } + } + + @RequestMapping(params = "action=delete") + public void removeSite(@RequestParam("site") String site, ActionResponse response) { + this.petSites.remove(site); + response.setRenderParameter("action", "list"); + } + } +---- + + + +[[portlet-ann-requestmapping-arguments]] +==== Supported handler method arguments +Handler methods which are annotated with `@RequestMapping` are allowed to have very +flexible signatures. They may have arguments of the following types, in arbitrary order +(except for validation results, which need to follow right after the corresponding +command object, if desired): + +* Request and/or response objects (Portlet API). You may choose any specific + request/response type, e.g. PortletRequest / ActionRequest / RenderRequest. An + explicitly declared action/render argument is also used for mapping specific request + types onto a handler method (in case of no other information given that differentiates + between action and render requests). +* Session object (Portlet API): of type PortletSession. An argument of this type will + enforce the presence of a corresponding session. As a consequence, such an argument + will never be `null`. +* `org.springframework.web.context.request.WebRequest` or + `org.springframework.web.context.request.NativeWebRequest`. Allows for generic request + parameter access as well as request/session attribute access, without ties to the + native Servlet/Portlet API. +* `java.util.Locale` for the current request locale (the portal locale in a Portlet + environment). +* `java.util.TimeZone` / `java.time.ZoneId` for the current request time zone. +* `java.io.InputStream` / `java.io.Reader` for access to the request's content. This + will be the raw InputStream/Reader as exposed by the Portlet API. +* `java.io.OutputStream` / `java.io.Writer` for generating the response's content. This + will be the raw OutputStream/Writer as exposed by the Portlet API. +* `@RequestParam` annotated parameters for access to specific Portlet request + parameters. Parameter values will be converted to the declared method argument type. +* `java.util.Map` / `org.springframework.ui.Model` / `org.springframework.ui.ModelMap` + for enriching the implicit model that will be exposed to the web view. +* Command/form objects to bind parameters to: as bean properties or fields, with + customizable type conversion, depending on `@InitBinder` methods and/or the + HandlerAdapter configuration - see the " `webBindingInitializer`" property on + `AnnotationMethodHandlerAdapter`. Such command objects along with their validation + results will be exposed as model attributes, by default using the non-qualified + command class name in property notation (e.g. "orderAddress" for type + "mypackage.OrderAddress"). Specify a parameter-level `ModelAttribute` annotation for + declaring a specific model attribute name. +* `org.springframework.validation.Errors` / + `org.springframework.validation.BindingResult` validation results for a preceding + command/form object (the immediate preceding argument). +* `org.springframework.web.bind.support.SessionStatus` status handle for marking form + processing as complete (triggering the cleanup of session attributes that have been + indicated by the `@SessionAttributes` annotation at the handler type level). + +The following return types are supported for handler methods: + +* A `ModelAndView` object, with the model implicitly enriched with command objects and + the results of `@ModelAttribute` annotated reference data accessor methods. +* A `Model` object, with the view name implicitly determined through a + `RequestToViewNameTranslator` and the model implicitly enriched with command objects + and the results of `@ModelAttribute` annotated reference data accessor methods. +* A `Map` object for exposing a model, with the view name implicitly determined through + a `RequestToViewNameTranslator` and the model implicitly enriched with command objects + and the results of `@ModelAttribute` annotated reference data accessor methods. +* A `View` object, with the model implicitly determined through command objects and + `@ModelAttribute` annotated reference data accessor methods. The handler method may + also programmatically enrich the model by declaring a `Model` argument (see above). +* A `String` value which is interpreted as view name, with the model implicitly + determined through command objects and `@ModelAttribute` annotated reference data + accessor methods. The handler method may also programmatically enrich the model by + declaring a `Model` argument (see above). +* `void` if the method handles the response itself (e.g. by writing the response content + directly). +* Any other return type will be considered a single model attribute to be exposed to the + view, using the attribute name specified through `@ModelAttribute` at the method level + (or the default attribute name based on the return type's class name otherwise). The + model will be implicitly enriched with command objects and the results of + `@ModelAttribute` annotated reference data accessor methods. + + + +[[portlet-ann-requestparam]] +==== Binding request parameters to method parameters with @RequestParam + +The `@RequestParam` annotation is used to bind request parameters to a method parameter +in your controller. + +The following code snippet from the PetPortal sample application shows the usage: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Controller + @RequestMapping("EDIT") + @SessionAttributes("site") + public class PetSitesEditController { + + // ... + + public void removeSite(@RequestParam("site") String site, ActionResponse response) { + this.petSites.remove(site); + response.setRenderParameter("action", "list"); + } + + // ... + + } +---- + +Parameters using this annotation are required by default, but you can specify that a +parameter is optional by setting `@RequestParam`'s `required` attribute to `false` +(e.g., `@RequestParam(value="id", required=false)`). + + + +[[portlet-ann-modelattrib]] +==== Providing a link to data from the model with @ModelAttribute + +`@ModelAttribute` has two usage scenarios in controllers. When placed on a method +parameter, `@ModelAttribute` is used to map a model attribute to the specific, annotated +method parameter (see the `populateSite()` method below). This is how the controller +gets a reference to the object holding the data entered in the form. In addition, the +parameter can be declared as the specific type of the form backing object rather than as +a generic `java.lang.Object`, thus increasing type safety. + +`@ModelAttribute` is also used at the method level to provide __reference data__ for the +model (see the `getPetSites()` method below). For this usage the method signature can +contain the same types as documented above for the `@RequestMapping` annotation. + +[NOTE] +==== +`@ModelAttribute` annotated methods will be executed __before__ the chosen +`@RequestMapping` annotated handler method. They effectively pre-populate the implicit +model with specific attributes, often loaded from a database. Such an attribute can then +already be accessed through `@ModelAttribute` annotated handler method parameters in the +chosen handler method, potentially with binding and validation applied to it. +==== + +The following code snippet shows these two usages of this annotation: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Controller + @RequestMapping("EDIT") + @SessionAttributes("site") + public class PetSitesEditController { + + // ... + + @ModelAttribute("petSites") + public Properties getPetSites() { + return this.petSites; + } + + @RequestMapping(params = "action=add") // action phase + public void populateSite( @ModelAttribute("site") PetSite petSite, BindingResult result, SessionStatus status, ActionResponse response) { + new PetSiteValidator().validate(petSite, result); + if (!result.hasErrors()) { + this.petSites.put(petSite.getName(), petSite.getUrl()); + status.setComplete(); + response.setRenderParameter("action", "list"); + } + } + } +---- + + + +[[portlet-ann-sessionattrib]] +==== Specifying attributes to store in a Session with @SessionAttributes + +The type-level `@SessionAttributes` annotation declares session attributes used by a +specific handler. This will typically list the names of model attributes or types of +model attributes which should be transparently stored in the session or some +conversational storage, serving as form-backing beans between subsequent requests. + +The following code snippet shows the usage of this annotation: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Controller + @RequestMapping("EDIT") + @SessionAttributes("site") + public class PetSitesEditController { + // ... + } +---- + + + +[[portlet-ann-webdatabinder]] +==== Customizing WebDataBinder initialization + +To customize request parameter binding with PropertyEditors, etc. via Spring's +`WebDataBinder`, you can either use `@InitBinder`-annotated methods within your +controller or externalize your configuration by providing a custom +`WebBindingInitializer`. + + +[[portlet-ann-initbinder]] +===== Customizing data binding with @InitBinder + +Annotating controller methods with `@InitBinder` allows you to configure web data +binding directly within your controller class. `@InitBinder` identifies methods which +initialize the `WebDataBinder` which will be used for populating command and form object +arguments of annotated handler methods. + +Such init-binder methods support all arguments that `@RequestMapping` supports, except +for command/form objects and corresponding validation result objects. Init-binder +methods must not have a return value. Thus, they are usually declared as `void`. Typical +arguments include `WebDataBinder` in combination with `WebRequest` or +`java.util.Locale`, allowing code to register context-specific editors. + +The following example demonstrates the use of `@InitBinder` for configuring a +`CustomDateEditor` for all `java.util.Date` form properties. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Controller + public class MyFormController { + + @InitBinder + public void initBinder(WebDataBinder binder) { + SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd"); + dateFormat.setLenient(false); + binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, false)); + } + + // ... + + } +---- + + +[[portlet-ann-webbindinginitializer]] +===== Configuring a custom WebBindingInitializer + +To externalize data binding initialization, you can provide a custom implementation of +the `WebBindingInitializer` interface, which you then enable by supplying a custom bean +configuration for an `AnnotationMethodHandlerAdapter`, thus overriding the default +configuration. + + + + +[[portlet-deployment]] +=== Portlet application deployment +The process of deploying a Spring Portlet MVC application is no different than deploying +any JSR-168 Portlet application. However, this area is confusing enough in general that +it is worth talking about here briefly. + +Generally, the portal/portlet container runs in one webapp in your servlet container and +your portlets run in another webapp in your servlet container. In order for the portlet +container webapp to make calls into your portlet webapp it must make cross-context calls +to a well-known servlet that provides access to the portlet services defined in your +`portlet.xml` file. + +The JSR-168 specification does not specify exactly how this should happen, so each +portlet container has its own mechanism for this, which usually involves some kind of +"deployment process" that makes changes to the portlet webapp itself and then registers +the portlets within the portlet container. + +At a minimum, the `web.xml` file in your portlet webapp is modified to inject the +well-known servlet that the portlet container will call. In some cases a single servlet +will service all portlets in the webapp, in other cases there will be an instance of the +servlet for each portlet. + +Some portlet containers will also inject libraries and/or configuration files into the +webapp as well. The portlet container must also make its implementation of the Portlet +JSP Tag Library available to your webapp. + +The bottom line is that it is important to understand the deployment needs of your +target portal and make sure they are met (usually by following the automated deployment +process it provides). Be sure to carefully review the documentation from your portal for +this process. + +Once you have deployed your portlet, review the resulting `web.xml` file for sanity. +Some older portals have been known to corrupt the definition of the +`ViewRendererServlet`, thus breaking the rendering of your portlets. + diff --git a/src/asciidoc/remoting.adoc b/src/asciidoc/remoting.adoc new file mode 100644 index 000000000000..9f553f3a7c98 --- /dev/null +++ b/src/asciidoc/remoting.adoc @@ -0,0 +1,1435 @@ +[[remoting]] +== Remoting and web services using Spring + + + + +[[remoting-introduction]] +=== Introduction +Spring features integration classes for remoting support using various technologies. The +remoting support eases the development of remote-enabled services, implemented by your +usual (Spring) POJOs. Currently, Spring supports the following remoting technologies: + +* __Remote Method Invocation (RMI)__. Through the use of the `RmiProxyFactoryBean` and + the `RmiServiceExporter` Spring supports both traditional RMI (with `java.rmi.Remote` + interfaces and `java.rmi.RemoteException`) and transparent remoting via RMI invokers + (with any Java interface). +* __Spring's HTTP invoker__. Spring provides a special remoting strategy which allows + for Java serialization via HTTP, supporting any Java interface (just like the RMI + invoker). The corresponding support classes are `HttpInvokerProxyFactoryBean` and + `HttpInvokerServiceExporter`. +* __Hessian__. By using Spring's `HessianProxyFactoryBean` and the + `HessianServiceExporter` you can transparently expose your services using the + lightweight binary HTTP-based protocol provided by Caucho. +* __Burlap__. Burlap is Caucho's XML-based alternative to Hessian. Spring provides + support classes such as `BurlapProxyFactoryBean` and `BurlapServiceExporter`. +* __JAX-WS__. Spring provides remoting support for web services via JAX-WS (the + successor of JAX-RPC, as introduced in Java EE 5 and Java 6). +* __JMS__. Remoting using JMS as the underlying protocol is supported via the + `JmsInvokerServiceExporter` and `JmsInvokerProxyFactoryBean` classes. +* __AMQP__. Remoting using AMQP as the underlying protocol is supported by the Spring + AMQP project. + +While discussing the remoting capabilities of Spring, we'll use the following domain +model and corresponding services: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class Account implements Serializable{ + + private String name; + + public String getName(){ + return name; + } + + public void setName(String name) { + this.name = name; + } + + } +---- + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public interface AccountService { + + public void insertAccount(Account account); + + public List getAccounts(String name); + + } +---- + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public interface RemoteAccountService extends Remote { + + public void insertAccount(Account account) throws RemoteException; + + public List getAccounts(String name) throws RemoteException; + + } +---- + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + // the implementation doing nothing at the moment + public class AccountServiceImpl implements AccountService { + + public void insertAccount(Account acc) { + // do something... + } + + public List getAccounts(String name) { + // do something... + } + + } +---- + +We will start exposing the service to a remote client by using RMI and talk a bit about +the drawbacks of using RMI. We'll then continue to show an example using Hessian as the +protocol. + + + + +[[remoting-rmi]] +=== Exposing services using RMI +Using Spring's support for RMI, you can transparently expose your services through the +RMI infrastructure. After having this set up, you basically have a configuration similar +to remote EJBs, except for the fact that there is no standard support for security +context propagation or remote transaction propagation. Spring does provide hooks for +such additional invocation context when using the RMI invoker, so you can for example +plug in security frameworks or custom security credentials here. + + + +[[remoting-rmi-server]] +==== Exporting the service using the RmiServiceExporter + +Using the `RmiServiceExporter`, we can expose the interface of our AccountService object +as RMI object. The interface can be accessed by using `RmiProxyFactoryBean`, or via +plain RMI in case of a traditional RMI service. The `RmiServiceExporter` explicitly +supports the exposing of any non-RMI services via RMI invokers. + +Of course, we first have to set up our service in the Spring container: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + +---- + +Next we'll have to expose our service using the `RmiServiceExporter`: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + +---- + +As you can see, we're overriding the port for the RMI registry. Often, your application +server also maintains an RMI registry and it is wise to not interfere with that one. +Furthermore, the service name is used to bind the service under. So right now, the +service will be bound at `'rmi://HOST:1199/AccountService'`. We'll use the URL later on +to link in the service at the client side. + +[NOTE] +==== +The `servicePort` property has been omitted (it defaults to 0). This means that an +anonymous port will be used to communicate with the service. +==== + + + +[[remoting-rmi-client]] +==== Linking in the service at the client +Our client is a simple object using the `AccountService` to manage accounts: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class SimpleObject { + + private AccountService accountService; + + public void setAccountService(AccountService accountService) { + this.accountService = accountService; + } + + // additional methods using the accountService + + } +---- + +To link in the service on the client, we'll create a separate Spring container, +containing the simple object and the service linking configuration bits: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + +---- + +That's all we need to do to support the remote account service on the client. Spring +will transparently create an invoker and remotely enable the account service through the +`RmiServiceExporter`. At the client we're linking it in using the `RmiProxyFactoryBean`. + + + + +[[remoting-caucho-protocols]] +=== Using Hessian or Burlap to remotely call services via HTTP +Hessian offers a binary HTTP-based remoting protocol. It is developed by Caucho and more +information about Hessian itself can be found at http://www.caucho.com[]. + + + +[[remoting-caucho-protocols-hessian]] +==== Wiring up the DispatcherServlet for Hessian and co. + +Hessian communicates via HTTP and does so using a custom servlet. Using Spring's +`DispatcherServlet` principles, as known from Spring Web MVC usage, you can easily wire +up such a servlet exposing your services. First we'll have to create a new servlet in +your application (this is an excerpt from `'web.xml'`): + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + remoting + org.springframework.web.servlet.DispatcherServlet + 1 + + + + remoting + /remoting/* + +---- + +You're probably familiar with Spring's `DispatcherServlet` principles and if so, you +know that now you'll have to create a Spring container configuration resource named +`'remoting-servlet.xml'` (after the name of your servlet) in the `'WEB-INF'` directory. +The application context will be used in the next section. + +Alternatively, consider the use of Spring's simpler `HttpRequestHandlerServlet`. This +allows you to embed the remote exporter definitions in your root application context (by +default in `'WEB-INF/applicationContext.xml'`), with individual servlet definitions +pointing to specific exporter beans. Each servlet name needs to match the bean name of +its target exporter in this case. + + + +[[remoting-caucho-protocols-hessian-server]] +==== Exposing your beans by using the HessianServiceExporter + +In the newly created application context called `remoting-servlet.xml`, we'll create a +`HessianServiceExporter` exporting your services: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + +---- + +Now we're ready to link in the service at the client. No explicit handler mapping is +specified, mapping request URLs onto services, so `BeanNameUrlHandlerMapping` will be +used: Hence, the service will be exported at the URL indicated through its bean name +within the containing `DispatcherServlet`'s mapping (as defined above): +`'http://HOST:8080/remoting/AccountService'`. + +Alternatively, create a `HessianServiceExporter` in your root application context (e.g. +in `'WEB-INF/applicationContext.xml'`): + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + +---- + +In the latter case, define a corresponding servlet for this exporter in `'web.xml'`, +with the same end result: The exporter getting mapped to the request path +`/remoting/AccountService`. Note that the servlet name needs to match the bean name of +the target exporter. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + accountExporter + org.springframework.web.context.support.HttpRequestHandlerServlet + + + + accountExporter + /remoting/AccountService + +---- + + + +[[remoting-caucho-protocols-hessian-client]] +==== Linking in the service on the client +Using the `HessianProxyFactoryBean` we can link in the service at the client. The same +principles apply as with the RMI example. We'll create a separate bean factory or +application context and mention the following beans where the `SimpleObject` is using +the `AccountService` to manage accounts: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + +---- + + + +[[remoting-caucho-protocols-burlap]] +==== Using Burlap +We won't discuss Burlap, the XML-based equivalent of Hessian, in detail here, since it +is configured and set up in exactly the same way as the Hessian variant explained above. +Just replace the word `Hessian` with `Burlap` and you're all set to go. + + + +[[remoting-caucho-protocols-security]] +==== Applying HTTP basic authentication to a service exposed through Hessian or Burlap +One of the advantages of Hessian and Burlap is that we can easily apply HTTP basic +authentication, because both protocols are HTTP-based. Your normal HTTP server security +mechanism can easily be applied through using the `web.xml` security features, for +example. Usually, you don't use per-user security credentials here, but rather shared +credentials defined at the `Hessian/BurlapProxyFactoryBean` level (similar to a JDBC +`DataSource`). + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + +---- + +This is an example where we explicitly mention the `BeanNameUrlHandlerMapping` and set +an interceptor allowing only administrators and operators to call the beans mentioned in +this application context. + +[NOTE] +==== +Of course, this example doesn't show a flexible kind of security infrastructure. For +more options as far as security is concerned, have a look at the Spring Security project +at http://projects.spring.io/spring-security/[]. +==== + + + + +[[remoting-httpinvoker]] +=== Exposing services using HTTP invokers +As opposed to Burlap and Hessian, which are both lightweight protocols using their own +slim serialization mechanisms, Spring HTTP invokers use the standard Java serialization +mechanism to expose services through HTTP. This has a huge advantage if your arguments +and return types are complex types that cannot be serialized using the serialization +mechanisms Hessian and Burlap use (refer to the next section for more considerations +when choosing a remoting technology). + +Under the hood, Spring uses either the standard facilities provided by the JDK or +Apache `HttpComponents` to perform HTTP calls. Use the latter if you need more +advanced and easier-to-use functionality. Refer to +http://hc.apache.org/httpcomponents-client-ga/[hc.apache.org/httpcomponents-client-ga/] +for more information. + + + +[[remoting-httpinvoker-server]] +==== Exposing the service object +Setting up the HTTP invoker infrastructure for a service object resembles closely the +way you would do the same using Hessian or Burlap. Just as Hessian support provides the +`HessianServiceExporter`, Spring's HttpInvoker support provides the +`org.springframework.remoting.httpinvoker.HttpInvokerServiceExporter`. + +To expose the `AccountService` (mentioned above) within a Spring Web MVC +`DispatcherServlet`, the following configuration needs to be in place in the +dispatcher's application context: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + +---- + +Such an exporter definition will be exposed through the `DispatcherServlet`'s standard +mapping facilities, as explained in the section on Hessian. + +Alternatively, create an `HttpInvokerServiceExporter` in your root application context +(e.g. in `'WEB-INF/applicationContext.xml'`): + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + +---- + +In addition, define a corresponding servlet for this exporter in `'web.xml'`, with the +servlet name matching the bean name of the target exporter: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + accountExporter + org.springframework.web.context.support.HttpRequestHandlerServlet + + + + accountExporter + /remoting/AccountService + +---- + +If you are running outside of a servlet container and are using Oracle's Java 6, then you +can use the built-in HTTP server implementation. You can configure the +`SimpleHttpServerFactoryBean` together with a `SimpleHttpInvokerServiceExporter` as is +shown in this example: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + + + + + + +---- + + + +[[remoting-httpinvoker-client]] +==== Linking in the service at the client +Again, linking in the service from the client much resembles the way you would do it +when using Hessian or Burlap. Using a proxy, Spring will be able to translate your calls +to HTTP POST requests to the URL pointing to the exported service. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + +---- + +As mentioned before, you can choose what HTTP client you want to use. By default, the +`HttpInvokerProxy` uses the JDK's HTTP functionality, but you can also use the Apache +`HttpComponents` client by setting the `httpInvokerRequestExecutor` property: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + +---- + + + + +[[remoting-web-services]] +=== Web services +Spring provides full support for standard Java web services APIs: + +* Exposing web services using JAX-WS +* Accessing web services using JAX-WS + +In addition to stock support for JAX-WS in Spring Core, the Spring portfolio also +features http://www.springframework.org/spring-ws[Spring Web Services], a solution for +contract-first, document-driven web services - highly recommended for building modern, +future-proof web services. + + + +[[remoting-web-services-jaxws-export-servlet]] +==== Exposing servlet-based web services using JAX-WS +Spring provides a convenient base class for JAX-WS servlet endpoint implementations - +`SpringBeanAutowiringSupport`. To expose our `AccountService` we extend Spring's +`SpringBeanAutowiringSupport` class and implement our business logic here, usually +delegating the call to the business layer. We'll simply use Spring's `@Autowired` +annotation for expressing such dependencies on Spring-managed beans. + +[source,java,indent=0] +---- + /** + * JAX-WS compliant AccountService implementation that simply delegates + * to the AccountService implementation in the root web application context. + * + * This wrapper class is necessary because JAX-WS requires working with dedicated + * endpoint classes. If an existing service needs to be exported, a wrapper that + * extends SpringBeanAutowiringSupport for simple Spring bean autowiring (through + * the @Autowired annotation) is the simplest JAX-WS compliant way. + * + * This is the class registered with the server-side JAX-WS implementation. + * In the case of a Java EE 5 server, this would simply be defined as a servlet + * in web.xml, with the server detecting that this is a JAX-WS endpoint and reacting + * accordingly. The servlet name usually needs to match the specified WS service name. + * + * The web service engine manages the lifecycle of instances of this class. + * Spring bean references will just be wired in here. + */ + import org.springframework.web.context.support.SpringBeanAutowiringSupport; + + @WebService(serviceName="AccountService") + public class AccountServiceEndpoint extends SpringBeanAutowiringSupport { + + @Autowired + private AccountService biz; + + @WebMethod + public void insertAccount(Account acc) { + biz.insertAccount(acc); + } + + @WebMethod + public Account[] getAccounts(String name) { + return biz.getAccounts(name); + } + + } +---- + +Our `AccountServletEndpoint` needs to run in the same web application as the Spring +context to allow for access to Spring's facilities. This is the case by default in Java +EE 5 environments, using the standard contract for JAX-WS servlet endpoint deployment. +See Java EE 5 web service tutorials for details. + + + +[[remoting-web-services-jaxws-export-standalone]] +==== Exporting standalone web services using JAX-WS +The built-in JAX-WS provider that comes with Oracle's JDK 1.6 supports exposure of web +services using the built-in HTTP server that's included in JDK 1.6 as well. Spring's +`SimpleJaxWsServiceExporter` detects all `@WebService` annotated beans in the Spring +application context, exporting them through the default JAX-WS server (the JDK 1.6 HTTP +server). + +In this scenario, the endpoint instances are defined and managed as Spring beans +themselves; they will be registered with the JAX-WS engine but their lifecycle will be +up to the Spring application context. This means that Spring functionality like explicit +dependency injection may be applied to the endpoint instances. Of course, +annotation-driven injection through `@Autowired` will work as well. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + ... + + + ... +---- + +The `AccountServiceEndpoint` may derive from Spring's `SpringBeanAutowiringSupport` but +doesn't have to since the endpoint is a fully Spring-managed bean here. This means that +the endpoint implementation may look like as follows, without any superclass declared - +and Spring's `@Autowired` configuration annotation still being honored: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @WebService(serviceName="AccountService") + public class AccountServiceEndpoint { + + @Autowired + private AccountService biz; + + @WebMethod + public void insertAccount(Account acc) { + biz.insertAccount(acc); + } + + @WebMethod + public List getAccounts(String name) { + return biz.getAccounts(name); + } + + } +---- + + + +[[remoting-web-services-jaxws-export-ri]] +==== Exporting web services using the JAX-WS RI's Spring support +Oracle's JAX-WS RI, developed as part of the GlassFish project, ships Spring support as +part of its JAX-WS Commons project. This allows for defining JAX-WS endpoints as +Spring-managed beans, similar to the standalone mode discussed in the previous section - +but this time in a Servlet environment. __Note that this is not portable in a Java EE 5 +environment; it is mainly intended for non-EE environments such as Tomcat, embedding the +JAX-WS RI as part of the web application.__ + +The difference to the standard style of exporting servlet-based endpoints is that the +lifecycle of the endpoint instances themselves will be managed by Spring here, and that +there will be only one JAX-WS servlet defined in `web.xml`. With the standard Java EE 5 +style (as illustrated above), you'll have one servlet definition per service endpoint, +with each endpoint typically delegating to Spring beans (through the use of +`@Autowired`, as shown above). + +Check out https://jax-ws-commons.java.net/spring/[https://jax-ws-commons.java.net/spring/] +for details on setup and usage style. + + + +[[remoting-web-services-jaxws-access]] +==== Accessing web services using JAX-WS +Spring provides two factory beans to create JAX-WS web service proxies, namely +`LocalJaxWsServiceFactoryBean` and `JaxWsPortProxyFactoryBean`. The former can only +return a JAX-WS service class for us to work with. The latter is the full-fledged +version that can return a proxy that implements our business service interface. In this +example we use the latter to create a proxy for the `AccountService` endpoint (again): + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + +---- + +Where `serviceInterface` is our business interface the clients will use. +`wsdlDocumentUrl` is the URL for the WSDL file. Spring needs this a startup time to +create the JAX-WS Service. `namespaceUri` corresponds to the targetNamespace in the +.wsdl file. `serviceName` corresponds to the service name in the .wsdl file. `portName` +corresponds to the port name in the .wsdl file. + +Accessing the web service is now very easy as we have a bean factory for it that will +expose it as `AccountService` interface. We can wire this up in Spring: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + ... + + +---- + +From the client code we can access the web service just as if it was a normal class: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class AccountClientImpl { + + private AccountService service; + + public void setService(AccountService service) { + this.service = service; + } + + public void foo() { + service.insertAccount(...); + } + } +---- + +[NOTE] +==== +The above is slightly simplified in that JAX-WS requires endpoint interfaces +and implementation classes to be annotated with `@WebService`, `@SOAPBinding` etc +annotations. This means that you cannot (easily) use plain Java interfaces and +implementation classes as JAX-WS endpoint artifacts; you need to annotate them +accordingly first. Check the JAX-WS documentation for details on those requirements. +==== + + + + +[[remoting-jms]] +=== JMS +It is also possible to expose services transparently using JMS as the underlying +communication protocol. The JMS remoting support in the Spring Framework is pretty basic +- it sends and receives on the `same thread` and in the __same non-transactional__ +`Session`, and as such throughput will be very implementation dependent. Note that these +single-threaded and non-transactional constraints apply only to Spring's JMS +__remoting__ support. See <> for information on Spring's rich support for JMS-based +__messaging__. + +The following interface is used on both the server and the client side. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + package com.foo; + + public interface CheckingAccountService { + + public void cancelAccount(Long accountId); + + } +---- + +The following simple implementation of the above interface is used on the server-side. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + package com.foo; + + public class SimpleCheckingAccountService implements CheckingAccountService { + + public void cancelAccount(Long accountId) { + System.out.println("Cancelling account [" + accountId + "]"); + } + + } +---- + +This configuration file contains the JMS-infrastructure beans that are shared on both +the client and server. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + + + + + +---- + + + +[[remoting-jms-server]] +==== Server-side configuration +On the server, you just need to expose the service object using the +`JmsInvokerServiceExporter`. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + + + + + + + + + + + +---- + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + package com.foo; + + import org.springframework.context.support.ClassPathXmlApplicationContext; + + public class Server { + + public static void main(String[] args) throws Exception { + new ClassPathXmlApplicationContext(new String[]{"com/foo/server.xml", "com/foo/jms.xml"}); + } + + } +---- + + + +[[remoting-jms-client]] +==== Client-side configuration +The client merely needs to create a client-side proxy that will implement the agreed +upon interface ( `CheckingAccountService`). The resulting object created off the back of +the following bean definition can be injected into other client side objects, and the +proxy will take care of forwarding the call to the server-side object via JMS. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + + + +---- + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + package com.foo; + + import org.springframework.context.ApplicationContext; + import org.springframework.context.support.ClassPathXmlApplicationContext; + + public class Client { + + public static void main(String[] args) throws Exception { + ApplicationContext ctx = new ClassPathXmlApplicationContext( + new String[] {"com/foo/client.xml", "com/foo/jms.xml"}); + CheckingAccountService service = (CheckingAccountService) ctx.getBean("checkingAccountService"); + service.cancelAccount(new Long(10)); + } + + } +---- + +You may also wish to investigate the support provided by the +http://lingo.codehaus.org/[Lingo] project, which (to quote the homepage blurb) "__... is +a lightweight POJO based remoting and messaging library based on the Spring Framework's +remoting libraries which extends it to support JMS.__" + + + + +[[remoting-amqp]] +=== AMQP +Refer to the http://docs.spring.io/spring-amqp/reference/html/amqp.html#remoting[Spring +AMQP Reference Document 'Spring Remoting with AMQP' section] for more information. + + + + +[[remoting-autodection-remote-interfaces]] +=== Auto-detection is not implemented for remote interfaces +The main reason why auto-detection of implemented interfaces does not occur for remote +interfaces is to avoid opening too many doors to remote callers. The target object might +implement internal callback interfaces like `InitializingBean` or `DisposableBean` which +one would not want to expose to callers. + +Offering a proxy with all interfaces implemented by the target usually does not matter +in the local case. But when exporting a remote service, you should expose a specific +service interface, with specific operations intended for remote usage. Besides internal +callback interfaces, the target might implement multiple business interfaces, with just +one of them intended for remote exposure. For these reasons, we __require__ such a +service interface to be specified. + +This is a trade-off between configuration convenience and the risk of accidental +exposure of internal methods. Always specifying a service interface is not too much +effort, and puts you on the safe side regarding controlled exposure of specific methods. + + + + +[[remoting-considerations]] +=== Considerations when choosing a technology +Each and every technology presented here has its drawbacks. You should carefully +consider your needs, the services you are exposing and the objects you'll be sending +over the wire when choosing a technology. + +When using RMI, it's not possible to access the objects through the HTTP protocol, +unless you're tunneling the RMI traffic. RMI is a fairly heavy-weight protocol in that +it supports full-object serialization which is important when using a complex data model +that needs serialization over the wire. However, RMI-JRMP is tied to Java clients: It is +a Java-to-Java remoting solution. + +Spring's HTTP invoker is a good choice if you need HTTP-based remoting but also rely on +Java serialization. It shares the basic infrastructure with RMI invokers, just using +HTTP as transport. Note that HTTP invokers are not only limited to Java-to-Java remoting +but also to Spring on both the client and server side. (The latter also applies to +Spring's RMI invoker for non-RMI interfaces.) + +Hessian and/or Burlap might provide significant value when operating in a heterogeneous +environment, because they explicitly allow for non-Java clients. However, non-Java +support is still limited. Known issues include the serialization of Hibernate objects in +combination with lazily-initialized collections. If you have such a data model, consider +using RMI or HTTP invokers instead of Hessian. + +JMS can be useful for providing clusters of services and allowing the JMS broker to take +care of load balancing, discovery and auto-failover. By default: Java serialization is +used when using JMS remoting but the JMS provider could use a different mechanism for +the wire formatting, such as XStream to allow servers to be implemented in other +technologies. + +Last but not least, EJB has an advantage over RMI in that it supports standard +role-based authentication and authorization and remote transaction propagation. It is +possible to get RMI invokers or HTTP invokers to support security context propagation as +well, although this is not provided by core Spring: There are just appropriate hooks for +plugging in third-party or custom solutions here. + + + + +[[rest-client-access]] +=== Accessing RESTful services on the Client +The `RestTemplate` is the core class for client-side access to RESTful services. It is +conceptually similar to other template classes in Spring, such as `JdbcTemplate` and +`JmsTemplate` and other template classes found in other Spring portfolio projects. +`RestTemplate`'s behavior is customized by providing callback methods and configuring +the `HttpMessageConverter` used to marshal objects into the HTTP request body and to +unmarshal any response back into an object. As it is common to use XML as a message +format, Spring provides a `MarshallingHttpMessageConverter` that uses the Object-to-XML +framework that is part of the `org.springframework.oxm` package. This gives you a wide +range of choices of XML to Object mapping technologies to choose from. + +This section describes how to use the `RestTemplate` and its associated +`HttpMessageConverters`. + + + +[[rest-resttemplate]] +==== RestTemplate +Invoking RESTful services in Java is typically done using a helper class such as Apache +HttpComponents `HttpClient`. For common REST operations this approach is too low level as +shown below. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + String uri = "http://example.com/hotels/1/bookings"; + + PostMethod post = new PostMethod(uri); + String request = // create booking request content + post.setRequestEntity(new StringRequestEntity(request)); + + httpClient.executeMethod(post); + + if (HttpStatus.SC_CREATED == post.getStatusCode()) { + Header location = post.getRequestHeader("Location"); + if (location != null) { + System.out.println("Created new booking at :" + location.getValue()); + } + } +---- + +RestTemplate provides higher level methods that correspond to each of the six main HTTP +methods that make invoking many RESTful services a one-liner and enforce REST best +practices. + + +[NOTE] +==== +RestTemplate has an asynchronous counter-part: see <>. +==== + +[[rest-overview-of-resttemplate-methods-tbl]] +.Overview of RestTemplate methods +[cols="1,3"] +|=== +| HTTP Method | RestTemplate Method + +| DELETE +| {javadoc-baseurl}/org/springframework/web/client/RestTemplate.html#delete(String,%20Object...)[delete] + +| GET +| {javadoc-baseurl}/org/springframework/web/client/RestTemplate.html#getForObject(String,%20Class,%20Object...)[getForObject] + {javadoc-baseurl}/org/springframework/web/client/RestTemplate.html#getForEntity(String,%20Class,%20Object...)[getForEntity] + +| HEAD +| {javadoc-baseurl}/org/springframework/web/client/RestTemplate.html#headForHeaders(String,%20Object...)[headForHeaders(String + url, String... urlVariables)] + +| OPTIONS +| {javadoc-baseurl}/org/springframework/web/client/RestTemplate.html#optionsForAllow(String,%20Object...)[optionsForAllow(String + url, String... urlVariables)] + +| POST +| {javadoc-baseurl}/org/springframework/web/client/RestTemplate.html#postForLocation(String,%20Object,%20Object...)[postForLocation(String + url, Object request, String... urlVariables)] + {javadoc-baseurl}/org/springframework/web/client/RestTemplate.html#postForObject(java.lang.String,%20java.lang.Object,%20java.lang.Class,%20java.lang.String...)[postForObject(String + url, Object request, Class responseType, String... uriVariables)] + +| PUT +| {javadoc-baseurl}/org/springframework/web/client/RestTemplate.html#put(String,%20Object,%20Object...)[put(String + url, Object request, String...urlVariables)] + +| PATCH and others +| {javadoc-baseurl}/org/springframework/web/client/RestTemplate.html#exchange(java.lang.String,%20org.springframework.http.HttpMethod,%20org.springframework.http.HttpEntity,%20java.lang.Class,%20java.lang.Object...)[exchange] + {javadoc-baseurl}/org/springframework/web/client/RestTemplate.html#execute(java.lang.String,%20org.springframework.http.HttpMethod,%20org.springframework.web.client.RequestCallback,%20org.springframework.web.client.ResponseExtractor,%20java.lang.Object...)[execute] +|=== + +The names of `RestTemplate` methods follow a naming convention, the first part indicates +what HTTP method is being invoked and the second part indicates what is returned. For +example, the method `getForObject()` will perform a GET, convert the HTTP response into +an object type of your choice and return that object. The method `postForLocation()` +will do a POST, converting the given object into a HTTP request and return the response +HTTP Location header where the newly created object can be found. In case of an +exception processing the HTTP request, an exception of the type `RestClientException` +will be thrown; this behavior can be changed by plugging in another +`ResponseErrorHandler` implementation into the `RestTemplate`. + +The `exchange` and `execute` methods are generalized versions of the more +specific methods listed above them and can support additional combinations and methods, +like HTTP PATCH. However, note that the underlying HTTP library must also support the +desired combination. The JDK `HttpURLConnection` does not support the `PATCH` method, but +Apache HttpComponents HttpClient version 4.2 or later does. They also enable +`RestTemplate` to read an HTTP response to a generic type (e.g. `List`), using a +`ParameterizedTypeReference`, a new class that enables capturing and passing generic +type info. + +Objects passed to and returned from these methods are converted to and from HTTP +messages by `HttpMessageConverter` instances. Converters for the main mime types are +registered by default, but you can also write your own converter and register it via the +`messageConverters()` bean property. The default converter instances registered with the +template are `ByteArrayHttpMessageConverter`, `StringHttpMessageConverter`, +`FormHttpMessageConverter` and `SourceHttpMessageConverter`. You can override these +defaults using the `messageConverters()` bean property as would be required if using the +`MarshallingHttpMessageConverter` or `MappingJackson2HttpMessageConverter`. + +Each method takes URI template arguments in two forms, either as a `String` variable +length argument or a `Map`. For example, + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + String result = restTemplate.getForObject( + "http://example.com/hotels/{hotel}/bookings/{booking}", String.class,"42", "21"); +---- + +using variable length arguments and + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + Map vars = Collections.singletonMap("hotel", "42"); + String result = restTemplate.getForObject( + "http://example.com/hotels/{hotel}/rooms/{hotel}", String.class, vars); +---- + +using a `Map`. + +To create an instance of `RestTemplate` you can simply call the default no-arg +constructor. This will use standard Java classes from the `java.net` package as the +underlying implementation to create HTTP requests. This can be overridden by specifying +an implementation of `ClientHttpRequestFactory`. Spring provides the implementation +`HttpComponentsClientHttpRequestFactory` that uses the Apache HttpComponents +`HttpClient` to create requests. `HttpComponentsClientHttpRequestFactory` is configured +using an instance of `org.apache.http.client.HttpClient` which can in turn be configured +with credentials information or connection pooling functionality. + +[TIP] +==== +Note that the `java.net` implementation for HTTP requests may raise an exception when +accessing the status of a response that represents an error (e.g. 401). If this is an +issue, switch to `HttpComponentsClientHttpRequestFactory` instead. +==== +The previous example using Apache HttpComponents `HttpClient` directly rewritten to use +the `RestTemplate` is shown below + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + uri = "http://example.com/hotels/{id}/bookings"; + + RestTemplate template = new RestTemplate(); + + Booking booking = // create booking object + + URI location = template.postForLocation(uri, booking, "1"); +---- + +To use Apache HttpComponents instead of the native `java.net` functionality, construct +the `RestTemplate` as follows: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + RestTemplate template = new RestTemplate(new HttpComponentsClientHttpRequestFactory()); +---- + +[TIP] +==== +Apache HttpClient supports gzip encoding. To use it, +construct a `HttpComponentsClientHttpRequestFactory` like so: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + HttpClient httpClient = HttpClientBuilder.create().build(); + ClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(httpClient); + RestTemplate restTemplate = new RestTemplate(requestFactory); +---- +==== +The general callback interface is `RequestCallback` and is called when the execute +method is invoked. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public T execute(String url, HttpMethod method, RequestCallback requestCallback, + ResponseExtractor responseExtractor, String... urlVariables) + + // also has an overload with urlVariables as a Map. +---- + +The `RequestCallback` interface is defined as + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public interface RequestCallback { + void doWithRequest(ClientHttpRequest request) throws IOException; + } +---- + +and allows you to manipulate the request headers and write to the request body. When +using the execute method you do not have to worry about any resource management, the +template will always close the request and handle any errors. Refer to the API +documentation for more information on using the execute method and the meaning of its +other method arguments. + + +[[rest-resttemplate-uri]] +===== Working with the URI +For each of the main HTTP methods, the `RestTemplate` provides variants that either take +a String URI or `java.net.URI` as the first argument. + +The String URI variants accept template arguments as a String variable length argument +or as a `Map`. They also assume the URL String is not encoded and needs +to be encoded. For example the following: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + restTemplate.getForObject("http://example.com/hotel list", String.class); +---- + +will perform a GET on `http://example.com/hotel%20list`. That means if the input URL +String is already encoded, it will be encoded twice -- i.e. +`http://example.com/hotel%20list` will become `http://example.com/hotel%2520list`. If +this is not the intended effect, use the `java.net.URI` method variant, which assumes +the URL is already encoded is also generally useful if you want to reuse a single (fully +expanded) `URI` multiple times. + +The `UriComponentsBuilder` class can be used to build and encode the `URI` including +support for URI templates. For example you can start with a URL String: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + UriComponents uriComponents = UriComponentsBuilder.fromUriString( + "http://example.com/hotels/{hotel}/bookings/{booking}").build() + .expand("42", "21") + .encode(); + + URI uri = uriComponents.toUri(); +---- + +Or specify each URI component individually: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + UriComponents uriComponents = UriComponentsBuilder.newInstance() + .scheme("http").host("example.com").path("/hotels/{hotel}/bookings/{booking}").build() + .expand("42", "21") + .encode(); + + URI uri = uriComponents.toUri(); +---- + + +[[rest-template-headers]] +===== Dealing with request and response headers +Besides the methods described above, the `RestTemplate` also has the `exchange()` +method, which can be used for arbitrary HTTP method execution based on the `HttpEntity` +class. + +Perhaps most importantly, the `exchange()` method can be used to add request headers and +read response headers. For example: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + HttpHeaders requestHeaders = new HttpHeaders(); + requestHeaders.set("MyRequestHeader", "MyValue"); + HttpEntity requestEntity = new HttpEntity(requestHeaders); + + HttpEntity response = template.exchange( + "http://example.com/hotels/{hotel}", + HttpMethod.GET, requestEntity, String.class, "42"); + + String responseHeader = response.getHeaders().getFirst("MyResponseHeader"); + String body = response.getBody(); +---- + +In the above example, we first prepare a request entity that contains the +`MyRequestHeader` header. We then retrieve the response, and read the `MyResponseHeader` +and body. + +[[rest-template-jsonview]] +===== Jackson JSON Views support + +It is possible to specify a http://wiki.fasterxml.com/JacksonJsonViews[Jackson JSON View] +to serialize only a subset of the object properties. For example: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + JacksonSerializationValue jsv = new JacksonSerializationValue(new User("eric", "7!jd#h23"), + User.WithoutPasswordView.class); + HttpEntity entity = new HttpEntity(jsv); + String s = template.postForObject("http://example.com/user", entity, String.class); +---- + + +[[rest-message-conversion]] +==== HTTP Message Conversion +Objects passed to and returned from the methods `getForObject()`, `postForLocation()`, +and `put()` are converted to HTTP requests and from HTTP responses by +`HttpMessageConverters`. The `HttpMessageConverter` interface is shown below to give you +a better feel for its functionality + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public interface HttpMessageConverter { + + // Indicate whether the given class and media type can be read by this converter. + boolean canRead(Class clazz, MediaType mediaType); + + // Indicate whether the given class and media type can be written by this converter. + boolean canWrite(Class clazz, MediaType mediaType); + + // Return the list of MediaType objects supported by this converter. + List getSupportedMediaTypes(); + + // Read an object of the given type from the given input message, and returns it. + T read(Class clazz, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException; + + // Write an given object to the given output message. + void write(T t, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException; + + } +---- + +Concrete implementations for the main media (mime) types are provided in the framework +and are registered by default with the `RestTemplate` on the client-side and with +`AnnotationMethodHandlerAdapter` on the server-side. + +The implementations of ++HttpMessageConverter++s are described in the following sections. +For all converters a default media type is used but can be overridden by setting the +`supportedMediaTypes` bean property + + +[[rest-string-converter]] +===== StringHttpMessageConverter +An `HttpMessageConverter` implementation that can read and write Strings from the HTTP +request and response. By default, this converter supports all text media types ( +`text/*`), and writes with a `Content-Type` of `text/plain`. + + +[[rest-form-converter]] +===== FormHttpMessageConverter +An `HttpMessageConverter` implementation that can read and write form data from the HTTP +request and response. By default, this converter reads and writes the media type +`application/x-www-form-urlencoded`. Form data is read from and written into a +`MultiValueMap`. + + +[[rest-byte-converter]] +===== ByteArrayHttpMessageConverter +An `HttpMessageConverter` implementation that can read and write byte arrays from the +HTTP request and response. By default, this converter supports all media types ( `*/*`), +and writes with a `Content-Type` of `application/octet-stream`. This can be overridden +by setting the `supportedMediaTypes` property, and overriding `getContentType(byte[])`. + + +[[rest-marhsalling-converter]] +===== MarshallingHttpMessageConverter +An `HttpMessageConverter` implementation that can read and write XML using Spring's +`Marshaller` and `Unmarshaller` abstractions from the `org.springframework.oxm` package. +This converter requires a `Marshaller` and `Unmarshaller` before it can be used. These +can be injected via constructor or bean properties. By default this converter supports ( +`text/xml`) and ( `application/xml`). + + +[[rest-mapping-json-converter]] +===== MappingJackson2HttpMessageConverter +An `HttpMessageConverter` implementation that can read and write JSON using Jackson's +`ObjectMapper`. JSON mapping can be customized as needed through the use of Jackson's +provided annotations. When further control is needed, a custom `ObjectMapper` can be +injected through the `ObjectMapper` property for cases where custom JSON +serializers/deserializers need to be provided for specific types. By default this +converter supports ( `application/json`). + + +[[rest-mapping-xml-converter]] +===== MappingJackson2XmlHttpMessageConverter +An `HttpMessageConverter` implementation that can read and write XML using +https://github.com/FasterXML/jackson-dataformat-xml[Jackson XML] extension's +`XmlMapper`. XML mapping can be customized as needed through the use of JAXB +or Jackson's provided annotations. When further control is needed, a custom `XmlMapper` +can be injected through the `ObjectMapper` property for cases where custom XML +serializers/deserializers need to be provided for specific types. By default this +converter supports ( `application/xml`). + + +[[rest-source-converter]] +===== SourceHttpMessageConverter +An `HttpMessageConverter` implementation that can read and write +`javax.xml.transform.Source` from the HTTP request and response. Only `DOMSource`, +`SAXSource`, and `StreamSource` are supported. By default, this converter supports ( +`text/xml`) and ( `application/xml`). + + +[[rest-buffered-image-converter]] +===== BufferedImageHttpMessageConverter +An `HttpMessageConverter` implementation that can read and write +`java.awt.image.BufferedImage` from the HTTP request and response. This converter reads +and writes the media type supported by the Java I/O API. + +[[rest-async-resttemplate]] +==== Async RestTemplate + +Web applications often need to query external REST services those days. The very nature of +HTTP and synchronous calls can lead up to challenges when scaling applications for those +needs: multiple threads may be blocked, waiting for remote HTTP responses. + +`AsyncRestTemplate` and <>'s APIs are very similar; see +<>. The main difference between those APIs is +that `AsyncRestTemplate` returns +{javadoc-baseurl}/org/springframework/util/concurrent/ListenableFuture.html[`ListenableFuture`] +wrappers as opposed to concrete results. + +The previous `RestTemplate` example translates to: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + // async call + Future> futureEntity = template.getForEntity( + "http://example.com/hotels/{hotel}/bookings/{booking}", String.class, "42", "21"); + + // get the concrete result - synchronous call + ResponseEntity entity = futureEntity.get(); +---- + +{javadoc-baseurl}/org/springframework/util/concurrent/ListenableFuture.html[`ListenableFuture`] +accepts completion callbacks: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + ListenableFuture> futureEntity = template.getForEntity( + "http://example.com/hotels/{hotel}/bookings/{booking}", String.class, "42", "21"); + + // register a callback + futureEntity.addCallback(new ListenableFutureCallback>() { + @Override + public void onSuccess(ResponseEntity entity) { + //... + } + + @Override + public void onFailure(Throwable t) { + //... + } + }); +---- + +[NOTE] +==== +The default `AsyncRestTemplate` constructor registers a +{javadoc-baseurl}/org/springframework/core/task/SimpleAsyncTaskExecutor.html[`SimpleAsyncTaskExecutor` +] for executing HTTP requests. +When dealing with a large number of short-lived requests, a thread-pooling TaskExecutor +implementation like +{javadoc-baseurl}/org/springframework/scheduling/concurrent/ThreadPoolTaskExecutor.html[`ThreadPoolTaskExecutor`] +may be a good choice. +==== + +See the +{javadoc-baseurl}/org/springframework/util/concurrent/ListenableFuture.html[`ListenableFuture` javadocs] +and +{javadoc-baseurl}/org/springframework/web/client/AsyncRestTemplate.html[`AsyncRestTemplate` javadocs] +for more details. + + + diff --git a/src/asciidoc/resources.adoc b/src/asciidoc/resources.adoc new file mode 100644 index 000000000000..7a31fadd3869 --- /dev/null +++ b/src/asciidoc/resources.adoc @@ -0,0 +1,669 @@ +[[resources]] +== Resources + + + + +[[resources-introduction]] +=== Introduction +Java's standard `java.net.URL` class and standard handlers for various URL prefixes +unfortunately are not quite adequate enough for all access to low-level resources. For +example, there is no standardized `URL` implementation that may be used to access a +resource that needs to be obtained from the classpath, or relative to a +`ServletContext`. While it is possible to register new handlers for specialized `URL` +prefixes (similar to existing handlers for prefixes such as `http:`), this is generally +quite complicated, and the `URL` interface still lacks some desirable functionality, +such as a method to check for the existence of the resource being pointed to. + + + + +[[resources-resource]] +=== The Resource interface + +Spring's `Resource` interface is meant to be a more capable interface for abstracting +access to low-level resources. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public interface Resource extends InputStreamSource { + + boolean exists(); + + boolean isOpen(); + + URL getURL() throws IOException; + + File getFile() throws IOException; + + Resource createRelative(String relativePath) throws IOException; + + String getFilename(); + + String getDescription(); + + } +---- + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public interface InputStreamSource { + + InputStream getInputStream() throws IOException; + + } +---- + +Some of the most important methods from the `Resource` interface are: + +* `getInputStream()`: locates and opens the resource, returning an `InputStream` for + reading from the resource. It is expected that each invocation returns a fresh + `InputStream`. It is the responsibility of the caller to close the stream. +* `exists()`: returns a `boolean` indicating whether this resource actually exists in + physical form. +* `isOpen()`: returns a `boolean` indicating whether this resource represents a handle + with an open stream. If `true`, the `InputStream` cannot be read multiple times, and + must be read once only and then closed to avoid resource leaks. Will be `false` for + all usual resource implementations, with the exception of `InputStreamResource`. +* `getDescription()`: returns a description for this resource, to be used for error + output when working with the resource. This is often the fully qualified file name or + the actual URL of the resource. + +Other methods allow you to obtain an actual `URL` or `File` object representing the +resource (if the underlying implementation is compatible, and supports that +functionality). + +The `Resource` abstraction is used extensively in Spring itself, as an argument type in +many method signatures when a resource is needed. Other methods in some Spring APIs +(such as the constructors to various `ApplicationContext` implementations), take a +`String` which in unadorned or simple form is used to create a `Resource` appropriate to +that context implementation, or via special prefixes on the `String` path, allow the +caller to specify that a specific `Resource` implementation must be created and used. + +While the `Resource` interface is used a lot with Spring and by Spring, it's actually +very useful to use as a general utility class by itself in your own code, for access to +resources, even when your code doesn't know or care about any other parts of Spring. +While this couples your code to Spring, it really only couples it to this small set of +utility classes, which are serving as a more capable replacement for `URL`, and can be +considered equivalent to any other library you would use for this purpose. + +It is important to note that the `Resource` abstraction does not replace functionality: +it wraps it where possible. For example, a `UrlResource` wraps a URL, and uses the +wrapped `URL` to do its work. + + + + +[[resources-implementations]] +=== Built-in Resource implementations + +There are a number of `Resource` implementations that come supplied straight out of the +box in Spring: + + + +[[resources-implementations-urlresource]] +==== UrlResource + +The `UrlResource` wraps a `java.net.URL`, and may be used to access any object that is +normally accessible via a URL, such as files, an HTTP target, an FTP target, etc. All +URLs have a standardized `String` representation, such that appropriate standardized +prefixes are used to indicate one URL type from another. This includes `file:` for +accessing filesystem paths, `http:` for accessing resources via the HTTP protocol, +`ftp:` for accessing resources via FTP, etc. + +A `UrlResource` is created by Java code explicitly using the `UrlResource` constructor, +but will often be created implicitly when you call an API method which takes a `String` +argument which is meant to represent a path. For the latter case, a JavaBeans +`PropertyEditor` will ultimately decide which type of `Resource` to create. If the path +string contains a few well-known (to it, that is) prefixes such as `classpath:`, it will +create an appropriate specialized `Resource` for that prefix. However, if it doesn't +recognize the prefix, it will assume the this is just a standard URL string, and will +create a `UrlResource`. + + + +[[resources-implementations-classpathresource]] +==== ClassPathResource + +This class represents a resource which should be obtained from the classpath. This uses +either the thread context class loader, a given class loader, or a given class for +loading resources. + +This `Resource` implementation supports resolution as `java.io.File` if the class path +resource resides in the file system, but not for classpath resources which reside in a +jar and have not been expanded (by the servlet engine, or whatever the environment is) +to the filesystem. To address this the various `Resource` implementations always support +resolution as a `java.net.URL`. + +A `ClassPathResource` is created by Java code explicitly using the `ClassPathResource` +constructor, but will often be created implicitly when you call an API method which +takes a `String` argument which is meant to represent a path. For the latter case, a +JavaBeans `PropertyEditor` will recognize the special prefix `classpath:` on the string +path, and create a `ClassPathResource` in that case. + + + +[[resources-implementations-filesystemresource]] +==== FileSystemResource + +This is a `Resource` implementation for `java.io.File` handles. It obviously supports +resolution as a `File`, and as a `URL`. + + + +[[resources-implementations-servletcontextresource]] +==== ServletContextResource + +This is a `Resource` implementation for `ServletContext` resources, interpreting +relative paths within the relevant web application's root directory. + +This always supports stream access and URL access, but only allows `java.io.File` access +when the web application archive is expanded and the resource is physically on the +filesystem. Whether or not it's expanded and on the filesystem like this, or accessed +directly from the JAR or somewhere else like a DB (it's conceivable) is actually +dependent on the Servlet container. + + + +[[resources-implementations-inputstreamresource]] +==== InputStreamResource + +A `Resource` implementation for a given `InputStream`. This should only be used if no +specific `Resource` implementation is applicable. In particular, prefer +`ByteArrayResource` or any of the file-based `Resource` implementations where possible. + +In contrast to other `Resource` implementations, this is a descriptor for an __already__ +opened resource - therefore returning `true` from `isOpen()`. Do not use it if you need +to keep the resource descriptor somewhere, or if you need to read a stream multiple +times. + + + +[[resources-implementations-bytearrayresource]] +==== ByteArrayResource + +This is a `Resource` implementation for a given byte array. It creates a +`ByteArrayInputStream` for the given byte array. + +It's useful for loading content from any given byte array, without having to resort to a +single-use `InputStreamResource`. + + + + +[[resources-resourceloader]] +=== The ResourceLoader + +The `ResourceLoader` interface is meant to be implemented by objects that can return +(i.e. load) `Resource` instances. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public interface ResourceLoader { + + Resource getResource(String location); + + } +---- + +All application contexts implement the `ResourceLoader` interface, and therefore all +application contexts may be used to obtain `Resource` instances. + +When you call `getResource()` on a specific application context, and the location path +specified doesn't have a specific prefix, you will get back a `Resource` type that is +appropriate to that particular application context. For example, assume the following +snippet of code was executed against a `ClassPathXmlApplicationContext` instance: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + Resource template = ctx.getResource("some/resource/path/myTemplate.txt"); +---- + +What would be returned would be a `ClassPathResource`; if the same method was executed +against a `FileSystemXmlApplicationContext` instance, you'd get back a +`FileSystemResource`. For a `WebApplicationContext`, you'd get back a +`ServletContextResource`, and so on. + +As such, you can load resources in a fashion appropriate to the particular application +context. + +On the other hand, you may also force `ClassPathResource` to be used, regardless of the +application context type, by specifying the special `classpath:` prefix: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + Resource template = ctx.getResource("classpath:some/resource/path/myTemplate.txt"); +---- + +Similarly, one can force a `UrlResource` to be used by specifying any of the standard +`java.net.URL` prefixes: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + Resource template = ctx.getResource("file:/some/resource/path/myTemplate.txt"); +---- + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + Resource template = ctx.getResource("http://myhost.com/resource/path/myTemplate.txt"); +---- + +The following table summarizes the strategy for converting ++String++s to ++Resource++s: + +[[resources-resource-strings]] +.Resource strings +|=== +| Prefix| Example| Explanation + +| classpath: +| `classpath:com/myapp/config.xml` +| Loaded from the classpath. + +| file: +| `file:/data/config.xml` +| Loaded as a `URL`, from the filesystem. footnote:[But see also + pass:specialcharacters,macros[<>].] + +| http: +| `http://myserver/logo.png` +| Loaded as a `URL`. + +| (none) +| `/data/config.xml` +| Depends on the underlying `ApplicationContext`. +|=== + + + + +[[resources-resourceloaderaware]] +=== The ResourceLoaderAware interface + +The `ResourceLoaderAware` interface is a special marker interface, identifying objects +that expect to be provided with a `ResourceLoader` reference. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public interface ResourceLoaderAware { + + void setResourceLoader(ResourceLoader resourceLoader); + } +---- + +When a class implements `ResourceLoaderAware` and is deployed into an application +context (as a Spring-managed bean), it is recognized as `ResourceLoaderAware` by the +application context. The application context will then invoke the +`setResourceLoader(ResourceLoader)`, supplying itself as the argument (remember, all +application contexts in Spring implement the `ResourceLoader` interface). + +Of course, since an `ApplicationContext` is a `ResourceLoader`, the bean could also +implement the `ApplicationContextAware` interface and use the supplied application +context directly to load resources, but in general, it's better to use the specialized +`ResourceLoader` interface if that's all that's needed. The code would just be coupled +to the resource loading interface, which can be considered a utility interface, and not +the whole Spring `ApplicationContext` interface. + +As of Spring 2.5, you can rely upon autowiring of the `ResourceLoader` as an alternative +to implementing the `ResourceLoaderAware` interface. The "traditional" `constructor` and +`byType` autowiring modes (as described in <>) are now capable +of providing a dependency of type `ResourceLoader` for either a constructor argument or +setter method parameter respectively. For more flexibility (including the ability to +autowire fields and multiple parameter methods), consider using the new annotation-based +autowiring features. In that case, the `ResourceLoader` will be autowired into a field, +constructor argument, or method parameter that is expecting the `ResourceLoader` type as +long as the field, constructor, or method in question carries the `@Autowired` +annotation. For more information, see <>. + + + + +[[resources-as-dependencies]] +=== Resources as dependencies + +If the bean itself is going to determine and supply the resource path through some sort +of dynamic process, it probably makes sense for the bean to use the `ResourceLoader` +interface to load resources. Consider as an example the loading of a template of some +sort, where the specific resource that is needed depends on the role of the user. If the +resources are static, it makes sense to eliminate the use of the `ResourceLoader` +interface completely, and just have the bean expose the `Resource` properties it needs, +and expect that they will be injected into it. + +What makes it trivial to then inject these properties, is that all application contexts +register and use a special JavaBeans `PropertyEditor` which can convert `String` paths +to `Resource` objects. So if `myBean` has a template property of type `Resource`, it can +be configured with a simple string for that resource, as follows: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + +---- + +Note that the resource path has no prefix, so because the application context itself is +going to be used as the `ResourceLoader`, the resource itself will be loaded via a +`ClassPathResource`, `FileSystemResource`, or `ServletContextResource` (as appropriate) +depending on the exact type of the context. + +If there is a need to force a specific `Resource` type to be used, then a prefix may be +used. The following two examples show how to force a `ClassPathResource` and a +`UrlResource` (the latter being used to access a filesystem file). + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + +---- + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + +---- + + + + +[[resources-app-ctx]] +=== Application contexts and Resource paths + + + +[[resources-app-ctx-construction]] +==== Constructing application contexts +An application context constructor (for a specific application context type) generally +takes a string or array of strings as the location path(s) of the resource(s) such as +XML files that make up the definition of the context. + +When such a location path doesn't have a prefix, the specific `Resource` type built from +that path and used to load the bean definitions, depends on and is appropriate to the +specific application context. For example, if you create a +`ClassPathXmlApplicationContext` as follows: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + ApplicationContext ctx = new ClassPathXmlApplicationContext("conf/appContext.xml"); +---- + +The bean definitions will be loaded from the classpath, as a `ClassPathResource` will be +used. But if you create a `FileSystemXmlApplicationContext` as follows: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + ApplicationContext ctx = + new FileSystemXmlApplicationContext("conf/appContext.xml"); +---- + +The bean definition will be loaded from a filesystem location, in this case relative to +the current working directory. + +Note that the use of the special classpath prefix or a standard URL prefix on the +location path will override the default type of `Resource` created to load the +definition. So this `FileSystemXmlApplicationContext`... + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + ApplicationContext ctx = + new FileSystemXmlApplicationContext("classpath:conf/appContext.xml"); +---- + +... will actually load its bean definitions from the classpath. However, it is still a +`FileSystemXmlApplicationContext`. If it is subsequently used as a `ResourceLoader`, any +unprefixed paths will still be treated as filesystem paths. + + +[[resources-app-ctx-classpathxml]] +===== Constructing ClassPathXmlApplicationContext instances - shortcuts + +The `ClassPathXmlApplicationContext` exposes a number of constructors to enable +convenient instantiation. The basic idea is that one supplies merely a string array +containing just the filenames of the XML files themselves (without the leading path +information), and one __also__ supplies a `Class`; the `ClassPathXmlApplicationContext` +will derive the path information from the supplied class. + +An example will hopefully make this clear. Consider a directory layout that looks like +this: + +[literal] +[subs="verbatim,quotes"] +---- +com/ + foo/ + services.xml + daos.xml + MessengerService.class +---- + +A `ClassPathXmlApplicationContext` instance composed of the beans defined in the +`'services.xml'` and `'daos.xml'` could be instantiated like so... + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + ApplicationContext ctx = new ClassPathXmlApplicationContext( + new String[] {"services.xml", "daos.xml"}, MessengerService.class); +---- + +Please do consult the `ClassPathXmlApplicationContext` javadocs for details +on the various constructors. + + + +[[resources-app-ctx-wildcards-in-resource-paths]] +==== Wildcards in application context constructor resource paths +The resource paths in application context constructor values may be a simple path (as +shown above) which has a one-to-one mapping to a target Resource, or alternately may +contain the special "classpath*:" prefix and/or internal Ant-style regular expressions +(matched using Spring's `PathMatcher` utility). Both of the latter are effectively +wildcards + +One use for this mechanism is when doing component-style application assembly. All +components can 'publish' context definition fragments to a well-known location path, and +when the final application context is created using the same path prefixed via +`classpath*:`, all component fragments will be picked up automatically. + +Note that this wildcarding is specific to use of resource paths in application context +constructors (or when using the `PathMatcher` utility class hierarchy directly), and is +resolved at construction time. It has nothing to do with the `Resource` type itself. +It's not possible to use the `classpath*:` prefix to construct an actual `Resource`, as +a resource points to just one resource at a time. + + +[[resources-app-ctx-ant-patterns-in-paths]] +===== Ant-style Patterns +When the path location contains an Ant-style pattern, for example: + +[literal] +[subs="verbatim,quotes"] +---- +/WEB-INF/*-context.xml + com/mycompany/**/applicationContext.xml + file:C:/some/path/*-context.xml + classpath:com/mycompany/**/applicationContext.xml +---- + +... the resolver follows a more complex but defined procedure to try to resolve the +wildcard. It produces a Resource for the path up to the last non-wildcard segment and +obtains a URL from it. If this URL is not a "jar:" URL or container-specific variant +(e.g. " `zip:`" in WebLogic, " `wsjar`" in WebSphere, etc.), then a `java.io.File` is +obtained from it and used to resolve the wildcard by traversing the filesystem. In the +case of a jar URL, the resolver either gets a `java.net.JarURLConnection` from it or +manually parses the jar URL and then traverses the contents of the jar file to resolve +the wildcards. + +[[resources-app-ctx-portability]] +====== Implications on portability +If the specified path is already a file URL (either explicitly, or implicitly because +the base `ResourceLoader` is a filesystem one, then wildcarding is guaranteed to work in +a completely portable fashion. + +If the specified path is a classpath location, then the resolver must obtain the last +non-wildcard path segment URL via a `Classloader.getResource()` call. Since this is just +a node of the path (not the file at the end) it is actually undefined (in the +`ClassLoader` javadocs) exactly what sort of a URL is returned in this case. In +practice, it is always a `java.io.File` representing the directory, where the classpath +resource resolves to a filesystem location, or a jar URL of some sort, where the +classpath resource resolves to a jar location. Still, there is a portability concern on +this operation. + +If a jar URL is obtained for the last non-wildcard segment, the resolver must be able to +get a `java.net.JarURLConnection` from it, or manually parse the jar URL, to be able to +walk the contents of the jar, and resolve the wildcard. This will work in most +environments, but will fail in others, and it is strongly recommended that the wildcard +resolution of resources coming from jars be thoroughly tested in your specific +environment before you rely on it. + + +[[resources-classpath-wildcards]] +===== The Classpath*: portability classpath*: prefix + +When constructing an XML-based application context, a location string may use the +special `classpath*:` prefix: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + ApplicationContext ctx = + new ClassPathXmlApplicationContext("classpath*:conf/appContext.xml"); +---- + +This special prefix specifies that all classpath resources that match the given name +must be obtained (internally, this essentially happens via a +`ClassLoader.getResources(...)` call), and then merged to form the final application +context definition. + +[NOTE] +==== +The wildcard classpath relies on the `getResources()` method of the underlying +classloader. As most application servers nowadays supply their own classloader +implementation, the behavior might differ especially when dealing with jar files. A +simple test to check if `classpath*` works is to use the classloader to load a file from +within a jar on the classpath: +`getClass().getClassLoader().getResources("")`. Try this test with +files that have the same name but are placed inside two different locations. In case an +inappropriate result is returned, check the application server documentation for +settings that might affect the classloader behavior. +==== + +The " `classpath*:`" prefix can also be combined with a `PathMatcher` pattern in the +rest of the location path, for example " `classpath*:META-INF/*-beans.xml`". In this +case, the resolution strategy is fairly simple: a ClassLoader.getResources() call is +used on the last non-wildcard path segment to get all the matching resources in the +class loader hierarchy, and then off each resource the same PathMatcher resolution +strategy described above is used for the wildcard subpath. + + +[[resources-wildcards-in-path-other-stuff]] +===== Other notes relating to wildcards +Please note that " `classpath*:`" when combined with Ant-style patterns will only work +reliably with at least one root directory before the pattern starts, unless the actual +target files reside in the file system. This means that a pattern like " +`classpath*:*.xml`" will not retrieve files from the root of jar files but rather only +from the root of expanded directories. This originates from a limitation in the JDK's +`ClassLoader.getResources()` method which only returns file system locations for a +passed-in empty string (indicating potential roots to search). + +Ant-style patterns with " `classpath:`" resources are not guaranteed to find matching +resources if the root package to search is available in multiple class path locations. +This is because a resource such as + +[literal] +[subs="verbatim,quotes"] +---- +com/mycompany/package1/service-context.xml +---- + +may be in only one location, but when a path such as + +[literal] +[subs="verbatim,quotes"] +---- +classpath:com/mycompany/**/service-context.xml +---- + +is used to try to resolve it, the resolver will work off the (first) URL returned by +`getResource("com/mycompany")`;. If this base package node exists in multiple +classloader locations, the actual end resource may not be underneath. Therefore, +preferably, use " `classpath*:`" with the same Ant-style pattern in such a case, which +will search all class path locations that contain the root package. + + + +[[resources-filesystemresource-caveats]] +==== FileSystemResource caveats + +A `FileSystemResource` that is not attached to a `FileSystemApplicationContext` (that +is, a `FileSystemApplicationContext` is not the actual `ResourceLoader`) will treat +absolute vs. relative paths as you would expect. Relative paths are relative to the +current working directory, while absolute paths are relative to the root of the +filesystem. + +For backwards compatibility (historical) reasons however, this changes when the +`FileSystemApplicationContext` is the `ResourceLoader`. The +`FileSystemApplicationContext` simply forces all attached `FileSystemResource` instances +to treat all location paths as relative, whether they start with a leading slash or not. +In practice, this means the following are equivalent: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + ApplicationContext ctx = + new FileSystemXmlApplicationContext("conf/context.xml"); +---- + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + ApplicationContext ctx = + new FileSystemXmlApplicationContext("/conf/context.xml"); +---- + +As are the following: (Even though it would make sense for them to be different, as one +case is relative and the other absolute.) + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + FileSystemXmlApplicationContext ctx = ...; + ctx.getResource("some/resource/path/myTemplate.txt"); +---- + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + FileSystemXmlApplicationContext ctx = ...; + ctx.getResource("/some/resource/path/myTemplate.txt"); +---- + +In practice, if true absolute filesystem paths are needed, it is better to forgo the use +of absolute paths with `FileSystemResource` / `FileSystemXmlApplicationContext`, and +just force the use of a `UrlResource`, by using the `file:` URL prefix. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + // actual context type doesn't matter, the Resource will always be UrlResource + ctx.getResource("file:/some/resource/path/myTemplate.txt"); +---- + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + // force this FileSystemXmlApplicationContext to load its definition via a UrlResource + ApplicationContext ctx = + new FileSystemXmlApplicationContext("file:/conf/context.xml"); +---- + diff --git a/src/asciidoc/scheduling.adoc b/src/asciidoc/scheduling.adoc new file mode 100644 index 000000000000..a4787f9d3c6d --- /dev/null +++ b/src/asciidoc/scheduling.adoc @@ -0,0 +1,882 @@ +[[scheduling]] +== Task Execution and Scheduling + + + + +[[scheduling-introduction]] +=== Introduction +The Spring Framework provides abstractions for asynchronous execution and scheduling of +tasks with the `TaskExecutor` and `TaskScheduler` interfaces, respectively. Spring also +features implementations of those interfaces that support thread pools or delegation to +CommonJ within an application server environment. Ultimately the use of these +implementations behind the common interfaces abstracts away the differences between Java +SE 5, Java SE 6 and Java EE environments. + +Spring also features integration classes for supporting scheduling with the `Timer`, +part of the JDK since 1.3, and the Quartz Scheduler ( http://quartz-scheduler.org[]). +Both of those schedulers are set up using a `FactoryBean` with optional references to +`Timer` or `Trigger` instances, respectively. Furthermore, a convenience class for both +the Quartz Scheduler and the `Timer` is available that allows you to invoke a method of +an existing target object (analogous to the normal `MethodInvokingFactoryBean` +operation). + + + + +[[scheduling-task-executor]] +=== The Spring TaskExecutor abstraction + +Spring 2.0 introduces a new abstraction for dealing with executors. Executors are the +Java 5 name for the concept of thread pools. The "executor" naming is due to the fact +that there is no guarantee that the underlying implementation is actually a pool; an +executor may be single-threaded or even synchronous. Spring's abstraction hides +implementation details between Java SE 1.4, Java SE 5 and Java EE environments. + +Spring's `TaskExecutor` interface is identical to the `java.util.concurrent.Executor` +interface. In fact, its primary reason for existence was to abstract away the need for +Java 5 when using thread pools. The interface has a single method `execute(Runnable +task)` that accepts a task for execution based on the semantics and configuration of the +thread pool. + +The `TaskExecutor` was originally created to give other Spring components an abstraction +for thread pooling where needed. Components such as the `ApplicationEventMulticaster`, +JMS's `AbstractMessageListenerContainer`, and Quartz integration all use the +`TaskExecutor` abstraction to pool threads. However, if your beans need thread pooling +behavior, it is possible to use this abstraction for your own needs. + + + +[[scheduling-task-executor-types]] +==== TaskExecutor types + +There are a number of pre-built implementations of `TaskExecutor` included with the +Spring distribution. In all likelihood, you shouldn't ever need to implement your own. + +* `SimpleAsyncTaskExecutor` + This implementation does not reuse any threads, rather it starts up a new thread + for each invocation. However, it does support a concurrency limit which will block + any invocations that are over the limit until a slot has been freed up. If you + re looking for true pooling, keep scrolling further down the page. +* `SyncTaskExecutor` + This implementation doesn't execute invocations asynchronously. Instead, each + invocation takes place in the calling thread. It is primarily used in situations + where multi-threading isn't necessary such as simple test cases. +* `ConcurrentTaskExecutor` + This implementation is an adapter for a `java.util.concurrent.Executor` object. + There is an alternative, `ThreadPoolTaskExecutor, that exposes the `Executor` + configuration parameters as bean properties. It is rare to need to use the + `ConcurrentTaskExecutor` but if the <> + isn't flexible enough for your needs, the `ConcurrentTaskExecutor` is an alternative. +* `SimpleThreadPoolTaskExecutor` + This implementation is actually a subclass of Quartz's `SimpleThreadPool` which + listens to Spring's lifecycle callbacks. This is typically used when you have a + thread pool that may need to be shared by both Quartz and non-Quartz components. +* `ThreadPoolTaskExecutor` + This implementation is the most commonly used one. It exposes bean properties for + configuring a java.util.concurrent.ThreadPoolExecutor` and wraps it in a `TaskExecutor`. + If you need to adapt to a different kind of `java.util.concurrent.Executor`, it is + recommended that you use a <> instead. +* `TimerTaskExecutor` + This implementation uses a single `TimerTask` as its backing implementation. + It's different from the <> in that the method + invocations are executed in a separate thread, although they are effectively + synchronously batched in that thread. +* `WorkManagerTaskExecutor` + ++ + +**** +CommonJ is a set of specifications jointly developed between BEA and IBM. These +specifications are not Java EE standards, but are standard across BEA's and IBM's +Application Server implementations. +**** + ++ + +This implementation uses the CommonJ WorkManager as its backing implementation and is +the central convenience class for setting up a CommonJ WorkManager reference in a Spring +context. Similar to the <>, +this class implements the WorkManager interface and therefore can be used directly as a +WorkManager as well. + + + +[[scheduling-task-executor-usage]] +==== Using a TaskExecutor + +Spring's `TaskExecutor` implementations are used as simple JavaBeans. In the example +below, we define a bean that uses the `ThreadPoolTaskExecutor` to asynchronously print +out a set of messages. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + import org.springframework.core.task.TaskExecutor; + + public class TaskExecutorExample { + + private class MessagePrinterTask implements Runnable { + + private String message; + + public MessagePrinterTask(String message) { + this.message = message; + } + + public void run() { + System.out.println(message); + } + + } + + private TaskExecutor taskExecutor; + + public TaskExecutorExample(TaskExecutor taskExecutor) { + this.taskExecutor = taskExecutor; + } + + public void printMessages() { + for(int i = 0; i < 25; i++) { + taskExecutor.execute(new MessagePrinterTask("Message" + i)); + } + } + + } +---- + +As you can see, rather than retrieving a thread from the pool and executing yourself, +you add your `Runnable` to the queue and the `TaskExecutor` uses its internal rules to +decide when the task gets executed. + +To configure the rules that the `TaskExecutor` will use, simple bean properties have +been exposed. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + + +---- + + + + +[[scheduling-task-scheduler]] +=== The Spring TaskScheduler abstraction + +In addition to the `TaskExecutor` abstraction, Spring 3.0 introduces a `TaskScheduler` +with a variety of methods for scheduling tasks to run at some point in the future. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public interface TaskScheduler { + + ScheduledFuture schedule(Runnable task, Trigger trigger); + + ScheduledFuture schedule(Runnable task, Date startTime); + + ScheduledFuture scheduleAtFixedRate(Runnable task, Date startTime, long period); + + ScheduledFuture scheduleAtFixedRate(Runnable task, long period); + + ScheduledFuture scheduleWithFixedDelay(Runnable task, Date startTime, long delay); + + ScheduledFuture scheduleWithFixedDelay(Runnable task, long delay); + + } +---- + +The simplest method is the one named 'schedule' that takes a `Runnable` and `Date` only. +That will cause the task to run once after the specified time. All of the other methods +are capable of scheduling tasks to run repeatedly. The fixed-rate and fixed-delay +methods are for simple, periodic execution, but the method that accepts a Trigger is +much more flexible. + + + +[[scheduling-trigger-interface]] +==== the Trigger interface + +The `Trigger` interface is essentially inspired by JSR-236, which, as of Spring 3.0, has +not yet been officially implemented. The basic idea of the `Trigger` is that execution +times may be determined based on past execution outcomes or even arbitrary conditions. +If these determinations do take into account the outcome of the preceding execution, +that information is available within a `TriggerContext`. The `Trigger` interface itself +is quite simple: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public interface Trigger { + + Date nextExecutionTime(TriggerContext triggerContext); + + } +---- + +As you can see, the `TriggerContext` is the most important part. It encapsulates all of +the relevant data, and is open for extension in the future if necessary. The +`TriggerContext` is an interface (a `SimpleTriggerContext` implementation is used by +default). Here you can see what methods are available for `Trigger` implementations. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public interface TriggerContext { + + Date lastScheduledExecutionTime(); + + Date lastActualExecutionTime(); + + Date lastCompletionTime(); + + } +---- + + + +[[scheduling-trigger-implementations]] +==== Trigger implementations + +Spring provides two implementations of the `Trigger` interface. The most interesting one +is the `CronTrigger`. It enables the scheduling of tasks based on cron expressions. For +example the following task is being scheduled to run 15 minutes past each hour but only +during the 9-to-5 "business hours" on weekdays. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + scheduler.schedule(task, new CronTrigger("* 15 9-17 * * MON-FRI")); +---- + +The other out-of-the-box implementation is a `PeriodicTrigger` that accepts a fixed +period, an optional initial delay value, and a boolean to indicate whether the period +should be interpreted as a fixed-rate or a fixed-delay. Since the `TaskScheduler` +interface already defines methods for scheduling tasks at a fixed-rate or with a +fixed-delay, those methods should be used directly whenever possible. The value of the +`PeriodicTrigger` implementation is that it can be used within components that rely on +the `Trigger` abstraction. For example, it may be convenient to allow periodic triggers, +cron-based triggers, and even custom trigger implementations to be used interchangeably. +Such a component could take advantage of dependency injection so that such `Triggers` +could be configured externally. + + + +[[scheduling-task-scheduler-implementations]] +==== TaskScheduler implementations + +As with Spring's `TaskExecutor` abstraction, the primary benefit of the `TaskScheduler` +is that code relying on scheduling behavior need not be coupled to a particular +scheduler implementation. The flexibility this provides is particularly relevant when +running within Application Server environments where threads should not be created +directly by the application itself. For such cases, Spring provides a +`TimerManagerTaskScheduler` that delegates to a CommonJ TimerManager instance, typically +configured with a JNDI-lookup. + +A simpler alternative, the `ThreadPoolTaskScheduler`, can be used whenever external +thread management is not a requirement. Internally, it delegates to a +`ScheduledExecutorService` instance. `ThreadPoolTaskScheduler` actually implements +Spring's `TaskExecutor` interface as well, so that a single instance can be used for +asynchronous execution __as soon as possible__ as well as scheduled, and potentially +recurring, executions. + + + + +[[scheduling-annotation-support]] +=== Annotation Support for Scheduling and Asynchronous Execution +Spring provides annotation support for both task scheduling and asynchronous method +execution. + + + +[[scheduling-enable-annotation-support]] +==== Enable scheduling annotations +To enable support for `@Scheduled` and `@Async` annotations add `@EnableScheduling` and +`@EnableAsync` to one of your `@Configuration` classes: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Configuration + @EnableAsync + @EnableScheduling + public class AppConfig { + } +---- + +You are free to pick and choose the relevant annotations for your application. For +example, if you only need support for `@Scheduled`, simply omit `@EnableAsync`. For more +fine-grained control you can additionally implement the `SchedulingConfigurer` and/or +`AsyncConfigurer` interfaces. See the javadocs for full details. + +If you prefer XML configuration use the `` element. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + +---- + +Notice with the above XML that an executor reference is provided for handling those +tasks that correspond to methods with the `@Async` annotation, and the scheduler +reference is provided for managing those methods annotated with `@Scheduled`. + + + +[[scheduling-annotation-support-scheduled]] +==== The @Scheduled Annotation +The @Scheduled annotation can be added to a method along with trigger metadata. For +example, the following method would be invoked every 5 seconds with a fixed delay, +meaning that the period will be measured from the completion time of each preceding +invocation. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Scheduled(fixedDelay=5000) + public void doSomething() { + // something that should execute periodically + } +---- + +If a fixed rate execution is desired, simply change the property name specified within +the annotation. The following would be executed every 5 seconds measured between the +successive start times of each invocation. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Scheduled(fixedRate=5000) + public void doSomething() { + // something that should execute periodically + } +---- + +For fixed-delay and fixed-rate tasks, an initial delay may be specified indicating the +number of milliseconds to wait before the first execution of the method. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Scheduled(initialDelay=1000, fixedRate=5000) + public void doSomething() { + // something that should execute periodically + } +---- + +If simple periodic scheduling is not expressive enough, then a cron expression may be +provided. For example, the following will only execute on weekdays. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Scheduled(cron="*/5 * * * * MON-FRI") + public void doSomething() { + // something that should execute on weekdays only + } +---- + +[TIP] +==== +You can additionally use the `zone` attribute to specify the time zone in which the cron +expression will be resolved. +==== + + +Notice that the methods to be scheduled must have void returns and must not expect any +arguments. If the method needs to interact with other objects from the Application +Context, then those would typically have been provided through dependency injection. + +[NOTE] +==== +Make sure that you are not initializing multiple instances of the same @Scheduled +annotation class at runtime, unless you do want to schedule callbacks to each such +instance. Related to this, make sure that you do not use @Configurable on bean classes +which are annotated with @Scheduled and registered as regular Spring beans with the +container: You would get double initialization otherwise, once through the container and +once through the @Configurable aspect, with the consequence of each @Scheduled method +being invoked twice. +==== + + + +[[scheduling-annotation-support-async]] +==== The @Async Annotation +The `@Async` annotation can be provided on a method so that invocation of that method +will occur asynchronously. In other words, the caller will return immediately upon +invocation and the actual execution of the method will occur in a task that has been +submitted to a Spring `TaskExecutor`. In the simplest case, the annotation may be +applied to a `void`-returning method. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Async + void doSomething() { + // this will be executed asynchronously + } +---- + +Unlike the methods annotated with the `@Scheduled` annotation, these methods can expect +arguments, because they will be invoked in the "normal" way by callers at runtime rather +than from a scheduled task being managed by the container. For example, the following is +a legitimate application of the `@Async` annotation. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Async + void doSomething(String s) { + // this will be executed asynchronously + } +---- + +Even methods that return a value can be invoked asynchronously. However, such methods +are required to have a `Future` typed return value. This still provides the benefit of +asynchronous execution so that the caller can perform other tasks prior to calling +`get()` on that Future. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Async + Future returnSomething(int i) { + // this will be executed asynchronously + } +---- + +`@Async` can not be used in conjunction with lifecycle callbacks such as +`@PostConstruct`. To asynchronously initialize Spring beans you currently have to use a +separate initializing Spring bean that invokes the `@Async` annotated method on the +target then. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class SampleBeanImpl implements SampleBean { + + @Async + void doSomething() { + // ... + } + + } + + public class SampleBeanInititalizer { + + private final SampleBean bean; + + public SampleBeanInitializer(SampleBean bean) { + this.bean = bean; + } + + @PostConstruct + public void initialize() { + bean.doSomething(); + } + + } +---- + + + +[[scheduling-annotation-support-qualification]] +==== Executor qualification with @Async +By default when specifying `@Async` on a method, the executor that will be used is the +one supplied to the 'annotation-driven' element as described above. However, the `value` +attribute of the `@Async` annotation can be used when needing to indicate that an +executor other than the default should be used when executing a given method. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Async("otherExecutor") + void doSomething(String s) { + // this will be executed asynchronously by "otherExecutor" + } +---- + +In this case, "otherExecutor" may be the name of any `Executor` bean in the Spring +container, or may be the name of a __qualifier__ associated with any `Executor`, e.g. as +specified with the `` element or Spring's `@Qualifier` annotation. + + + +[[scheduling-annotation-support-exception]] +==== Exception management with @Async +When an `@Async` method has a `Future` typed return value, it is easy to manage +an exception that was thrown during the method execution as this exception will +be thrown when calling `get` on the `Future` result. With a void return type +however, the exception is uncaught and cannot be transmitted. For those cases, an +`AsyncUncaughtExceptionHandler` can be provided to handle such exceptions. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class MyAsyncUncaughtExceptionHandler implements AsyncUncaughtExceptionHandler { + + @Override + public void handleUncaughtException(Throwable ex, Method method, Object... params) { + // handle exception + } + } +---- + +By default, the exception is simply logged. A custom `AsyncUncaughtExceptionHandler` can +be defined _via_ `AsyncConfigurer` or the `task:annotation-driven` XML element. + +[[scheduling-task-namespace]] +=== The Task Namespace +Beginning with Spring 3.0, there is an XML namespace for configuring `TaskExecutor` and +`TaskScheduler` instances. It also provides a convenient way to configure tasks to be +scheduled with a trigger. + + + +[[scheduling-task-namespace-scheduler]] +==== The 'scheduler' element +The following element will create a `ThreadPoolTaskScheduler` instance with the +specified thread pool size. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + +---- + +The value provided for the 'id' attribute will be used as the prefix for thread names +within the pool. The 'scheduler' element is relatively straightforward. If you do not +provide a 'pool-size' attribute, the default thread pool will only have a single thread. +There are no other configuration options for the scheduler. + + + +[[scheduling-task-namespace-executor]] +==== The 'executor' element +The following will create a `ThreadPoolTaskExecutor` instance: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + +---- + +As with the scheduler above, the value provided for the 'id' attribute will be used as +the prefix for thread names within the pool. As far as the pool size is concerned, the +'executor' element supports more configuration options than the 'scheduler' element. For +one thing, the thread pool for a `ThreadPoolTaskExecutor` is itself more configurable. +Rather than just a single size, an executor's thread pool may have different values for +the __core__ and the __max__ size. If a single value is provided then the executor will +have a fixed-size thread pool (the core and max sizes are the same). However, the +'executor' element's 'pool-size' attribute also accepts a range in the form of "min-max". + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + +---- + +As you can see from that configuration, a 'queue-capacity' value has also been provided. +The configuration of the thread pool should also be considered in light of the +executor's queue capacity. For the full description of the relationship between pool +size and queue capacity, consult the documentation for +http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/ThreadPoolExecutor.html[ThreadPoolExecutor]. +The main idea is that when a task is submitted, the executor will first try to use a +free thread if the number of active threads is currently less than the core size. If the +core size has been reached, then the task will be added to the queue as long as its +capacity has not yet been reached. Only then, if the queue's capacity __has__ been +reached, will the executor create a new thread beyond the core size. If the max size has +also been reached, then the executor will reject the task. + +By default, the queue is __unbounded__, but this is rarely the desired configuration, +because it can lead to `OutOfMemoryErrors` if enough tasks are added to that queue while +all pool threads are busy. Furthermore, if the queue is unbounded, then the max size has +no effect at all. Since the executor will always try the queue before creating a new +thread beyond the core size, a queue must have a finite capacity for the thread pool to +grow beyond the core size (this is why a __fixed size__ pool is the only sensible case +when using an unbounded queue). + +In a moment, we will review the effects of the keep-alive setting which adds yet another +factor to consider when providing a pool size configuration. First, let's consider the +case, as mentioned above, when a task is rejected. By default, when a task is rejected, +a thread pool executor will throw a `TaskRejectedException`. However, the rejection +policy is actually configurable. The exception is thrown when using the default +rejection policy which is the `AbortPolicy` implementation. For applications where some +tasks can be skipped under heavy load, either the `DiscardPolicy` or +`DiscardOldestPolicy` may be configured instead. Another option that works well for +applications that need to throttle the submitted tasks under heavy load is the +`CallerRunsPolicy`. Instead of throwing an exception or discarding tasks, that policy +will simply force the thread that is calling the submit method to run the task itself. +The idea is that such a caller will be busy while running that task and not able to +submit other tasks immediately. Therefore it provides a simple way to throttle the +incoming load while maintaining the limits of the thread pool and queue. Typically this +allows the executor to "catch up" on the tasks it is handling and thereby frees up some +capacity on the queue, in the pool, or both. Any of these options can be chosen from an +enumeration of values available for the 'rejection-policy' attribute on the 'executor' +element. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + +---- + + + +[[scheduling-task-namespace-scheduled-tasks]] +==== The 'scheduled-tasks' element +The most powerful feature of Spring's task namespace is the support for configuring +tasks to be scheduled within a Spring Application Context. This follows an approach +similar to other "method-invokers" in Spring, such as that provided by the JMS namespace +for configuring Message-driven POJOs. Basically a "ref" attribute can point to any +Spring-managed object, and the "method" attribute provides the name of a method to be +invoked on that object. Here is a simple example. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + +---- + +As you can see, the scheduler is referenced by the outer element, and each individual +task includes the configuration of its trigger metadata. In the preceding example, that +metadata defines a periodic trigger with a fixed delay indicating the number of +milliseconds to wait after each task execution has completed. Another option is +'fixed-rate', indicating how often the method should be executed regardless of how long +any previous execution takes. Additionally, for both fixed-delay and fixed-rate tasks an +'initial-delay' parameter may be specified indicating the number of milliseconds to wait +before the first execution of the method. For more control, a "cron" attribute may be +provided instead. Here is an example demonstrating these other options. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + +---- + + + + +[[scheduling-quartz]] +=== Using the Quartz Scheduler +Quartz uses `Trigger`, `Job` and `JobDetail` objects to realize scheduling of all kinds +of jobs. For the basic concepts behind Quartz, have a look at +http://quartz-scheduler.org[]. For convenience purposes, Spring offers a couple of +classes that simplify the usage of Quartz within Spring-based applications. + + + +[[scheduling-quartz-jobdetail]] +==== Using the JobDetailBean +`JobDetail` objects contain all information needed to run a job. The Spring Framework +provides a `JobDetailBean` that makes the `JobDetail` more of an actual JavaBean with +sensible defaults. Let's have a look at an example: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + +---- + +The job detail bean has all information it needs to run the job ( `ExampleJob`). The +timeout is specified in the job data map. The job data map is available through the +`JobExecutionContext` (passed to you at execution time), but the `JobDetailBean` also +maps the properties from the job data map to properties of the actual job. So in this +case, if the `ExampleJob` contains a property named `timeout`, the `JobDetailBean` will +automatically apply it: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + package example; + + public class ExampleJob extends QuartzJobBean { + + private int timeout; + + /** + * Setter called after the ExampleJob is instantiated + * with the value from the JobDetailBean (5) + */ + public void setTimeout(int timeout) { + this.timeout = timeout; + } + + protected void executeInternal(JobExecutionContext ctx) throws JobExecutionException { + // do the actual work + } + + } +---- + +All additional settings from the job detail bean are of course available to you as well. + +[NOTE] +==== +Using the `name` and `group` properties, you can modify the name and the group +of the job, respectively. By default, the name of the job matches the bean name of the +job detail bean (in the example above, this is `exampleJob`). +==== + + + +[[scheduling-quartz-method-invoking-job]] +==== Using the MethodInvokingJobDetailFactoryBean + +Often you just need to invoke a method on a specific object. Using the +`MethodInvokingJobDetailFactoryBean` you can do exactly this: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + +---- + +The above example will result in the `doIt` method being called on the +`exampleBusinessObject` method (see below): + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class ExampleBusinessObject { + + // properties and collaborators + + public void doIt() { + // do the actual work + } + } +---- + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + +---- + +Using the `MethodInvokingJobDetailFactoryBean`, you don't need to create one-line jobs +that just invoke a method, and you only need to create the actual business object and +wire up the detail object. + +By default, Quartz Jobs are stateless, resulting in the possibility of jobs interfering +with each other. If you specify two triggers for the same `JobDetail`, it might be +possible that before the first job has finished, the second one will start. If +`JobDetail` classes implement the `Stateful` interface, this won't happen. The second +job will not start before the first one has finished. To make jobs resulting from the +`MethodInvokingJobDetailFactoryBean` non-concurrent, set the `concurrent` flag to +`false`. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + +---- + +[NOTE] +==== +By default, jobs will run in a concurrent fashion. +==== + + + +[[scheduling-quartz-cron]] +==== Wiring up jobs using triggers and the SchedulerFactoryBean + +We've created job details and jobs. We've also reviewed the convenience bean that allows +you to invoke a method on a specific object. Of course, we still need to schedule the +jobs themselves. This is done using triggers and a `SchedulerFactoryBean`. Several +triggers are available within Quartz and Spring offers two Quartz `FactoryBean` +implementations with convenient defaults: `CronTriggerFactoryBean` and +`SimpleTriggerFactoryBean`. + +Triggers need to be scheduled. Spring offers a `SchedulerFactoryBean` that exposes +triggers to be set as properties. `SchedulerFactoryBean` schedules the actual jobs with +those triggers. + +Find below a couple of examples: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + + + + + + + +---- + +Now we've set up two triggers, one running every 50 seconds with a starting delay of 10 +seconds and one every morning at 6 AM. To finalize everything, we need to set up the +`SchedulerFactoryBean`: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + +---- + +More properties are available for the `SchedulerFactoryBean` for you to set, such as the +calendars used by the job details, properties to customize Quartz with, etc. Have a look +at the +{javadoc-baseurl}/org/springframework/scheduling/quartz/SchedulerFactoryBean.html[`SchedulerFactoryBean` +javadocs] for more information. + diff --git a/src/asciidoc/spring-form-tld.adoc b/src/asciidoc/spring-form-tld.adoc new file mode 100644 index 000000000000..3bbd1bcb15ca --- /dev/null +++ b/src/asciidoc/spring-form-tld.adoc @@ -0,0 +1,2033 @@ +[[spring-form.tld]] +== spring-form.tld + + + + +[[spring-form.tld-intro]] +=== Introduction +One of the view technologies you can use with the Spring Framework is Java Server Pages +(JSPs). To help you implement views using Java Server Pages the Spring Framework +provides you with some tags for evaluating errors, setting themes and outputting +internationalized messages. + +Please note that the various tags generated by this form tag library are compliant with +the http://www.w3.org/TR/xhtml1/[XHTML-1.0-Strict specification] and attendant +http://www.w3.org/TR/xhtml1/dtds.html#a_dtd_XHTML-1.0-Strict[DTD]. + +This appendix describes the `spring-form.tld` tag library. + +* <> +* <> +* <> +* <> +* <> +* <> +* <> +* <> +* <> +* <> +* <> +* <> +* <> +* <> + + + + +[[spring-form.tld.checkbox]] +=== the checkbox tag + +Renders an HTML 'input' tag with type 'checkbox'. + +[[spring-form.tld.checkbox.attrs.tbl]] +.Attributes +[cols="1,1,1,3"] +|=== +| Attribute| Required?| Runtime Expression?| Description + +| accesskey +| false +| true +| HTML Standard Attribute + +| cssClass +| false +| true +| Equivalent to "class" - HTML Optional Attribute + +| cssErrorClass +| false +| true +| Equivalent to "class" - HTML Optional Attribute. Used when the bound field has errors. + +| cssStyle +| false +| true +| Equivalent to "style" - HTML Optional Attribute + +| dir +| false +| true +| HTML Standard Attribute + +| disabled +| false +| true +| HTML Optional Attribute. Setting the value of this attribute to 'true' (without the + quotes) will disable the HTML element. + +| htmlEscape +| false +| true +| Enable/disable HTML escaping of rendered values. + +| id +| false +| true +| HTML Standard Attribute + +| label +| false +| true +| Value to be displayed as part of the tag + +| lang +| false +| true +| HTML Standard Attribute + +| onblur +| false +| true +| HTML Event Attribute + +| onchange +| false +| true +| HTML Event Attribute + +| onclick +| false +| true +| HTML Event Attribute + +| ondblclick +| false +| true +| HTML Event Attribute + +| onfocus +| false +| true +| HTML Event Attribute + +| onkeydown +| false +| true +| HTML Event Attribute + +| onkeypress +| false +| true +| HTML Event Attribute + +| onkeyup +| false +| true +| HTML Event Attribute + +| onmousedown +| false +| true +| HTML Event Attribute + +| onmousemove +| false +| true +| HTML Event Attribute + +| onmouseout +| false +| true +| HTML Event Attribute + +| onmouseover +| false +| true +| HTML Event Attribute + +| onmouseup +| false +| true +| HTML Event Attribute + +| path +| true +| true +| Path to property for data binding + +| tabindex +| false +| true +| HTML Standard Attribute + +| title +| false +| true +| HTML Standard Attribute + +| value +| false +| true +| HTML Optional Attribute +|=== + + + + +[[spring-form.tld.checkboxes]] +=== the checkboxes tag + +Renders multiple HTML 'input' tags with type 'checkbox'. + +[[spring-form.tld.checkboxes.table]] +.Attributes +[cols="1,1,1,3"] +|=== +| Attribute| Required?| Runtime Expression?| Description + +| accesskey +| false +| true +| HTML Standard Attribute + +| cssClass +| false +| true +| Equivalent to "class" - HTML Optional Attribute + +| cssErrorClass +| false +| true +| Equivalent to "class" - HTML Optional Attribute. Used when the bound field has errors. + +| cssStyle +| false +| true +| Equivalent to "style" - HTML Optional Attribute + +| delimiter +| false +| true +| Delimiter to use between each 'input' tag with type 'checkbox'. There is no delimiter + by default. + +| dir +| false +| true +| HTML Standard Attribute + +| disabled +| false +| true +| HTML Optional Attribute. Setting the value of this attribute to 'true' (without the + quotes) will disable the HTML element. + +| element +| false +| true +| Specifies the HTML element that is used to enclose each 'input' tag with type + 'checkbox'. Defaults to 'span'. + +| htmlEscape +| false +| true +| Enable/disable HTML escaping of rendered values. + +| id +| false +| true +| HTML Standard Attribute + +| itemLabel +| false +| true +| Value to be displayed as part of the 'input' tags with type 'checkbox' + +| items +| true +| true +| The Collection, Map or array of objects used to generate the 'input' tags with type + 'checkbox' + +| itemValue +| false +| true +| Name of the property mapped to 'value' attribute of the 'input' tags with type + 'checkbox' + +| lang +| false +| true +| HTML Standard Attribute + +| onblur +| false +| true +| HTML Event Attribute + +| onchange +| false +| true +| HTML Event Attribute + +| onclick +| false +| true +| HTML Event Attribute + +| ondblclick +| false +| true +| HTML Event Attribute + +| onfocus +| false +| true +| HTML Event Attribute + +| onkeydown +| false +| true +| HTML Event Attribute + +| onkeypress +| false +| true +| HTML Event Attribute + +| onkeyup +| false +| true +| HTML Event Attribute + +| onmousedown +| false +| true +| HTML Event Attribute + +| onmousemove +| false +| true +| HTML Event Attribute + +| onmouseout +| false +| true +| HTML Event Attribute + +| onmouseover +| false +| true +| HTML Event Attribute + +| onmouseup +| false +| true +| HTML Event Attribute + +| path +| true +| true +| Path to property for data binding + +| tabindex +| false +| true +| HTML Standard Attribute + +| title +| false +| true +| HTML Standard Attribute +|=== + + + + +[[spring-form.tld.errors]] +=== the errors tag + +Renders field errors in an HTML 'span' tag. + +[[spring-form.tld.errors.table]] +.Attributes +[cols="1,1,1,3"] +|=== +| Attribute| Required?| Runtime Expression?| Description + +| cssClass +| false +| true +| Equivalent to "class" - HTML Optional Attribute + +| cssStyle +| false +| true +| Equivalent to "style" - HTML Optional Attribute + +| delimiter +| false +| true +| Delimiter for displaying multiple error messages. Defaults to the br tag. + +| dir +| false +| true +| HTML Standard Attribute + +| element +| false +| true +| Specifies the HTML element that is used to render the enclosing errors. + +| htmlEscape +| false +| true +| Enable/disable HTML escaping of rendered values. + +| id +| false +| true +| HTML Standard Attribute + +| lang +| false +| true +| HTML Standard Attribute + +| onclick +| false +| true +| HTML Event Attribute + +| ondblclick +| false +| true +| HTML Event Attribute + +| onkeydown +| false +| true +| HTML Event Attribute + +| onkeypress +| false +| true +| HTML Event Attribute + +| onkeyup +| false +| true +| HTML Event Attribute + +| onmousedown +| false +| true +| HTML Event Attribute + +| onmousemove +| false +| true +| HTML Event Attribute + +| onmouseout +| false +| true +| HTML Event Attribute + +| onmouseover +| false +| true +| HTML Event Attribute + +| onmouseup +| false +| true +| HTML Event Attribute + +| path +| false +| true +| Path to errors object for data binding + +| tabindex +| false +| true +| HTML Standard Attribute + +| title +| false +| true +| HTML Standard Attribute +|=== + + + + +[[spring-form.tld.form]] +=== the form tag + +Renders an HTML 'form' tag and exposes a binding path to inner tags for binding. + +[[spring-form.tld.form.table]] +.Attributes +[cols="1,1,1,3"] +|=== +| Attribute| Required?| Runtime Expression?| Description + +| acceptCharset +| false +| true +| Specifies the list of character encodings for input data that is accepted by the + server processing this form. The value is a space- and/or comma-delimited list of + charset values. The client must interpret this list as an exclusive-or list, i.e., the + server is able to accept any single character encoding per entity received. + +| action +| false +| true +| HTML Required Attribute + +| commandName +| false +| true +| Name of the model attribute under which the form object is exposed. Defaults to + 'command'. + +| cssClass +| false +| true +| Equivalent to "class" - HTML Optional Attribute + +| cssStyle +| false +| true +| Equivalent to "style" - HTML Optional Attribute + +| dir +| false +| true +| HTML Standard Attribute + +| enctype +| false +| true +| HTML Optional Attribute + +| htmlEscape +| false +| true +| Enable/disable HTML escaping of rendered values. + +| id +| false +| true +| HTML Standard Attribute + +| lang +| false +| true +| HTML Standard Attribute + +| method +| false +| true +| HTML Optional Attribute + +| modelAttribute +| false +| true +| Name of the model attribute under which the form object is exposed. Defaults to + 'command'. + +| name +| false +| true +| HTML Standard Attribute - added for backwards compatibility cases + +| onclick +| false +| true +| HTML Event Attribute + +| ondblclick +| false +| true +| HTML Event Attribute + +| onkeydown +| false +| true +| HTML Event Attribute + +| onkeypress +| false +| true +| HTML Event Attribute + +| onkeyup +| false +| true +| HTML Event Attribute + +| onmousedown +| false +| true +| HTML Event Attribute + +| onmousemove +| false +| true +| HTML Event Attribute + +| onmouseout +| false +| true +| HTML Event Attribute + +| onmouseover +| false +| true +| HTML Event Attribute + +| onmouseup +| false +| true +| HTML Event Attribute + +| onreset +| false +| true +| HTML Event Attribute + +| onsubmit +| false +| true +| HTML Event Attribute + +| target +| false +| true +| HTML Optional Attribute + +| title +| false +| true +| HTML Standard Attribute +|=== + + + + +[[spring-form.tld.hidden]] +=== the hidden tag + +Renders an HTML 'input' tag with type 'hidden' using the bound value. + +[[spring-form.tld.hidden.table]] +.Attributes +[cols="1,1,1,3"] +|=== +| Attribute| Required?| Runtime Expression?| Description + +| htmlEscape +| false +| true +| Enable/disable HTML escaping of rendered values. + +| id +| false +| true +| HTML Standard Attribute + +| path +| true +| true +| Path to property for data binding +|=== + + + + +[[spring-form.tld.input]] +=== the input tag + +Renders an HTML 'input' tag with type 'text' using the bound value. + +[[spring-form.tld.input.table]] +.Attributes +[cols="1,1,1,3"] +|=== +| Attribute| Required?| Runtime Expression?| Description + +| accesskey +| false +| true +| HTML Standard Attribute + +| alt +| false +| true +| HTML Optional Attribute + +| autocomplete +| false +| true +| Common Optional Attribute + +| cssClass +| false +| true +| Equivalent to "class" - HTML Optional Attribute + +| cssErrorClass +| false +| true +| Equivalent to "class" - HTML Optional Attribute. Used when the bound field has errors. + +| cssStyle +| false +| true +| Equivalent to "style" - HTML Optional Attribute + +| dir +| false +| true +| HTML Standard Attribute + +| disabled +| false +| true +| HTML Optional Attribute. Setting the value of this attribute to 'true' (without the + quotes) will disable the HTML element. + +| htmlEscape +| false +| true +| Enable/disable HTML escaping of rendered values. + +| id +| false +| true +| HTML Standard Attribute + +| lang +| false +| true +| HTML Standard Attribute + +| maxlength +| false +| true +| HTML Optional Attribute + +| onblur +| false +| true +| HTML Event Attribute + +| onchange +| false +| true +| HTML Event Attribute + +| onclick +| false +| true +| HTML Event Attribute + +| ondblclick +| false +| true +| HTML Event Attribute + +| onfocus +| false +| true +| HTML Event Attribute + +| onkeydown +| false +| true +| HTML Event Attribute + +| onkeypress +| false +| true +| HTML Event Attribute + +| onkeyup +| false +| true +| HTML Event Attribute + +| onmousedown +| false +| true +| HTML Event Attribute + +| onmousemove +| false +| true +| HTML Event Attribute + +| onmouseout +| false +| true +| HTML Event Attribute + +| onmouseover +| false +| true +| HTML Event Attribute + +| onmouseup +| false +| true +| HTML Event Attribute + +| onselect +| false +| true +| HTML Event Attribute + +| path +| true +| true +| Path to property for data binding + +| readonly +| false +| true +| HTML Optional Attribute. Setting the value of this attribute to 'true' (without the + quotes) will make the HTML element readonly. + +| size +| false +| true +| HTML Optional Attribute + +| tabindex +| false +| true +| HTML Standard Attribute + +| title +| false +| true +| HTML Standard Attribute +|=== + + + + +[[spring-form.tld.label]] +=== the label tag + +Renders a form field label in an HTML 'label' tag. + +[[spring-form.tld.label.table]] +[cols="1,1,1,3"] +.Attributes +|=== +| Attribute| Required?| Runtime Expression?| Description + +| cssClass +| false +| true +| Equivalent to "class" - HTML Optional Attribute. + +| cssErrorClass +| false +| true +| Equivalent to "class" - HTML Optional Attribute. Used only when errors are present. + +| cssStyle +| false +| true +| Equivalent to "style" - HTML Optional Attribute + +| dir +| false +| true +| HTML Standard Attribute + +| for +| false +| true +| HTML Standard Attribute + +| htmlEscape +| false +| true +| Enable/disable HTML escaping of rendered values. + +| id +| false +| true +| HTML Standard Attribute + +| lang +| false +| true +| HTML Standard Attribute + +| onclick +| false +| true +| HTML Event Attribute + +| ondblclick +| false +| true +| HTML Event Attribute + +| onkeydown +| false +| true +| HTML Event Attribute + +| onkeypress +| false +| true +| HTML Event Attribute + +| onkeyup +| false +| true +| HTML Event Attribute + +| onmousedown +| false +| true +| HTML Event Attribute + +| onmousemove +| false +| true +| HTML Event Attribute + +| onmouseout +| false +| true +| HTML Event Attribute + +| onmouseover +| false +| true +| HTML Event Attribute + +| onmouseup +| false +| true +| HTML Event Attribute + +| path +| true +| true +| Path to errors object for data binding + +| tabindex +| false +| true +| HTML Standard Attribute + +| title +| false +| true +| HTML Standard Attribute +|=== + + + + +[[spring-form.tld.option]] +=== the option tag + +Renders a single HTML 'option'. Sets 'selected' as appropriate based on bound value. + +[[spring-form.tld.option.table]] +.Attributes +[cols="1,1,1,3"] +|=== +| Attribute| Required?| Runtime Expression?| Description + +| cssClass +| false +| true +| Equivalent to "class" - HTML Optional Attribute + +| cssErrorClass +| false +| true +| Equivalent to "class" - HTML Optional Attribute. Used when the bound field has errors. + +| cssStyle +| false +| true +| Equivalent to "style" - HTML Optional Attribute + +| dir +| false +| true +| HTML Standard Attribute + +| disabled +| false +| true +| HTML Optional Attribute. Setting the value of this attribute to 'true' (without the + quotes) will disable the HTML element. + +| htmlEscape +| false +| true +| Enable/disable HTML escaping of rendered values. + +| id +| false +| true +| HTML Standard Attribute + +| label +| false +| true +| HTML Optional Attribute + +| lang +| false +| true +| HTML Standard Attribute + +| onclick +| false +| true +| HTML Event Attribute + +| ondblclick +| false +| true +| HTML Event Attribute + +| onkeydown +| false +| true +| HTML Event Attribute + +| onkeypress +| false +| true +| HTML Event Attribute + +| onkeyup +| false +| true +| HTML Event Attribute + +| onmousedown +| false +| true +| HTML Event Attribute + +| onmousemove +| false +| true +| HTML Event Attribute + +| onmouseout +| false +| true +| HTML Event Attribute + +| onmouseover +| false +| true +| HTML Event Attribute + +| onmouseup +| false +| true +| HTML Event Attribute + +| tabindex +| false +| true +| HTML Standard Attribute + +| title +| false +| true +| HTML Standard Attribute + +| value +| true +| true +| HTML Optional Attribute +|=== + + + + +[[spring-form.tld.options]] +=== the options tag + +Renders a list of HTML 'option' tags. Sets 'selected' as appropriate based on bound value. + +[[spring-form.tld.options.table]] +.Attributes +[cols="1,1,1,3"] +|=== +| Attribute| Required?| Runtime Expression?| Description + +| cssClass +| false +| true +| Equivalent to "class" - HTML Optional Attribute + +| cssErrorClass +| false +| true +| Equivalent to "class" - HTML Optional Attribute. Used when the bound field has errors. + +| cssStyle +| false +| true +| Equivalent to "style" - HTML Optional Attribute + +| dir +| false +| true +| HTML Standard Attribute + +| disabled +| false +| true +| HTML Optional Attribute. Setting the value of this attribute to 'true' (without the + quotes) will disable the HTML element. + +| htmlEscape +| false +| true +| Enable/disable HTML escaping of rendered values. + +| id +| false +| true +| HTML Standard Attribute + +| itemLabel +| false +| true +| Name of the property mapped to the inner text of the 'option' tag + +| items +| true +| true +| The Collection, Map or array of objects used to generate the inner 'option' tags + +| itemValue +| false +| true +| Name of the property mapped to 'value' attribute of the 'option' tag + +| lang +| false +| true +| HTML Standard Attribute + +| onclick +| false +| true +| HTML Event Attribute + +| ondblclick +| false +| true +| HTML Event Attribute + +| onkeydown +| false +| true +| HTML Event Attribute + +| onkeypress +| false +| true +| HTML Event Attribute + +| onkeyup +| false +| true +| HTML Event Attribute + +| onmousedown +| false +| true +| HTML Event Attribute + +| onmousemove +| false +| true +| HTML Event Attribute + +| onmouseout +| false +| true +| HTML Event Attribute + +| onmouseover +| false +| true +| HTML Event Attribute + +| onmouseup +| false +| true +| HTML Event Attribute + +| tabindex +| false +| true +| HTML Standard Attribute + +| title +| false +| true +| HTML Standard Attribute +|=== + + + + +[[spring-form.tld.password]] +=== the password tag + +Renders an HTML 'input' tag with type 'password' using the bound value. + +[[spring-form.tld.password.table]] +.Attributes +[cols="1,1,1,3"] +|=== +| Attribute| Required?| Runtime Expression?| Description + +| accesskey +| false +| true +| HTML Standard Attribute + +| alt +| false +| true +| HTML Optional Attribute + +| autocomplete +| false +| true +| Common Optional Attribute + +| cssClass +| false +| true +| Equivalent to "class" - HTML Optional Attribute + +| cssErrorClass +| false +| true +| Equivalent to "class" - HTML Optional Attribute. Used when the bound field has errors. + +| cssStyle +| false +| true +| Equivalent to "style" - HTML Optional Attribute + +| dir +| false +| true +| HTML Standard Attribute + +| disabled +| false +| true +| HTML Optional Attribute. Setting the value of this attribute to 'true' (without the + quotes) will disable the HTML element. + +| htmlEscape +| false +| true +| Enable/disable HTML escaping of rendered values. + +| id +| false +| true +| HTML Standard Attribute + +| lang +| false +| true +| HTML Standard Attribute + +| maxlength +| false +| true +| HTML Optional Attribute + +| onblur +| false +| true +| HTML Event Attribute + +| onchange +| false +| true +| HTML Event Attribute + +| onclick +| false +| true +| HTML Event Attribute + +| ondblclick +| false +| true +| HTML Event Attribute + +| onfocus +| false +| true +| HTML Event Attribute + +| onkeydown +| false +| true +| HTML Event Attribute + +| onkeypress +| false +| true +| HTML Event Attribute + +| onkeyup +| false +| true +| HTML Event Attribute + +| onmousedown +| false +| true +| HTML Event Attribute + +| onmousemove +| false +| true +| HTML Event Attribute + +| onmouseout +| false +| true +| HTML Event Attribute + +| onmouseover +| false +| true +| HTML Event Attribute + +| onmouseup +| false +| true +| HTML Event Attribute + +| onselect +| false +| true +| HTML Event Attribute + +| path +| true +| true +| Path to property for data binding + +| readonly +| false +| true +| HTML Optional Attribute. Setting the value of this attribute to 'true' (without the + quotes) will make the HTML element readonly. + +| showPassword +| false +| true +| Is the password value to be shown? Defaults to false. + +| size +| false +| true +| HTML Optional Attribute + +| tabindex +| false +| true +| HTML Standard Attribute + +| title +| false +| true +| HTML Standard Attribute +|=== + + + + +[[spring-form.tld.radiobutton]] +=== the radiobutton tag + +Renders an HTML 'input' tag with type 'radio'. + +[[spring-form.tld.radiobutton.table]] +.Attributes +[cols="1,1,1,3"] +|=== +| Attribute| Required?| Runtime Expression?| Description + +| accesskey +| false +| true +| HTML Standard Attribute + +| cssClass +| false +| true +| Equivalent to "class" - HTML Optional Attribute + +| cssErrorClass +| false +| true +| Equivalent to "class" - HTML Optional Attribute. Used when the bound field has errors. + +| cssStyle +| false +| true +| Equivalent to "style" - HTML Optional Attribute + +| dir +| false +| true +| HTML Standard Attribute + +| disabled +| false +| true +| HTML Optional Attribute. Setting the value of this attribute to 'true' (without the + quotes) will disable the HTML element. + +| htmlEscape +| false +| true +| Enable/disable HTML escaping of rendered values. + +| id +| false +| true +| HTML Standard Attribute + +| label +| false +| true +| Value to be displayed as part of the tag + +| lang +| false +| true +| HTML Standard Attribute + +| onblur +| false +| true +| HTML Event Attribute + +| onchange +| false +| true +| HTML Event Attribute + +| onclick +| false +| true +| HTML Event Attribute + +| ondblclick +| false +| true +| HTML Event Attribute + +| onfocus +| false +| true +| HTML Event Attribute + +| onkeydown +| false +| true +| HTML Event Attribute + +| onkeypress +| false +| true +| HTML Event Attribute + +| onkeyup +| false +| true +| HTML Event Attribute + +| onmousedown +| false +| true +| HTML Event Attribute + +| onmousemove +| false +| true +| HTML Event Attribute + +| onmouseout +| false +| true +| HTML Event Attribute + +| onmouseover +| false +| true +| HTML Event Attribute + +| onmouseup +| false +| true +| HTML Event Attribute + +| path +| true +| true +| Path to property for data binding + +| tabindex +| false +| true +| HTML Standard Attribute + +| title +| false +| true +| HTML Standard Attribute + +| value +| false +| true +| HTML Optional Attribute +|=== + + + + +[[spring-form.tld.radiobuttons]] +=== the radiobuttons tag + +Renders multiple HTML 'input' tags with type 'radio'. + +[[spring-form.tld.radiobuttons.table]] +.Attributes +[cols="1,1,1,3"] +|=== +| Attribute| Required?| Runtime Expression?| Description + +| accesskey +| false +| true +| HTML Standard Attribute + +| cssClass +| false +| true +| Equivalent to "class" - HTML Optional Attribute + +| cssErrorClass +| false +| true +| Equivalent to "class" - HTML Optional Attribute. Used when the bound field has errors. + +| cssStyle +| false +| true +| Equivalent to "style" - HTML Optional Attribute + +| delimiter +| false +| true +| Delimiter to use between each 'input' tag with type 'radio'. There is no delimiter by + default. + +| dir +| false +| true +| HTML Standard Attribute + +| disabled +| false +| true +| HTML Optional Attribute. Setting the value of this attribute to 'true' (without the + quotes) will disable the HTML element. + +| element +| false +| true +| Specifies the HTML element that is used to enclose each 'input' tag with type 'radio'. + Defaults to 'span'. + +| htmlEscape +| false +| true +| Enable/disable HTML escaping of rendered values. + +| id +| false +| true +| HTML Standard Attribute + +| itemLabel +| false +| true +| Value to be displayed as part of the 'input' tags with type 'radio' + +| items +| true +| true +| The Collection, Map or array of objects used to generate the 'input' tags with type + 'radio' + +| itemValue +| false +| true +| Name of the property mapped to 'value' attribute of the 'input' tags with type 'radio' + +| lang +| false +| true +| HTML Standard Attribute + +| onblur +| false +| true +| HTML Event Attribute + +| onchange +| false +| true +| HTML Event Attribute + +| onclick +| false +| true +| HTML Event Attribute + +| ondblclick +| false +| true +| HTML Event Attribute + +| onfocus +| false +| true +| HTML Event Attribute + +| onkeydown +| false +| true +| HTML Event Attribute + +| onkeypress +| false +| true +| HTML Event Attribute + +| onkeyup +| false +| true +| HTML Event Attribute + +| onmousedown +| false +| true +| HTML Event Attribute + +| onmousemove +| false +| true +| HTML Event Attribute + +| onmouseout +| false +| true +| HTML Event Attribute + +| onmouseover +| false +| true +| HTML Event Attribute + +| onmouseup +| false +| true +| HTML Event Attribute + +| path +| true +| true +| Path to property for data binding + +| tabindex +| false +| true +| HTML Standard Attribute + +| title +| false +| true +| HTML Standard Attribute +|=== + + + + +[[spring-form.tld.select]] +=== the select tag + +Renders an HTML 'select' element. Supports databinding to the selected option. + +[[spring-form.tld.select.table]] +.Attributes +[cols="1,1,1,3"] +|=== +| Attribute| Required?| Runtime Expression?| Description + +| accesskey +| false +| true +| HTML Standard Attribute + +| cssClass +| false +| true +| Equivalent to "class" - HTML Optional Attribute + +| cssErrorClass +| false +| true +| Equivalent to "class" - HTML Optional Attribute. Used when the bound field has errors. + +| cssStyle +| false +| true +| Equivalent to "style" - HTML Optional Attribute + +| dir +| false +| true +| HTML Standard Attribute + +| disabled +| false +| true +| HTML Optional Attribute. Setting the value of this attribute to 'true' (without the + quotes) will disable the HTML element. + +| htmlEscape +| false +| true +| Enable/disable HTML escaping of rendered values. + +| id +| false +| true +| HTML Standard Attribute + +| itemLabel +| false +| true +| Name of the property mapped to the inner text of the 'option' tag + +| items +| false +| true +| The Collection, Map or array of objects used to generate the inner 'option' tags + +| itemValue +| false +| true +| Name of the property mapped to 'value' attribute of the 'option' tag + +| lang +| false +| true +| HTML Standard Attribute + +| multiple +| false +| true +| HTML Optional Attribute + +| onblur +| false +| true +| HTML Event Attribute + +| onchange +| false +| true +| HTML Event Attribute + +| onclick +| false +| true +| HTML Event Attribute + +| ondblclick +| false +| true +| HTML Event Attribute + +| onfocus +| false +| true +| HTML Event Attribute + +| onkeydown +| false +| true +| HTML Event Attribute + +| onkeypress +| false +| true +| HTML Event Attribute + +| onkeyup +| false +| true +| HTML Event Attribute + +| onmousedown +| false +| true +| HTML Event Attribute + +| onmousemove +| false +| true +| HTML Event Attribute + +| onmouseout +| false +| true +| HTML Event Attribute + +| onmouseover +| false +| true +| HTML Event Attribute + +| onmouseup +| false +| true +| HTML Event Attribute + +| path +| true +| true +| Path to property for data binding + +| size +| false +| true +| HTML Optional Attribute + +| tabindex +| false +| true +| HTML Standard Attribute + +| title +| false +| true +| HTML Standard Attribute +|=== + + + + +[[spring-form.tld.textarea]] +=== the textarea tag + +Renders an HTML 'textarea'. + +[[spring-form.tld.textarea.table]] +.Attributes +[cols="1,1,1,3"] +|=== +| Attribute| Required?| Runtime Expression?| Description + +| accesskey +| false +| true +| HTML Standard Attribute + +| cols +| false +| true +| HTML Required Attribute + +| cssClass +| false +| true +| Equivalent to "class" - HTML Optional Attribute + +| cssErrorClass +| false +| true +| Equivalent to "class" - HTML Optional Attribute. Used when the bound field has errors. + +| cssStyle +| false +| true +| Equivalent to "style" - HTML Optional Attribute + +| dir +| false +| true +| HTML Standard Attribute + +| disabled +| false +| true +| HTML Optional Attribute. Setting the value of this attribute to 'true' (without the + quotes) will disable the HTML element. + +| htmlEscape +| false +| true +| Enable/disable HTML escaping of rendered values. + +| id +| false +| true +| HTML Standard Attribute + +| lang +| false +| true +| HTML Standard Attribute + +| onblur +| false +| true +| HTML Event Attribute + +| onchange +| false +| true +| HTML Event Attribute + +| onclick +| false +| true +| HTML Event Attribute + +| ondblclick +| false +| true +| HTML Event Attribute + +| onfocus +| false +| true +| HTML Event Attribute + +| onkeydown +| false +| true +| HTML Event Attribute + +| onkeypress +| false +| true +| HTML Event Attribute + +| onkeyup +| false +| true +| HTML Event Attribute + +| onmousedown +| false +| true +| HTML Event Attribute + +| onmousemove +| false +| true +| HTML Event Attribute + +| onmouseout +| false +| true +| HTML Event Attribute + +| onmouseover +| false +| true +| HTML Event Attribute + +| onmouseup +| false +| true +| HTML Event Attribute + +| onselect +| false +| true +| HTML Event Attribute + +| path +| true +| true +| Path to property for data binding + +| readonly +| false +| true +| HTML Optional Attribute. Setting the value of this attribute to 'true' (without the + quotes) will make the HTML element readonly. + +| rows +| false +| true +| HTML Required Attribute + +| tabindex +| false +| true +| HTML Standard Attribute + +| title +| false +| true +| HTML Standard Attribute +|=== diff --git a/src/asciidoc/spring-tld.adoc b/src/asciidoc/spring-tld.adoc new file mode 100644 index 000000000000..4b58af26a322 --- /dev/null +++ b/src/asciidoc/spring-tld.adoc @@ -0,0 +1,452 @@ +[[spring.tld]] +== spring.tld + + + + +[[spring.tld-intro]] +=== Introduction +One of the view technologies you can use with the Spring Framework is Java Server Pages +(JSPs). To help you implement views using Java Server Pages the Spring Framework +provides you with some tags for evaluating errors, setting themes and outputting +internationalized messages. + +Please note that the various tags generated by this form tag library are compliant with +the http://www.w3.org/TR/xhtml1/[XHTML-1.0-Strict specification] and attendant +http://www.w3.org/TR/xhtml1/dtds.html#a_dtd_XHTML-1.0-Strict[DTD]. + +This appendix describes the `spring.tld` tag library. + +* <> +* <> +* <> +* <> +* <> +* <> +* <> +* <> +* <> +* <> + + + + +[[spring.tld.bind]] +=== the bind tag + +Provides BindStatus object for the given bind path. The HTML escaping flag participates +in a page-wide or application-wide setting (i.e. by HtmlEscapeTag or a +"defaultHtmlEscape" context-param in web.xml). + +[[spring.tld.bind.table]] +.Attributes +[cols="1,1,1,3"] +|=== +| Attribute| Required?| Runtime Expression?| Description + +| htmlEscape +| false +| true +| Set HTML escaping for this tag, as boolean value. Overrides the default HTML escaping + setting for the current page. + +| ignoreNestedPath +| false +| true +| Set whether to ignore a nested path, if any. Default is to not ignore. + +| path +| true +| true +| The path to the bean or bean property to bind status information for. For instance + account.name, company.address.zipCode or just employee. The status object will + exported to the page scope, specifically for this bean or bean property +|=== + + + + +[[spring.tld.escapeBody]] +=== the escapeBody tag + +Escapes its enclosed body content, applying HTML escaping and/or JavaScript escaping. +The HTML escaping flag participates in a page-wide or application-wide setting (i.e. by +HtmlEscapeTag or a "defaultHtmlEscape" context-param in web.xml). + +[[spring.tld.escapeBody.table]] +.Attributes +[cols="1,1,1,3"] +|=== +| Attribute| Required?| Runtime Expression?| Description + +| htmlEscape +| false +| true +| Set HTML escaping for this tag, as boolean value. Overrides the default HTML escaping + setting for the current page. + +| javaScriptEscape +| false +| true +| Set JavaScript escaping for this tag, as boolean value. Default is false. +|=== + + + + +[[spring.tld.hasBindErrors]] +=== the hasBindErrors tag + +Provides Errors instance in case of bind errors. The HTML escaping flag participates in +a page-wide or application-wide setting (i.e. by HtmlEscapeTag or a "defaultHtmlEscape" +context-param in web.xml). + +[[spring.tld.hasBindErrors.table]] +.Attributes +[cols="1,1,1,3"] +|=== +| Attribute| Required?| Runtime Expression?| Description + +| htmlEscape +| false +| true +| Set HTML escaping for this tag, as boolean value. Overrides the default HTML escaping + setting for the current page. + +| name +| true +| true +| The name of the bean in the request, that needs to be inspected for errors. If errors + are available for this bean, they will be bound under the 'errors' key. +|=== + + + + +[[spring.tld.htmlEscape]] +=== the htmlEscape tag + +Sets default HTML escape value for the current page. Overrides a "defaultHtmlEscape" +context-param in web.xml, if any. + +[[spring.tld.htmlEscape.table]] +.Attributes +[cols="1,1,1,3"] +|=== +| Attribute| Required?| Runtime Expression?| Description + +| defaultHtmlEscape +| true +| true +| Set the default value for HTML escaping, to be put into the current PageContext. +|=== + + + + +[[spring.tld.message]] +=== the message tag + +Retrieves the message with the given code, or text if code isn't resolvable. The HTML +escaping flag participates in a page-wide or application-wide setting (i.e. by +HtmlEscapeTag or a "defaultHtmlEscape" context-param in web.xml). + +[[spring.tld.message.table]] +.Attributes +[cols="1,1,1,3"] +|=== +| Attribute| Required?| Runtime Expression?| Description + +| arguments +| false +| true +| Set optional message arguments for this tag, as a (comma-)delimited String (each + String argument can contain JSP EL), an Object array (used as argument array), or a + single Object (used as single argument). + +| argumentSeparator +| false +| true +| The separator character to be used for splitting the arguments string value; defaults + to a 'comma' (','). + +| code +| false +| true +| The code (key) to use when looking up the message. If code is not provided, the text + attribute will be used. + +| htmlEscape +| false +| true +| Set HTML escaping for this tag, as boolean value. Overrides the default HTML escaping + setting for the current page. + +| javaScriptEscape +| false +| true +| Set JavaScript escaping for this tag, as boolean value. Default is false. + +| message +| false +| true +| A MessageSourceResolvable argument (direct or through JSP EL). Fits nicely when used + in conjunction with Spring's own validation error classes which all implement the + MessageSourceResolvable interface. For example, this allows you to iterate over all of + the errors in a form, passing each error (using a runtime expression) as the value of + this 'message' attribute, thus effecting the easy display of such error messages. + +| scope +| false +| true +| The scope to use when exporting the result to a variable. This attribute is only used + when var is also set. Possible values are page, request, session and application. + +| text +| false +| true +| Default text to output when a message for the given code could not be found. If both + text and code are not set, the tag will output null. + +| var +| false +| true +| The string to use when binding the result to the page, request, session or application + scope. If not specified, the result gets outputted to the writer (i.e. typically + directly to the JSP). +|=== + + + + +[[spring.tld.nestedPath]] +=== the nestedPath tag + +Sets a nested path to be used by the bind tag's path. + +[[spring.tld.nestedPath.table]] +.Attributes +[cols="1,1,1,3"] +|=== +| Attribute| Required?| Runtime Expression?| Description + +| path +| true +| true +| Set the path that this tag should apply. E.g. 'customer' to allow bind paths like + 'address.street' rather than 'customer.address.street'. +|=== + + + + +[[spring.tld.theme]] +=== the theme tag + +Retrieves the theme message with the given code, or text if code isn't resolvable. The +HTML escaping flag participates in a page-wide or application-wide setting (i.e. by +HtmlEscapeTag or a "defaultHtmlEscape" context-param in web.xml). + +[[spring.tld.theme.table]] +.Attributes +[cols="1,1,1,3"] +|=== +| Attribute| Required?| Runtime Expression?| Description + +| arguments +| false +| true +| Set optional message arguments for this tag, as a (comma-)delimited String (each + String argument can contain JSP EL), an Object array (used as argument array), or a + single Object (used as single argument). + +| argumentSeparator +| false +| true +| The separator character to be used for splitting the arguments string value; defaults + to a 'comma' (','). + +| code +| false +| true +| The code (key) to use when looking up the message. If code is not provided, the text + attribute will be used. + +| htmlEscape +| false +| true +| Set HTML escaping for this tag, as boolean value. Overrides the default HTML escaping + setting for the current page. + +| javaScriptEscape +| false +| true +| Set JavaScript escaping for this tag, as boolean value. Default is false. + +| message +| false +| true +| A MessageSourceResolvable argument (direct or through JSP EL). + +| scope +| false +| true +| The scope to use when exporting the result to a variable. This attribute is only used + when var is also set. Possible values are page, request, session and application. + +| text +| false +| true +| Default text to output when a message for the given code could not be found. If both + text and code are not set, the tag will output null. + +| var +| false +| true +| The string to use when binding the result to the page, request, session or application + scope. If not specified, the result gets outputted to the writer (i.e. typically + directly to the JSP). +|=== + + + + +[[spring.tld.transform]] +=== the transform tag + +Provides transformation of variables to Strings, using an appropriate custom +PropertyEditor from BindTag (can only be used inside BindTag). The HTML escaping flag +participates in a page-wide or application-wide setting (i.e. by HtmlEscapeTag or a +'defaultHtmlEscape' context-param in web.xml). + +[[spring.tld.transform.table]] +.Attributes +[cols="1,1,1,3"] +|=== +| Attribute| Required?| Runtime Expression?| Description + +| htmlEscape +| false +| true +| Set HTML escaping for this tag, as boolean value. Overrides the default HTML escaping + setting for the current page. + +| scope +| false +| true +| The scope to use when exported the result to a variable. This attribute is only used + when var is also set. Possible values are page, request, session and application. + +| value +| true +| true +| The value to transform. This is the actual object you want to have transformed (for + instance a Date). Using the PropertyEditor that is currently in use by the + 'spring:bind' tag. + +| var +| false +| true +| The string to use when binding the result to the page, request, session or application + scope. If not specified, the result gets outputted to the writer (i.e. typically + directly to the JSP). +|=== + + + + +[[spring.tld.url]] +=== the url tag + +Creates URLs with support for URI template variables, HTML/XML escaping, and Javascript +escaping. Modeled after the JSTL c:url tag with backwards compatibility in mind. + +[[spring.tld.url.table]] +.Attributes +[cols="1,1,1,3"] +|=== +| Attribute| Required?| Runtime Expression?| Description + +| url +| true +| true +| The URL to build. This value can include template {placeholders} that are replaced + with the URL encoded value of the named parameter. Parameters must be defined using + the param tag inside the body of this tag. + +| context +| false +| true +| Specifies a remote application context path. The default is the current application + context path. + +| var +| false +| true +| The name of the variable to export the URL value to. If not specified the URL is + written as output. + +| scope +| false +| true +| The scope for the var. 'application', 'session', 'request' and 'page' scopes are + supported. Defaults to page scope. This attribute has no effect unless the var + attribute is also defined. + +| htmlEscape +| false +| true +| Set HTML escaping for this tag, as a boolean value. Overrides the default HTML + escaping setting for the current page. + +| javaScriptEscape +| false +| true +| Set JavaScript escaping for this tag, as a boolean value. Default is false. +|=== + + + + +[[spring.tld.eval]] +=== the eval tag + +Evaluates a Spring expression (SpEL) and either prints the result or assigns it to a +variable. + +[[spring.tld.eval.table]] +[cols="1,1,1,3"] +.Attributes +|=== +| Attribute| Required?| Runtime Expression?| Description + +| expression +| true +| true +| The expression to evaluate. + +| var +| false +| true +| The name of the variable to export the evaluation result to. If not specified the + evaluation result is converted to a String and written as output. + +| scope +| false +| true +| The scope for the var. 'application', 'session', 'request' and 'page' scopes are + supported. Defaults to page scope. This attribute has no effect unless the var + attribute is also defined. + +| htmlEscape +| false +| true +| Set HTML escaping for this tag, as a boolean value. Overrides the default HTML + escaping setting for the current page. + +| javaScriptEscape +| false +| true +| Set JavaScript escaping for this tag, as a boolean value. Default is false. +|=== + diff --git a/src/asciidoc/testing.adoc b/src/asciidoc/testing.adoc new file mode 100644 index 000000000000..43e9d14fcc54 --- /dev/null +++ b/src/asciidoc/testing.adoc @@ -0,0 +1,4216 @@ +[[testing]] +== Testing + + + + +[[testing-introduction]] +=== Introduction to Spring Testing +Testing is an integral part of enterprise software development. This chapter focuses on +the value-add of the IoC principle to <> and on the benefits +of the Spring Framework's support for <>. __(A +thorough treatment of testing in the enterprise is beyond the scope of this reference +manual.)__ + + + + +[[unit-testing]] +=== Unit Testing +Dependency Injection should make your code less dependent on the container than it would +be with traditional Java EE development. The POJOs that make up your application should +be testable in JUnit or TestNG tests, with objects simply instantiated using the `new` +operator, __without Spring or any other container__. You can use <> (in conjunction with other valuable testing techniques) to test your code in +isolation. If you follow the architecture recommendations for Spring, the resulting +clean layering and componentization of your codebase will facilitate easier unit +testing. For example, you can test service layer objects by stubbing or mocking DAO or +Repository interfaces, without needing to access persistent data while running unit +tests. + +True unit tests typically run extremely quickly, as there is no runtime infrastructure +to set up. Emphasizing true unit tests as part of your development methodology will +boost your productivity. You may not need this section of the testing chapter to help +you write effective unit tests for your IoC-based applications. For certain unit testing +scenarios, however, the Spring Framework provides the following mock objects and testing +support classes. + + + +[[mock-objects]] +==== Mock Objects + + +[[mock-objects-env]] +===== Environment +The `org.springframework.mock.env` package contains mock implementations of the +`Environment` and `PropertySource` abstractions (see <> +and <>). `MockEnvironment` and +`MockPropertySource` are useful for developing __out-of-container__ tests for code that +depends on environment-specific properties. + + +[[mock-objects-jndi]] +===== JNDI +The `org.springframework.mock.jndi` package contains an implementation of the JNDI SPI, +which you can use to set up a simple JNDI environment for test suites or stand-alone +applications. If, for example, JDBC ++DataSource++s get bound to the same JNDI names in +test code as within a Java EE container, you can reuse both application code and +configuration in testing scenarios without modification. + + +[[mock-objects-servlet]] +===== Servlet API +The `org.springframework.mock.web` package contains a comprehensive set of Servlet API +mock objects, targeted at usage with Spring's Web MVC framework, which are useful for +testing web contexts and controllers. These mock objects are generally more convenient +to use than dynamic mock objects such as http://www.easymock.org[EasyMock] or existing +Servlet API mock objects such as http://www.mockobjects.com[MockObjects]. + + +[[mock-objects-portlet]] +===== Portlet API +The `org.springframework.mock.web.portlet` package contains a set of Portlet API mock +objects, targeted at usage with Spring's Portlet MVC framework. + + + +[[unit-testing-support-classes]] +==== Unit Testing support Classes + + +[[unit-testing-utilities]] +===== General utilities +The `org.springframework.test.util` package contains `ReflectionTestUtils`, which is a +collection of reflection-based utility methods. Developers use these methods in unit and +integration testing scenarios in which they need to set a non- `public` field or invoke +a non- `public` setter method when testing application code involving, for example: + +* ORM frameworks such as JPA and Hibernate that condone `private` or `protected` field + access as opposed to `public` setter methods for properties in a domain entity. +* Spring's support for annotations such as `@Autowired`, `@Inject`, and `@Resource,` + which provides dependency injection for `private` or `protected` fields, setter + methods, and configuration methods. + + +[[unit-testing-spring-mvc]] +===== Spring MVC +The `org.springframework.test.web` package contains `ModelAndViewAssert`, which you can +use in combination with JUnit, TestNG, or any other testing framework for unit tests +dealing with Spring MVC `ModelAndView` objects. + +.Unit testing Spring MVC Controllers +[TIP] +==== +To test your Spring MVC ++Controller++s, use `ModelAndViewAssert` combined with +`MockHttpServletRequest`, `MockHttpSession`, and so on from the <> package. + +Note: As of Spring 4.0, the set of mocks in the `org.springframework.mock.web` package +is now based on the Servlet 3.0 API. +==== + + + + +[[integration-testing]] +=== Integration Testing + + + +[[integration-testing-overview]] +==== Overview +It is important to be able to perform some integration testing without requiring +deployment to your application server or connecting to other enterprise infrastructure. +This will enable you to test things such as: + +* The correct wiring of your Spring IoC container contexts. +* Data access using JDBC or an ORM tool. This would include such things as the + correctness of SQL statements, Hibernate queries, JPA entity mappings, etc. + +The Spring Framework provides first-class support for integration testing in the +`spring-test` module. The name of the actual JAR file might include the release version +and might also be in the long `org.springframework.test` form, depending on where you +get it from (see the <> for an +explanation). This library includes the `org.springframework.test` package, which +contains valuable classes for integration testing with a Spring container. This testing +does not rely on an application server or other deployment environment. Such tests are +slower to run than unit tests but much faster than the equivalent Selenium tests or remote +tests that rely on deployment to an application server. + +In Spring 2.5 and later, unit and integration testing support is provided in the form of +the annotation-driven <>. The +TestContext framework is agnostic of the actual testing framework in use, thus allowing +instrumentation of tests in various environments including JUnit, TestNG, and so on. + + + +[[integration-testing-goals]] +==== Goals of Integration Testing +Spring's integration testing support has the following primary goals: + +* To manage <> between test + execution. +* To provide <>. +* To provide <> appropriate to integration testing. +* To supply <> that assist + developers in writing integration tests. + +The next few sections describe each goal and provide links to implementation and +configuration details. + + +[[testing-ctx-management]] +===== Context management and caching +The Spring TestContext Framework provides consistent loading of Spring +++ApplicationContext++s and ++WebApplicationContext++s as well as caching of those +contexts. Support for the caching of loaded contexts is important, because startup time +can become an issue -- not because of the overhead of Spring itself, but because the +objects instantiated by the Spring container take time to instantiate. For example, a +project with 50 to 100 Hibernate mapping files might take 10 to 20 seconds to load the +mapping files, and incurring that cost before running every test in every test fixture +leads to slower overall test runs that reduce developer productivity. + +Test classes typically declare either an array of __resource locations__ for XML +configuration metadata -- often in the classpath -- or an array of __annotated classes__ +that is used to configure the application. These locations or classes are the same as or +similar to those specified in `web.xml` or other deployment configuration files. + +By default, once loaded, the configured `ApplicationContext` is reused for each test. +Thus the setup cost is incurred only once per test suite, and subsequent test execution +is much faster. In this context, the term __test suite__ means all tests run in the same +JVM -- for example, all tests run from an Ant, Maven, or Gradle build for a given +project or module. In the unlikely case that a test corrupts the application context and +requires reloading -- for example, by modifying a bean definition or the state of an +application object -- the TestContext framework can be configured to reload the +configuration and rebuild the application context before executing the next test. + +See <> and <> with the +TestContext framework. + + +[[testing-fixture-di]] +===== Dependency Injection of test fixtures +When the TestContext framework loads your application context, it can optionally +configure instances of your test classes via Dependency Injection. This provides a +convenient mechanism for setting up test fixtures using preconfigured beans from your +application context. A strong benefit here is that you can reuse application contexts +across various testing scenarios (e.g., for configuring Spring-managed object graphs, +transactional proxies, ++DataSource++s, etc.), thus avoiding the need to duplicate +complex test fixture setup for individual test cases. + +As an example, consider the scenario where we have a class, `HibernateTitleRepository`, +that implements data access logic for a `Title` domain entity. We want to write +integration tests that test the following areas: + +* The Spring configuration: basically, is everything related to the configuration of the + `HibernateTitleRepository` bean correct and present? +* The Hibernate mapping file configuration: is everything mapped correctly, and are the + correct lazy-loading settings in place? +* The logic of the `HibernateTitleRepository`: does the configured instance of this + class perform as anticipated? + +See dependency injection of test fixtures with the <>. + + +[[testing-tx]] +===== Transaction management +One common issue in tests that access a real database is their effect on the state of +the persistence store. Even when you're using a development database, changes to the +state may affect future tests. Also, many operations -- such as inserting or modifying +persistent data -- cannot be performed (or verified) outside a transaction. + +The TestContext framework addresses this issue. By default, the framework will create +and roll back a transaction for each test. You simply write code that can assume the +existence of a transaction. If you call transactionally proxied objects in your tests, +they will behave correctly, according to their configured transactional semantics. In +addition, if a test method deletes the contents of selected tables while running within +the transaction managed for the test, the transaction will roll back by default, and the +database will return to its state prior to execution of the test. Transactional support +is provided to a test via a `PlatformTransactionManager` bean defined in the test's +application context. + +If you want a transaction to commit -- unusual, but occasionally useful when you want a +particular test to populate or modify the database -- the TestContext framework can be +instructed to cause the transaction to commit instead of roll back via the +<> and +<> annotations. + +See transaction management with the <>. + + +[[testing-support-classes]] +===== Support classes for integration testing +The Spring TestContext Framework provides several `abstract` support classes that +simplify the writing of integration tests. These base test classes provide well-defined +hooks into the testing framework as well as convenient instance variables and methods, +which enable you to access: + +* The `ApplicationContext`, for performing explicit bean lookups or testing the state of + the context as a whole. +* A `JdbcTemplate`, for executing SQL statements to query the database. Such queries can + be used to confirm database state both __prior to__ and __after__ execution of + database-related application code, and Spring ensures that such queries run in the + scope of the same transaction as the application code. When used in conjunction with + an ORM tool, be sure to avoid <>. + +In addition, you may want to create your own custom, application-wide superclass with +instance variables and methods specific to your project. + +See support classes for the <>. + + + +[[integration-testing-support-jdbc]] +==== JDBC Testing Support +The `org.springframework.test.jdbc` package contains `JdbcTestUtils`, which is a +collection of JDBC related utility functions intended to simplify standard database +testing scenarios. Specifically, `JdbcTestUtils` provides the following static utility +methods. + +* `countRowsInTable(..)`: counts the number of rows in the given table +* `countRowsInTableWhere(..)`: counts the number of rows in the given table, using +the provided `WHERE` clause +* `deleteFromTables(..)`: deletes all rows from the specified tables +* `deleteFromTableWhere(..)`: deletes rows from the given table, using the provided +`WHERE` clause +* `dropTables(..)`: drops the specified tables + +__Note that <> and +<> +provide convenience methods which delegate to the aforementioned methods in +`JdbcTestUtils`.__ + +The `spring-jdbc` module provides support for configuring and launching an embedded +database which can be used in integration tests that interact with a database. For +details, see <> and +<>. + + + +[[integration-testing-annotations]] +==== Annotations + + +[[integration-testing-annotations-spring]] +===== Spring Testing Annotations +The Spring Framework provides the following set of __Spring-specific__ annotations that +you can use in your unit and integration tests in conjunction with the TestContext +framework. Refer to the corresponding javadocs for further information, including +default attribute values, attribute aliases, and so on. + +* `@ContextConfiguration` + ++ + +Defines class-level metadata that is used to determine how to load and configure an +`ApplicationContext` for integration tests. Specifically, `@ContextConfiguration` +declares the application context resource `locations` or the annotated `classes` +that will be used to load the context. + ++ + +Resource locations are typically XML configuration files located in the classpath; +whereas, annotated classes are typically `@Configuration` classes. However, resource +locations can also refer to files in the file system, and annotated classes can be +component classes, etc. + ++ + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + **@ContextConfiguration**("/test-config.xml") + public class XmlApplicationContextTests { + // class body... + } +---- + ++ + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + **@ContextConfiguration**(**classes** = TestConfig.class) + public class ConfigClassApplicationContextTests { + // class body... + } +---- + ++ + +As an alternative or in addition to declaring resource locations or annotated classes, +`@ContextConfiguration` may be used to declare `ApplicationContextInitializer` classes. + ++ + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + **@ContextConfiguration**(**initializers** = CustomContextIntializer.class) + public class ContextInitializerTests { + // class body... + } +---- + ++ + +`@ContextConfiguration` may optionally be used to declare the `ContextLoader` strategy +as well. Note, however, that you typically do not need to explicitly configure the +loader since the default loader supports either resource `locations` or annotated +`classes` as well as `initializers`. + ++ + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + **@ContextConfiguration**(**locations** = "/test-context.xml", **loader** = CustomContextLoader.class) + public class CustomLoaderXmlApplicationContextTests { + // class body... + } +---- + ++ + +[NOTE] +==== +`@ContextConfiguration` provides support for __inheriting__ resource locations or +configuration classes as well as context initializers declared by superclasses by +default. +==== + ++ + +See <> and the `@ContextConfiguration` javadocs for +further details. + +* `@WebAppConfiguration` + ++ + +A class-level annotation that is used to declare that the `ApplicationContext` loaded +for an integration test should be a `WebApplicationContext`. The mere presence of +`@WebAppConfiguration` on a test class ensures that a `WebApplicationContext` will be +loaded for the test, using the default value of `"file:src/main/webapp"` for the path to +the root of the web application (i.e., the __resource base path__). The resource base +path is used behind the scenes to create a `MockServletContext` which serves as the +`ServletContext` for the test's `WebApplicationContext`. + ++ + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @ContextConfiguration + **@WebAppConfiguration** + public class WebAppTests { + // class body... + } +---- + ++ + +To override the default, specify a different base resource path via the __implicit__ +`value` attribute. Both `classpath:` and `file:` resource prefixes are supported. If no +resource prefix is supplied the path is assumed to be a file system resource. + ++ + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @ContextConfiguration + **@WebAppConfiguration("classpath:test-web-resources")** + public class WebAppTests { + // class body... + } +---- + ++ + +Note that `@WebAppConfiguration` must be used in conjunction with +`@ContextConfiguration`, either within a single test class or within a test class +hierarchy. See the `@WebAppConfiguration` javadocs for further details. + ++ + +* `@ContextHierarchy` + ++ + +A class-level annotation that is used to define a hierarchy of ++ApplicationContext++s +for integration tests. `@ContextHierarchy` should be declared with a list of one or more +`@ContextConfiguration` instances, each of which defines a level in the context +hierarchy. The following examples demonstrate the use of `@ContextHierarchy` within a +single test class; however, `@ContextHierarchy` can also be used within a test class +hierarchy. + ++ + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @ContextHierarchy({ + @ContextConfiguration("/parent-config.xml"), + @ContextConfiguration("/child-config.xml") + }) + public class ContextHierarchyTests { + // class body... + } +---- + ++ + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @WebAppConfiguration + @ContextHierarchy({ + @ContextConfiguration(classes = AppConfig.class), + @ContextConfiguration(classes = WebConfig.class) + }) + public class WebIntegrationTests { + // class body... + } +---- + ++ + +If you need to merge or override the configuration for a given level of the context +hierarchy within a test class hierarchy, you must explicitly name that level by +supplying the same value to the `name` attribute in `@ContextConfiguration` at each +corresponding level in the class hierarchy. See +<> and the `@ContextHierarchy` javadocs +for further examples. + +* `@ActiveProfiles` + ++ + +A class-level annotation that is used to declare which __bean definition profiles__ +should be active when loading an `ApplicationContext` for test classes. + ++ + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @ContextConfiguration + **@ActiveProfiles**("dev") + public class DeveloperTests { + // class body... + } +---- + ++ + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @ContextConfiguration + **@ActiveProfiles**({"dev", "integration"}) + public class DeveloperIntegrationTests { + // class body... + } +---- + ++ + +[NOTE] +==== +`@ActiveProfiles` provides support for __inheriting__ active bean definition profiles +declared by superclasses by default. It is also possible to resolve active bean +definition profiles programmatically by implementing a custom +<> +and registering it via the `resolver` attribute of `@ActiveProfiles`. +==== + ++ + +See <> and the `@ActiveProfiles` javadocs +for examples and further details. + +* `@TestPropertySource` + ++ + +A class-level annotation that is used to configure the locations of properties files and +inlined properties to be added to the `Environment`'s set of `PropertySources` for an +`ApplicationContext` loaded for an integration test. + ++ + +Test property sources have higher precedence than those loaded from the operating +system's environment or Java system properties as well as property sources added by the +application declaratively via `@PropertySource` or programmatically. Thus, test property +sources can be used to selectively override properties defined in system and application +property sources. Furthermore, inlined properties have higher precedence than properties +loaded from resource locations. + ++ + +The following example demonstrates how to declare a properties file from the classpath. + ++ + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @ContextConfiguration + **@TestPropertySource**("/test.properties") + public class MyIntegrationTests { + // class body... + } +---- + ++ + +The following example demonstrates how to declare _inlined_ properties. + ++ + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @ContextConfiguration + **@TestPropertySource**(properties = { "timezone = GMT", "port: 4242" }) + public class MyIntegrationTests { + // class body... + } +---- + +* `@DirtiesContext` + ++ + +Indicates that the underlying Spring `ApplicationContext` has been __dirtied__ during +the execution of a test (i.e., modified or corrupted in some manner -- for example, by +changing the state of a singleton bean) and should be closed, regardless of whether the +test passed. When an application context is marked __dirty__, it is removed from the +testing framework's cache and closed. As a consequence, the underlying Spring container +will be rebuilt for any subsequent test that requires a context with the same +configuration metadata. + ++ + +`@DirtiesContext` can be used as both a class-level and method-level annotation within +the same test class. In such scenarios, the `ApplicationContext` is marked as __dirty__ +after any such annotated method as well as after the entire class. If the `ClassMode` is +set to `AFTER_EACH_TEST_METHOD`, the context is marked dirty after each test method in +the class. + ++ + +The following examples explain when the context would be dirtied for various +configuration scenarios: + ++ + +** After the current test class, when declared on a class with class mode set to +`AFTER_CLASS` (i.e., the default class mode). + ++ + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + **@DirtiesContext** + public class ContextDirtyingTests { + // some tests that result in the Spring container being dirtied + } +---- + ++ + +** After each test method in the current test class, when declared on a class with class +mode set to `AFTER_EACH_TEST_METHOD.` + ++ + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + **@DirtiesContext**(**classMode** = ClassMode.AFTER_EACH_TEST_METHOD) + public class ContextDirtyingTests { + // some tests that result in the Spring container being dirtied + } +---- + ++ + +** After the current test, when declared on a method. + ++ + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + **@DirtiesContext** + @Test + public void testProcessWhichDirtiesAppCtx() { + // some logic that results in the Spring container being dirtied + } +---- + ++ + +If `@DirtiesContext` is used in a test whose context is configured as part of a context +hierarchy via `@ContextHierarchy`, the `hierarchyMode` flag can be used to control how +the context cache is cleared. By default an __exhaustive__ algorithm will be used that +clears the context cache including not only the current level but also all other context +hierarchies that share an ancestor context common to the current test; all +++ApplicationContext++s that reside in a sub-hierarchy of the common ancestor context +will be removed from the context cache and closed. If the __exhaustive__ algorithm is +overkill for a particular use case, the simpler __current level__ algorithm can be +specified instead, as seen below. + ++ + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @ContextHierarchy({ + @ContextConfiguration("/parent-config.xml"), + @ContextConfiguration("/child-config.xml") + }) + public class BaseTests { + // class body... + } + + public class ExtendedTests extends BaseTests { + + @Test + @DirtiesContext(**hierarchyMode = HierarchyMode.CURRENT_LEVEL**) + public void test() { + // some logic that results in the child context being dirtied + } + } +---- + ++ + +For further details regarding the `EXHAUSTIVE` and `CURRENT_LEVEL` algorithms see the +`DirtiesContext.HierarchyMode` javadocs. + +* `@TestExecutionListeners` + ++ + +Defines class-level metadata for configuring which ++TestExecutionListener++s should be +registered with the `TestContextManager`. Typically, `@TestExecutionListeners` is used +in conjunction with `@ContextConfiguration`. + ++ + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @ContextConfiguration + **@TestExecutionListeners**({CustomTestExecutionListener.class, AnotherTestExecutionListener.class}) + public class CustomTestExecutionListenerTests { + // class body... + } +---- + ++ + +`@TestExecutionListeners` supports __inherited__ listeners by default. See the javadocs +for an example and further details. + +* `@TransactionConfiguration` + ++ + +Defines class-level metadata for configuring transactional tests. Specifically, the bean +name of the `PlatformTransactionManager` that should be used to drive transactions can +be explicitly specified if there are multiple beans of type `PlatformTransactionManager` +in the test's `ApplicationContext` and if the bean name of the desired +`PlatformTransactionManager` is not "transactionManager". In addition, you can change +the `defaultRollback` flag to `false`. Typically, `@TransactionConfiguration` is used in +conjunction with `@ContextConfiguration`. + ++ + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @ContextConfiguration + **@TransactionConfiguration**(**transactionManager** = "txMgr", **defaultRollback** = false) + public class CustomConfiguredTransactionalTests { + // class body... + } +---- + ++ + +[NOTE] +==== +If the default conventions are sufficient for your test configuration, you can avoid +using `@TransactionConfiguration` altogether. In other words, if you have only one +transaction manager -- or if you have multiple transaction managers but the transaction +manager for tests is named "transactionManager" or specified via a +`TransactionManagementConfigurer` -- and if you want transactions to roll back +automatically, then there is no need to annotate your test class with +`@TransactionConfiguration`. +==== + ++ + +* `@Rollback` + ++ + +Indicates whether the transaction for the annotated test method should be __rolled +back__ after the test method has completed. If `true`, the transaction is rolled back; +otherwise, the transaction is committed. Use `@Rollback` to override the default +rollback flag configured at the class level. + ++ + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + **@Rollback**(false) + @Test + public void testProcessWithoutRollback() { + // ... + } +---- + +* `@BeforeTransaction` + ++ + +Indicates that the annotated `public void` method should be executed __before__ a +transaction is started for test methods configured to run within a transaction via the +`@Transactional` annotation. + ++ + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + **@BeforeTransaction** + public void beforeTransaction() { + // logic to be executed before a transaction is started + } +---- + +* `@AfterTransaction` + ++ + +Indicates that the annotated `public void` method should be executed __after__ a +transaction has ended for test methods configured to run within a transaction via the +`@Transactional` annotation. + ++ + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + **@AfterTransaction** + public void afterTransaction() { + // logic to be executed after a transaction has ended + } +---- + +* `@Sql` + ++ + +Used to annotate a test class or test method to configure SQL scripts to be executed +against a given database during integration tests. + ++ + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Test + **@Sql**({"/test-schema.sql", "/test-user-data.sql"}) + public void userTest { + // execute code that relies on the test schema and test data + } +---- + ++ + +See <> for further details. + +* `@SqlConfig` + ++ + +Defines metadata that is used to determine how to parse and execute SQL scripts +configured via the `@Sql` annotation. + ++ + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Test + @Sql( + scripts = "/test-user-data.sql", + config = **@SqlConfig**(commentPrefix = "`", separator = "@@") + ) + public void userTest { + // execute code that relies on the test data + } +---- + +* `@SqlGroup` + ++ + +A container annotation that aggregates several `@Sql` annotations. Can be used natively, +declaring several nested `@Sql` annotations. Can also be used in conjunction with Java +8's support for repeatable annotations, where `@Sql` can simply be declared several times +on the same class or method, implicitly generating this container annotation. + ++ + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Test + **@SqlGroup**({ + @Sql(scripts = "/test-schema.sql", config = @SqlConfig(commentPrefix = "`")), + @Sql("/test-user-data.sql") + )} + public void userTest { + // execute code that uses the test schema and test data + } +---- + + +[[integration-testing-annotations-standard]] +===== Standard Annotation Support +The following annotations are supported with standard semantics for all configurations +of the Spring TestContext Framework. Note that these annotations are not specific to +tests and can be used anywhere in the Spring Framework. + +* `@Autowired` +* `@Qualifier` +* `@Resource` (javax.annotation) _if JSR-250 is present_ +* `@Inject` (javax.inject) _if JSR-330 is present_ +* `@Named` (javax.inject) _if JSR-330 is present_ +* `@PersistenceContext` (javax.persistence) _if JPA is present_ +* `@PersistenceUnit` (javax.persistence) _if JPA is present_ +* `@Required` +* `@Transactional` + +.JSR-250 Lifecycle Annotations +[NOTE] +==== +In the Spring TestContext Framework `@PostConstruct` and `@PreDestroy` may be used with +standard semantics on any application components configured in the `ApplicationContext`; +however, these lifecycle annotations have limited usage within an actual test class. + +If a method within a test class is annotated with `@PostConstruct`, that method will be +executed before any __before__ methods of the underlying test framework (e.g., methods +annotated with JUnit's `@Before`), and that will apply for every test method in the test +class. On the other hand, if a method within a test class is annotated with +`@PreDestroy`, that method will __never__ be executed. Within a test class it is +therefore recommended to use test lifecycle callbacks from the underlying test framework +instead of `@PostConstruct` and `@PreDestroy`. +==== + + +[[integration-testing-annotations-junit]] +===== Spring JUnit Testing Annotations +The following annotations are __only__ supported when used in conjunction with the +<> or the +<> support classes. + +* `@IfProfileValue` + ++ + +Indicates that the annotated test is enabled for a specific testing environment. If the +configured `ProfileValueSource` returns a matching `value` for the provided `name`, the +test is enabled. This annotation can be applied to an entire class or to individual +methods. Class-level usage overrides method-level usage. + ++ + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + **@IfProfileValue**(**name**="java.vendor", **value**="Oracle Corporation") + @Test + public void testProcessWhichRunsOnlyOnOracleJvm() { + // some logic that should run only on Java VMs from Oracle Corporation + } +---- + ++ + +Alternatively, you can configure `@IfProfileValue` with a list of `values` (with __OR__ +semantics) to achieve TestNG-like support for __test groups__ in a JUnit environment. +Consider the following example: + ++ + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + **@IfProfileValue**(**name**="test-groups", **values**={"unit-tests", "integration-tests"}) + @Test + public void testProcessWhichRunsForUnitOrIntegrationTestGroups() { + // some logic that should run only for unit and integration test groups + } +---- + ++ + +* `@ProfileValueSourceConfiguration` + ++ + +Class-level annotation that specifies what type of `ProfileValueSource` to use when +retrieving __profile values__ configured through the `@IfProfileValue` annotation. If +`@ProfileValueSourceConfiguration` is not declared for a test, +`SystemProfileValueSource` is used by default. + ++ + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + **@ProfileValueSourceConfiguration**(CustomProfileValueSource.class) + public class CustomProfileValueSourceTests { + // class body... + } +---- + +* `@Timed` + ++ + +Indicates that the annotated test method must finish execution in a specified time +period (in milliseconds). If the text execution time exceeds the specified time period, +the test fails. + ++ + +The time period includes execution of the test method itself, any repetitions of the +test (see `@Repeat`), as well as any __set up__ or __tear down__ of the test fixture. + ++ + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + **@Timed**(millis=1000) + public void testProcessWithOneSecondTimeout() { + // some logic that should not take longer than 1 second to execute + } +---- + ++ + +Spring's `@Timed` annotation has different semantics than JUnit's `@Test(timeout=...)` +support. Specifically, due to the manner in which JUnit handles test execution timeouts +(that is, by executing the test method in a separate `Thread`), `@Test(timeout=...)` +preemptively fails the test if the test takes too long. Spring's `@Timed`, on the other +hand, does not preemptively fail the test but rather waits for the test to complete +before failing. + +* `@Repeat` + ++ + +Indicates that the annotated test method must be executed repeatedly. The number of +times that the test method is to be executed is specified in the annotation. + ++ + +The scope of execution to be repeated includes execution of the test method itself as +well as any __set up__ or __tear down__ of the test fixture. + ++ + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + **@Repeat**(10) + @Test + public void testProcessRepeatedly() { + // ... + } +---- + + +[[integration-testing-annotations-meta]] +===== Meta-Annotation Support for Testing +As of Spring Framework 4.0, it is possible to use test-related annotations as +<> in order to create custom _composed annotations_ +and reduce configuration duplication across a test suite. + +Each of the following may be used as meta-annotations in conjunction with the +<>. + +* `@ContextConfiguration` +* `@ContextHierarchy` +* `@ActiveProfiles` +* `@TestPropertySource` +* `@DirtiesContext` +* `@WebAppConfiguration` +* `@TestExecutionListeners` +* `@Transactional` +* `@BeforeTransaction` +* `@AfterTransaction` +* `@TransactionConfiguration` +* `@Rollback` +* `@Sql` +* `@SqlConfig` +* `@SqlGroup` +* `@Repeat` +* `@Timed` +* `@IfProfileValue` +* `@ProfileValueSourceConfiguration` + +For example, if we discover that we are repeating the following configuration +across our JUnit-based test suite... + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @RunWith(SpringJUnit4ClassRunner.class) + @ContextConfiguration({"/app-config.xml", "/test-data-access-config.xml"}) + @ActiveProfiles("dev") + @Transactional + public class OrderRepositoryTests { } + + @RunWith(SpringJUnit4ClassRunner.class) + @ContextConfiguration({"/app-config.xml", "/test-data-access-config.xml"}) + @ActiveProfiles("dev") + @Transactional + public class UserRepositoryTests { } +---- + +We can reduce the above duplication by introducing a custom _composed annotation_ +that centralizes the common test configuration like this: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Target(ElementType.TYPE) + @Retention(RetentionPolicy.RUNTIME) + @ContextConfiguration({"/app-config.xml", "/test-data-access-config.xml"}) + @ActiveProfiles("dev") + @Transactional + public @interface TransactionalDevTest { } +---- + +Then we can use our custom `@TransactionalDevTest` annotation to simplify the +configuration of individual test classes as follows: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @RunWith(SpringJUnit4ClassRunner.class) + @TransactionalDevTest + public class OrderRepositoryTests { } + + @RunWith(SpringJUnit4ClassRunner.class) + @TransactionalDevTest + public class UserRepositoryTests { } +---- + + + +[[testcontext-framework]] +==== Spring TestContext Framework +The __Spring TestContext Framework__ (located in the +`org.springframework.test.context` package) provides generic, annotation-driven unit and +integration testing support that is agnostic of the testing framework in use. The +TestContext framework also places a great deal of importance on __convention over +configuration__ with reasonable defaults that can be overridden through annotation-based +configuration. + +In addition to generic testing infrastructure, the TestContext framework provides +explicit support for JUnit and TestNG in the form of `abstract` support classes. For +JUnit, Spring also provides a custom JUnit `Runner` that allows one to write so-called +__POJO test classes__. POJO test classes are not required to extend a particular class +hierarchy. + +The following section provides an overview of the internals of the TestContext +framework. If you are only interested in using the framework and not necessarily +interested in extending it with your own custom listeners or custom loaders, feel free +to go directly to the configuration (<>, +<>, <>), <>, and +<> sections. + + +[[testcontext-key-abstractions]] +===== Key abstractions +The core of the framework consists of the `TestContext` and `TestContextManager` classes +and the `TestExecutionListener`, `ContextLoader`, and `SmartContextLoader` interfaces. A +`TestContextManager` is created on a per-test basis (e.g., for the execution of a single +test method in JUnit). The `TestContextManager` in turn manages a `TestContext` that +holds the context of the current test. The `TestContextManager` also updates the state +of the `TestContext` as the test progresses and delegates to ++TestExecutionListener++s, +which instrument the actual test execution by providing dependency injection, managing +transactions, and so on. A `ContextLoader` (or `SmartContextLoader`) is responsible for +loading an `ApplicationContext` for a given test class. Consult the javadocs and the +Spring test suite for further information and examples of various implementations. + +* `TestContext`: Encapsulates the context in which a test is executed, agnostic of the + actual testing framework in use, and provides context management and caching support + for the test instance for which it is responsible. The `TestContext` also delegates to + a `ContextLoader` (or `SmartContextLoader`) to load an `ApplicationContext` if + requested. +* `TestContextManager`: The main entry point into the __Spring TestContext Framework__, + which manages a single `TestContext` and signals events to all registered + ++TestExecutionListener++s at well-defined test execution points: +** prior to any __before class methods__ of a particular testing framework +** test instance preparation +** prior to any __before methods__ of a particular testing framework +** after any __after methods__ of a particular testing framework +** after any __after class methods__ of a particular testing framework +* `TestExecutionListener`: Defines a __listener__ API for reacting to test execution + events published by the `TestContextManager` with which the listener is registered. See + <>. +* `ContextLoader`: Strategy interface introduced in Spring 2.5 for loading an + `ApplicationContext` for an integration test managed by the Spring TestContext + Framework. + ++ + +Implement `SmartContextLoader` instead of this interface in order to provide support for +annotated classes, active bean definition profiles, test property sources, context +hierarchies, and ++WebApplicationContext++s. + +* `SmartContextLoader`: Extension of the `ContextLoader` interface introduced in Spring + 3.1. + ++ + +The `SmartContextLoader` SPI supersedes the `ContextLoader` SPI that was introduced in +Spring 2.5. Specifically, a `SmartContextLoader` can choose to process resource +`locations`, annotated `classes`, or context `initializers`. Furthermore, a +`SmartContextLoader` can set active bean definition profiles and test property sources in +the context that it loads. + ++ + +Spring provides the following implementations: + ++ + +** `DelegatingSmartContextLoader`: one of two default loaders which delegates internally +to an `AnnotationConfigContextLoader`, a `GenericXmlContextLoader`, or a +`GenericGroovyXmlContextLoader` depending either on the configuration declared for the +test class or on the presence of default locations or default configuration classes. +Groovy support is only enabled if Groovy is on the classpath. +** `WebDelegatingSmartContextLoader`: one of two default loaders which delegates +internally to an `AnnotationConfigWebContextLoader`, a `GenericXmlWebContextLoader`, or a +`GenericGroovyXmlWebContextLoader` depending either on the configuration declared for the +test class or on the presence of default locations or default configuration classes. A +web `ContextLoader` will only be used if `@WebAppConfiguration` is present on the test +class. Groovy support is only enabled if Groovy is on the classpath. +** `AnnotationConfigContextLoader`: loads a standard `ApplicationContext` from +__annotated classes__. +** `AnnotationConfigWebContextLoader`: loads a `WebApplicationContext` from __annotated +classes__. +** `GenericGroovyXmlContextLoader`: loads a standard `ApplicationContext` from __resource +locations__ that are either Groovy scripts or XML configuration files. +** `GenericGroovyXmlWebContextLoader`: loads a `WebApplicationContext` from __resource +locations__ that are either Groovy scripts or XML configuration files. +** `GenericXmlContextLoader`: loads a standard `ApplicationContext` from XML __resource +locations__. +** `GenericXmlWebContextLoader`: loads a `WebApplicationContext` from XML __resource +locations__. +** `GenericPropertiesContextLoader`: loads a standard `ApplicationContext` from Java +Properties files. + +The following sections explain how to configure the TestContext framework through +annotations and provide working examples of how to write unit and integration tests with +the framework. + +[[testcontext-tel-config]] +===== TestExecutionListener configuration + +Spring provides the following `TestExecutionListener` implementations that are registered +by default, exactly in this order. + +* `ServletTestExecutionListener`: configures Servlet API mocks for a + `WebApplicationContext` +* `DependencyInjectionTestExecutionListener`: provides dependency injection for the test + instance +* `DirtiesContextTestExecutionListener`: handles the `@DirtiesContext` annotation +* `TransactionalTestExecutionListener`: provides transactional test execution with + default rollback semantics +* `SqlScriptsTestExecutionListener`: executes SQL scripts configured via the `@Sql` + annotation + +[[testcontext-tel-config-registering-tels]] +====== Registering custom TestExecutionListeners + +Custom ++TestExecutionListener++s can be registered for a test class and its subclasses +via the `@TestExecutionListeners` annotation. See +<> and the javadocs for +`@TestExecutionListeners` for details and examples. + +[[testcontext-tel-config-automatic-discovery]] +====== Automatic discovery of default TestExecutionListeners + +Registering custom ++TestExecutionListener++s via `@TestExecutionListeners` is suitable +for custom listeners that are used in limited testing scenarios; however, it can become +cumbersome if a custom listener needs to be used across a test suite. To address this +issue, Spring Framework 4.1 supports automatic discovery of _default_ +`TestExecutionListener` implementations via the `SpringFactoriesLoader` mechanism. + +Specifically, the `spring-test` module declares all core default +++TestExecutionListener++s under the +`org.springframework.test.context.TestExecutionListener` key in its +`META-INF/spring.factories` properties file. Third-party frameworks and developers can +contribute their own ++TestExecutionListener++s to the list of default listeners in the +same manner via their own `META-INF/spring.factories` properties file. + +[[testcontext-tel-config-ordering]] +====== Ordering TestExecutionListeners + +When the TestContext framework discovers default ++TestExecutionListeners++ via the +aforementioned `SpringFactoriesLoader` mechanism, the instantiated listeners are sorted +using Spring's `AnnotationAwareOrderComparator` which honors Spring's `Ordered` interface +and `@Order` annotation for ordering. `AbstractTestExecutionListener` and all default +++TestExecutionListener++s provided by Spring implement `Ordered` with appropriate +values. Third-party frameworks and developers should therefore make sure that their +_default_ ++TestExecutionListener++s are registered in the proper order by implementing +`Ordered` or declaring `@Order`. Consult the javadocs for the `getOrder()` methods of the +core default ++TestExecutionListener++s for details on what values are assigned to each +core listener. + +[[testcontext-tel-config-merging]] +====== Merging TestExecutionListeners + +If a custom `TestExecutionListener` is registered via `@TestExecutionListeners`, the +_default_ listeners will not be registered. In most common testing scenarios, this +effectively forces the developer to manually declare all default listeners in addition to +any custom listeners. The following listing demonstrates this style of configuration. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @ContextConfiguration + @TestExecutionListeners({ + MyCustomTestExecutionListener.class, + ServletTestExecutionListener.class, + DependencyInjectionTestExecutionListener.class, + DirtiesContextTestExecutionListener.class, + TransactionalTestExecutionListener.class, + SqlScriptsTestExecutionListener.class + }) + public class MyTest { + // class body... + } +---- + +The challenge with this approach is that it requires that the developer know exactly +which listeners are registered by default. Moreover, the set of default listeners can +change from release to release -- for example, `SqlScriptsTestExecutionListener` was +introduced in Spring Framework 4.1. Furthermore, third-party frameworks like Spring +Security register their own default ++TestExecutionListener++s via the aforementioned +<>. + +To avoid having to be aware of and re-declare **all** _default_ listeners, the +`mergeMode` attribute of `@TestExecutionListeners` can be set to +`MergeMode.MERGE_WITH_DEFAULTS`. `MERGE_WITH_DEFAULTS` indicates that locally declared +listeners should be merged with the default listeners. The merging algorithm ensures that +duplicates are removed from the list and that the resulting set of merged listeners is +sorted according to the semantics of `AnnotationAwareOrderComparator` as described in +<>. If a listener implements `Ordered` or is annotated +with `@Order` it can influence the position in which it is merged with the defaults; +otherwise, locally declared listeners will simply be appended to the list of default +listeners when merged. + +For example, if the `MyCustomTestExecutionListener` class in the previous example +configures its `order` value (for example, `500`) to be less than the order of the +`ServletTestExecutionListener` (which happens to be `1000`), the +`MyCustomTestExecutionListener` can then be automatically merged with the list of +defaults _in front of_ the `ServletTestExecutionListener`, and the previous example could +be replaced with the following. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @ContextConfiguration + @TestExecutionListeners( + listeners = MyCustomTestExecutionListener.class, + mergeMode = MERGE_WITH_DEFAULTS, + ) + public class MyTest { + // class body... + } +---- + + +[[testcontext-ctx-management]] +===== Context management + +Each `TestContext` provides context management and caching support for the test instance +it is responsible for. Test instances do not automatically receive access to the +configured `ApplicationContext`. However, if a test class implements the +`ApplicationContextAware` interface, a reference to the `ApplicationContext` is supplied +to the test instance. Note that `AbstractJUnit4SpringContextTests` and +`AbstractTestNGSpringContextTests` implement `ApplicationContextAware` and therefore +provide access to the `ApplicationContext` automatically. + +.@Autowired ApplicationContext +[TIP] +==== +As an alternative to implementing the `ApplicationContextAware` interface, you can +inject the application context for your test class through the `@Autowired` annotation +on either a field or setter method. For example: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @RunWith(SpringJUnit4ClassRunner.class) + @ContextConfiguration + public class MyTest { + + **@Autowired** + private ApplicationContext applicationContext; + + // class body... + } +---- + +Similarly, if your test is configured to load a `WebApplicationContext`, you can inject +the web application context into your test as follows: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @RunWith(SpringJUnit4ClassRunner.class) + **@WebAppConfiguration** + @ContextConfiguration + public class MyWebAppTest { + **@Autowired** + private WebApplicationContext wac; + + // class body... + } +---- + +Dependency injection via `@Autowired` is provided by the +`DependencyInjectionTestExecutionListener` which is configured by default (see +<>). +==== + +Test classes that use the TestContext framework do not need to extend any particular +class or implement a specific interface to configure their application context. Instead, +configuration is achieved simply by declaring the `@ContextConfiguration` annotation at +the class level. If your test class does not explicitly declare application context +resource `locations` or annotated `classes`, the configured `ContextLoader` determines +how to load a context from a default location or default configuration classes. In +addition to context resource `locations` and annotated `classes`, an application context +can also be configured via application context `initializers`. + +The following sections explain how to configure an `ApplicationContext` via XML +configuration files, annotated classes (typically `@Configuration` classes), or context +initializers using Spring's `@ContextConfiguration` annotation. Alternatively, you can +implement and configure your own custom `SmartContextLoader` for advanced use cases. + +[[testcontext-ctx-management-xml]] +====== Context configuration with XML resources + +To load an `ApplicationContext` for your tests using XML configuration files, annotate +your test class with `@ContextConfiguration` and configure the `locations` attribute with +an array that contains the resource locations of XML configuration metadata. A plain or +relative path -- for example `"context.xml"` -- will be treated as a classpath resource +that is relative to the package in which the test class is defined. A path starting with +a slash is treated as an absolute classpath location, for example +`"/org/example/config.xml"`. A path which represents a resource URL (i.e., a path +prefixed with `classpath:`, `file:`, `http:`, etc.) will be used __as is__. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @RunWith(SpringJUnit4ClassRunner.class) + // ApplicationContext will be loaded from "/app-config.xml" and + // "/test-config.xml" in the root of the classpath + **@ContextConfiguration(locations={"/app-config.xml", "/test-config.xml"})** + public class MyTest { + // class body... + } +---- + +`@ContextConfiguration` supports an alias for the `locations` attribute through the +standard Java `value` attribute. Thus, if you do not need to declare additional +attributes in `@ContextConfiguration`, you can omit the declaration of the `locations` +attribute name and declare the resource locations by using the shorthand format +demonstrated in the following example. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @RunWith(SpringJUnit4ClassRunner.class) + **@ContextConfiguration({"/app-config.xml", "/test-config.xml"})** + public class MyTest { + // class body... + } +---- + +If you omit both the `locations` and `value` attributes from the `@ContextConfiguration` +annotation, the TestContext framework will attempt to detect a default XML resource +location. Specifically, `GenericXmlContextLoader` and `GenericXmlWebContextLoader` detect +a default location based on the name of the test class. If your class is named +`com.example.MyTest`, `GenericXmlContextLoader` loads your application context from +`"classpath:com/example/MyTest-context.xml"`. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + package com.example; + + @RunWith(SpringJUnit4ClassRunner.class) + // ApplicationContext will be loaded from + // "classpath:com/example/MyTest-context.xml" + **@ContextConfiguration** + public class MyTest { + // class body... + } +---- + +[[testcontext-ctx-management-groovy]] +====== Context configuration with Groovy scripts + +To load an `ApplicationContext` for your tests using Groovy scripts that utilize the +<>, annotate your test class with +`@ContextConfiguration` and configure the `locations` or `value` attribute with an array +that contains the resource locations of Groovy scripts. Resource lookup semantics for +Groovy scripts are the same as those described for <>. + + +.Enabling Groovy script support +[TIP] +==== +Support for using Groovy scripts to load an `ApplicationContext` in the Spring +TestContext Framework is enabled automatically if Groovy is on the classpath. +==== + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @RunWith(SpringJUnit4ClassRunner.class) + // ApplicationContext will be loaded from "/AppConfig.groovy" and + // "/TestConfig.groovy" in the root of the classpath + **@ContextConfiguration({"/AppConfig.groovy", "/TestConfig.Groovy"})** + public class MyTest { + // class body... + } +---- + +If you omit both the `locations` and `value` attributes from the `@ContextConfiguration` +annotation, the TestContext framework will attempt to detect a default Groovy script. +Specifically, `GenericGroovyXmlContextLoader` and `GenericGroovyXmlWebContextLoader` +detect a default location based on the name of the test class. If your class is named +`com.example.MyTest`, the Groovy context loader will load your application context from +`"classpath:com/example/MyTestContext.groovy"`. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + package com.example; + + @RunWith(SpringJUnit4ClassRunner.class) + // ApplicationContext will be loaded from + // "classpath:com/example/MyTestContext.groovy" + **@ContextConfiguration** + public class MyTest { + // class body... + } +---- + +.Declaring XML config and Groovy scripts simultaneously +[TIP] +==== +Both XML configuration files and Groovy scripts can be declared simultaneously via the +`locations` or `value` attribute of `@ContextConfiguration`. If the path to a configured +resource location ends with `.xml` it will be loaded using an `XmlBeanDefinitionReader`; +otherwise it will be loaded using a `GroovyBeanDefinitionReader`. + +The following listing demonstrates how to combine both in an integration test. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @RunWith(SpringJUnit4ClassRunner.class) + // ApplicationContext will be loaded from + // "/app-config.xml" and "/TestConfig.groovy" + @ContextConfiguration({ "/app-config.xml", "/TestConfig.groovy" }) + public class MyTest { + // class body... + } +---- +==== + +[[testcontext-ctx-management-javaconfig]] +====== Context configuration with annotated classes + +To load an `ApplicationContext` for your tests using __annotated classes__ (see +<>), annotate your test class with `@ContextConfiguration` and configure the +`classes` attribute with an array that contains references to annotated classes. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @RunWith(SpringJUnit4ClassRunner.class) + // ApplicationContext will be loaded from AppConfig and TestConfig + **@ContextConfiguration(classes = {AppConfig.class, TestConfig.class})** + public class MyTest { + // class body... + } +---- + +.Annotated Classes +[TIP] +==== +The term __annotated class__ can refer to any of the following. + +* A class annotated with `@Configuration` +* A component (i.e., a class annotated with `@Component`, `@Service`, `@Repository`, etc.) +* A JSR-330 compliant class that is annotated with `javax.inject` annotations +* Any other class that contains `@Bean`-methods + +Consult the javadocs of `@Configuration` and `@Bean` for further information regarding +the configuration and semantics of __annotated classes__, paying special attention to +the discussion of __`@Bean` Lite Mode__. +==== + +If you omit the `classes` attribute from the `@ContextConfiguration` annotation, the +TestContext framework will attempt to detect the presence of default configuration +classes. Specifically, `AnnotationConfigContextLoader` and +`AnnotationConfigWebContextLoader` will detect all static inner classes of the test class +that meet the requirements for configuration class implementations as specified in the +`@Configuration` javadocs. In the following example, the `OrderServiceTest` class +declares a static inner configuration class named `Config` that will be automatically +used to load the `ApplicationContext` for the test class. Note that the name of the +configuration class is arbitrary. In addition, a test class can contain more than one +static inner configuration class if desired. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @RunWith(SpringJUnit4ClassRunner.class) + // ApplicationContext will be loaded from the + // static inner Config class + **@ContextConfiguration** + public class OrderServiceTest { + + @Configuration + static class Config { + + // this bean will be injected into the OrderServiceTest class + @Bean + public OrderService orderService() { + OrderService orderService = new OrderServiceImpl(); + // set properties, etc. + return orderService; + } + } + + @Autowired + private OrderService orderService; + + @Test + public void testOrderService() { + // test the orderService + } + + } +---- + +[[testcontext-ctx-management-mixed-config]] +====== Mixing XML, Groovy scripts, and annotated classes + +It may sometimes be desirable to mix XML configuration files, Groovy scripts, and +annotated classes (i.e., typically `@Configuration` classes) to configure an +`ApplicationContext` for your tests. For example, if you use XML configuration in +production, you may decide that you want to use `@Configuration` classes to configure +specific Spring-managed components for your tests, or vice versa. + +Furthermore, some third-party frameworks (like Spring Boot) provide first-class support +for loading an `ApplicationContext` from different types of resources simultaneously +(e.g., XML configuration files, Groovy scripts, and `@Configuration` classes). The Spring +Framework historically has not supported this for standard deployments. Consequently, +most of the `SmartContextLoader` implementations that the Spring Framework delivers in +the `spring-test` module support only one resource type per test context; however, this +does not mean that you cannot use both. One exception to the general rule is that the +`GenericGroovyXmlContextLoader` and `GenericGroovyXmlWebContextLoader` support both XML +configuration files and Groovy scripts simultaneously. Furthermore, third-party +frameworks may choose to support the declaration of both `locations` and `classes` via +`@ContextConfiguration`, and with the standard testing support in the TestContext +framework, you have the following options. + +If you want to use resource locations (e.g., XML or Groovy) __and__ `@Configuration` +classes to configure your tests, you will have to pick one as the __entry point__, and +that one will have to include or import the other. For example, in XML or Groovy scripts +you can include `@Configuration` classes via component scanning or define them as normal +Spring beans; whereas, in a `@Configuration` class you can use `@ImportResource` to +import XML configuration files. Note that this behavior is semantically equivalent to how +you configure your application in production: in production configuration you will define +either a set of XML or Groovy resource locations or a set of `@Configuration` classes +that your production `ApplicationContext` will be loaded from, but you still have the +freedom to include or import the other type of configuration. + +[[testcontext-ctx-management-initializers]] +====== Context configuration with context initializers +To configure an `ApplicationContext` for your tests using context initializers, annotate +your test class with `@ContextConfiguration` and configure the `initializers` attribute +with an array that contains references to classes that implement +`ApplicationContextInitializer`. The declared context initializers will then be used to +initialize the `ConfigurableApplicationContext` that is loaded for your tests. Note that +the concrete `ConfigurableApplicationContext` type supported by each declared +initializer must be compatible with the type of `ApplicationContext` created by the +`SmartContextLoader` in use (i.e., typically a `GenericApplicationContext`). +Furthermore, the order in which the initializers are invoked depends on whether they +implement Spring's `Ordered` interface, are annotated with Spring's `@Order` or the +standard `@Priority` annotation. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @RunWith(SpringJUnit4ClassRunner.class) + // ApplicationContext will be loaded from TestConfig + // and initialized by TestAppCtxInitializer + **@ContextConfiguration( + classes = TestConfig.class, + initializers = TestAppCtxInitializer.class)** + public class MyTest { + // class body... + } +---- + +It is also possible to omit the declaration of XML configuration files or annotated +classes in `@ContextConfiguration` entirely and instead declare only +`ApplicationContextInitializer` classes which are then responsible for registering beans +in the context -- for example, by programmatically loading bean definitions from XML +files or configuration classes. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @RunWith(SpringJUnit4ClassRunner.class) + // ApplicationContext will be initialized by EntireAppInitializer + // which presumably registers beans in the context + **@ContextConfiguration(initializers = EntireAppInitializer.class)** + public class MyTest { + // class body... + } +---- + +[[testcontext-ctx-management-inheritance]] +====== Context configuration inheritance +`@ContextConfiguration` supports boolean `inheritLocations` and `inheritInitializers` +attributes that denote whether resource locations or annotated classes and context +initializers declared by superclasses should be __inherited__. The default value for +both flags is `true`. This means that a test class inherits the resource locations or +annotated classes as well as the context initializers declared by any superclasses. +Specifically, the resource locations or annotated classes for a test class are appended +to the list of resource locations or annotated classes declared by superclasses. +Similarly, the initializers for a given test class will be added to the set of +initializers defined by test superclasses. Thus, subclasses have the option +of __extending__ the resource locations, annotated classes, or context initializers. + +If `@ContextConfiguration`'s `inheritLocations` or `inheritInitializers` attribute is +set to `false`, the resource locations or annotated classes and the context +initializers, respectively, for the test class __shadow__ and effectively replace the +configuration defined by superclasses. + +In the following example that uses XML resource locations, the `ApplicationContext` for +`ExtendedTest` will be loaded from __"base-config.xml"__ __and__ +__"extended-config.xml"__, in that order. Beans defined in __"extended-config.xml"__ may +therefore __override__ (i.e., replace) those defined in __"base-config.xml"__. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @RunWith(SpringJUnit4ClassRunner.class) + // ApplicationContext will be loaded from "/base-config.xml" + // in the root of the classpath + **@ContextConfiguration("/base-config.xml")** + public class BaseTest { + // class body... + } + + // ApplicationContext will be loaded from "/base-config.xml" and + // "/extended-config.xml" in the root of the classpath + **@ContextConfiguration("/extended-config.xml")** + public class ExtendedTest extends BaseTest { + // class body... + } +---- + +Similarly, in the following example that uses annotated classes, the +`ApplicationContext` for `ExtendedTest` will be loaded from the `BaseConfig` __and__ +`ExtendedConfig` classes, in that order. Beans defined in `ExtendedConfig` may therefore +override (i.e., replace) those defined in `BaseConfig`. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @RunWith(SpringJUnit4ClassRunner.class) + // ApplicationContext will be loaded from BaseConfig + **@ContextConfiguration(classes = BaseConfig.class)** + public class BaseTest { + // class body... + } + + // ApplicationContext will be loaded from BaseConfig and ExtendedConfig + **@ContextConfiguration(classes = ExtendedConfig.class)** + public class ExtendedTest extends BaseTest { + // class body... + } +---- + +In the following example that uses context initializers, the `ApplicationContext` for +`ExtendedTest` will be initialized using `BaseInitializer` __and__ +`ExtendedInitializer`. Note, however, that the order in which the initializers are +invoked depends on whether they implement Spring's `Ordered` interface, are annotated +with Spring's `@Order` or the standard `@Priority` annotation. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @RunWith(SpringJUnit4ClassRunner.class) + // ApplicationContext will be initialized by BaseInitializer + **@ContextConfiguration(initializers = BaseInitializer.class)** + public class BaseTest { + // class body... + } + + // ApplicationContext will be initialized by BaseInitializer + // and ExtendedInitializer + **@ContextConfiguration(initializers = ExtendedInitializer.class)** + public class ExtendedTest extends BaseTest { + // class body... + } +---- + +[[testcontext-ctx-management-env-profiles]] +====== Context configuration with environment profiles +Spring 3.1 introduced first-class support in the framework for the notion of +environments and profiles (a.k.a., __bean definition profiles__), and integration tests +can be configured to activate particular bean definition profiles for various testing +scenarios. This is achieved by annotating a test class with the `@ActiveProfiles` +annotation and supplying a list of profiles that should be activated when loading the +`ApplicationContext` for the test. + +[NOTE] +==== +`@ActiveProfiles` may be used with any implementation of the new `SmartContextLoader` +SPI, but `@ActiveProfiles` is not supported with implementations of the older +`ContextLoader` SPI. +==== + +Let's take a look at some examples with XML configuration and `@Configuration` classes. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +---- + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + package com.bank.service; + + @RunWith(SpringJUnit4ClassRunner.class) + // ApplicationContext will be loaded from "classpath:/app-config.xml" + @ContextConfiguration("/app-config.xml") + @ActiveProfiles("dev") + public class TransferServiceTest { + + @Autowired + private TransferService transferService; + + @Test + public void testTransferService() { + // test the transferService + } + } +---- + +When `TransferServiceTest` is run, its `ApplicationContext` will be loaded from the +`app-config.xml` configuration file in the root of the classpath. If you inspect +`app-config.xml` you'll notice that the `accountRepository` bean has a dependency on a +`dataSource` bean; however, `dataSource` is not defined as a top-level bean. Instead, +`dataSource` is defined three times: in the __production__ profile, the +__dev__ profile, and the __default__ profile. + +By annotating `TransferServiceTest` with `@ActiveProfiles("dev")` we instruct the Spring +TestContext Framework to load the `ApplicationContext` with the active profiles set to +`{"dev"}`. As a result, an embedded database will be created and populated with test data, +and the `accountRepository` bean will be wired with a reference to the development +`DataSource`. And that's likely what we want in an integration test. + +It is sometimes useful to assign beans to a `default` profile. Beans within the default profile +are only included when no other profile is specifically activated. This can be used to define +_fallback_ beans to be used in the application's default state. For example, you may +explicitly provide a data source for `dev` and `production` profiles, but define an in-memory +data source as a default when neither of these is active. + +The following code listings demonstrate how to implement the same configuration and +integration test but using `@Configuration` classes instead of XML. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Configuration + @Profile("dev") + public class StandaloneDataConfig { + + @Bean + public DataSource dataSource() { + return new EmbeddedDatabaseBuilder() + .setType(EmbeddedDatabaseType.HSQL) + .addScript("classpath:com/bank/config/sql/schema.sql") + .addScript("classpath:com/bank/config/sql/test-data.sql") + .build(); + } + } +---- + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Configuration + @Profile("production") + public class JndiDataConfig { + + @Bean + public DataSource dataSource() throws Exception { + Context ctx = new InitialContext(); + return (DataSource) ctx.lookup("java:comp/env/jdbc/datasource"); + } + } +---- + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Configuration + @Profile("default") + public class DefaultDataConfig { + + @Bean + public DataSource dataSource() { + return new EmbeddedDatabaseBuilder() + .setType(EmbeddedDatabaseType.HSQL) + .addScript("classpath:com/bank/config/sql/schema.sql") + .build(); + } + } +---- + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Configuration + public class TransferServiceConfig { + + @Autowired DataSource dataSource; + + @Bean + public TransferService transferService() { + return new DefaultTransferService(accountRepository(), feePolicy()); + } + + @Bean + public AccountRepository accountRepository() { + return new JdbcAccountRepository(dataSource); + } + + @Bean + public FeePolicy feePolicy() { + return new ZeroFeePolicy(); + } + + } +---- + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + package com.bank.service; + + @RunWith(SpringJUnit4ClassRunner.class) + @ContextConfiguration(classes = { + TransferServiceConfig.class, + StandaloneDataConfig.class, + JndiDataConfig.class, + DefaultDataConfig.class}) + @ActiveProfiles("dev") + public class TransferServiceTest { + + @Autowired + private TransferService transferService; + + @Test + public void testTransferService() { + // test the transferService + } + } +---- + +In this variation, we have split the XML configuration into four independent +`@Configuration` classes: + +* `TransferServiceConfig`: acquires a `dataSource` via dependency injection using + `@Autowired` +* `StandaloneDataConfig`: defines a `dataSource` for an embedded database suitable for + developer tests +* `JndiDataConfig`: defines a `dataSource` that is retrieved from JNDI in a production + environment +* `DefaultDataConfig`: defines a `dataSource` for a default embedded database in case + no profile is active + +As with the XML-based configuration example, we still annotate `TransferServiceTest` +with `@ActiveProfiles("dev")`, but this time we specify all four configuration classes +via the `@ContextConfiguration` annotation. The body of the test class itself remains +completely unchanged. + +It is often the case that a single set of profiles is used across multiple test classes +within a given project. Thus, to avoid duplicate declarations of the `@ActiveProfiles` +annotation it is possible to declare `@ActiveProfiles` once on a base class, and +subclasses will automatically inherit the `@ActiveProfiles` configuration from the base +class. In the following example, the declaration of `@ActiveProfiles` (as well as other +annotations) has been moved to an abstract superclass, `AbstractIntegrationTest`. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + package com.bank.service; + + @RunWith(SpringJUnit4ClassRunner.class) + @ContextConfiguration(classes = { + TransferServiceConfig.class, + StandaloneDataConfig.class, + JndiDataConfig.class, + DefaultDataConfig.class}) + @ActiveProfiles("dev") + public abstract class AbstractIntegrationTest { + } +---- + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + package com.bank.service; + + // "dev" profile inherited from superclass + public class TransferServiceTest extends AbstractIntegrationTest { + + @Autowired + private TransferService transferService; + + @Test + public void testTransferService() { + // test the transferService + } + } +---- + +`@ActiveProfiles` also supports an `inheritProfiles` attribute that can be used to +disable the inheritance of active profiles. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + package com.bank.service; + + // "dev" profile overridden with "production" + @ActiveProfiles(profiles = "production", inheritProfiles = false) + public class ProductionTransferServiceTest extends AbstractIntegrationTest { + // test body + } +---- + +[[testcontext-ctx-management-env-profiles-ActiveProfilesResolver]] +Furthermore, it is sometimes necessary to resolve active profiles for tests +__programmatically__ instead of declaratively -- for example, based on: + +* the current operating system +* whether tests are being executed on a continuous integration build server +* the presence of certain environment variables +* the presence of custom class-level annotations +* etc. + +To resolve active bean definition profiles programmatically, simply implement a custom +`ActiveProfilesResolver` and register it via the `resolver` attribute of +`@ActiveProfiles`. The following example demonstrates how to implement and register a +custom `OperatingSystemActiveProfilesResolver`. For further information, refer to the +corresponding javadocs. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + package com.bank.service; + + // "dev" profile overridden programmatically via a custom resolver + @ActiveProfiles( + resolver = OperatingSystemActiveProfilesResolver.class, + inheritProfiles = false) + public class TransferServiceTest extends AbstractIntegrationTest { + // test body + } +---- + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + package com.bank.service.test; + + public class OperatingSystemActiveProfilesResolver implements ActiveProfilesResolver { + + @Override + String[] resolve(Class testClass) { + String profile = ...; + // determine the value of profile based on the operating system + return new String[] {profile}; + } + } +---- + +[[testcontext-ctx-management-property-sources]] +====== Context configuration with test property sources + +Spring 3.1 introduced first-class support in the framework for the notion of an +environment with a hierarchy of _property sources_, and since Spring 4.1 integration +tests can be configured with test-specific property sources. In contrast to the +`@PropertySource` annotation used on `@Configuration` classes, the `@TestPropertySource` +annotation can be declared on a test class to declare resource locations for test +properties files or _inlined_ properties. These test property sources will be added to +the `Environment`'s set of `PropertySources` for the `ApplicationContext` loaded for the +annotated integration test. + +[NOTE] +==== +`@TestPropertySource` may be used with any implementation of the `SmartContextLoader` +SPI, but `@TestPropertySource` is not supported with implementations of the older +`ContextLoader` SPI. + +Implementations of `SmartContextLoader` gain access to merged test property source values +via the `getPropertySourceLocations()` and `getPropertySourceProperties()` methods in +`MergedContextConfiguration`. +==== + +*Declaring test property sources* + +Test properties files can be configured via the `locations` or `value` attribute of +`@TestPropertySource` as shown in the following example. + +Both traditional and XML-based properties file formats are supported -- for example, +`"classpath:/com/example/test.properties"` or `"file:/path/to/file.xml"`. + +Each path will be interpreted as a Spring `Resource`. A plain path -- for example, +`"test.properties"` -- will be treated as a classpath resource that is _relative_ to the +package in which the test class is defined. A path starting with a slash will be treated +as an _absolute_ classpath resource, for example: `"/org/example/test.xml"`. A path which +references a URL (e.g., a path prefixed with `classpath:`, `file:`, `http:`, etc.) will +be loaded using the specified resource protocol. Resource location wildcards (e.g. +`**/*.properties`) are not permitted: each location must evaluate to exactly one +`.properties` or `.xml` resource. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @ContextConfiguration + @TestPropertySource("/test.properties") + public class MyIntegrationTests { + // class body... + } +---- + +_Inlined_ properties in the form of key-value pairs can be configured via the +`properties` attribute of `@TestPropertySource` as shown in the following example. All +key-value pairs will be added to the enclosing `Environment` as a single test +`PropertySource` with the highest precedence. + +The supported syntax for key-value pairs is the same as the syntax defined for entries in +a Java properties file: + +* `"key=value"` +* `"key:value"` +* `"key value"` + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @ContextConfiguration + @TestPropertySource(properties = {"timezone = GMT", "port: 4242"}) + public class MyIntegrationTests { + // class body... + } +---- + +*Default properties file detection* + +If `@TestPropertySource` is declared as an empty annotation (i.e., without explicit +values for the `locations` or `properties` attributes), an attempt will be made to detect +a _default_ properties file relative to the class that declared the annotation. For +example, if the annotated test class is `com.example.MyTest`, the corresponding default +properties file is `"classpath:com/example/MyTest.properties"`. If the default cannot be +detected, an `IllegalStateException` will be thrown. + +*Precedence* + +Test property sources have higher precedence than those loaded from the operating +system's environment or Java system properties as well as property sources added by the +application declaratively via `@PropertySource` or programmatically. Thus, test property +sources can be used to selectively override properties defined in system and application +property sources. Furthermore, inlined properties have higher precedence than properties +loaded from resource locations. + +In the following example, the `timezone` and `port` properties as well as any properties +defined in `"/test.properties"` will override any properties of the same name that are +defined in system and application property sources. Furthermore, if the +`"/test.properties"` file defines entries for the `timezone` and `port` properties those +will be overridden by the _inlined_ properties declared via the `properties` attribute. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @ContextConfiguration + @TestPropertySource( + locations = "/test.properties", + properties = {"timezone = GMT", "port: 4242"} + ) + public class MyIntegrationTests { + // class body... + } +---- + +*Inheriting and overriding test property sources* + +`@TestPropertySource` supports boolean `inheritLocations` and `inheritProperties` +attributes that denote whether resource locations for properties files and inlined +properties declared by superclasses should be __inherited__. The default value for both +flags is `true`. This means that a test class inherits the locations and inlined +properties declared by any superclasses. Specifically, the locations and inlined +properties for a test class are appended to the locations and inlined properties declared +by superclasses. Thus, subclasses have the option of __extending__ the locations and +inlined properties. Note that properties that appear later will __shadow__ (i.e.., +override) properties of the same name that appear earlier. In addition, the +aforementioned precedence rules apply for inherited test property sources as well. + +If `@TestPropertySource`'s `inheritLocations` or `inheritProperties` attribute is set to +`false`, the locations or inlined properties, respectively, for the test class __shadow__ +and effectively replace the configuration defined by superclasses. + +In the following example, the `ApplicationContext` for `BaseTest` will be loaded using +only the `"base.properties"` file as a test property source. In contrast, the +`ApplicationContext` for `ExtendedTest` will be loaded using the `"base.properties"` +**and** `"extended.properties"` files as test property source locations. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @TestPropertySource("base.properties") + @ContextConfiguration + public class BaseTest { + // ... + } + + @TestPropertySource("extended.properties") + @ContextConfiguration + public class ExtendedTest extends BaseTest { + // ... + } +---- + +In the following example, the `ApplicationContext` for `BaseTest` will be loaded using only +the _inlined_ `key1` property. In contrast, the `ApplicationContext` for `ExtendedTest` will be +loaded using the _inlined_ `key1` and `key2` properties. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @TestPropertySource(properties = "key1 = value1") + @ContextConfiguration + public class BaseTest { + // ... + } + + @TestPropertySource(properties = "key2 = value2") + @ContextConfiguration + public class ExtendedTest extends BaseTest { + // ... + } +---- + +[[testcontext-ctx-management-web]] +====== Loading a WebApplicationContext +Spring 3.2 introduced support for loading a `WebApplicationContext` in integration +tests. To instruct the TestContext framework to load a `WebApplicationContext` instead +of a standard `ApplicationContext`, simply annotate the respective test class with +`@WebAppConfiguration`. + +The presence of `@WebAppConfiguration` on your test class instructs the TestContext +framework (TCF) that a `WebApplicationContext` (WAC) should be loaded for your +integration tests. In the background the TCF makes sure that a `MockServletContext` is +created and supplied to your test's WAC. By default the base resource path for your +`MockServletContext` will be set to __"src/main/webapp"__. This is interpreted as a path +relative to the root of your JVM (i.e., normally the path to your project). If you're +familiar with the directory structure of a web application in a Maven project, you'll +know that __"src/main/webapp"__ is the default location for the root of your WAR. If you +need to override this default, simply provide an alternate path to the +`@WebAppConfiguration` annotation (e.g., `@WebAppConfiguration("src/test/webapp")`). If +you wish to reference a base resource path from the classpath instead of the file +system, just use Spring's __classpath:__ prefix. + +Please note that Spring's testing support for `WebApplicationContexts` is on par with +its support for standard `ApplicationContexts`. When testing with a +`WebApplicationContext` you are free to declare either XML configuration files or +`@Configuration` classes via `@ContextConfiguration`. You are of course also free to use +any other test annotations such as `@TestExecutionListeners`, +`@TransactionConfiguration`, `@ActiveProfiles`, etc. + +The following examples demonstrate some of the various configuration options for loading +a `WebApplicationContext`. + +.Conventions +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @RunWith(SpringJUnit4ClassRunner.class) + + // defaults to "file:src/main/webapp" + @WebAppConfiguration + + // detects "WacTests-context.xml" in same package + // or static nested @Configuration class + @ContextConfiguration + + public class WacTests { + //... + } +---- + +The above example demonstrates the TestContext framework's support for __convention over +configuration__. If you annotate a test class with `@WebAppConfiguration` without +specifying a resource base path, the resource path will effectively default +to __"file:src/main/webapp"__. Similarly, if you declare `@ContextConfiguration` without +specifying resource `locations`, annotated `classes`, or context `initializers`, Spring +will attempt to detect the presence of your configuration using conventions +(i.e., __"WacTests-context.xml"__ in the same package as the `WacTests` class or static +nested `@Configuration` classes). + +.Default resource semantics +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @RunWith(SpringJUnit4ClassRunner.class) + + // file system resource + @WebAppConfiguration("webapp") + + // classpath resource + @ContextConfiguration("/spring/test-servlet-config.xml") + + public class WacTests { + //... + } +---- + +This example demonstrates how to explicitly declare a resource base path with +`@WebAppConfiguration` and an XML resource location with `@ContextConfiguration`. The +important thing to note here is the different semantics for paths with these two +annotations. By default, `@WebAppConfiguration` resource paths are file system based; +whereas, `@ContextConfiguration` resource locations are classpath based. + +.Explicit resource semantics +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @RunWith(SpringJUnit4ClassRunner.class) + + // classpath resource + @WebAppConfiguration("classpath:test-web-resources") + + // file system resource + @ContextConfiguration("file:src/main/webapp/WEB-INF/servlet-config.xml") + + public class WacTests { + //... + } +---- + +In this third example, we see that we can override the default resource semantics for +both annotations by specifying a Spring resource prefix. Contrast the comments in this +example with the previous example. + +.[[testcontext-ctx-management-web-mocks]]Working with Web Mocks +-- +To provide comprehensive web testing support, Spring 3.2 introduced a +`ServletTestExecutionListener` that is enabled by default. When testing against a +`WebApplicationContext` this <> sets +up default thread-local state via Spring Web's `RequestContextHolder` before each test +method and creates a `MockHttpServletRequest`, `MockHttpServletResponse`, and +`ServletWebRequest` based on the base resource path configured via +`@WebAppConfiguration`. `ServletTestExecutionListener` also ensures that the +`MockHttpServletResponse` and `ServletWebRequest` can be injected into the test +instance, and once the test is complete it cleans up thread-local state. + +Once you have a `WebApplicationContext` loaded for your test you might find that you +need to interact with the web mocks -- for example, to set up your test fixture or to +perform assertions after invoking your web component. The following example demonstrates +which mocks can be autowired into your test instance. Note that the +`WebApplicationContext` and `MockServletContext` are both cached across the test suite; +whereas, the other mocks are managed per test method by the +`ServletTestExecutionListener`. + +.Injecting mocks +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @WebAppConfiguration + @ContextConfiguration + public class WacTests { + + @Autowired + WebApplicationContext wac; // cached + + @Autowired + MockServletContext servletContext; // cached + + @Autowired + MockHttpSession session; + + @Autowired + MockHttpServletRequest request; + + @Autowired + MockHttpServletResponse response; + + @Autowired + ServletWebRequest webRequest; + + //... + } +---- +-- + +[[testcontext-ctx-management-caching]] +====== Context caching + +Once the TestContext framework loads an `ApplicationContext` (or `WebApplicationContext`) +for a test, that context will be cached and reused for __all__ subsequent tests that +declare the same unique context configuration within the same test suite. To understand +how caching works, it is important to understand what is meant by __unique__ and __test +suite__. + +An `ApplicationContext` can be __uniquely__ identified by the combination of +configuration parameters that are used to load it. Consequently, the unique combination +of configuration parameters are used to generate a __key__ under which the context is +cached. The TestContext framework uses the following configuration parameters to build +the context cache key: + +* `locations` __(from @ContextConfiguration)__ +* `classes` __(from @ContextConfiguration)__ +* `contextInitializerClasses` __(from @ContextConfiguration)__ +* `contextLoader` __(from @ContextConfiguration)__ +* `parent` __(from @ContextHierarchy)__ +* `activeProfiles` __(from @ActiveProfiles)__ +* `propertySourceLocations` __(from @TestPropertySource)__ +* `propertySourceProperties` __(from @TestPropertySource)__ +* `resourceBasePath` __(from @WebAppConfiguration)__ + +For example, if `TestClassA` specifies `{"app-config.xml", "test-config.xml"}` for the +`locations` (or `value`) attribute of `@ContextConfiguration`, the TestContext framework +will load the corresponding `ApplicationContext` and store it in a `static` context cache +under a key that is based solely on those locations. So if `TestClassB` also defines +`{"app-config.xml", "test-config.xml"}` for its locations (either explicitly or +implicitly through inheritance) but does not define `@WebAppConfiguration`, a different +`ContextLoader`, different active profiles, different context initializers, different +test property sources, or a different parent context, then the same `ApplicationContext` +will be shared by both test classes. This means that the setup cost for loading an +application context is incurred only once (per test suite), and subsequent test execution +is much faster. + +.Test suites and forked processes +[NOTE] +==== +The Spring TestContext framework stores application contexts in a __static__ cache. This +means that the context is literally stored in a `static` variable. In other words, if +tests execute in separate processes the static cache will be cleared between each test +execution, and this will effectively disable the caching mechanism. + +To benefit from the caching mechanism, all tests must run within the same process or +test suite. This can be achieved by executing all tests as a group within an IDE. +Similarly, when executing tests with a build framework such as Ant, Maven, or Gradle it +is important to make sure that the build framework does not __fork__ between tests. For +example, if the +http://maven.apache.org/plugins/maven-surefire-plugin/test-mojo.html#forkMode[forkMode] +for the Maven Surefire plug-in is set to `always` or `pertest`, the TestContext +framework will not be able to cache application contexts between test classes and the +build process will run significantly slower as a result. +==== + +In the unlikely case that a test corrupts the application context and requires reloading +-- for example, by modifying a bean definition or the state of an application object -- +you can annotate your test class or test method with `@DirtiesContext` (see the +discussion of `@DirtiesContext` in <>). This +instructs Spring to remove the context from the cache and rebuild the application +context before executing the next test. Note that support for the `@DirtiesContext` +annotation is provided by the `DirtiesContextTestExecutionListener` which is enabled by +default. + +[[testcontext-ctx-management-ctx-hierarchies]] +====== Context hierarchies + +When writing integration tests that rely on a loaded Spring `ApplicationContext`, it is +often sufficient to test against a single context; however, there are times when it is +beneficial or even necessary to test against a hierarchy of ++ApplicationContext++s. For +example, if you are developing a Spring MVC web application you will typically have a +root `WebApplicationContext` loaded via Spring's `ContextLoaderListener` and a child +`WebApplicationContext` loaded via Spring's `DispatcherServlet`. This results in a +parent-child context hierarchy where shared components and infrastructure configuration +are declared in the root context and consumed in the child context by web-specific +components. Another use case can be found in Spring Batch applications where you often +have a parent context that provides configuration for shared batch infrastructure and a +child context for the configuration of a specific batch job. + +As of Spring Framework 3.2.2, it is possible to write integration tests that use context +hierarchies by declaring context configuration via the `@ContextHierarchy` annotation, +either on an individual test class or within a test class hierarchy. If a context +hierarchy is declared on multiple classes within a test class hierarchy it is also +possible to merge or override the context configuration for a specific, named level in +the context hierarchy. When merging configuration for a given level in the hierarchy the +configuration resource type (i.e., XML configuration files or annotated classes) must be +consistent; otherwise, it is perfectly acceptable to have different levels in a context +hierarchy configured using different resource types. + +The following JUnit-based examples demonstrate common configuration scenarios for +integration tests that require the use of context hierarchies. + +.Single test class with context hierarchy +-- +`ControllerIntegrationTests` represents a typical integration testing scenario for a +Spring MVC web application by declaring a context hierarchy consisting of two levels, +one for the __root__ WebApplicationContext (loaded using the `TestAppConfig` +`@Configuration` class) and one for the __dispatcher servlet__ `WebApplicationContext` +(loaded using the `WebConfig` `@Configuration` class). The `WebApplicationContext` that +is __autowired__ into the test instance is the one for the child context (i.e., the +lowest context in the hierarchy). + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @RunWith(SpringJUnit4ClassRunner.class) + @WebAppConfiguration + @ContextHierarchy({ + @ContextConfiguration(classes = TestAppConfig.class), + @ContextConfiguration(classes = WebConfig.class) + }) + public class ControllerIntegrationTests { + + @Autowired + private WebApplicationContext wac; + + // ... + } +---- + +-- + + +.Class hierarchy with implicit parent context +-- +The following test classes define a context hierarchy within a test class hierarchy. +`AbstractWebTests` declares the configuration for a root `WebApplicationContext` in a +Spring-powered web application. Note, however, that `AbstractWebTests` does not declare +`@ContextHierarchy`; consequently, subclasses of `AbstractWebTests` can optionally +participate in a context hierarchy or simply follow the standard semantics for +`@ContextConfiguration`. `SoapWebServiceTests` and `RestWebServiceTests` both extend +`AbstractWebTests` and define a context hierarchy via `@ContextHierarchy`. The result is +that three application contexts will be loaded (one for each declaration of +`@ContextConfiguration`), and the application context loaded based on the configuration +in `AbstractWebTests` will be set as the parent context for each of the contexts loaded +for the concrete subclasses. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @RunWith(SpringJUnit4ClassRunner.class) + @WebAppConfiguration + @ContextConfiguration("file:src/main/webapp/WEB-INF/applicationContext.xml") + public abstract class AbstractWebTests {} + + @ContextHierarchy(@ContextConfiguration("/spring/soap-ws-config.xml") + public class SoapWebServiceTests extends AbstractWebTests {} + + @ContextHierarchy(@ContextConfiguration("/spring/rest-ws-config.xml") + public class RestWebServiceTests extends AbstractWebTests {} +---- +-- + + +.Class hierarchy with merged context hierarchy configuration +-- +The following classes demonstrate the use of __named__ hierarchy levels in order to +__merge__ the configuration for specific levels in a context hierarchy. `BaseTests` +defines two levels in the hierarchy, `parent` and `child`. `ExtendedTests` extends +`BaseTests` and instructs the Spring TestContext Framework to merge the context +configuration for the `child` hierarchy level, simply by ensuring that the names +declared via `ContextConfiguration`'s `name` attribute are both `"child"`. The result is +that three application contexts will be loaded: one for `"/app-config.xml"`, one for +`"/user-config.xml"`, and one for `{"/user-config.xml", "/order-config.xml"}`. As with +the previous example, the application context loaded from `"/app-config.xml"` will be +set as the parent context for the contexts loaded from `"/user-config.xml"` and +`{"/user-config.xml", "/order-config.xml"}`. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @RunWith(SpringJUnit4ClassRunner.class) + @ContextHierarchy({ + @ContextConfiguration(name = "parent", locations = "/app-config.xml"), + @ContextConfiguration(name = "child", locations = "/user-config.xml") + }) + public class BaseTests {} + + @ContextHierarchy( + @ContextConfiguration(name = "child", locations = "/order-config.xml") + ) + public class ExtendedTests extends BaseTests {} +---- +-- + +.Class hierarchy with overridden context hierarchy configuration +-- +In contrast to the previous example, this example demonstrates how to __override__ the +configuration for a given named level in a context hierarchy by setting +++ContextConfiguration++'s `inheritLocations` flag to `false`. Consequently, the +application context for `ExtendedTests` will be loaded only from +`"/test-user-config.xml"` and will have its parent set to the context loaded from +`"/app-config.xml"`. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @RunWith(SpringJUnit4ClassRunner.class) + @ContextHierarchy({ + @ContextConfiguration(name = "parent", locations = "/app-config.xml"), + @ContextConfiguration(name = "child", locations = "/user-config.xml") + }) + public class BaseTests {} + + @ContextHierarchy( + @ContextConfiguration( + name = "child", + locations = "/test-user-config.xml", + inheritLocations = false + )) + public class ExtendedTests extends BaseTests {} +---- + +.Dirtying a context within a context hierarchy +[NOTE] +==== +If `@DirtiesContext` is used in a test whose context is configured as part of a context +hierarchy, the `hierarchyMode` flag can be used to control how the context cache is +cleared. For further details consult the discussion of `@DirtiesContext` in +<> and the +`@DirtiesContext` javadocs. +==== +-- + + +[[testcontext-fixture-di]] +===== Dependency injection of test fixtures +When you use the `DependencyInjectionTestExecutionListener` -- which is configured by +default -- the dependencies of your test instances are __injected__ from beans in the +application context that you configured with `@ContextConfiguration`. You may use setter +injection, field injection, or both, depending on which annotations you choose and +whether you place them on setter methods or fields. For consistency with the annotation +support introduced in Spring 2.5 and 3.0, you can use Spring's `@Autowired` annotation +or the `@Inject` annotation from JSR 300. + +[TIP] +==== + +The TestContext framework does not instrument the manner in which a test instance is +instantiated. Thus the use of `@Autowired` or `@Inject` for constructors has no effect +for test classes. +==== + +Because `@Autowired` is used to perform <>, if you have multiple bean definitions of the same type, you cannot rely on this +approach for those particular beans. In that case, you can use `@Autowired` in +conjunction with `@Qualifier`. As of Spring 3.0 you may also choose to use `@Inject` in +conjunction with `@Named`. Alternatively, if your test class has access to its +`ApplicationContext`, you can perform an explicit lookup by using (for example) a call +to `applicationContext.getBean("titleRepository")`. + +If you do not want dependency injection applied to your test instances, simply do not +annotate fields or setter methods with `@Autowired` or `@Inject`. Alternatively, you can +disable dependency injection altogether by explicitly configuring your class with +`@TestExecutionListeners` and omitting `DependencyInjectionTestExecutionListener.class` +from the list of listeners. + +Consider the scenario of testing a `HibernateTitleRepository` class, as outlined in the +<> section. The next two code listings demonstrate the +use of `@Autowired` on fields and setter methods. The application context configuration +is presented after all sample code listings. + +[NOTE] +==== +The dependency injection behavior in the following code listings is not specific to +JUnit. The same DI techniques can be used in conjunction with any testing framework. + +The following examples make calls to static assertion methods such as `assertNotNull()` +but without prepending the call with `Assert`. In such cases, assume that the method was +properly imported through an `import static` declaration that is not shown in the +example. +==== + +The first code listing shows a JUnit-based implementation of the test class that uses +`@Autowired` for field injection. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @RunWith(SpringJUnit4ClassRunner.class) + // specifies the Spring configuration to load for this test fixture + **@ContextConfiguration("repository-config.xml")** + public class HibernateTitleRepositoryTests { + + // this instance will be dependency injected by type + **@Autowired** + private HibernateTitleRepository titleRepository; + + @Test + public void findById() { + Title title = titleRepository.findById(new Long(10)); + assertNotNull(title); + } + } +---- + +Alternatively, you can configure the class to use `@Autowired` for setter injection as +seen below. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @RunWith(SpringJUnit4ClassRunner.class) + // specifies the Spring configuration to load for this test fixture + **@ContextConfiguration("repository-config.xml")** + public class HibernateTitleRepositoryTests { + + // this instance will be dependency injected by type + private HibernateTitleRepository titleRepository; + + **@Autowired** + public void setTitleRepository(HibernateTitleRepository titleRepository) { + this.titleRepository = titleRepository; + } + + @Test + public void findById() { + Title title = titleRepository.findById(new Long(10)); + assertNotNull(title); + } + } +---- + +The preceding code listings use the same XML context file referenced by the +`@ContextConfiguration` annotation (that is, `repository-config.xml`), which looks like +this: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + + + + + + +---- + +[NOTE] +==== +If you are extending from a Spring-provided test base class that happens to use +`@Autowired` on one of its setter methods, you might have multiple beans of the affected +type defined in your application context: for example, multiple `DataSource` beans. In +such a case, you can override the setter method and use the `@Qualifier` annotation to +indicate a specific target bean as follows, but make sure to delegate to the overridden +method in the superclass as well. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + // ... + + @Autowired + @Override + public void setDataSource(**@Qualifier("myDataSource")** DataSource dataSource) { + **super**.setDataSource(dataSource); + } + + // ... +---- + +The specified qualifier value indicates the specific `DataSource` bean to inject, +narrowing the set of type matches to a specific bean. Its value is matched against +`` declarations within the corresponding `` definitions. The bean name +is used as a fallback qualifier value, so you may effectively also point to a specific +bean by name there (as shown above, assuming that "myDataSource" is the bean id). +==== + + +[[testcontext-web-scoped-beans]] +===== Testing request and session scoped beans + +<> have been supported by +Spring for several years now, but it's always been a bit non-trivial to test them. As of +Spring 3.2 it's a breeze to test your request-scoped and session-scoped beans by +following these steps. + +* Ensure that a `WebApplicationContext` is loaded for your test by annotating your test + class with `@WebAppConfiguration`. +* Inject the mock request or session into your test instance and prepare your test + fixture as appropriate. +* Invoke your web component that you retrieved from the configured + `WebApplicationContext` (i.e., via dependency injection). +* Perform assertions against the mocks. + +The following code snippet displays the XML configuration for a login use case. Note +that the `userService` bean has a dependency on a request-scoped `loginAction` bean. +Also, the `LoginAction` is instantiated using <> that +retrieve the username and password from the current HTTP request. In our test, we will +want to configure these request parameters via the mock managed by the TestContext +framework. + +.Request-scoped bean configuration +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + + +---- + +In `RequestScopedBeanTests` we inject both the `UserService` (i.e., the subject under +test) and the `MockHttpServletRequest` into our test instance. Within our +`requestScope()` test method we set up our test fixture by setting request parameters in +the provided `MockHttpServletRequest`. When the `loginUser()` method is invoked on our +`userService` we are assured that the user service has access to the request-scoped +`loginAction` for the current `MockHttpServletRequest` (i.e., the one we just set +parameters in). We can then perform assertions against the results based on the known +inputs for the username and password. + +.Request-scoped bean test +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @RunWith(SpringJUnit4ClassRunner.class) + @ContextConfiguration + @WebAppConfiguration + public class RequestScopedBeanTests { + + @Autowired UserService userService; + @Autowired MockHttpServletRequest request; + + @Test + public void requestScope() { + + request.setParameter("user", "enigma"); + request.setParameter("pswd", "$pr!ng"); + + LoginResults results = userService.loginUser(); + + // assert results + } + } +---- + +The following code snippet is similar to the one we saw above for a request-scoped bean; +however, this time the `userService` bean has a dependency on a session-scoped +`userPreferences` bean. Note that the `UserPreferences` bean is instantiated using a +SpEL expression that retrieves the __theme__ from the current HTTP session. In our test, +we will need to configure a theme in the mock session managed by the TestContext +framework. + +.Session-scoped bean configuration +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + + +---- + +In `SessionScopedBeanTests` we inject the `UserService` and the `MockHttpSession` into +our test instance. Within our `sessionScope()` test method we set up our test fixture by +setting the expected "theme" attribute in the provided `MockHttpSession`. When the +`processUserPreferences()` method is invoked on our `userService` we are assured that +the user service has access to the session-scoped `userPreferences` for the current +`MockHttpSession`, and we can perform assertions against the results based on the +configured theme. + +.Session-scoped bean test +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @RunWith(SpringJUnit4ClassRunner.class) + @ContextConfiguration + @WebAppConfiguration + public class SessionScopedBeanTests { + + @Autowired UserService userService; + @Autowired MockHttpSession session; + + @Test + public void sessionScope() throws Exception { + + session.setAttribute("theme", "blue"); + + Results results = userService.processUserPreferences(); + + // assert results + } + } +---- + +[[testcontext-tx]] +===== Transaction management + +In the TestContext framework, transactions are managed by the +`TransactionalTestExecutionListener` which is configured by default, even if you do not +explicitly declare `@TestExecutionListeners` on your test class. To enable support for +transactions, however, you must configure a `PlatformTransactionManager` bean in the +`ApplicationContext` that is loaded via `@ContextConfiguration` semantics (further +details are provided below). In addition, you must declare Spring's `@Transactional` +annotation either at the class or method level for your tests. + +[[testcontext-tx-test-managed-transactions]] +====== Test-managed transactions + +_Test-managed transactions_ are transactions that are managed _declaratively_ via the +`TransactionalTestExecutionListener` or _programmatically_ via `TestTransaction` (see +below). Such transactions should not be confused with _Spring-managed transactions_ +(i.e., those managed directly by Spring within the `ApplicationContext` loaded for tests) +or _application-managed transactions_ (i.e., those managed programmatically within +application code that is invoked via tests). Spring-managed and application-managed +transactions will typically participate in test-managed transactions; however, caution +should be taken if Spring-managed or application-managed transactions are configured with +any _propagation_ type other than `REQUIRED` or `SUPPORTS` (see the discussion on +<> for details). + +[[testcontext-tx-enabling-transactions]] +====== Enabling and disabling transactions + +Annotating a test method with `@Transactional` causes the test to be run within a +transaction that will, by default, be automatically rolled back after completion of the +test. If a test class is annotated with `@Transactional`, each test method within that +class hierarchy will be run within a transaction. Test methods that are not annotated +with `@Transactional` (at the class or method level) will not be run within a +transaction. Furthermore, tests that are annotated with `@Transactional` but have the +`propagation` type set to `NOT_SUPPORTED` will not be run within a transaction. + +__Note that <> and +<> +are preconfigured for transactional support at the class level.__ + +The following example demonstrates a common scenario for writing an integration test for +a Hibernate-based `UserRepository`. As explained in +<>, there is no need to clean up the +database after the `createUser()` method is executed since any changes made to the +database will be automatically rolled back by the `TransactionalTestExecutionListener`. +See <> for an additional example. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @RunWith(SpringJUnit4ClassRunner.class) + @ContextConfiguration(classes = TestConfig.class) + @Transactional + public class HibernateUserRepositoryTests { + + @Autowired + HibernateUserRepository repository; + + @Autowired + SessionFactory sessionFactory; + + JdbcTemplate jdbcTemplate; + + @Autowired + public void setDataSource(DataSource dataSource) { + this.jdbcTemplate = new JdbcTemplate(dataSource); + } + + @Test + public void createUser() { + // track initial state in test database: + final int count = countRowsInTable("user"); + + User user = new User(...); + repository.save(user); + + // Manual flush is required to avoid false positive in test + sessionFactory.getCurrentSession().flush(); + assertNumUsers(count + 1); + } + + protected int countRowsInTable(String tableName) { + return JdbcTestUtils.countRowsInTable(this.jdbcTemplate, tableName); + } + + protected void assertNumUsers(int expected) { + assertEquals("Number of rows in the 'user' table.", expected, countRowsInTable("user")); + } + } +---- + +[[testcontext-tx-rollback-and-commit-behavior]] +====== Transaction rollback and commit behavior + +By default, test transactions will be automatically rolled back after completion of the +test; however, transactional commit and rollback behavior can be configured declaratively +via the class-level `@TransactionConfiguration` and method-level `@Rollback` annotations. +See the corresponding entries in the <> section for further details. + +[[testcontext-tx-programmatic-tx-mgt]] +====== Programmatic transaction management +As of Spring Framework 4.1, it is possible to interact with test-managed transactions +_programmatically_ via the static methods in `TestTransaction`. For example, +`TestTransaction` may be used within _test_ methods, _before_ methods, and _after_ +methods to start or end the current test-managed transaction or to configure the current +test-managed transaction for rollback or commit. Support for `TestTransaction` is +automatically available whenever the `TransactionalTestExecutionListener` is enabled. + +The following example demonstrates some of the features of `TestTransaction`. Consult the +javadocs for `TestTransaction` for further details. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @ContextConfiguration(classes = TestConfig.class) + public class ProgrammaticTransactionManagementTests extends + AbstractTransactionalJUnit4SpringContextTests { + + @Test + public void transactionalTest() { + // assert initial state in test database: + assertNumUsers(2); + + deleteFromTables("user"); + + // changes to the database will be committed! + TestTransaction.flagForCommit(); + TestTransaction.end(); + assertFalse(TestTransaction.isActive()); + assertNumUsers(0); + + TestTransaction.start(); + // perform other actions against the database that will + // be automatically rolled back after the test completes... + } + + protected void assertNumUsers(int expected) { + assertEquals("Number of rows in the 'user' table.", expected, countRowsInTable("user")); + } + } +---- + +[[testcontext-tx-before-and-after-tx]] +====== Executing code outside of a transaction + +Occasionally you need to execute certain code before or after a transactional test method +but outside the transactional context -- for example, to verify the initial database state +prior to execution of your test or to verify expected transactional commit behavior after +test execution (if the test was configured not to roll back the transaction). +`TransactionalTestExecutionListener` supports the `@BeforeTransaction` and +`@AfterTransaction` annotations exactly for such scenarios. Simply annotate any `public +void` method in your test class with one of these annotations, and the +`TransactionalTestExecutionListener` ensures that your __before transaction method__ or +__after transaction method__ is executed at the appropriate time. + +[TIP] +==== +Any __before methods__ (such as methods annotated with JUnit's `@Before`) and any __after +methods__ (such as methods annotated with JUnit's `@After`) are executed __within__ a +transaction. In addition, methods annotated with `@BeforeTransaction` or +`@AfterTransaction` are naturally not executed for test methods that are not configured +to run within a transaction. +==== + +[[testcontext-tx-mgr-config]] +====== Configuring a transaction manager + +`TransactionalTestExecutionListener` expects a `PlatformTransactionManager` bean to be +defined in the Spring `ApplicationContext` for the test. In case there are multiple +instances of `PlatformTransactionManager` within the test's `ApplicationContext`, +`@TransactionConfiguration` supports configuring the bean name of the +`PlatformTransactionManager` that should be used to drive transactions. Alternatively, a +_qualifier_ may be declared via `@Transactional("myQualifier")`, or +`TransactionManagementConfigurer` can be implemented by an `@Configuration` class. +Consult the javadocs for `TestContextTransactionUtils.retrieveTransactionManager()` for +details on the algorithm used to look up a transaction manager in the test's +`ApplicationContext`. + +[[testcontext-tx-annotation-demo]] +====== Demonstration of all transaction-related annotations + +The following JUnit-based example displays a fictitious integration testing scenario +highlighting all transaction-related annotations. The example is **not** intended to +demonstrate best practices but rather to demonstrate how these annotations can be used. +Consult the <> section for further +information and configuration examples. <> contains an additional example using `@Sql` for +declarative SQL script execution with default transaction rollback semantics. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @RunWith(SpringJUnit4ClassRunner.class) + @ContextConfiguration + **@TransactionConfiguration(transactionManager="txMgr", defaultRollback=false) + @Transactional** + public class FictitiousTransactionalTest { + + **@BeforeTransaction** + public void verifyInitialDatabaseState() { + // logic to verify the initial state before a transaction is started + } + + @Before + public void setUpTestDataWithinTransaction() { + // set up test data within the transaction + } + + @Test + // overrides the class-level defaultRollback setting + **@Rollback(true)** + public void modifyDatabaseWithinTransaction() { + // logic which uses the test data and modifies database state + } + + @After + public void tearDownWithinTransaction() { + // execute "tear down" logic within the transaction + } + + **@AfterTransaction** + public void verifyFinalDatabaseState() { + // logic to verify the final state after transaction has rolled back + } + + } +---- + +[[testcontext-tx-false-positives]] +.Avoid false positives when testing ORM code +[NOTE] +==== +When you test application code that manipulates the state of the Hibernate session, make +sure to __flush__ the underlying session within test methods that execute that code. +Failing to flush the underlying session can produce __false positives__: your test may +pass, but the same code throws an exception in a live, production environment. In the +following Hibernate-based example test case, one method demonstrates a false positive, +and the other method correctly exposes the results of flushing the session. Note that +this applies to JPA and any other ORM frameworks that maintain an in-memory __unit of +work__. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + // ... + + @Autowired + private SessionFactory sessionFactory; + + @Test // no expected exception! + public void falsePositive() { + updateEntityInHibernateSession(); + // False positive: an exception will be thrown once the session is + // finally flushed (i.e., in production code) + } + + @Test(expected = GenericJDBCException.class) + public void updateWithSessionFlush() { + updateEntityInHibernateSession(); + // Manual flush is required to avoid false positive in test + sessionFactory.getCurrentSession().flush(); + } + + // ... +---- +==== + + +[[testcontext-executing-sql]] +===== Executing SQL scripts + +When writing integration tests against a relational database, it is often beneficial +to execute SQL scripts to modify the database schema or insert test data into tables. +The `spring-jdbc` module provides support for _initializing_ an embedded or existing +database by executing SQL scripts when the Spring `ApplicationContext` is loaded. See +<> and <> for +details. + +Although it is very useful to initialize a database for testing _once_ when the +`ApplicationContext` is loaded, sometimes it is essential to be able to modify the +database _during_ integration tests. The following sections explain how to execute SQL +scripts programmatically and declaratively during integration tests. + +[[testcontext-executing-sql-programmatically]] +====== Executing SQL scripts programmatically + +Spring provides the following options for executing SQL scripts programmatically within +integration test methods. + +* `org.springframework.jdbc.datasource.init.ScriptUtils` +* `org.springframework.jdbc.datasource.init.ResourceDatabasePopulator` +* `org.springframework.test.context.junit4.AbstractTransactionalJUnit4SpringContextTests` +* `org.springframework.test.context.testng.AbstractTransactionalTestNGSpringContextTests` + +`ScriptUtils` provides a collection of static utility methods for working with SQL scripts +and is mainly intended for internal use within the framework. However, if you require +full control over how SQL scripts are parsed and executed, `ScriptUtils` may suit your +needs better than some of the other alternatives described below. Consult the javadocs for +individual methods in `ScriptUtils` for further details. + +`ResourceDatabasePopulator` provides a simple object-based API for programmatically +populating, initializing, or cleaning up a database using SQL scripts defined in +external resources. `ResourceDatabasePopulator` provides options for configuring the +character encoding, statement separator, comment delimiters, and error handling flags +used when parsing and executing the scripts, and each of the configuration options has +a reasonable default value. Consult the javadocs for details on default values. To +execute the scripts configured in a `ResourceDatabasePopulator`, you can invoke either +the `populate(Connection)` method to execute the populator against a +`java.sql.Connection` or the `execute(DataSource)` method to execute the populator +against a `javax.sql.DataSource`. The following example specifies SQL scripts for a test +schema and test data, sets the statement separator to `"@@"`, and then executes the +scripts against a `DataSource`. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Test + public void databaseTest { + ResourceDatabasePopulator populator = new ResourceDatabasePopulator(); + populator.addScripts( + new ClassPathResource("test-schema.sql"), + new ClassPathResource("test-data.sql")); + populator.setSeparator("@@"); + populator.execute(this.dataSource); + // execute code that uses the test schema and data + } +---- + +Note that `ResourceDatabasePopulator` internally delegates to `ScriptUtils` for parsing +and executing SQL scripts. Similarly, the `executeSqlScript(..)` methods in +<> and +<> +internally use a `ResourceDatabasePopulator` for executing SQL scripts. Consult the javadocs +for the various `executeSqlScript(..)` methods for further details. + + +[[testcontext-executing-sql-declaratively]] +====== Executing SQL scripts declaratively with `@Sql` + +In addition to the aforementioned mechanisms for executing SQL scripts +_programmatically_, SQL scripts can also be configured _declaratively_ in the Spring +TestContext Framework. Specifically, the `@Sql` annotation can be declared on a test +class or test method to configure the resource paths to SQL scripts that should be +executed against a given database either before or after an integration test method. Note +that method-level declarations override class-level declarations and that support for +`@Sql` is provided by the `SqlScriptsTestExecutionListener` which is enabled by default. + +*Path resource semantics* + +Each path will be interpreted as a Spring `Resource`. A plain path -- for example, +`"schema.sql"` -- will be treated as a classpath resource that is _relative_ to the +package in which the test class is defined. A path starting with a slash will be treated +as an _absolute_ classpath resource, for example: `"/org/example/schema.sql"`. A path +which references a URL (e.g., a path prefixed with `classpath:`, `file:`, `http:`, etc.) +will be loaded using the specified resource protocol. + +The following example demonstrates how to use `@Sql` at the class level and at the method +level within a JUnit-based integration test class. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @RunWith(SpringJUnit4ClassRunner.class) + @ContextConfiguration + @Sql("/test-schema.sql") + public class DatabaseTests { + + @Test + public void emptySchemaTest { + // execute code that uses the test schema without any test data + } + + @Test + @Sql({"/test-schema.sql", "/test-user-data.sql"}) + public void userTest { + // execute code that uses the test schema and test data + } + } +---- + +*Default script detection* + +If no SQL scripts are specified, an attempt will be made to detect a `default` script +depending on where `@Sql` is declared. If a default cannot be detected, an +`IllegalStateException` will be thrown. + +* __class-level declaration__: if the annotated test class is `com.example.MyTest`, the + corresponding default script is `"classpath:com/example/MyTest.sql"`. +* __method-level declaration__: if the annotated test method is named `testMethod()` and is + defined in the class `com.example.MyTest`, the corresponding default script is + `"classpath:com/example/MyTest.testMethod.sql"`. + +*Declaring multiple `@Sql` sets* + +If multiple sets of SQL scripts need to be configured for a given test class or test +method but with different syntax configuration, different error handling rules, or +different execution phases per set, it is possible to declare multiple instances of +`@Sql`. With Java 8, `@Sql` can be used as a _repeatable_ annotation. Otherwise, the +`@SqlGroup` annotation can be used as an explicit container for declaring multiple +instances of `@Sql`. + +The following example demonstrates the use of `@Sql` as a repeatable annotation using +Java 8. In this scenario the `test-schema.sql` script uses a different syntax for +single-line comments. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Test + @Sql(scripts = "/test-schema.sql", config = @SqlConfig(commentPrefix = "`")) + @Sql("/test-user-data.sql") + public void userTest { + // execute code that uses the test schema and test data + } +---- + +The following example is identical to the above except that the `@Sql` declarations are +grouped together within `@SqlGroup` for compatibility with Java 6 and Java 7. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Test + @SqlGroup({ + @Sql(scripts = "/test-schema.sql", config = @SqlConfig(commentPrefix = "`")), + @Sql("/test-user-data.sql") + )} + public void userTest { + // execute code that uses the test schema and test data + } +---- + +*Script execution phases* + +By default, SQL scripts will be executed _before_ the corresponding test method. However, +if a particular set of scripts needs to be executed _after_ the test method -- for +example, to clean up database state -- the `executionPhase` attribute in `@Sql` can be +used as seen in the following example. Note that `ISOLATED` and `AFTER_TEST_METHOD` are +statically imported from `Sql.TransactionMode` and `Sql.ExecutionPhase` respectively. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Test + @Sql( + scripts = "create-test-data.sql", + config = @SqlConfig(transactionMode = ISOLATED) + ) + @Sql( + scripts = "delete-test-data.sql", + config = @SqlConfig(transactionMode = ISOLATED), + executionPhase = AFTER_TEST_METHOD + ) + public void userTest { + // execute code that needs the test data to be committed + // to the database outside of the test's transaction + } +---- + +*Script configuration with `@SqlConfig`* + +Configuration for script parsing and error handling can be configured via the +`@SqlConfig` annotation. When declared as a class-level annotation on an integration test +class, `@SqlConfig` serves as _global_ configuration for all SQL scripts within the test +class hierarchy. When declared directly via the `config` attribute of the `@Sql` +annotation, `@SqlConfig` serves as _local_ configuration for the SQL scripts declared +within the enclosing `@Sql` annotation. Every attribute in `@SqlConfig` has an implicit +default value which is documented in the javadocs of the corresponding attribute. Due to +the rules defined for annotation attributes in the Java Language Specification, it is +unfortunately not possible to assign a value of `null` to an annotation attribute. Thus, +in order to support overrides of inherited global configuration, `@SqlConfig` attributes +have an explicit default value of either `""` for Strings or `DEFAULT` for Enums. This +approach allows local declarations of `@SqlConfig` to selectively override individual +attributes from global declarations of `@SqlConfig` by providing a value other than `""` +or `DEFAULT`. Global `@SqlConfig` attributes are inherited whenever local `@SqlConfig` +attributes do not supply an explicit value other than `""` or `DEFAULT`. Explicit _local_ +configuration therefore overrides _global_ configuration. + +The configuration options provided by `@Sql` and `@SqlConfig` are equivalent to those +supported by `ScriptUtils` and `ResourceDatabasePopulator` but are a superset of those +provided by the `` XML namespace element. Consult the javadocs +of individual attributes in `@Sql` and `@SqlConfig` for details. + +[[testcontext-executing-sql-declaratively-tx]] +*Transaction management for `@Sql`* + +By default, the `SqlScriptsTestExecutionListener` will infer the desired transaction +semantics for scripts configured via `@Sql`. Specifically, SQL scripts will be executed +without a transaction, within an existing Spring-managed transaction -- for example, a +transaction managed by the `TransactionalTestExecutionListener` for a test annotated with +`@Transactional` -- or within an isolated transaction, depending on the configured value +of the `transactionMode` attribute in `@SqlConfig` and the presence of a +`PlatformTransactionManager` in the test's `ApplicationContext`. As a bare minimum +however, a `javax.sql.DataSource` must be present in the test's `ApplicationContext`. + +If the algorithms used by `SqlScriptsTestExecutionListener` to detect a `DataSource` and +`PlatformTransactionManager` and infer the transaction semantics do not suit your needs, +you may specify explicit names via the `dataSource` and `transactionManager` attributes +of `@SqlConfig`. Furthermore, the transaction propagation behavior can be controlled via +the `transactionMode` attribute of `@SqlConfig` -- for example, if scripts should be +executed in an isolated transaction. Although a thorough discussion of all supported +options for transaction management with `@Sql` is beyond the scope of this reference +manual, the javadocs for `@SqlConfig` and `SqlScriptsTestExecutionListener` provide +detailed information, and the following example demonstrates a typical testing scenario +using JUnit and transactional tests with `@Sql`. Note that there is no need to clean up +the database after the `usersTest()` method is executed since any changes made to the +database (either within the the test method or within the `/test-data.sql` script) will +be automatically rolled back by the `TransactionalTestExecutionListener` (see +<> for details). + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @RunWith(SpringJUnit4ClassRunner.class) + @ContextConfiguration(classes = TestDatabaseConfig.class) + @Transactional + public class TransactionalSqlScriptsTests { + + protected JdbcTemplate jdbcTemplate; + + @Autowired + public void setDataSource(DataSource dataSource) { + this.jdbcTemplate = new JdbcTemplate(dataSource); + } + + @Test + @Sql("/test-data.sql") + public void usersTest() { + // verify state in test database: + assertNumUsers(2); + // execute code that uses the test data... + } + + protected int countRowsInTable(String tableName) { + return JdbcTestUtils.countRowsInTable(this.jdbcTemplate, tableName); + } + + protected void assertNumUsers(int expected) { + assertEquals("Number of rows in the 'user' table.", expected, countRowsInTable("user")); + } + } +---- + + +[[testcontext-support-classes]] +===== TestContext Framework support classes + +[[testcontext-support-classes-junit4]] +====== JUnit support classes +The `org.springframework.test.context.junit4` package provides the following support +classes for JUnit-based test cases. + +* `AbstractJUnit4SpringContextTests` +* `AbstractTransactionalJUnit4SpringContextTests` + +`AbstractJUnit4SpringContextTests` is an abstract base test class that integrates the +__Spring TestContext Framework__ with explicit `ApplicationContext` testing support in +a JUnit 4.9+ environment. When you extend `AbstractJUnit4SpringContextTests`, you can +access a `protected` `applicationContext` instance variable that can be used to perform +explicit bean lookups or to test the state of the context as a whole. + +`AbstractTransactionalJUnit4SpringContextTests` is an abstract __transactional__ extension +of `AbstractJUnit4SpringContextTests` that adds some convenience functionality for JDBC +access. This class expects a `javax.sql.DataSource` bean and a `PlatformTransactionManager` +bean to be defined in the `ApplicationContext`. When you extend +`AbstractTransactionalJUnit4SpringContextTests` you can access a `protected` `jdbcTemplate` +instance variable that can be used to execute SQL statements to query the database. Such +queries can be used to confirm database state both __prior to__ and __after__ execution of +database-related application code, and Spring ensures that such queries run in the scope of +the same transaction as the application code. When used in conjunction with an ORM tool, +be sure to avoid <>. As mentioned in +<>, `AbstractTransactionalJUnit4SpringContextTests` +also provides convenience methods which delegate to methods in `JdbcTestUtils` using the +aforementioned `jdbcTemplate`. Furthermore, `AbstractTransactionalJUnit4SpringContextTests` +provides an `executeSqlScript(..)` method for executing SQL scripts against the configured +`DataSource`. + +[TIP] +==== +These classes are a convenience for extension. If you do not want your test classes to be +tied to a Spring-specific class hierarchy, you can configure your own custom test classes +by using `@RunWith(SpringJUnit4ClassRunner.class)`, `@ContextConfiguration`, +`@TestExecutionListeners`, and so on. +==== + +[[testcontext-junit4-runner]] +====== Spring JUnit Runner +The __Spring TestContext Framework__ offers full integration with JUnit 4.9+ through a +custom runner (tested on JUnit 4.9 -- 4.11). By annotating test classes with +`@RunWith(SpringJUnit4ClassRunner.class)`, developers can implement standard JUnit-based +unit and integration tests and simultaneously reap the benefits of the TestContext +framework such as support for loading application contexts, dependency injection of test +instances, transactional test method execution, and so on. The following code listing +displays the minimal requirements for configuring a test class to run with the custom +Spring Runner. `@TestExecutionListeners` is configured with an empty list in order to +disable the default listeners, which otherwise would require an ApplicationContext to be +configured through `@ContextConfiguration`. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @RunWith(SpringJUnit4ClassRunner.class) + @TestExecutionListeners({}) + public class SimpleTest { + + @Test + public void testMethod() { + // execute test logic... + } + } +---- + +[[testcontext-support-classes-testng]] +====== TestNG support classes +The `org.springframework.test.context.testng` package provides the following support +classes for TestNG based test cases. + +* `AbstractTestNGSpringContextTests` +* `AbstractTransactionalTestNGSpringContextTests` + +`AbstractTestNGSpringContextTests` is an abstract base test class that integrates the +__Spring TestContext Framework__ with explicit `ApplicationContext` testing support in +a TestNG environment. When you extend `AbstractTestNGSpringContextTests`, you can +access a `protected` `applicationContext` instance variable that can be used to perform +explicit bean lookups or to test the state of the context as a whole. + +`AbstractTransactionalTestNGSpringContextTests` is an abstract __transactional__ extension +of `AbstractTestNGSpringContextTests` that adds some convenience functionality for JDBC +access. This class expects a `javax.sql.DataSource` bean and a `PlatformTransactionManager` +bean to be defined in the `ApplicationContext`. When you extend +`AbstractTransactionalTestNGSpringContextTests` you can access a `protected` `jdbcTemplate` +instance variable that can be used to execute SQL statements to query the database. Such +queries can be used to confirm database state both __prior to__ and __after__ execution of +database-related application code, and Spring ensures that such queries run in the scope of +the same transaction as the application code. When used in conjunction with an ORM tool, +be sure to avoid <>. As mentioned in +<>, `AbstractTransactionalTestNGSpringContextTests` +also provides convenience methods which delegate to methods in `JdbcTestUtils` using the +aforementioned `jdbcTemplate`. Furthermore, `AbstractTransactionalTestNGSpringContextTests` +provides an `executeSqlScript(..)` method for executing SQL scripts against the configured +`DataSource`. + + +[TIP] +==== +These classes are a convenience for extension. If you do not want your test classes to be +tied to a Spring-specific class hierarchy, you can configure your own custom test classes +by using `@ContextConfiguration`, `@TestExecutionListeners`, and so on, and by manually +instrumenting your test class with a `TestContextManager`. See the source code of +`AbstractTestNGSpringContextTests` for an example of how to instrument your test class. +==== + + + +[[spring-mvc-test-framework]] +==== Spring MVC Test Framework + +.Standalone project +**** +Before inclusion in Spring Framework 3.2, the Spring MVC Test framework had already +existed as a separate project on GitHub where it grew and evolved through actual use, +feedback, and the contribution of many. + +The standalone https://github.com/spring-projects/spring-test-mvc[spring-test-mvc project] +is still available on GitHub and can be used in conjunction with Spring Framework 3.1.x. +Applications upgrading to 3.2 or later should replace the `spring-test-mvc` dependency with a +dependency on `spring-test`. + +The `spring-test` module uses a different package `org.springframework.test.web` but +otherwise is nearly identical with two exceptions. One is support for features new in +3.2 (e.g. asynchronous web requests). The other relates to the options for creating a +`MockMvc` instance. In Spring Framework 3.2 and later, this can only be done through the +TestContext framework, which provides caching benefits for the loaded configuration. +**** + +The __Spring MVC Test framework__ provides first class JUnit support for testing client +and server-side Spring MVC code through a fluent API. Typically it loads the actual +Spring configuration through the __TestContext framework__ and always uses the +`DispatcherServlet` to process requests thus approximating full integration tests +without requiring a running Servlet container. + +Client-side tests are `RestTemplate`-based and allow tests for code that relies on the +`RestTemplate` without requiring a running server to respond to the requests. + + +[[spring-mvc-test-server]] +===== Server-Side Tests +Before Spring Framework 3.2, the most likely way to test a Spring MVC controller was to +write a unit test that instantiates the controller, injects it with mock or stub +dependencies, and then calls its methods directly, using a `MockHttpServletRequest` and +`MockHttpServletResponse` where necessary. + +Although this is pretty easy to do, controllers have many annotations, and much remains +untested. Request mappings, data binding, type conversion, and validation are just a few +examples of what isn't tested. Furthermore, there are other types of annotated methods +such as `@InitBinder`, `@ModelAttribute`, and `@ExceptionHandler` that get invoked as +part of request processing. + +The idea behind Spring MVC Test is to be able to re-write those controller tests by +performing actual requests and generating responses, as they would be at runtime, along +the way invoking controllers through the Spring MVC `DispatcherServlet`. Controllers can +still be injected with mock dependencies, so tests can remain focused on the web layer. + +Spring MVC Test builds on the familiar "mock" implementations of the Servlet API +available in the `spring-test` module. This allows performing requests and generating +responses without the need for running in a Servlet container. For the most part +everything should work as it does at runtime with the exception of JSP rendering, which +is not available outside a Servlet container. Furthermore, if you are familiar with how +the `MockHttpServletResponse` works, you'll know that forwards and redirects are not +actually executed. Instead "forwarded" and "redirected" URLs are saved and can be +asserted in tests. This means if you are using JSPs, you can verify the JSP page to +which the request was forwarded. + +All other means of rendering including `@ResponseBody` methods and `View` types (besides +JSPs) such as Freemarker, Velocity, Thymeleaf, and others for rendering HTML, JSON, XML, +and so on should work as expected, and the response will contain the generated content. + +Below is an example of a test requesting account information in JSON format: + +[source,java,indent=0] +---- + import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; + import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; + + @RunWith(SpringJUnit4ClassRunner.class) + @WebAppConfiguration + @ContextConfiguration("test-servlet-context.xml") + public class ExampleTests { + + @Autowired + private WebApplicationContext wac; + + private MockMvc mockMvc; + + @Before + public void setup() { + this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build(); + } + + @Test + public void getAccount() throws Exception { + this.mockMvc.perform(get("/accounts/1").accept(MediaType.parseMediaType("application/json;charset=UTF-8"))) + .andExpect(status().isOk()) + .andExpect(content().contentType("application/json")) + .andExpect(jsonPath("$.name").value("Lee")); + } + + } +---- + +The test relies on the `WebApplicationContext` support of the __TestContext framework__. +It loads Spring configuration from an XML configuration file located in the same package +as the test class (also supports JavaConfig) and injects the created +`WebApplicationContext` into the test so a `MockMvc` instance can be created with it. + +The `MockMvc` is then used to perform a request to `"/accounts/1"` and verify the +resulting response status is 200, the response content type is `"application/json"`, and +response content has a JSON property called "name" with the value "Lee". JSON content is +inspected with the help of Jayway's https://github.com/jayway/JsonPath[JsonPath +project]. There are lots of other options for verifying the result of the performed +request and those will be discussed later. + +[[spring-mvc-test-server-static-imports]] +====== Static Imports +The fluent API in the example above requires a few static imports such as +`MockMvcRequestBuilders.*`, `MockMvcResultMatchers.*`, and `MockMvcBuilders.*`. An easy +way to find these classes is to search for types matching __"MockMvc*"__. If using +Eclipse, be sure to add them as "favorite static members" in the Eclipse preferences +under__Java -> Editor -> Content Assist -> Favorites__. That will allow use of content +assist after typing the first character of the static method name. Other IDEs (e.g. +IntelliJ) may not require any additional configuration. Just check the support for code +completion on static members. + +[[spring-mvc-test-server-setup-options]] +====== Setup Options +The goal of server-side test setup is to create an instance of `MockMvc` that can be +used to perform requests. There are two main options. + +The first option is to point to Spring MVC configuration through the __TestContext +framework__, which loads the Spring configuration and injects a `WebApplicationContext` +into the test to use to create a `MockMvc`: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @RunWith(SpringJUnit4ClassRunner.class) + @WebAppConfiguration + @ContextConfiguration("my-servlet-context.xml") + public class MyWebTests { + + @Autowired + private WebApplicationContext wac; + + private MockMvc mockMvc; + + @Before + public void setup() { + this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build(); + } + + // ... + + } +---- + +The second option is to simply register a controller instance without loading any Spring +configuration. Instead basic Spring MVC configuration suitable for testing annotated +controllers is automatically created. The created configuration is comparable to that of +the MVC JavaConfig (and the MVC namespace) and can be customized to a degree through +builder-style methods: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class MyWebTests { + + private MockMvc mockMvc; + + @Before + public void setup() { + this.mockMvc = MockMvcBuilders.standaloneSetup(new AccountController()).build(); + } + + // ... + + } +---- + +Which option should you use? + +The __"webAppContextSetup"__ loads the actual Spring MVC configuration resulting in a +more complete integration test. Since the __TestContext framework__ caches the loaded +Spring configuration, it helps to keep tests running fast even as more tests get added. +Furthermore, you can inject mock services into controllers through Spring configuration, +in order to remain focused on testing the web layer. Here is an example of declaring a +mock service with Mockito: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + +---- + +Then you can inject the mock service into the test in order set up and verify +expectations: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @RunWith(SpringJUnit4ClassRunner.class) + @WebAppConfiguration + @ContextConfiguration("test-servlet-context.xml") + public class AccountTests { + + @Autowired + private WebApplicationContext wac; + + private MockMvc mockMvc; + + @Autowired + private AccountService accountService; + + // ... + + } +---- + +The __"standaloneSetup"__ on the other hand is a little closer to a unit test. It tests +one controller at a time, the controller can be injected with mock dependencies +manually, and it doesn't involve loading Spring configuration. Such tests are more +focused in style and make it easier to see which controller is being tested, whether any +specific Spring MVC configuration is required to work, and so on. The "standaloneSetup" +is also a very convenient way to write ad-hoc tests to verify some behavior or to debug +an issue. + +Just like with integration vs unit testing, there is no right or wrong answer. Using the +"standaloneSetup" does imply the need for some additional "webAppContextSetup" tests to +verify the Spring MVC configuration. Alternatively, you can decide write all tests with +"webAppContextSetup" and always test against actual Spring MVC configuration. + +[[spring-mvc-test-server-performing-requests]] +====== Performing Requests +To perform requests, use the appropriate HTTP method and additional builder-style +methods corresponding to properties of `MockHttpServletRequest`. For example: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + mockMvc.perform(post("/hotels/{id}", 42).accept(MediaType.APPLICATION_JSON)); +---- + +In addition to all the HTTP methods, you can also perform file upload requests, which +internally creates an instance of `MockMultipartHttpServletRequest`: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + mockMvc.perform(fileUpload("/doc").file("a1", "ABC".getBytes("UTF-8"))); +---- + +Query string parameters can be specified in the URI template: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + mockMvc.perform(get("/hotels?foo={foo}", "bar")); +---- + +Or by adding Servlet request parameters: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + mockMvc.perform(get("/hotels").param("foo", "bar")); +---- + +If application code relies on Servlet request parameters, and doesn't check the query +string, as is most often the case, then it doesn't matter how parameters are added. Keep +in mind though that parameters provided in the URI template will be decoded while +parameters provided through the `param(...)` method are expected to be decoded. + +In most cases it's preferable to leave out the context path and the Servlet path from +the request URI. If you must test with the full request URI, be sure to set the +`contextPath` and `servletPath` accordingly so that request mappings will work: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + mockMvc.perform(get("/app/main/hotels/{id}").contextPath("/app").servletPath("/main")) +---- + +Looking at the above example, it would be cumbersome to set the contextPath and +servletPath with every performed request. That's why you can define default request +properties when building the `MockMvc`: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class MyWebTests { + + private MockMvc mockMvc; + + @Before + public void setup() { + mockMvc = standaloneSetup(new AccountController()) + .defaultRequest(get("/") + .contextPath("/app").servletPath("/main") + .accept(MediaType.APPLICATION_JSON).build(); + } +---- + +The above properties will apply to every request performed through the `MockMvc`. If the +same property is also specified on a given request, it will override the default value. +That is why, the HTTP method and URI don't matter, when setting default request +properties, since they must be specified on every request. + +[[spring-mvc-test-server-defining-expectations]] +====== Defining Expectations +Expectations can be defined by appending one or more `.andExpect(..)` after call to +perform the request: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + mockMvc.perform(get("/accounts/1")).andExpect(status().isOk()); +---- + +`MockMvcResultMatchers.*` defines a number of static members, some of which return types +with additional methods, for asserting the result of the performed request. The +assertions fall in two general categories. + +The first category of assertions verify properties of the response, i.e the response +status, headers, and content. Those are the most important things to test for. + +The second category of assertions go beyond the response, and allow inspecting Spring +MVC specific constructs such as which controller method processed the request, whether +an exception was raised and handled, what the content of the model is, what view was +selected, what flash attributes were added, and so on. It is also possible to verify +Servlet specific constructs such as request and session attributes. The following test +asserts that binding/validation failed: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + mockMvc.perform(post("/persons")) + .andExpect(status().isOk()) + .andExpect(model().attributeHasErrors("person")); +---- + +Many times when writing tests, it's useful to dump the result of the performed request. +This can be done as follows, where `print()` is a static import from +`MockMvcResultHandlers`: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + mockMvc.perform(post("/persons")) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(model().attributeHasErrors("person")); +---- + +As long as request processing causes an unhandled exception, the `print()` method will +print all the available result data to `System.out`. + +In some cases, you may want to get direct access to the result and verify something that +cannot be verified otherwise. This can be done by appending `.andReturn()` at the end +after all expectations: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + MvcResult mvcResult = mockMvc.perform(post("/persons")).andExpect(status().isOk()).andReturn(); + // ... +---- + +When all tests repeat the same expectations, you can define the common expectations once +when building the `MockMvc`: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + standaloneSetup(new SimpleController()) + .alwaysExpect(status().isOk()) + .alwaysExpect(content().contentType("application/json;charset=UTF-8")) + .build() +---- + +Note that the expectation is __always__ applied and cannot be overridden without +creating a separate `MockMvc` instance. + +When JSON response content contains hypermedia links created with +https://github.com/spring-projects/spring-hateoas[Spring HATEOAS], the resulting links can +be verified: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + mockMvc.perform(get("/people").accept(MediaType.APPLICATION_JSON)) + .andExpect(jsonPath("$.links[?(@.rel == 'self')].href").value("http://localhost:8080/people")); +---- + +When XML response content contains hypermedia links created with +https://github.com/spring-projects/spring-hateoas[Spring HATEOAS], the resulting links can +be verified: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + Map ns = Collections.singletonMap("ns", "http://www.w3.org/2005/Atom"); + mockMvc.perform(get("/handle").accept(MediaType.APPLICATION_XML)) + .andExpect(xpath("/person/ns:link[@rel='self']/@href", ns).string("http://localhost:8080/people")); +---- + +[[spring-mvc-test-server-filters]] +====== Filter Registrations +When setting up a `MockMvc`, you can register one or more `Filter` instances: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + mockMvc = standaloneSetup(new PersonController()).addFilters(new CharacterEncodingFilter()).build(); +---- + +Registered filters will be invoked through `MockFilterChain` from `spring-test` and the +last filter will delegates to the `DispatcherServlet`. + +[[spring-mvc-test-server-resources]] +====== Further Server-Side Test Examples +The framework's own tests include +https://github.com/spring-projects/spring-framework/tree/master/spring-test/src/test/java/org/springframework/test/web/servlet/samples[many +sample tests] intended to demonstrate how to use Spring MVC Test. Browse these examples +for further ideas. Also the +https://github.com/spring-projects/spring-mvc-showcase[spring-mvc-showcase] has full test +coverage based on Spring MVC Test. + + +[[spring-mvc-test-client]] +===== Client-Side REST Tests +Client-side tests are for code using the `RestTemplate`. The goal is to define expected +requests and provide "stub" responses: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + RestTemplate restTemplate = new RestTemplate(); + + MockRestServiceServer mockServer = MockRestServiceServer.createServer(restTemplate); + mockServer.expect(requestTo("/greeting")).andRespond(withSuccess("Hello world", MediaType.TEXT_PLAIN)); + + // use RestTemplate ... + + mockServer.verify(); +---- + +In the above example, `MockRestServiceServer` -- the central class for client-side REST +tests -- configures the `RestTemplate` with a custom `ClientHttpRequestFactory` that +asserts actual requests against expectations and returns "stub" responses. In this case +we expect a single request to "/greeting" and want to return a 200 response with +"text/plain" content. We could define as many additional requests and stub responses as +necessary. + +Once expected requests and stub responses have been defined, the `RestTemplate` can be +used in client-side code as usual. At the end of the tests `mockServer.verify()` can be +used to verify that all expected requests were performed. + +[[spring-mvc-test-client-static-imports]] +====== Static Imports +Just like with server-side tests, the fluent API for client-side tests requires a few +static imports. Those are easy to find by searching __"MockRest*"__. Eclipse users +should add `"MockRestRequestMatchers.*"` and `"MockRestResponseCreators.*"` as "favorite +static members" in the Eclipse preferences under __Java -> Editor -> Content Assist -> +Favorites__. That allows using content assist after typing the first character of the +static method name. Other IDEs (e.g. IntelliJ) may not require any additional +configuration. Just check the support for code completion on static members. + +[[spring-mvc-test-client-resources]] +====== Further Examples of Client-side REST Tests +Spring MVC Test's own tests include +https://github.com/spring-projects/spring-framework/tree/master/spring-test/src/test/java/org/springframework/test/web/client/samples[example +tests] of client-side REST tests. + + + +[[testing-examples-petclinic]] +==== PetClinic Example + +The PetClinic application, available on +https://github.com/spring-projects/spring-petclinic[GitHub], illustrates several features +of the __Spring TestContext Framework__ in a JUnit environment. Most test functionality +is included in the `AbstractClinicTests`, for which a partial listing is shown below: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + import static org.junit.Assert.assertEquals; + // import ... + + **@ContextConfiguration** + public abstract class AbstractClinicTests **extends AbstractTransactionalJUnit4SpringContextTests** { + + **@Autowired** + protected Clinic clinic; + + @Test + public void getVets() { + Collection vets = this.clinic.getVets(); + assertEquals("JDBC query must show the same number of vets", + **super.countRowsInTable("VETS")**, vets.size()); + Vet v1 = EntityUtils.getById(vets, Vet.class, 2); + assertEquals("Leary", v1.getLastName()); + assertEquals(1, v1.getNrOfSpecialties()); + assertEquals("radiology", (v1.getSpecialties().get(0)).getName()); + // ... + } + + // ... + } +---- + +Notes: + +* This test case extends the `AbstractTransactionalJUnit4SpringContextTests` class, from + which it inherits configuration for Dependency Injection (through the + `DependencyInjectionTestExecutionListener`) and transactional behavior (through the + `TransactionalTestExecutionListener`). +* The `clinic` instance variable -- the application object being tested -- is set by + Dependency Injection through `@Autowired` semantics. +* The `getVets()` method illustrates how you can use the inherited `countRowsInTable()` + method to easily verify the number of rows in a given table, thus verifying correct + behavior of the application code being tested. This allows for stronger tests and + lessens dependency on the exact test data. For example, you can add additional rows in + the database without breaking tests. +* Like many integration tests that use a database, most of the tests in + `AbstractClinicTests` depend on a minimum amount of data already in the database before + the test cases run. Alternatively, you might choose to populate the database within the + test fixture set up of your test cases -- again, within the same transaction as the + tests. + +The PetClinic application supports three data access technologies: JDBC, Hibernate, and +JPA. By declaring `@ContextConfiguration` without any specific resource locations, the +`AbstractClinicTests` class will have its application context loaded from the default +location, `AbstractClinicTests-context.xml`, which declares a common `DataSource`. +Subclasses specify additional context locations that must declare a +`PlatformTransactionManager` and a concrete implementation of `Clinic`. + +For example, the Hibernate implementation of the PetClinic tests contains the following +implementation. For this example, `HibernateClinicTests` does not contain a single line +of code: we only need to declare `@ContextConfiguration`, and the tests are inherited +from `AbstractClinicTests`. Because `@ContextConfiguration` is declared without any +specific resource locations, the __Spring TestContext Framework__ loads an application +context from all the beans defined in `AbstractClinicTests-context.xml` (i.e., the +inherited locations) and `HibernateClinicTests-context.xml`, with +`HibernateClinicTests-context.xml` possibly overriding beans defined in +`AbstractClinicTests-context.xml`. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + **@ContextConfiguration** + public class HibernateClinicTests extends AbstractClinicTests { } +---- + +In a large-scale application, the Spring configuration is often split across multiple +files. Consequently, configuration locations are typically specified in a common base +class for all application-specific integration tests. Such a base class may also add +useful instance variables -- populated by Dependency Injection, naturally -- such as a +`SessionFactory` in the case of an application using Hibernate. + +As far as possible, you should have exactly the same Spring configuration files in your +integration tests as in the deployed environment. One likely point of difference +concerns database connection pooling and transaction infrastructure. If you are +deploying to a full-blown application server, you will probably use its connection pool +(available through JNDI) and JTA implementation. Thus in production you will use a +`JndiObjectFactoryBean` or `` for the `DataSource` and +`JtaTransactionManager`. JNDI and JTA will not be available in out-of-container +integration tests, so you should use a combination like the Commons DBCP +`BasicDataSource` and `DataSourceTransactionManager` or `HibernateTransactionManager` +for them. You can factor out this variant behavior into a single XML file, having the +choice between application server and a 'local' configuration separated from all other +configuration, which will not vary between the test and production environments. In +addition, it is advisable to use properties files for connection settings. See the +PetClinic application for an example. + + + + +[[testing-resources]] +=== Further Resources +Consult the following resources for more information about testing: + +* http://www.junit.org/[JUnit]: "__A programmer-oriented testing framework for Java__". + Used by the Spring Framework in its test suite. +* http://testng.org/[TestNG]: A testing framework inspired by JUnit with added support + for annotations, test groups, data-driven testing, distributed testing, etc. +* http://www.mockobjects.com/[MockObjects.com]: Web site dedicated to mock objects, a + technique for improving the design of code within test-driven development. +* http://en.wikipedia.org/wiki/Mock_Object["Mock Objects"]: Article in Wikipedia. +* http://www.easymock.org/[EasyMock]: Java library " __that provides Mock Objects for + interfaces (and objects through the class extension) by generating them on the fly + using Java's proxy mechanism.__ " Used by the Spring Framework in its test suite. +* http://www.jmock.org/[JMock]: Library that supports test-driven development of Java + code with mock objects. +* http://mockito.org/[Mockito]: Java mock library based on the + http://xunitpatterns.com/Test%20Spy.html[test spy] pattern. +* http://dbunit.sourceforge.net/[DbUnit]: JUnit extension (also usable with Ant and + Maven) targeted for database-driven projects that, among other things, puts your + database into a known state between test runs. +* http://grinder.sourceforge.net/[The Grinder]: Java load testing framework. diff --git a/src/asciidoc/transaction.adoc b/src/asciidoc/transaction.adoc new file mode 100644 index 000000000000..2557d2a581e1 --- /dev/null +++ b/src/asciidoc/transaction.adoc @@ -0,0 +1,1985 @@ +[[transaction]] +== Transaction Management + + + + +[[transaction-intro]] +=== Introduction to Spring Framework transaction management +Comprehensive transaction support is among the most compelling reasons to use the Spring +Framework. The Spring Framework provides a consistent abstraction for transaction +management that delivers the following benefits: + +* Consistent programming model across different transaction APIs such as Java + Transaction API (JTA), JDBC, Hibernate, Java Persistence API (JPA), and Java Data + Objects (JDO). +* Support for <>. +* Simpler API for <> transaction management than + complex transaction APIs such as JTA. +* Excellent integration with Spring's data access abstractions. + +The following sections describe the Spring Framework's transaction value-adds and +technologies. (The chapter also includes discussions of best practices, application +server integration, and solutions to common problems.) + +* <> describes __why__ you would use the Spring Framework's transaction abstraction + instead of EJB Container-Managed Transactions (CMT) or choosing to drive local + transactions through a proprietary API such as Hibernate. +* <> + outlines the core classes and describes how to configure and obtain `DataSource` + instances from a variety of sources. +* <>describes + how the application code ensures that resources are created, reused, and cleaned up + properly. +* <> describes support for + declarative transaction management. +* <> covers support for + programmatic (that is, explicitly coded) transaction management. + + + + +[[transaction-motivation]] +=== Advantages of the Spring Framework's transaction support model +Traditionally, Java EE developers have had two choices for transaction management: +__global__ or __local__ transactions, both of which have profound limitations. Global +and local transaction management is reviewed in the next two sections, followed by a +discussion of how the Spring Framework's transaction management support addresses the +limitations of the global and local transaction models. + + + +[[transaction-global]] +==== Global transactions +Global transactions enable you to work with multiple transactional resources, typically +relational databases and message queues. The application server manages global +transactions through the JTA, which is a cumbersome API to use (partly due to its +exception model). Furthermore, a JTA `UserTransaction` normally needs to be sourced from +JNDI, meaning that you __also__ need to use JNDI in order to use JTA. Obviously the use +of global transactions would limit any potential reuse of application code, as JTA is +normally only available in an application server environment. + +Previously, the preferred way to use global transactions was via EJB __CMT__ +(__Container Managed Transaction__): CMT is a form of __declarative transaction +management__ (as distinguished from __programmatic transaction management__). EJB CMT +removes the need for transaction-related JNDI lookups, although of course the use of EJB +itself necessitates the use of JNDI. It removes most but not all of the need to write +Java code to control transactions. The significant downside is that CMT is tied to JTA +and an application server environment. Also, it is only available if one chooses to +implement business logic in EJBs, or at least behind a transactional EJB facade. The +negatives of EJB in general are so great that this is not an attractive proposition, +especially in the face of compelling alternatives for declarative transaction management. + + + +[[transaction-local]] +==== Local transactions +Local transactions are resource-specific, such as a transaction associated with a JDBC +connection. Local transactions may be easier to use, but have significant disadvantages: +they cannot work across multiple transactional resources. For example, code that manages +transactions using a JDBC connection cannot run within a global JTA transaction. Because +the application server is not involved in transaction management, it cannot help ensure +correctness across multiple resources. (It is worth noting that most applications use a +single transaction resource.) Another downside is that local transactions are invasive +to the programming model. + + + +[[transaction-programming-model]] +==== Spring Framework's consistent programming model + +Spring resolves the disadvantages of global and local transactions. It enables +application developers to use a __consistent__ programming model __in any environment__. +You write your code once, and it can benefit from different transaction management +strategies in different environments. The Spring Framework provides both declarative and +programmatic transaction management. Most users prefer declarative transaction +management, which is recommended in most cases. + +With programmatic transaction management, developers work with the Spring Framework +transaction abstraction, which can run over any underlying transaction infrastructure. +With the preferred declarative model, developers typically write little or no code +related to transaction management, and hence do not depend on the Spring Framework +transaction API, or any other transaction API. + +.Do you need an application server for transaction management? +**** +The Spring Framework's transaction management support changes traditional rules as to +when an enterprise Java application requires an application server. + +In particular, you do not need an application server simply for declarative transactions +through EJBs. In fact, even if your application server has powerful JTA capabilities, +you may decide that the Spring Framework's declarative transactions offer more power and +a more productive programming model than EJB CMT. + +Typically you need an application server's JTA capability only if your application needs +to handle transactions across multiple resources, which is not a requirement for many +applications. Many high-end applications use a single, highly scalable database (such as +Oracle RAC) instead. Standalone transaction managers such as +http://www.atomikos.com/[Atomikos Transactions] and http://jotm.objectweb.org/[JOTM] +are other options. Of course, you may need other application server capabilities such as +Java Message Service (JMS) and Java EE Connector Architecture (JCA). + +The Spring Framework __gives you the choice of when to scale your application to a fully +loaded application server__. Gone are the days when the only alternative to using EJB +CMT or JTA was to write code with local transactions such as those on JDBC connections, +and face a hefty rework if you need that code to run within global, container-managed +transactions. With the Spring Framework, only some of the bean definitions in your +configuration file, rather than your code, need to change. +**** + + + + +[[transaction-strategies]] +=== Understanding the Spring Framework transaction abstraction +The key to the Spring transaction abstraction is the notion of a __transaction +strategy__. A transaction strategy is defined by the +`org.springframework.transaction.PlatformTransactionManager` interface: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public interface PlatformTransactionManager { + + TransactionStatus getTransaction( + TransactionDefinition definition) throws TransactionException; + + void commit(TransactionStatus status) throws TransactionException; + + void rollback(TransactionStatus status) throws TransactionException; + } +---- + +This is primarily a service provider interface (SPI), although it can be used +<> from your application code. Because +`PlatformTransactionManager` is an __interface__, it can be easily mocked or stubbed as +necessary. It is not tied to a lookup strategy such as JNDI. +`PlatformTransactionManager` implementations are defined like any other object (or bean) +in the Spring Framework IoC container. This benefit alone makes Spring Framework +transactions a worthwhile abstraction even when you work with JTA. Transactional code +can be tested much more easily than if it used JTA directly. + +Again in keeping with Spring's philosophy, the `TransactionException` that can be thrown +by any of the `PlatformTransactionManager` interface's methods is __unchecked__ (that +is, it extends the `java.lang.RuntimeException` class). Transaction infrastructure +failures are almost invariably fatal. In rare cases where application code can actually +recover from a transaction failure, the application developer can still choose to catch +and handle `TransactionException`. The salient point is that developers are not +__forced__ to do so. + +The `getTransaction(..)` method returns a `TransactionStatus` object, depending on a +`TransactionDefinition` parameter. The returned `TransactionStatus` might represent a +new transaction, or can represent an existing transaction if a matching transaction +exists in the current call stack. The implication in this latter case is that, as with +Java EE transaction contexts, a `TransactionStatus` is associated with a __thread__ of +execution. + +The `TransactionDefinition` interface specifies: + +* __Isolation__: The degree to which this transaction is isolated from the work of other + transactions. For example, can this transaction see uncommitted writes from other + transactions? +* __Propagation__: Typically, all code executed within a transaction scope will run in + that transaction. However, you have the option of specifying the behavior in the event + that a transactional method is executed when a transaction context already exists. For + example, code can continue running in the existing transaction (the common case); or + the existing transaction can be suspended and a new transaction created. __Spring + offers all of the transaction propagation options familiar from EJB CMT__. To read + about the semantics of transaction propagation in Spring, see <>. +* __Timeout__: How long this transaction runs before timing out and being rolled back + automatically by the underlying transaction infrastructure. +* __Read-only status__: A read-only transaction can be used when your code reads but + does not modify data. Read-only transactions can be a useful optimization in some + cases, such as when you are using Hibernate. + +These settings reflect standard transactional concepts. If necessary, refer to resources +that discuss transaction isolation levels and other core transaction concepts. +Understanding these concepts is essential to using the Spring Framework or any +transaction management solution. + +The `TransactionStatus` interface provides a simple way for transactional code to +control transaction execution and query transaction status. The concepts should be +familiar, as they are common to all transaction APIs: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public interface TransactionStatus extends SavepointManager { + + boolean isNewTransaction(); + + boolean hasSavepoint(); + + void setRollbackOnly(); + + boolean isRollbackOnly(); + + void flush(); + + boolean isCompleted(); + + } +---- + +Regardless of whether you opt for declarative or programmatic transaction management in +Spring, defining the correct `PlatformTransactionManager` implementation is absolutely +essential. You typically define this implementation through dependency injection. + +`PlatformTransactionManager` implementations normally require knowledge of the +environment in which they work: JDBC, JTA, Hibernate, and so on. The following examples +show how you can define a local `PlatformTransactionManager` implementation. (This +example works with plain JDBC.) + +You define a JDBC `DataSource` + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + +---- + +The related `PlatformTransactionManager` bean definition will then have a reference to +the `DataSource` definition. It will look like this: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + +---- + +If you use JTA in a Java EE container then you use a container `DataSource`, obtained +through JNDI, in conjunction with Spring's `JtaTransactionManager`. This is what the JTA +and JNDI lookup version would look like: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + + + +---- + +The `JtaTransactionManager` does not need to know about the `DataSource`, or any other +specific resources, because it uses the container's global transaction management +infrastructure. + +[NOTE] +==== +The above definition of the `dataSource` bean uses the `` tag from the +`jee` namespace. For more information on schema-based configuration, see <>, +and for more information on the `` tags see the section entitled +<>. +==== + +You can also use Hibernate local transactions easily, as shown in the following +examples. In this case, you need to define a Hibernate `LocalSessionFactoryBean`, which +your application code will use to obtain Hibernate `Session` instances. + +The `DataSource` bean definition will be similar to the local JDBC example shown +previously and thus is not shown in the following example. + +[NOTE] +==== +If the `DataSource`, used by any non-JTA transaction manager, is looked up via JNDI and +managed by a Java EE container, then it should be non-transactional because the Spring +Framework, rather than the Java EE container, will manage the transactions. +==== + +The `txManager` bean in this case is of the `HibernateTransactionManager` type. In the +same way as the `DataSourceTransactionManager` needs a reference to the `DataSource`, +the `HibernateTransactionManager` needs a reference to the `SessionFactory`. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + org/springframework/samples/petclinic/hibernate/petclinic.hbm.xml + + + + + hibernate.dialect=${hibernate.dialect} + + + + + + + +---- + +If you are using Hibernate and Java EE container-managed JTA transactions, then you +should simply use the same `JtaTransactionManager` as in the previous JTA example for +JDBC. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + +---- + +[NOTE] +==== +If you use JTA , then your transaction manager definition will look the same regardless +of what data access technology you use, be it JDBC, Hibernate JPA or any other supported +technology. This is due to the fact that JTA transactions are global transactions, which +can enlist any transactional resource. +==== + +In all these cases, application code does not need to change. You can change how +transactions are managed merely by changing configuration, even if that change means +moving from local to global transactions or vice versa. + + + + +[[tx-resource-synchronization]] +=== Synchronizing resources with transactions +It should now be clear how you create different transaction managers, and how they are +linked to related resources that need to be synchronized to transactions (for example +`DataSourceTransactionManager` to a JDBC `DataSource`, `HibernateTransactionManager` to +a Hibernate `SessionFactory`, and so forth). This section describes how the application +code, directly or indirectly using a persistence API such as JDBC, Hibernate, or JDO, +ensures that these resources are created, reused, and cleaned up properly. The section +also discusses how transaction synchronization is triggered (optionally) through the +relevant `PlatformTransactionManager`. + + + +[[tx-resource-synchronization-high]] +==== High-level synchronization approach +The preferred approach is to use Spring's highest level template based persistence +integration APIs or to use native ORM APIs with transaction- aware factory beans or +proxies for managing the native resource factories. These transaction-aware solutions +internally handle resource creation and reuse, cleanup, optional transaction +synchronization of the resources, and exception mapping. Thus user data access code does +not have to address these tasks, but can be focused purely on non-boilerplate +persistence logic. Generally, you use the native ORM API or take a __template__ approach +for JDBC access by using the `JdbcTemplate`. These solutions are detailed in subsequent +chapters of this reference documentation. + + + +[[tx-resource-synchronization-low]] +==== Low-level synchronization approach +Classes such as `DataSourceUtils` (for JDBC), `EntityManagerFactoryUtils` (for JPA), +`SessionFactoryUtils` (for Hibernate), `PersistenceManagerFactoryUtils` (for JDO), and +so on exist at a lower level. When you want the application code to deal directly with +the resource types of the native persistence APIs, you use these classes to ensure that +proper Spring Framework-managed instances are obtained, transactions are (optionally) +synchronized, and exceptions that occur in the process are properly mapped to a +consistent API. + +For example, in the case of JDBC, instead of the traditional JDBC approach of calling +the `getConnection()` method on the `DataSource`, you instead use Spring's +`org.springframework.jdbc.datasource.DataSourceUtils` class as follows: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + Connection conn = DataSourceUtils.getConnection(dataSource); +---- + +If an existing transaction already has a connection synchronized (linked) to it, that +instance is returned. Otherwise, the method call triggers the creation of a new +connection, which is (optionally) synchronized to any existing transaction, and made +available for subsequent reuse in that same transaction. As mentioned, any +`SQLException` is wrapped in a Spring Framework `CannotGetJdbcConnectionException`, one +of the Spring Framework's hierarchy of unchecked DataAccessExceptions. This approach +gives you more information than can be obtained easily from the `SQLException`, and +ensures portability across databases, even across different persistence technologies. + +This approach also works without Spring transaction management (transaction +synchronization is optional), so you can use it whether or not you are using Spring for +transaction management. + +Of course, once you have used Spring's JDBC support, JPA support or Hibernate support, +you will generally prefer not to use `DataSourceUtils` or the other helper classes, +because you will be much happier working through the Spring abstraction than directly +with the relevant APIs. For example, if you use the Spring `JdbcTemplate` or +`jdbc.object` package to simplify your use of JDBC, correct connection retrieval occurs +behind the scenes and you won't need to write any special code. + + + +[[tx-resource-synchronization-tadsp]] +==== TransactionAwareDataSourceProxy + +At the very lowest level exists the `TransactionAwareDataSourceProxy` class. This is a +proxy for a target `DataSource`, which wraps the target `DataSource` to add awareness of +Spring-managed transactions. In this respect, it is similar to a transactional JNDI +`DataSource` as provided by a Java EE server. + +It should almost never be necessary or desirable to use this class, except when existing +code must be called and passed a standard JDBC `DataSource` interface implementation. In +that case, it is possible that this code is usable, but participating in Spring managed +transactions. It is preferable to write your new code by using the higher level +abstractions mentioned above. + + + + +[[transaction-declarative]] +=== Declarative transaction management +[NOTE] +==== +Most Spring Framework users choose declarative transaction management. This option has +the least impact on application code, and hence is most consistent with the ideals of a +__non-invasive__ lightweight container. +==== + +The Spring Framework's declarative transaction management is made possible with Spring +aspect-oriented programming (AOP), although, as the transactional aspects code comes +with the Spring Framework distribution and may be used in a boilerplate fashion, AOP +concepts do not generally have to be understood to make effective use of this code. + +The Spring Framework's declarative transaction management is similar to EJB CMT in that +you can specify transaction behavior (or lack of it) down to individual method level. It +is possible to make a `setRollbackOnly()` call within a transaction context if +necessary. The differences between the two types of transaction management are: + +* Unlike EJB CMT, which is tied to JTA, the Spring Framework's declarative transaction + management works in any environment. It can work with JTA transactions or local + transactions using JDBC, JPA, Hibernate or JDO by simply adjusting the configuration + files. +* You can apply the Spring Framework declarative transaction management to any class, + not merely special classes such as EJBs. +* The Spring Framework offers declarative + <>a feature with no EJB + equivalent. Both programmatic and declarative support for rollback rules is provided. +* The Spring Framework enables you to customize transactional behavior, by using AOP. + For example, you can insert custom behavior in the case of transaction rollback. You + can also add arbitrary advice, along with the transactional advice. With EJB CMT, you + cannot influence the container's transaction management except with + `setRollbackOnly()`. +* The Spring Framework does not support propagation of transaction contexts across + remote calls, as do high-end application servers. If you need this feature, we + recommend that you use EJB. However, consider carefully before using such a feature, + because normally, one does not want transactions to span remote calls. + +.Where is TransactionProxyFactoryBean? +**** +Declarative transaction configuration in versions of Spring 2.0 and above differs +considerably from previous versions of Spring. The main difference is that there is no +longer any need to configure `TransactionProxyFactoryBean` beans. + +The pre-Spring 2.0 configuration style is still 100% valid configuration; think of the +new `` as simply defining `TransactionProxyFactoryBean` beans on your behalf. +**** + +The concept of rollback rules is important: they enable you to specify which exceptions +(and throwables) should cause automatic rollback. You specify this declaratively, in +configuration, not in Java code. So, although you can still call `setRollbackOnly()` on +the `TransactionStatus` object to roll back the current transaction back, most often you +can specify a rule that `MyApplicationException` must always result in rollback. The +significant advantage to this option is that business objects do not depend on the +transaction infrastructure. For example, they typically do not need to import Spring +transaction APIs or other Spring APIs. + +Although EJB container default behavior automatically rolls back the transaction on a +__system exception__ (usually a runtime exception), EJB CMT does not roll back the +transaction automatically on an__application exception__ (that is, a checked exception +other than `java.rmi.RemoteException`). While the Spring default behavior for +declarative transaction management follows EJB convention (roll back is automatic only +on unchecked exceptions), it is often useful to customize this behavior. + + + +[[tx-decl-explained]] +==== Understanding the Spring Framework's declarative transaction implementation +It is not sufficient to tell you simply to annotate your classes with the +`@Transactional` annotation, add `@EnableTransactionManagement` to your configuration, +and then expect you to understand how it all works. This section explains the inner +workings of the Spring Framework's declarative transaction infrastructure in the event +of transaction-related issues. + +The most important concepts to grasp with regard to the Spring Framework's declarative +transaction support are that this support is enabled +<>, and that the transactional advice +is driven by __metadata__ (currently XML- or annotation-based). The combination of AOP +with transactional metadata yields an AOP proxy that uses a `TransactionInterceptor` in +conjunction with an appropriate `PlatformTransactionManager` implementation to drive +transactions __around method invocations__. + +[NOTE] +==== +Spring AOP is covered in <>. +==== + +Conceptually, calling a method on a transactional proxy looks like this... + +image::images/tx.png[width=400] + + + +[[transaction-declarative-first-example]] +==== Example of declarative transaction implementation +Consider the following interface, and its attendant implementation. This example uses +`Foo` and `Bar` classes as placeholders so that you can concentrate on the transaction +usage without focusing on a particular domain model. For the purposes of this example, +the fact that the `DefaultFooService` class throws `UnsupportedOperationException` +instances in the body of each implemented method is good; it allows you to see +transactions created and then rolled back in response to the +`UnsupportedOperationException` instance. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + // the service interface that we want to make transactional + + package x.y.service; + + public interface FooService { + + Foo getFoo(String fooName); + + Foo getFoo(String fooName, String barName); + + void insertFoo(Foo foo); + + void updateFoo(Foo foo); + + } +---- + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + // an implementation of the above interface + + package x.y.service; + + public class DefaultFooService implements FooService { + + public Foo getFoo(String fooName) { + throw new UnsupportedOperationException(); + } + + public Foo getFoo(String fooName, String barName) { + throw new UnsupportedOperationException(); + } + + public void insertFoo(Foo foo) { + throw new UnsupportedOperationException(); + } + + public void updateFoo(Foo foo) { + throw new UnsupportedOperationException(); + } + + } +---- + +Assume that the first two methods of the `FooService` interface, `getFoo(String)` and +`getFoo(String, String)`, must execute in the context of a transaction with read-only +semantics, and that the other methods, `insertFoo(Foo)` and `updateFoo(Foo)`, must +execute in the context of a transaction with read-write semantics. The following +configuration is explained in detail in the next few paragraphs. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +---- + +Examine the preceding configuration. You want to make a service object, the `fooService` +bean, transactional. The transaction semantics to apply are encapsulated in the +`` definition. The `` definition reads as "__... all methods on +starting with `'get'` are to execute in the context of a read-only transaction, and all +other methods are to execute with the default transaction semantics__". The +`transaction-manager` attribute of the `` tag is set to the name of the +`PlatformTransactionManager` bean that is going to __drive__ the transactions, in this +case, the `txManager` bean. + +[TIP] +==== + +You can omit the `transaction-manager` attribute in the transactional advice ( +``) if the bean name of the `PlatformTransactionManager` that you want to +wire in has the name `transactionManager`. If the `PlatformTransactionManager` bean that +you want to wire in has any other name, then you must use the `transaction-manager` +attribute explicitly, as in the preceding example. +==== + +The `` definition ensures that the transactional advice defined by the +`txAdvice` bean executes at the appropriate points in the program. First you define a +pointcut that matches the execution of any operation defined in the `FooService` +interface ( `fooServiceOperation`). Then you associate the pointcut with the `txAdvice` +using an advisor. The result indicates that at the execution of a `fooServiceOperation`, +the advice defined by `txAdvice` will be run. + +The expression defined within the `` element is an AspectJ pointcut +expression; see <> for more details on pointcut expressions in Spring. + +A common requirement is to make an entire service layer transactional. The best way to +do this is simply to change the pointcut expression to match any operation in your +service layer. For example: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + +---- + +[NOTE] +==== +__In this example it is assumed that all your service interfaces are defined in the +`x.y.service` package; see <> for more details.__ +==== + +Now that we've analyzed the configuration, you may be asking yourself, "__Okay... but +what does all this configuration actually do?__". + +The above configuration will be used to create a transactional proxy around the object +that is created from the `fooService` bean definition. The proxy will be configured with +the transactional advice, so that when an appropriate method is invoked __on the +proxy__, a transaction is started, suspended, marked as read-only, and so on, depending +on the transaction configuration associated with that method. Consider the following +program that test drives the above configuration: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public final class Boot { + + public static void main(final String[] args) throws Exception { + ApplicationContext ctx = new ClassPathXmlApplicationContext("context.xml", Boot.class); + FooService fooService = (FooService) ctx.getBean("fooService"); + fooService.insertFoo (new Foo()); + } + } +---- + +The output from running the preceding program will resemble the following. (The Log4J +output and the stack trace from the UnsupportedOperationException thrown by the +insertFoo(..) method of the DefaultFooService class have been truncated for clarity.) + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + [AspectJInvocationContextExposingAdvisorAutoProxyCreator] - Creating implicit proxy for bean 'fooService' with 0 common interceptors and 1 specific interceptors + + + [JdkDynamicAopProxy] - Creating JDK dynamic proxy for [x.y.service.DefaultFooService] + + + [TransactionInterceptor] - Getting transaction for x.y.service.FooService.insertFoo + + + [DataSourceTransactionManager] - Creating new transaction with name [x.y.service.FooService.insertFoo] + [DataSourceTransactionManager] - Acquired Connection [org.apache.commons.dbcp.PoolableConnection@a53de4] for JDBC transaction + + + [RuleBasedTransactionAttribute] - Applying rules to determine whether transaction should rollback on java.lang.UnsupportedOperationException + [TransactionInterceptor] - Invoking rollback for transaction on x.y.service.FooService.insertFoo due to throwable [java.lang.UnsupportedOperationException] + + + [DataSourceTransactionManager] - Rolling back JDBC transaction on Connection [org.apache.commons.dbcp.PoolableConnection@a53de4] + [DataSourceTransactionManager] - Releasing JDBC Connection after transaction + [DataSourceUtils] - Returning JDBC Connection to DataSource + + Exception in thread "main" java.lang.UnsupportedOperationException at x.y.service.DefaultFooService.insertFoo(DefaultFooService.java:14) + + at $Proxy0.insertFoo(Unknown Source) + at Boot.main(Boot.java:11) +---- + + + +[[transaction-declarative-rolling-back]] +==== Rolling back a declarative transaction +The previous section outlined the basics of how to specify transactional settings for +classes, typically service layer classes, declaratively in your application. This +section describes how you can control the rollback of transactions in a simple +declarative fashion. + +The recommended way to indicate to the Spring Framework's transaction infrastructure +that a transaction's work is to be rolled back is to throw an `Exception` from code that +is currently executing in the context of a transaction. The Spring Framework's +transaction infrastructure code will catch any unhandled `Exception` as it bubbles up +the call stack, and make a determination whether to mark the transaction for rollback. + +In its default configuration, the Spring Framework's transaction infrastructure code +__only__ marks a transaction for rollback in the case of runtime, unchecked exceptions; +that is, when the thrown exception is an instance or subclass of `RuntimeException`. ( +++Error++s will also - by default - result in a rollback). Checked exceptions that are +thrown from a transactional method do __not__ result in rollback in the default +configuration. + +You can configure exactly which `Exception` types mark a transaction for rollback, +including checked exceptions. The following XML snippet demonstrates how you configure +rollback for a checked, application-specific `Exception` type. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + +---- + +You can also specify 'no rollback rules', if you do __not__ want a transaction rolled +back when an exception is thrown. The following example tells the Spring Framework's +transaction infrastructure to commit the attendant transaction even in the face of an +unhandled `InstrumentNotFoundException`. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + +---- + +When the Spring Framework's transaction infrastructure catches an exception and is +consults configured rollback rules to determine whether to mark the transaction for +rollback, the __strongest__ matching rule wins. So in the case of the following +configuration, any exception other than an `InstrumentNotFoundException` results in a +rollback of the attendant transaction. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + +---- + +You can also indicate a required rollback __programmatically__. Although very simple, +this process is quite invasive, and tightly couples your code to the Spring Framework's +transaction infrastructure: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public void resolvePosition() { + try { + // some business logic... + } catch (NoProductInStockException ex) { + // trigger rollback programmatically + TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); + } + } +---- + +You are strongly encouraged to use the declarative approach to rollback if at all +possible. Programmatic rollback is available should you absolutely need it, but its +usage flies in the face of achieving a clean POJO-based architecture. + + + +[[transaction-declarative-diff-tx]] +==== Configuring different transactional semantics for different beans +Consider the scenario where you have a number of service layer objects, and you want to +apply a __totally different__ transactional configuration to each of them. You do this +by defining distinct `` elements with differing `pointcut` and +`advice-ref` attribute values. + +As a point of comparison, first assume that all of your service layer classes are +defined in a root `x.y.service` package. To make all beans that are instances of classes +defined in that package (or in subpackages) and that have names ending in `Service` have +the default transactional configuration, you would write the following: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +---- + +The following example shows how to configure two distinct beans with totally different +transactional settings. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +---- + + + +[[transaction-declarative-txadvice-settings]] +==== settings + +This section summarizes the various transactional settings that can be specified using +the `` tag. The default `` settings are: + +* <> is `REQUIRED.` +* Isolation level is `DEFAULT.` +* Transaction is read/write. +* Transaction timeout defaults to the default timeout of the underlying transaction + system, or none if timeouts are not supported. +* Any `RuntimeException` triggers rollback, and any checked `Exception` does not. + +You can change these default settings; the various attributes of the `` tags +that are nested within `` and `` tags are summarized below: + +[[tx-method-settings]] +. settings +|=== +| Attribute| Required?| Default| Description + +| `name` +| Yes +| +| Method name(s) with which the transaction attributes are to be associated. The + wildcard (*) character can be used to associate the same transaction attribute + settings with a number of methods; for example, `get*`, `handle*`, `on*Event`, and so + forth. + +| `propagation` +| No +| REQUIRED +| Transaction propagation behavior. + +| `isolation` +| No +| DEFAULT +| Transaction isolation level. + +| `timeout` +| No +| -1 +| Transaction timeout value (in seconds). + +| `read-only` +| No +| false +| Is this transaction read-only? + +| `rollback-for` +| No +| +| `Exception(s)` that trigger rollback; comma-delimited. For example, + `com.foo.MyBusinessException,ServletException.` + +| `no-rollback-for` +| No +| +| `Exception(s)` that do __not__ trigger rollback; comma-delimited. For example, + `com.foo.MyBusinessException,ServletException.` +|=== + + + +[[transaction-declarative-annotations]] +==== Using @Transactional + +In addition to the XML-based declarative approach to transaction configuration, you can +use an annotation-based approach. Declaring transaction semantics directly in the Java +source code puts the declarations much closer to the affected code. There is not much +danger of undue coupling, because code that is meant to be used transactionally is +almost always deployed that way anyway. + +The ease-of-use afforded by the use of the `@Transactional` annotation is best +illustrated with an example, which is explained in the text that follows. Consider the +following class definition: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + // the service class that we want to make transactional + **@Transactional** + public class DefaultFooService implements FooService { + + Foo getFoo(String fooName); + + Foo getFoo(String fooName, String barName); + + void insertFoo(Foo foo); + + void updateFoo(Foo foo); + } +---- + +When the above POJO is defined as a bean in a Spring IoC container, the bean instance +can be made transactional by adding merely __one__ line of XML configuration: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + + ____ + + + + + + + + +---- + +[TIP] +==== +You can omit the `transaction-manager` attribute in the `` tag if +the bean name of the `PlatformTransactionManager` that you want to wire in has the name +`transactionManager`. If the `PlatformTransactionManager` bean that you want to +dependency-inject has any other name, then you have to use the `transaction-manager` +attribute explicitly, as in the preceding example. +==== + +[NOTE] +==== +The `@EnableTransactionManagement` annotation provides equivalent support if you are +using Java based configuration. Simply add the annotation to a `@Configuration` class. +See the javadocs for full details. +==== + +.Method visibility and @Transactional +**** +When using proxies, you should apply the `@Transactional` annotation only to methods +with __public__ visibility. If you do annotate protected, private or package-visible +methods with the `@Transactional` annotation, no error is raised, but the annotated +method does not exhibit the configured transactional settings. Consider the use of +AspectJ (see below) if you need to annotate non-public methods. +**** + +You can place the `@Transactional` annotation before an interface definition, a method +on an interface, a class definition, or a __public__ method on a class. However, the +mere presence of the `@Transactional` annotation is not enough to activate the +transactional behavior. The `@Transactional` annotation is simply metadata that can be +consumed by some runtime infrastructure that is `@Transactional`-aware and that can use +the metadata to configure the appropriate beans with transactional behavior. In the +preceding example, the `` element __switches on__ the +transactional behavior. + +[TIP] +==== + +Spring recommends that you only annotate concrete classes (and methods of concrete +classes) with the `@Transactional` annotation, as opposed to annotating interfaces. You +certainly can place the `@Transactional` annotation on an interface (or an interface +method), but this works only as you would expect it to if you are using interface-based +proxies. The fact that Java annotations are __not inherited from interfaces__ means that +if you are using class-based proxies ( `proxy-target-class="true"`) or the weaving-based +aspect ( `mode="aspectj"`), then the transaction settings are not recognized by the +proxying and weaving infrastructure, and the object will not be wrapped in a +transactional proxy, which would be decidedly __bad__. +==== + +[NOTE] +==== +In proxy mode (which is the default), only external method calls coming in through the +proxy are intercepted. This means that self-invocation, in effect, a method within the +target object calling another method of the target object, will not lead to an actual +transaction at runtime even if the invoked method is marked with `@Transactional`. +==== + +Consider the use of AspectJ mode (see mode attribute in table below) if you expect +self-invocations to be wrapped with transactions as well. In this case, there will not +be a proxy in the first place; instead, the target class will be weaved (that is, its +byte code will be modified) in order to turn `@Transactional` into runtime behavior on +any kind of method. + +[[tx-annotation-driven-settings]] +.Annotation driven transaction settings +|=== +| XML Attribute| Annotation Attribute| Default| Description + +| `transaction-manager` +| N/A (See `TransactionManagementConfigurer` javadocs) +| transactionManager +| Name of transaction manager to use. Only required if the name of the transaction + manager is not `transactionManager`, as in the example above. + +| `mode` +| `mode` +| proxy +| The default mode "proxy" processes annotated beans to be proxied using Spring's AOP + framework (following proxy semantics, as discussed above, applying to method calls + coming in through the proxy only). The alternative mode "aspectj" instead weaves the + affected classes with Spring's AspectJ transaction aspect, modifying the target class + byte code to apply to any kind of method call. AspectJ weaving requires + spring-aspects.jar in the classpath as well as load-time weaving (or compile-time + weaving) enabled. (See <> for details on how to set up load-time + weaving.) + +| `proxy-target-class` +| `proxyTargetClass` +| false +| Applies to proxy mode only. Controls what type of transactional proxies are created + for classes annotated with the `@Transactional` annotation. If the + `proxy-target-class` attribute is set to `true`, then class-based proxies are created. + If `proxy-target-class` is `false` or if the attribute is omitted, then standard JDK + interface-based proxies are created. (See <> for a detailed examination + of the different proxy types.) + +| `order` +| `order` +| Ordered.LOWEST_PRECEDENCE +| Defines the order of the transaction advice that is applied to beans annotated with + `@Transactional`. (For more information about the rules related to ordering of AOP + advice, see <>.) No specified ordering means that the + AOP subsystem determines the order of the advice. +|=== + +[NOTE] +==== +The `proxy-target-class` attribute controls what type of transactional proxies are +created for classes annotated with the `@Transactional` annotation. If +`proxy-target-class` is set to `true`, class-based proxies are created. If +`proxy-target-class` is `false` or if the attribute is omitted, standard JDK +interface-based proxies are created. (See <> for a discussion of the +different proxy types.) +==== + +[NOTE] +==== +`@EnableTransactionManagement` and `` only looks for +`@Transactional` on beans in the same application context they are defined in. This +means that, if you put annotation driven configuration in a `WebApplicationContext` for +a `DispatcherServlet`, it only checks for `@Transactional` beans in your controllers, +and not your services. See <> for more information. +==== + +The most derived location takes precedence when evaluating the transactional settings +for a method. In the case of the following example, the `DefaultFooService` class is +annotated at the class level with the settings for a read-only transaction, but the +`@Transactional` annotation on the `updateFoo(Foo)` method in the same class takes +precedence over the transactional settings defined at the class level. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Transactional(readOnly = true) + public class DefaultFooService implements FooService { + + public Foo getFoo(String fooName) { + // do something + } + + // these settings have precedence for this method + @Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW) + public void updateFoo(Foo foo) { + // do something + } + } +---- + + +[[transaction-declarative-attransactional-settings]] +===== @Transactional settings + +The `@Transactional` annotation is metadata that specifies that an interface, class, or +method must have transactional semantics; for example, "__start a brand new read-only +transaction when this method is invoked, suspending any existing transaction__". The +default `@Transactional` settings are as follows: + +* Propagation setting is `PROPAGATION_REQUIRED.` +* Isolation level is `ISOLATION_DEFAULT.` +* Transaction is read/write. +* Transaction timeout defaults to the default timeout of the underlying transaction + system, or to none if timeouts are not supported. +* Any `RuntimeException` triggers rollback, and any checked `Exception` does not. + +These default settings can be changed; the various properties of the `@Transactional` +annotation are summarized in the following table: + +[[tx-attransactional-properties]] +.@ +|=== +| Property| Type| Description + +| <> +| String +| Optional qualifier specifying the transaction manager to be used. + +| <> +| enum: `Propagation` +| Optional propagation setting. + +| `isolation` +| enum: `Isolation` +| Optional isolation level. + +| `readOnly` +| boolean +| Read/write vs. read-only transaction + +| `timeout` +| int (in seconds granularity) +| Transaction timeout. + +| `rollbackFor` +| Array of `Class` objects, which must be derived from `Throwable.` +| Optional array of exception classes that __must__ cause rollback. + +| `rollbackForClassName` +| Array of class names. Classes must be derived from `Throwable.` +| Optional array of names of exception classes that __must__ cause rollback. + +| `noRollbackFor` +| Array of `Class` objects, which must be derived from `Throwable.` +| Optional array of exception classes that __must not__ cause rollback. + +| `noRollbackForClassName` +| Array of `String` class names, which must be derived from `Throwable.` +| Optional array of names of exception classes that __must not__ cause rollback. +|=== + +Currently you cannot have explicit control over the name of a transaction, where 'name' +means the transaction name that will be shown in a transaction monitor, if applicable +(for example, WebLogic's transaction monitor), and in logging output. For declarative +transactions, the transaction name is always the fully-qualified class name + "." ++ method name of the transactionally-advised class. For example, if the +`handlePayment(..)` method of the `BusinessService` class started a transaction, the +name of the transaction would be: `com.foo.BusinessService.handlePayment`. + + +[[tx-multiple-tx-mgrs-with-attransactional]] +===== Multiple Transaction Managers with @Transactional +Most Spring applications only need a single transaction manager, but there may be +situations where you want multiple independent transaction managers in a single +application. The value attribute of the `@Transactional` annotation can be used to +optionally specify the identity of the `PlatformTransactionManager` to be used. This can +either be the bean name or the qualifier value of the transaction manager bean. For +example, using the qualifier notation, the following Java code + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class TransactionalService { + + @Transactional("order") + public void setSomething(String name) { ... } + + @Transactional("account") + public void doSomething() { ... } + } +---- + +could be combined with the following transaction manager bean declarations in the +application context. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + ... + + + + + ... + + +---- + +In this case, the two methods on `TransactionalService` will run under separate +transaction managers, differentiated by the "order" and "account" qualifiers. The +default `` target bean name `transactionManager` will still be +used if no specifically qualified PlatformTransactionManager bean is found. + + +[[tx-custom-attributes]] +===== Custom shortcut annotations +If you find you are repeatedly using the same attributes with `@Transactional` on many +different methods, then <> allows +you to define custom shortcut annotations for your specific use cases. For example, +defining the following annotations + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Target({ElementType.METHOD, ElementType.TYPE}) + @Retention(RetentionPolicy.RUNTIME) + @Transactional("order") + public @interface OrderTx { + } + + @Target({ElementType.METHOD, ElementType.TYPE}) + @Retention(RetentionPolicy.RUNTIME) + @Transactional("account") + public @interface AccountTx { + } +---- + +allows us to write the example from the previous section as + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class TransactionalService { + + @OrderTx + public void setSomething(String name) { ... } + + @AccountTx + public void doSomething() { ... } + } +---- + +Here we have used the syntax to define the transaction manager qualifier, but could also +have included propagation behavior, rollback rules, timeouts etc. + + + +[[tx-propagation]] +==== Transaction propagation +This section describes some semantics of transaction propagation in Spring. Please note +that this section is not an introduction to transaction propagation proper; rather it +details some of the semantics regarding transaction propagation in Spring. + +In Spring-managed transactions, be aware of the difference between __physical__ and +__logical__ transactions, and how the propagation setting applies to this difference. + + +[[tx-propagation-required]] +===== Required +image::images/tx_prop_required.png[width=400] + +PROPAGATION_REQUIRED + +When the propagation setting is `PROPAGATION_REQUIRED`, a __logical__ transaction scope +is created for each method upon which the setting is applied. Each such logical +transaction scope can determine rollback-only status individually, with an outer +transaction scope being logically independent from the inner transaction scope. Of +course, in case of standard `PROPAGATION_REQUIRED` behavior, all these scopes will be +mapped to the same physical transaction. So a rollback-only marker set in the inner +transaction scope does affect the outer transaction's chance to actually commit (as you +would expect it to). + +However, in the case where an inner transaction scope sets the rollback-only marker, the +outer transaction has not decided on the rollback itself, and so the rollback (silently +triggered by the inner transaction scope) is unexpected. A corresponding +`UnexpectedRollbackException` is thrown at that point. This is __expected behavior__ so +that the caller of a transaction can never be misled to assume that a commit was +performed when it really was not. So if an inner transaction (of which the outer caller +is not aware) silently marks a transaction as rollback-only, the outer caller still +calls commit. The outer caller needs to receive an `UnexpectedRollbackException` to +indicate clearly that a rollback was performed instead. + + +[[tx-propagation-requires_new]] +===== RequiresNew +image::images/tx_prop_requires_new.png[width=400] + +PROPAGATION_REQUIRES_NEW + +`PROPAGATION_REQUIRES_NEW`, in contrast to `PROPAGATION_REQUIRED`, uses a __completely__ +independent transaction for each affected transaction scope. In that case, the +underlying physical transactions are different and hence can commit or roll back +independently, with an outer transaction not affected by an inner transaction's rollback +status. + + +[[tx-propagation-nested]] +===== Nested +`PROPAGATION_NESTED` uses a __single__ physical transaction with multiple savepoints +that it can roll back to. Such partial rollbacks allow an inner transaction scope to +trigger a rollback __for its scope__, with the outer transaction being able to continue +the physical transaction despite some operations having been rolled back. This setting +is typically mapped onto JDBC savepoints, so will only work with JDBC resource +transactions. See Spring's `DataSourceTransactionManager`. + + + +[[transaction-declarative-applying-more-than-just-tx-advice]] +==== Advising transactional operations +Suppose you want to execute __both__ transactional __and__ some basic profiling advice. +How do you effect this in the context of ``? + +When you invoke the `updateFoo(Foo)` method, you want to see the following actions: + +* Configured profiling aspect starts up. +* Transactional advice executes. +* Method on the advised object executes. +* Transaction commits. +* Profiling aspect reports exact duration of the whole transactional method invocation. + +[NOTE] +==== +This chapter is not concerned with explaining AOP in any great detail (except as it +applies to transactions). See <> for detailed coverage of the following AOP +configuration and AOP in general. +==== + +Here is the code for a simple profiling aspect discussed above. The ordering of advice +is controlled through the `Ordered` interface. For full details on advice ordering, see +<>. +. +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + package x.y; + + import org.aspectj.lang.ProceedingJoinPoint; + import org.springframework.util.StopWatch; + import org.springframework.core.Ordered; + + public class SimpleProfiler implements Ordered { + + private int order; + + // allows us to control the ordering of advice + public int getOrder() { + return this.order; + } + + public void setOrder(int order) { + this.order = order; + } + + // this method *is* the around advice + public Object profile(ProceedingJoinPoint call) throws Throwable { + Object returnValue; + StopWatch clock = new StopWatch(getClass().getName()); + try { + clock.start(call.toShortString()); + returnValue = call.proceed(); + } finally { + clock.stop(); + System.out.println(clock.prettyPrint()); + } + return returnValue; + } + } +---- + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +---- + +The result of the above configuration is a `fooService` bean that has profiling and +transactional aspects applied to it __in the desired order__. You configure any number +of additional aspects in similar fashion. + +The following example effects the same setup as above, but uses the purely XML +declarative approach. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + + __ + + + + + + + + + + + + + + + + + + + + + + + + + + +---- + +The result of the above configuration will be a `fooService` bean that has profiling and +transactional aspects applied to it __in that order__. If you want the profiling advice +to execute __after__ the transactional advice on the way in, and __before__ the +transactional advice on the way out, then you simply swap the value of the profiling +aspect bean's `order` property so that it is higher than the transactional advice's +order value. + +You configure additional aspects in similar fashion. + + + +[[transaction-declarative-aspectj]] +==== Using @Transactional with AspectJ + +It is also possible to use the Spring Framework's `@Transactional` support outside of a +Spring container by means of an AspectJ aspect. To do so, you first annotate your +classes (and optionally your classes' methods) with the `@Transactional` annotation, and +then you link (weave) your application with the +`org.springframework.transaction.aspectj.AnnotationTransactionAspect` defined in the +`spring-aspects.jar` file. The aspect must also be configured with a transaction +manager. You can of course use the Spring Framework's IoC container to take care of +dependency-injecting the aspect. The simplest way to configure the transaction +management aspect is to use the `` element and specify the `mode` +attribute to `aspectj` as described in <>. Because +we're focusing here on applications running outside of a Spring container, we'll show +you how to do it programmatically. + +[NOTE] +==== +Prior to continuing, you may want to read <> and +<> respectively. +==== + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + // construct an appropriate transaction manager + DataSourceTransactionManager txManager = new DataSourceTransactionManager(getDataSource()); + + // configure the AnnotationTransactionAspect to use it; this must be done before executing any transactional methods + AnnotationTransactionAspect.aspectOf().setTransactionManager(txManager); +---- + +[NOTE] +==== +When using this aspect, you must annotate the __implementation__ class (and/or methods +within that class), __not__ the interface (if any) that the class implements. AspectJ +follows Java's rule that annotations on interfaces are __not inherited__. +==== + +The `@Transactional` annotation on a class specifies the default transaction semantics +for the execution of any method in the class. + +The `@Transactional` annotation on a method within the class overrides the default +transaction semantics given by the class annotation (if present). Any method may be +annotated, regardless of visibility. + +To weave your applications with the `AnnotationTransactionAspect` you must either build +your application with AspectJ (see the +http://www.eclipse.org/aspectj/doc/released/devguide/index.html[AspectJ Development +Guide]) or use load-time weaving. See <> for a discussion of load-time +weaving with AspectJ. + + + + +[[transaction-programmatic]] +=== Programmatic transaction management +The Spring Framework provides two means of programmatic transaction management: + +* Using the `TransactionTemplate`. +* Using a `PlatformTransactionManager` implementation directly. + +The Spring team generally recommends the `TransactionTemplate` for programmatic +transaction management. The second approach is similar to using the JTA +`UserTransaction` API, although exception handling is less cumbersome. + + + +[[tx-prog-template]] +==== Using the TransactionTemplate + +The `TransactionTemplate` adopts the same approach as other Spring __templates__ such as +the `JdbcTemplate`. It uses a callback approach, to free application code from having to +do the boilerplate acquisition and release of transactional resources, and results in +code that is intention driven, in that the code that is written focuses solely on what +the developer wants to do. + +[NOTE] +==== +As you will see in the examples that follow, using the `TransactionTemplate` absolutely +couples you to Spring's transaction infrastructure and APIs. Whether or not programmatic +transaction management is suitable for your development needs is a decision that you +will have to make yourself. +==== + +Application code that must execute in a transactional context, and that will use the +`TransactionTemplate` explicitly, looks like the following. You, as an application +developer, write a `TransactionCallback` implementation (typically expressed as an +anonymous inner class) that contains the code that you need to execute in the context of +a transaction. You then pass an instance of your custom `TransactionCallback` to the +`execute(..)` method exposed on the `TransactionTemplate`. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class SimpleService implements Service { + + // single TransactionTemplate shared amongst all methods in this instance + private final TransactionTemplate transactionTemplate; + + // use constructor-injection to supply the PlatformTransactionManager + public SimpleService(PlatformTransactionManager transactionManager) { + Assert.notNull(transactionManager, "The 'transactionManager' argument must not be null."); + this.transactionTemplate = new TransactionTemplate(transactionManager); + } + + public Object someServiceMethod() { + return transactionTemplate.execute(new TransactionCallback() { + // the code in this method executes in a transactional context + public Object doInTransaction(TransactionStatus status) { + updateOperation1(); + return resultOfUpdateOperation2(); + } + }); + } + } +---- + +If there is no return value, use the convenient `TransactionCallbackWithoutResult` class +with an anonymous class as follows: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + transactionTemplate.execute(new **TransactionCallbackWithoutResult**() { + protected void doInTransactionWithoutResult(TransactionStatus status) { + updateOperation1(); + updateOperation2(); + } + }); +---- + +Code within the callback can roll the transaction back by calling the +`setRollbackOnly()` method on the supplied `TransactionStatus` object: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + transactionTemplate.execute(new TransactionCallbackWithoutResult() { + + protected void doInTransactionWithoutResult(TransactionStatus status) { + try { + updateOperation1(); + updateOperation2(); + } catch (SomeBusinessExeption ex) { + **status.setRollbackOnly();** + } + } + }); +---- + + +[[tx-prog-template-settings]] +===== Specifying transaction settings +You can specify transaction settings such as the propagation mode, the isolation level, +the timeout, and so forth on the `TransactionTemplate` either programmatically or in +configuration. `TransactionTemplate` instances by default have the +<>. The +following example shows the programmatic customization of the transactional settings for +a specific `TransactionTemplate:` + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class SimpleService implements Service { + + private final TransactionTemplate transactionTemplate; + + public SimpleService(PlatformTransactionManager transactionManager) { + Assert.notNull(transactionManager, "The 'transactionManager' argument must not be null."); + this.transactionTemplate = new TransactionTemplate(transactionManager); + + // the transaction settings can be set here explicitly if so desired + this.transactionTemplate.setIsolationLevel(TransactionDefinition.ISOLATION_READ_UNCOMMITTED); + this.transactionTemplate.setTimeout(30); // 30 seconds + // and so forth... + } + } +---- + +The following example defines a `TransactionTemplate` with some custom transactional +settings, using Spring XML configuration. The `sharedTransactionTemplate` can then be +injected into as many services as are required. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + " +---- + +Finally, instances of the `TransactionTemplate` class are threadsafe, in that instances +do not maintain any conversational state. `TransactionTemplate` instances __do__ however +maintain configuration state, so while a number of classes may share a single instance +of a `TransactionTemplate`, if a class needs to use a `TransactionTemplate` with +different settings (for example, a different isolation level), then you need to create +two distinct `TransactionTemplate` instances. + + + +[[transaction-programmatic-ptm]] +==== Using the PlatformTransactionManager + +You can also use the `org.springframework.transaction.PlatformTransactionManager` +directly to manage your transaction. Simply pass the implementation of the +`PlatformTransactionManager` you are using to your bean through a bean reference. Then, +using the `TransactionDefinition` and `TransactionStatus` objects you can initiate +transactions, roll back, and commit. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + DefaultTransactionDefinition def = new DefaultTransactionDefinition(); + // explicitly setting the transaction name is something that can only be done programmatically + def.setName("SomeTxName"); + def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED); + + TransactionStatus status = txManager.getTransaction(def); + try { + // execute your business logic here + } + catch (MyException ex) { + txManager.rollback(status); + throw ex; + } + txManager.commit(status); +---- + + + + +[[tx-decl-vs-prog]] +=== Choosing between programmatic and declarative transaction management +Programmatic transaction management is usually a good idea only if you have a small +number of transactional operations. For example, if you have a web application that +require transactions only for certain update operations, you may not want to set up +transactional proxies using Spring or any other technology. In this case, using the +`TransactionTemplate` __may__ be a good approach. Being able to set the transaction name +explicitly is also something that can only be done using the programmatic approach to +transaction management. + +On the other hand, if your application has numerous transactional operations, +declarative transaction management is usually worthwhile. It keeps transaction +management out of business logic, and is not difficult to configure. When using the +Spring Framework, rather than EJB CMT, the configuration cost of declarative transaction +management is greatly reduced. + + + + +[[transaction-application-server-integration]] +=== Application server-specific integration +Spring's transaction abstraction generally is application server agnostic. Additionally, +Spring's `JtaTransactionManager` class, which can optionally perform a JNDI lookup for +the JTA `UserTransaction` and `TransactionManager` objects, autodetects the location for +the latter object, which varies by application server. Having access to the JTA +`TransactionManager` allows for enhanced transaction semantics, in particular supporting +transaction suspension. See the `JtaTransactionManager` javadocs for details. + +Spring's `JtaTransactionManager` is the standard choice to run on Java EE application +servers, and is known to work on all common servers. Advanced functionality such as +transaction suspension works on many servers as well -- including GlassFish, JBoss and +Geronimo -- without any special configuration required. However, for fully supported +transaction suspension and further advanced integration, Spring ships special adapters +for WebLogic Server and WebSphere. These adapters are discussed in the following +sections. + +__For standard scenarios, including WebLogic Server and WebSphere, consider using the +convenient `` configuration element.__ When configured, +this element automatically detects the underlying server and chooses the best +transaction manager available for the platform. This means that you won't have to +configure server-specific adapter classes (as discussed in the following sections) +explicitly; rather, they are chosen automatically, with the standard +`JtaTransactionManager` as default fallback. + + + +[[transaction-application-server-integration-websphere]] +==== IBM WebSphere +On WebSphere 6.1.0.9 and above, the recommended Spring JTA transaction manager to use is +`WebSphereUowTransactionManager`. This special adapter leverages IBM's `UOWManager` API, +which is available in WebSphere Application Server 6.0.2.19 and later and 6.1.0.9 and +later. With this adapter, Spring-driven transaction suspension (suspend/resume as +initiated by `PROPAGATION_REQUIRES_NEW`) is officially supported by IBM! + + + +[[transaction-application-server-integration-weblogic]] +==== Oracle WebLogic Server +On WebLogic Server 9.0 or above, you typically would use the +`WebLogicJtaTransactionManager` instead of the stock `JtaTransactionManager` class. This +special WebLogic-specific subclass of the normal `JtaTransactionManager` supports the +full power of Spring's transaction definitions in a WebLogic-managed transaction +environment, beyond standard JTA semantics: Features include transaction names, +per-transaction isolation levels, and proper resuming of transactions in all cases. + + + + +[[transaction-solutions-to-common-problems]] +=== Solutions to common problems + + + +[[transaction-solutions-to-common-problems-wrong-ptm]] +==== Use of the wrong transaction manager for a specific DataSource + +Use the __correct__ `PlatformTransactionManager` implementation based on your choice of +transactional technologies and requirements. Used properly, the Spring Framework merely +provides a straightforward and portable abstraction. If you are using global +transactions, you __must__ use the +`org.springframework.transaction.jta.JtaTransactionManager` class (or an +<> of +it) for all your transactional operations. Otherwise the transaction infrastructure +attempts to perform local transactions on resources such as container `DataSource` +instances. Such local transactions do not make sense, and a good application server +treats them as errors. + + + + +[[transaction-resources]] +=== Further Resources +For more information about the Spring Framework's transaction support: + +* http://www.javaworld.com/javaworld/jw-01-2009/jw-01-spring-transactions.html[Distributed + transactions in Spring, with and without XA] is a JavaWorld presentation in which + Spring's David Syer guides you through seven patterns for distributed + transactions in Spring applications, three of them with XA and four without. +* http://www.infoq.com/minibooks/JTDS[Java Transaction Design Strategies] is a book + available from http://www.infoq.com/[InfoQ] that provides a well-paced introduction + to transactions in Java. It also includes side-by-side examples of how to configure + and use transactions with both the Spring Framework and EJB3. diff --git a/src/asciidoc/validation.adoc b/src/asciidoc/validation.adoc new file mode 100644 index 000000000000..1299b1ac970a --- /dev/null +++ b/src/asciidoc/validation.adoc @@ -0,0 +1,1839 @@ +[[validation]] +== Validation, Data Binding, and Type Conversion + + + + +[[validation-introduction]] +=== Introduction + +.JSR-303/JSR-349 Bean Validation +**** +Spring Framework 4.0 supports Bean Validation 1.0 (JSR-303) and Bean Validation 1.1 +(JSR-349) in terms of setup support, also adapting it to Spring's `Validator` interface. + +An application can choose to enable Bean Validation once globally, as described in +<>, and use it exclusively for all validation needs. + +An application can also register additional Spring `Validator` instances per +`DataBinder` instance, as described in <>. This may be useful for +plugging in validation logic without the use of annotations. +**** + +There are pros and cons for considering validation as business logic, and Spring offers +a design for validation (and data binding) that does not exclude either one of them. +Specifically validation should not be tied to the web tier, should be easy to localize +and it should be possible to plug in any validator available. Considering the above, +Spring has come up with a `Validator` interface that is both basic ands eminently usable +in every layer of an application. + +Data binding is useful for allowing user input to be dynamically bound to the domain +model of an application (or whatever objects you use to process user input). Spring +provides the so-called `DataBinder` to do exactly that. The `Validator` and the +`DataBinder` make up the `validation` package, which is primarily used in but not +limited to the MVC framework. + +The `BeanWrapper` is a fundamental concept in the Spring Framework and is used in a lot +of places. However, you probably will not have the need to use the `BeanWrapper` +directly. Because this is reference documentation however, we felt that some explanation +might be in order. We will explain the `BeanWrapper` in this chapter since, if you were +going to use it at all, you would most likely do so when trying to bind data to objects. + +Spring's DataBinder and the lower-level BeanWrapper both use PropertyEditors to parse +and format property values. The `PropertyEditor` concept is part of the JavaBeans +specification, and is also explained in this chapter. Spring 3 introduces a +"core.convert" package that provides a general type conversion facility, as well as a +higher-level "format" package for formatting UI field values. These new packages may be +used as simpler alternatives to PropertyEditors, and will also be discussed in this +chapter. + + + + +[[validator]] +=== Validation using Spring's Validator interface + +Spring features a `Validator` interface that you can use to validate objects. The +`Validator` interface works using an `Errors` object so that while validating, +validators can report validation failures to the `Errors` object. + +Let's consider a small data object: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class Person { + + private String name; + private int age; + + // the usual getters and setters... + } +---- + +We're going to provide validation behavior for the `Person` class by implementing the +following two methods of the `org.springframework.validation.Validator` interface: + +* `supports(Class)` - Can this `Validator` validate instances of the supplied `Class`? +* `validate(Object, org.springframework.validation.Errors)` - validates the given object + and in case of validation errors, registers those with the given `Errors` object + +Implementing a `Validator` is fairly straightforward, especially when you know of the +`ValidationUtils` helper class that the Spring Framework also provides. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class PersonValidator implements Validator { + + /** + * This Validator validates *just* Person instances + */ + public boolean supports(Class clazz) { + return Person.class.equals(clazz); + } + + public void validate(Object obj, Errors e) { + ValidationUtils.rejectIfEmpty(e, "name", "name.empty"); + Person p = (Person) obj; + if (p.getAge() < 0) { + e.rejectValue("age", "negativevalue"); + } else if (p.getAge() > 110) { + e.rejectValue("age", "too.darn.old"); + } + } + } +---- + +As you can see, the `static` `rejectIfEmpty(..)` method on the `ValidationUtils` class +is used to reject the `'name'` property if it is `null` or the empty string. Have a look +at the `ValidationUtils` javadocs to see what functionality it provides besides the +example shown previously. + +While it is certainly possible to implement a single `Validator` class to validate each +of the nested objects in a rich object, it may be better to encapsulate the validation +logic for each nested class of object in its own `Validator` implementation. A simple +example of a __'rich'__ object would be a `Customer` that is composed of two `String` +properties (a first and second name) and a complex `Address` object. `Address` objects +may be used independently of `Customer` objects, and so a distinct `AddressValidator` +has been implemented. If you want your `CustomerValidator` to reuse the logic contained +within the `AddressValidator` class without resorting to copy-and-paste, you can +dependency-inject or instantiate an `AddressValidator` within your `CustomerValidator`, +and use it like so: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class CustomerValidator implements Validator { + + private final Validator addressValidator; + + public CustomerValidator(Validator addressValidator) { + if (addressValidator == null) { + throw new IllegalArgumentException("The supplied [Validator] is " + + "required and must not be null."); + } + if (!addressValidator.supports(Address.class)) { + throw new IllegalArgumentException("The supplied [Validator] must " + + support the validation of [Address] instances."); + } + this.addressValidator = addressValidator; + } + + /** + * This Validator validates Customer instances, and any subclasses of Customer too + */ + public boolean supports(Class clazz) { + return Customer.class.isAssignableFrom(clazz); + } + + public void validate(Object target, Errors errors) { + ValidationUtils.rejectIfEmptyOrWhitespace(errors, "firstName", "field.required"); + ValidationUtils.rejectIfEmptyOrWhitespace(errors, "surname", "field.required"); + Customer customer = (Customer) target; + try { + errors.pushNestedPath("address"); + ValidationUtils.invokeValidator(this.addressValidator, customer.getAddress(), errors); + } finally { + errors.popNestedPath(); + } + } + } +---- + +Validation errors are reported to the `Errors` object passed to the validator. In case +of Spring Web MVC you can use `` tag to inspect the error messages, but of +course you can also inspect the errors object yourself. More information about the +methods it offers can be found in the javadocs. + + + + +[[validation-conversion]] +=== Resolving codes to error messages +We've talked about databinding and validation. Outputting messages corresponding to +validation errors is the last thing we need to discuss. In the example we've shown +above, we rejected the `name` and the `age` field. If we're going to output the error +messages by using a `MessageSource`, we will do so using the error code we've given when +rejecting the field ('name' and 'age' in this case). When you call (either directly, or +indirectly, using for example the `ValidationUtils` class) `rejectValue` or one of the +other `reject` methods from the `Errors` interface, the underlying implementation will +not only register the code you've passed in, but also a number of additional error +codes. What error codes it registers is determined by the `MessageCodesResolver` that is +used. By default, the `DefaultMessageCodesResolver` is used, which for example not only +registers a message with the code you gave, but also messages that include the field +name you passed to the reject method. So in case you reject a field using +`rejectValue("age", "too.darn.old")`, apart from the `too.darn.old` code, Spring will +also register `too.darn.old.age` and `too.darn.old.age.int` (so the first will include +the field name and the second will include the type of the field); this is done as a +convenience to aid developers in targeting error messages and suchlike. + +More information on the `MessageCodesResolver` and the default strategy can be found +online in the javadocs of +{javadoc-baseurl}/org/springframework/validation/MessageCodesResolver.html[`MessageCodesResolver`] +and +{javadoc-baseurl}/org/springframework/validation/DefaultMessageCodesResolver.html[`DefaultMessageCodesResolver`], +respectively. + + + + +[[beans-beans]] +=== Bean manipulation and the BeanWrapper + +The `org.springframework.beans` package adheres to the JavaBeans standard provided by +Oracle. A JavaBean is simply a class with a default no-argument constructor, which follows +a naming convention where (by way of an example) a property named `bingoMadness` would +have a setter method `setBingoMadness(..)` and a getter method `getBingoMadness()`. For +more information about JavaBeans and the specification, please refer to Oracle's website ( +http://docs.oracle.com/javase/6/docs/api/java/beans/package-summary.html[javabeans]). + +One quite important class in the beans package is the `BeanWrapper` interface and its +corresponding implementation ( `BeanWrapperImpl`). As quoted from the javadocs, the +`BeanWrapper` offers functionality to set and get property values (individually or in +bulk), get property descriptors, and to query properties to determine if they are +readable or writable. Also, the `BeanWrapper` offers support for nested properties, +enabling the setting of properties on sub-properties to an unlimited depth. Then, the +`BeanWrapper` supports the ability to add standard JavaBeans `PropertyChangeListeners` +and `VetoableChangeListeners`, without the need for supporting code in the target class. +Last but not least, the `BeanWrapper` provides support for the setting of indexed +properties. The `BeanWrapper` usually isn't used by application code directly, but by +the `DataBinder` and the `BeanFactory`. + +The way the `BeanWrapper` works is partly indicated by its name: __it wraps a bean__ to +perform actions on that bean, like setting and retrieving properties. + + + +[[beans-beans-conventions]] +==== Setting and getting basic and nested properties +Setting and getting properties is done using the `setPropertyValue(s)` and +`getPropertyValue(s)` methods that both come with a couple of overloaded variants. +They're all described in more detail in the javadocs Spring comes with. What's important +to know is that there are a couple of conventions for indicating properties of an +object. A couple of examples: + +[[beans-beans-conventions-properties-tbl]] +.Examples of properties +|=== +| Expression| Explanation + +| `name` +| Indicates the property `name` corresponding to the methods `getName()` or `isName()` + and `setName(..)` + +| `account.name` +| Indicates the nested property `name` of the property `account` corresponding e.g. to + the methods `getAccount().setName()` or `getAccount().getName()` + +| `account[2]` +| Indicates the __third__ element of the indexed property `account`. Indexed properties + can be of type `array`, `list` or other __naturally ordered__ collection + +| `account[COMPANYNAME]` +| Indicates the value of the map entry indexed by the key __COMPANYNAME__ of the Map + property `account` +|=== + +Below you'll find some examples of working with the `BeanWrapper` to get and set +properties. + +__(This next section is not vitally important to you if you're not planning to work with +the `BeanWrapper` directly. If you're just using the `DataBinder` and the `BeanFactory` +and their out-of-the-box implementation, you should skip ahead to the section about +`PropertyEditors`.)__ + +Consider the following two classes: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class Company { + + private String name; + private Employee managingDirector; + + public String getName() { + return this.name; + } + + public void setName(String name) { + this.name = name; + } + + public Employee getManagingDirector() { + return this.managingDirector; + } + + public void setManagingDirector(Employee managingDirector) { + this.managingDirector = managingDirector; + } + } +---- + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class Employee { + + private String name; + + private float salary; + + public String getName() { + return this.name; + } + + public void setName(String name) { + this.name = name; + } + + public float getSalary() { + return salary; + } + + public void setSalary(float salary) { + this.salary = salary; + } + } +---- + +The following code snippets show some examples of how to retrieve and manipulate some of +the properties of instantiated `Companies` and `Employees`: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + BeanWrapper company = BeanWrapperImpl(new Company()); + // setting the company name.. + company.setPropertyValue("name", "Some Company Inc."); + // ... can also be done like this: + PropertyValue value = new PropertyValue("name", "Some Company Inc."); + company.setPropertyValue(value); + + // ok, let's create the director and tie it to the company: + BeanWrapper jim = BeanWrapperImpl(new Employee()); + jim.setPropertyValue("name", "Jim Stravinsky"); + company.setPropertyValue("managingDirector", jim.getWrappedInstance()); + + // retrieving the salary of the managingDirector through the company + Float salary = (Float) company.getPropertyValue("managingDirector.salary"); +---- + + + +[[beans-beans-conversion]] +==== Built-in PropertyEditor implementations + +Spring uses the concept of `PropertyEditors` to effect the conversion between an +`Object` and a `String`. If you think about it, it sometimes might be handy to be able +to represent properties in a different way than the object itself. For example, a `Date` +can be represented in a human readable way (as the `String` ' `2007-14-09`'), while +we're still able to convert the human readable form back to the original date (or even +better: convert any date entered in a human readable form, back to `Date` objects). This +behavior can be achieved by __registering custom editors__, of type +`java.beans.PropertyEditor`. Registering custom editors on a `BeanWrapper` or +alternately in a specific IoC container as mentioned in the previous chapter, gives it +the knowledge of how to convert properties to the desired type. Read more about +`PropertyEditors` in the javadocs of the `java.beans` package provided by Oracle. + +A couple of examples where property editing is used in Spring: + +* __setting properties on beans__ is done using `PropertyEditors`. When mentioning + `java.lang.String` as the value of a property of some bean you're declaring in XML + file, Spring will (if the setter of the corresponding property has a + `Class`-parameter) use the `ClassEditor` to try to resolve the parameter to a `Class` + object. +* __parsing HTTP request parameters__ in Spring's MVC framework is done using all kinds + of `PropertyEditors` that you can manually bind in all subclasses of the + `CommandController`. + +Spring has a number of built-in `PropertyEditors` to make life easy. Each of those is +listed below and they are all located in the `org.springframework.beans.propertyeditors` +package. Most, but not all (as indicated below), are registered by default by +`BeanWrapperImpl`. Where the property editor is configurable in some fashion, you can of +course still register your own variant to override the default one: + +[[beans-beans-property-editors-tbl]] +.Built-in PropertyEditors +|=== +| Class| Explanation + +| `ByteArrayPropertyEditor` +| Editor for byte arrays. Strings will simply be converted to their corresponding byte + representations. Registered by default by `BeanWrapperImpl`. + +| `ClassEditor` +| Parses Strings representing classes to actual classes and the other way around. When a + class is not found, an `IllegalArgumentException` is thrown. Registered by default by + `BeanWrapperImpl`. + +| `CustomBooleanEditor` +| Customizable property editor for `Boolean` properties. Registered by default by + `BeanWrapperImpl`, but, can be overridden by registering custom instance of it as + custom editor. + +| `CustomCollectionEditor` +| Property editor for Collections, converting any source `Collection` to a given target + `Collection` type. + +| `CustomDateEditor` +| Customizable property editor for java.util.Date, supporting a custom DateFormat. NOT + registered by default. Must be user registered as needed with appropriate format. + +| `CustomNumberEditor` +| Customizable property editor for any Number subclass like `Integer`, `Long`, `Float`, + `Double`. Registered by default by `BeanWrapperImpl`, but can be overridden by + registering custom instance of it as a custom editor. + +| `FileEditor` +| Capable of resolving Strings to `java.io.File` objects. Registered by default by + `BeanWrapperImpl`. + +| `InputStreamEditor` +| One-way property editor, capable of taking a text string and producing (via an + intermediate `ResourceEditor` and `Resource`) an `InputStream`, so `InputStream` + properties may be directly set as Strings. Note that the default usage will not close + the `InputStream` for you! Registered by default by `BeanWrapperImpl`. + +| `LocaleEditor` +| Capable of resolving Strings to `Locale` objects and vice versa (the String format is + [language]_[country]_[variant], which is the same thing the toString() method of + Locale provides). Registered by default by `BeanWrapperImpl`. + +| `PatternEditor` +| Capable of resolving Strings to `java.util.regex.Pattern` objects and vice versa. + +| `PropertiesEditor` +| Capable of converting Strings (formatted using the format as defined in the javadocs + of the `java.util.Properties` class) to `Properties` objects. Registered by default + by `BeanWrapperImpl`. + +| `StringTrimmerEditor` +| Property editor that trims Strings. Optionally allows transforming an empty string + into a `null` value. NOT registered by default; must be user registered as needed. + +| `URLEditor` +| Capable of resolving a String representation of a URL to an actual `URL` object. + Registered by default by `BeanWrapperImpl`. +|=== + +Spring uses the `java.beans.PropertyEditorManager` to set the search path for property +editors that might be needed. The search path also includes `sun.bean.editors`, which +includes `PropertyEditor` implementations for types such as `Font`, `Color`, and most of +the primitive types. Note also that the standard JavaBeans infrastructure will +automatically discover `PropertyEditor` classes (without you having to register them +explicitly) if they are in the same package as the class they handle, and have the same +name as that class, with `'Editor'` appended; for example, one could have the following +class and package structure, which would be sufficient for the `FooEditor` class to be +recognized and used as the `PropertyEditor` for `Foo`-typed properties. + +[literal] +[subs="verbatim,quotes"] +---- +com + chank + pop + Foo + FooEditor // the PropertyEditor for the Foo class +---- + +Note that you can also use the standard `BeanInfo` JavaBeans mechanism here as well +(described +http://docs.oracle.com/javase/tutorial/javabeans/advanced/customization.html[in +not-amazing-detail here]). Find below an example of using the `BeanInfo` mechanism for +explicitly registering one or more `PropertyEditor` instances with the properties of an +associated class. + +[literal] +[subs="verbatim,quotes"] +---- +com + chank + pop + Foo + FooBeanInfo // the BeanInfo for the Foo class +---- + +Here is the Java source code for the referenced `FooBeanInfo` class. This would +associate a `CustomNumberEditor` with the `age` property of the `Foo` class. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class FooBeanInfo extends SimpleBeanInfo { + + public PropertyDescriptor[] getPropertyDescriptors() { + try { + final PropertyEditor numberPE = new CustomNumberEditor(Integer.class, true); + PropertyDescriptor ageDescriptor = new PropertyDescriptor("age", Foo.class) { + public PropertyEditor createPropertyEditor(Object bean) { + return numberPE; + }; + }; + return new PropertyDescriptor[] { ageDescriptor }; + } + catch (IntrospectionException ex) { + throw new Error(ex.toString()); + } + } + } +---- + + +[[beans-beans-conversion-customeditor-registration]] +===== Registering additional custom PropertyEditors + +When setting bean properties as a string value, a Spring IoC container ultimately uses +standard JavaBeans `PropertyEditors` to convert these Strings to the complex type of the +property. Spring pre-registers a number of custom `PropertyEditors` (for example, to +convert a classname expressed as a string into a real `Class` object). Additionally, +Java's standard JavaBeans `PropertyEditor` lookup mechanism allows a `PropertyEditor` +for a class simply to be named appropriately and placed in the same package as the class +it provides support for, to be found automatically. + +If there is a need to register other custom `PropertyEditors`, there are several +mechanisms available. The most manual approach, which is not normally convenient or +recommended, is to simply use the `registerCustomEditor()` method of the +`ConfigurableBeanFactory` interface, assuming you have a `BeanFactory` reference. +Another, slightly more convenient, mechanism is to use a special bean factory +post-processor called `CustomEditorConfigurer`. Although bean factory post-processors +can be used with `BeanFactory` implementations, the `CustomEditorConfigurer` has a +nested property setup, so it is strongly recommended that it is used with the +`ApplicationContext`, where it may be deployed in similar fashion to any other bean, and +automatically detected and applied. + +Note that all bean factories and application contexts automatically use a number of +built-in property editors, through their use of something called a `BeanWrapper` to +handle property conversions. The standard property editors that the `BeanWrapper` +registers are listed in <>. Additionally, +`ApplicationContexts` also override or add an additional number of editors to handle +resource lookups in a manner appropriate to the specific application context type. + +Standard JavaBeans `PropertyEditor` instances are used to convert property values +expressed as strings to the actual complex type of the property. +`CustomEditorConfigurer`, a bean factory post-processor, may be used to conveniently add +support for additional `PropertyEditor` instances to an `ApplicationContext`. + +Consider a user class `ExoticType`, and another class `DependsOnExoticType` which needs +`ExoticType` set as a property: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + package example; + + public class ExoticType { + + private String name; + + public ExoticType(String name) { + this.name = name; + } + } + + public class DependsOnExoticType { + + private ExoticType type; + + public void setType(ExoticType type) { + this.type = type; + } + } +---- + +When things are properly set up, we want to be able to assign the type property as a +string, which a `PropertyEditor` will behind the scenes convert into an actual +`ExoticType` instance: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + +---- + +The `PropertyEditor` implementation could look similar to this: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + // converts string representation to ExoticType object + package example; + + public class ExoticTypeEditor extends PropertyEditorSupport { + + public void setAsText(String text) { + setValue(new ExoticType(text.toUpperCase())); + } + } +---- + +Finally, we use `CustomEditorConfigurer` to register the new `PropertyEditor` with the +`ApplicationContext`, which will then be able to use it as needed: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + +---- + +[[beans-beans-conversion-customeditor-registration-per]] +====== Using PropertyEditorRegistrars + +Another mechanism for registering property editors with the Spring container is to +create and use a `PropertyEditorRegistrar`. This interface is particularly useful when +you need to use the same set of property editors in several different situations: write +a corresponding registrar and reuse that in each case. `PropertyEditorRegistrars` work +in conjunction with an interface called `PropertyEditorRegistry`, an interface that is +implemented by the Spring `BeanWrapper` (and `DataBinder`). `PropertyEditorRegistrars` +are particularly convenient when used in conjunction with the `CustomEditorConfigurer` +(introduced <>), which exposes a +property called `setPropertyEditorRegistrars(..)`: `PropertyEditorRegistrars` added to a +`CustomEditorConfigurer` in this fashion can easily be shared with `DataBinder` and +Spring MVC `Controllers`. Furthermore, it avoids the need for synchronization on custom +editors: a `PropertyEditorRegistrar` is expected to create fresh `PropertyEditor` +instances for each bean creation attempt. + +Using a `PropertyEditorRegistrar` is perhaps best illustrated with an example. First +off, you need to create your own `PropertyEditorRegistrar` implementation: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + package com.foo.editors.spring; + + public final class CustomPropertyEditorRegistrar implements PropertyEditorRegistrar { + + public void registerCustomEditors(PropertyEditorRegistry registry) { + + // it is expected that new PropertyEditor instances are created + registry.registerCustomEditor(ExoticType.class, new ExoticTypeEditor()); + + // you could register as many custom property editors as are required here... + } + } +---- + +See also the `org.springframework.beans.support.ResourceEditorRegistrar` for an example +`PropertyEditorRegistrar` implementation. Notice how in its implementation of the +`registerCustomEditors(..)` method it creates new instances of each property editor. + +Next we configure a `CustomEditorConfigurer` and inject an instance of our +`CustomPropertyEditorRegistrar` into it: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + + +---- + +Finally, and in a bit of a departure from the focus of this chapter, for those of you +using <>, using `PropertyEditorRegistrars` in +conjunction with data-binding `Controllers` (such as `SimpleFormController`) can be very +convenient. Find below an example of using a `PropertyEditorRegistrar` in the +implementation of an `initBinder(..)` method: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public final class RegisterUserController extends SimpleFormController { + + private final PropertyEditorRegistrar customPropertyEditorRegistrar; + + public RegisterUserController(PropertyEditorRegistrar propertyEditorRegistrar) { + this.customPropertyEditorRegistrar = propertyEditorRegistrar; + } + + protected void initBinder(HttpServletRequest request, + ServletRequestDataBinder binder) throws Exception { + **this.customPropertyEditorRegistrar.registerCustomEditors(binder);** + } + + // other methods to do with registering a User + } +---- + +This style of `PropertyEditor` registration can lead to concise code (the implementation +of `initBinder(..)` is just one line long!), and allows common `PropertyEditor` +registration code to be encapsulated in a class and then shared amongst as many +`Controllers` as needed. + + + + +[[core-convert]] +=== Spring Type Conversion +Spring 3 introduces a `core.convert` package that provides a general type conversion +system. The system defines an SPI to implement type conversion logic, as well as an API +to execute type conversions at runtime. Within a Spring container, this system can be +used as an alternative to PropertyEditors to convert externalized bean property value +strings to required property types. The public API may also be used anywhere in your +application where type conversion is needed. + + + +[[core-convert-Converter-API]] +==== Converter SPI +The SPI to implement type conversion logic is simple and strongly typed: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + package org.springframework.core.convert.converter; + + public interface Converter { + + T convert(S source); + + } +---- + +To create your own converter, simply implement the interface above. Parameterize `S` +as the type you are converting from, and `T` as the type you are converting to. Such a +converter can also be applied transparently if a collection or array of `S` needs to be +converted to an array or collection of `T`, provided that a delegating array/collection +converter has been registered as well (which `DefaultConversionService` does by default). + +For each call to `convert(S)`, the source argument is guaranteed to be NOT null. Your +Converter may throw any unchecked exception if conversion fails; specifically, an +`IllegalArgumentException` should be thrown to report an invalid source value. +Take care to ensure that your `Converter` implementation is thread-safe. + +Several converter implementations are provided in the `core.convert.support` package as +a convenience. These include converters from Strings to Numbers and other common types. +Consider `StringToInteger` as an example for a typical `Converter` implementation: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + package org.springframework.core.convert.support; + + final class StringToInteger implements Converter { + + public Integer convert(String source) { + return Integer.valueOf(source); + } + + } +---- + + + +[[core-convert-ConverterFactory-SPI]] +==== ConverterFactory +When you need to centralize the conversion logic for an entire class hierarchy, for +example, when converting from String to java.lang.Enum objects, implement +`ConverterFactory`: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + package org.springframework.core.convert.converter; + + public interface ConverterFactory { + + Converter getConverter(Class targetType); + + } +---- + +Parameterize S to be the type you are converting from and R to be the base type defining +the __range__ of classes you can convert to. Then implement getConverter(Class), +where T is a subclass of R. + +Consider the `StringToEnum` ConverterFactory as an example: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + package org.springframework.core.convert.support; + + final class StringToEnumConverterFactory implements ConverterFactory { + + public Converter getConverter(Class targetType) { + return new StringToEnumConverter(targetType); + } + + private final class StringToEnumConverter implements Converter { + + private Class enumType; + + public StringToEnumConverter(Class enumType) { + this.enumType = enumType; + } + + public T convert(String source) { + return (T) Enum.valueOf(this.enumType, source.trim()); + } + } + } +---- + + + +[[core-convert-GenericConverter-SPI]] +==== GenericConverter +When you require a sophisticated Converter implementation, consider the GenericConverter +interface. With a more flexible but less strongly typed signature, a GenericConverter +supports converting between multiple source and target types. In addition, a +GenericConverter makes available source and target field context you can use when +implementing your conversion logic. Such context allows a type conversion to be driven +by a field annotation, or generic information declared on a field signature. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + package org.springframework.core.convert.converter; + + public interface GenericConverter { + + public Set getConvertibleTypes(); + + Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType); + + } +---- + +To implement a GenericConverter, have getConvertibleTypes() return the supported +source->target type pairs. Then implement convert(Object, TypeDescriptor, +TypeDescriptor) to implement your conversion logic. The source TypeDescriptor provides +access to the source field holding the value being converted. The target TypeDescriptor +provides access to the target field where the converted value will be set. + +A good example of a GenericConverter is a converter that converts between a Java Array +and a Collection. Such an ArrayToCollectionConverter introspects the field that declares +the target Collection type to resolve the Collection's element type. This allows each +element in the source array to be converted to the Collection element type before the +Collection is set on the target field. + +[NOTE] +==== +Because GenericConverter is a more complex SPI interface, only use it when you need it. +Favor Converter or ConverterFactory for basic type conversion needs. +==== + + +[[core-convert-ConditionalGenericConverter-SPI]] +===== ConditionalGenericConverter +Sometimes you only want a Converter to execute if a specific condition holds true. For +example, you might only want to execute a Converter if a specific annotation is present +on the target field. Or you might only want to execute a Converter if a specific method, +such as static valueOf method, is defined on the target class. +ConditionalGenericConverter is an subinterface of GenericConverter that allows you to +define such custom matching criteria: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public interface ConditionalGenericConverter extends GenericConverter { + + boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType); + + } +---- + +A good example of a ConditionalGenericConverter is an EntityConverter that converts +between an persistent entity identifier and an entity reference. Such a EntityConverter +might only match if the target entity type declares a static finder method e.g. +findAccount(Long). You would perform such a finder method check in the implementation of +matches(TypeDescriptor, TypeDescriptor). + + + +[[core-convert-ConversionService-API]] +==== ConversionService API +The ConversionService defines a unified API for executing type conversion logic at +runtime. Converters are often executed behind this facade interface: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + package org.springframework.core.convert; + + public interface ConversionService { + + boolean canConvert(Class sourceType, Class targetType); + + T convert(Object source, Class targetType); + + boolean canConvert(TypeDescriptor sourceType, TypeDescriptor targetType); + + Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType); + + } +---- + +Most ConversionService implementations also implement `ConverterRegistry`, which +provides an SPI for registering converters. Internally, a ConversionService +implementation delegates to its registered converters to carry out type conversion logic. + +A robust ConversionService implementation is provided in the `core.convert.support` +package. `GenericConversionService` is the general-purpose implementation suitable for +use in most environments. `ConversionServiceFactory` provides a convenient factory for +creating common ConversionService configurations. + + + +[[core-convert-Spring-config]] +==== Configuring a ConversionService +A ConversionService is a stateless object designed to be instantiated at application +startup, then shared between multiple threads. In a Spring application, you typically +configure a ConversionService instance per Spring container (or ApplicationContext). +That ConversionService will be picked up by Spring and then used whenever a type +conversion needs to be performed by the framework. You may also inject this +ConversionService into any of your beans and invoke it directly. + +[NOTE] +==== +If no ConversionService is registered with Spring, the original PropertyEditor-based +system is used. +==== + +To register a default ConversionService with Spring, add the following bean definition +with id `conversionService`: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + +---- + +A default ConversionService can convert between strings, numbers, enums, collections, +maps, and other common types. To supplement or override the default converters with your +own custom converter(s), set the `converters` property. Property values may implement +either of the Converter, ConverterFactory, or GenericConverter interfaces. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + +---- + +It is also common to use a ConversionService within a Spring MVC application. See +<> for details on use with ``. + +In certain situations you may wish to apply formatting during conversion. See +<> for details on using +`FormattingConversionServiceFactoryBean`. + + + +[[core-convert-programmatic-usage]] +==== Using a ConversionService programmatically +To work with a ConversionService instance programmatically, simply inject a reference to +it like you would for any other bean: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Service + public class MyService { + + @Autowired + public MyService(ConversionService conversionService) { + this.conversionService = conversionService; + } + + public void doIt() { + this.conversionService.convert(...) + } + } +---- + +For most use cases, the `convert` method specifying the _targetType_ can be used but it +will not work with more complex types such as a collection of a parameterized element. +If you want to convert a `List` of `Integer` to a `List` of `String` programmatically, +for instance, you need to provide a formal definition of the source and target types. + +Fortunately, `TypeDescriptor` provides various options to make that straightforward: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + DefaultConversionService cs = new DefaultConversionService(); + + List input = .... + cs.convert(input, + TypeDescriptor.forObject(input), // List type descriptor + TypeDescriptor.collection(List.class, TypeDescriptor.valueOf(String.class))); +---- + +Note that `DefaultConversionService` registers converters automatically which are +appropriate for most environments. This includes collection converters, scalar +converters, and also basic `Object` to `String` converters. The same converters can +be registered with any `ConverterRegistry` using the _static_ `addDefaultConverters` +method on the `DefaultConversionService` class. + +Converters for value types will be reused for arrays and collections, so there is +no need to create a specific converter to convert from a `Collection` of `S` to a +`Collection` of `T`, assuming that standard collection handling is appropriate. + + + + +[[format]] +=== Spring Field Formatting +As discussed in the previous section, <> is a +general-purpose type conversion system. It provides a unified ConversionService API as +well as a strongly-typed Converter SPI for implementing conversion logic from one type +to another. A Spring Container uses this system to bind bean property values. In +addition, both the Spring Expression Language (SpEL) and DataBinder use this system to +bind field values. For example, when SpEL needs to coerce a `Short` to a `Long` to +complete an `expression.setValue(Object bean, Object value)` attempt, the core.convert +system performs the coercion. + +Now consider the type conversion requirements of a typical client environment such as a +web or desktop application. In such environments, you typically convert __from String__ +to support the client postback process, as well as back __to String__ to support the +view rendering process. In addition, you often need to localize String values. The more +general __core.convert__ Converter SPI does not address such __formatting__ requirements +directly. To directly address them, Spring 3 introduces a convenient Formatter SPI that +provides a simple and robust alternative to PropertyEditors for client environments. + +In general, use the Converter SPI when you need to implement general-purpose type +conversion logic; for example, for converting between a java.util.Date and and +java.lang.Long. Use the Formatter SPI when you're working in a client environment, such +as a web application, and need to parse and print localized field values. The +ConversionService provides a unified type conversion API for both SPIs. + + + +[[format-Formatter-SPI]] +==== Formatter SPI +The Formatter SPI to implement field formatting logic is simple and strongly typed: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + package org.springframework.format; + + public interface Formatter extends Printer, Parser { + } +---- + +Where Formatter extends from the Printer and Parser building-block interfaces: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public interface Printer { + String print(T fieldValue, Locale locale); + } +---- + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + import java.text.ParseException; + + public interface Parser { + T parse(String clientValue, Locale locale) throws ParseException; + } +---- + +To create your own Formatter, simply implement the Formatter interface above. +Parameterize T to be the type of object you wish to format, for example, +`java.util.Date`. Implement the `print()` operation to print an instance of T for +display in the client locale. Implement the `parse()` operation to parse an instance of +T from the formatted representation returned from the client locale. Your Formatter +should throw a ParseException or IllegalArgumentException if a parse attempt fails. Take +care to ensure your Formatter implementation is thread-safe. + +Several Formatter implementations are provided in `format` subpackages as a convenience. +The `number` package provides a `NumberFormatter`, `CurrencyFormatter`, and +`PercentFormatter` to format `java.lang.Number` objects using a `java.text.NumberFormat`. +The `datetime` package provides a `DateFormatter` to format `java.util.Date` objects with +a `java.text.DateFormat`. The `datetime.joda` package provides comprehensive datetime +formatting support based on the http://joda-time.sourceforge.net[Joda Time library]. + +Consider `DateFormatter` as an example `Formatter` implementation: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + package org.springframework.format.datetime; + + public final class DateFormatter implements Formatter { + + private String pattern; + + public DateFormatter(String pattern) { + this.pattern = pattern; + } + + public String print(Date date, Locale locale) { + if (date == null) { + return ""; + } + return getDateFormat(locale).format(date); + } + + public Date parse(String formatted, Locale locale) throws ParseException { + if (formatted.length() == 0) { + return null; + } + return getDateFormat(locale).parse(formatted); + } + + protected DateFormat getDateFormat(Locale locale) { + DateFormat dateFormat = new SimpleDateFormat(this.pattern, locale); + dateFormat.setLenient(false); + return dateFormat; + } + + } +---- + +The Spring team welcomes community-driven `Formatter` contributions; see +https://jira.spring.io/browse/SPR[jira.spring.io] to contribute. + + + +[[format-CustomFormatAnnotations]] +==== Annotation-driven Formatting +As you will see, field formatting can be configured by field type or annotation. To bind +an Annotation to a formatter, implement AnnotationFormatterFactory: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + package org.springframework.format; + + public interface AnnotationFormatterFactory { + + Set> getFieldTypes(); + + Printer getPrinter(A annotation, Class fieldType); + + Parser getParser(A annotation, Class fieldType); + + } +---- + +Parameterize A to be the field annotationType you wish to associate formatting logic +with, for example `org.springframework.format.annotation.DateTimeFormat`. Have +`getFieldTypes()` return the types of fields the annotation may be used on. Have +`getPrinter()` return a Printer to print the value of an annotated field. Have +`getParser()` return a Parser to parse a clientValue for an annotated field. + +The example AnnotationFormatterFactory implementation below binds the @NumberFormat +Annotation to a formatter. This annotation allows either a number style or pattern to be +specified: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public final class NumberFormatAnnotationFormatterFactory + implements AnnotationFormatterFactory { + + public Set> getFieldTypes() { + return new HashSet>(asList(new Class[] { + Short.class, Integer.class, Long.class, Float.class, + Double.class, BigDecimal.class, BigInteger.class })); + } + + public Printer getPrinter(NumberFormat annotation, Class fieldType) { + return configureFormatterFrom(annotation, fieldType); + } + + public Parser getParser(NumberFormat annotation, Class fieldType) { + return configureFormatterFrom(annotation, fieldType); + } + + private Formatter configureFormatterFrom(NumberFormat annotation, + Class fieldType) { + if (!annotation.pattern().isEmpty()) { + return new NumberFormatter(annotation.pattern()); + } else { + Style style = annotation.style(); + if (style == Style.PERCENT) { + return new PercentFormatter(); + } else if (style == Style.CURRENCY) { + return new CurrencyFormatter(); + } else { + return new NumberFormatter(); + } + } + } + } +---- + +To trigger formatting, simply annotate fields with @NumberFormat: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class MyModel { + + @NumberFormat(style=Style.CURRENCY) + private BigDecimal decimal; + + } +---- + + +[[format-annotations-api]] +===== Format Annotation API +A portable format annotation API exists in the `org.springframework.format.annotation` +package. Use @NumberFormat to format java.lang.Number fields. Use @DateTimeFormat to +format java.util.Date, java.util.Calendar, java.util.Long, or Joda Time fields. + +The example below uses @DateTimeFormat to format a java.util.Date as a ISO Date +(yyyy-MM-dd): + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class MyModel { + + @DateTimeFormat(iso=ISO.DATE) + private Date date; + + } +---- + + + +[[format-FormatterRegistry-SPI]] +==== FormatterRegistry SPI +The FormatterRegistry is an SPI for registering formatters and converters. +`FormattingConversionService` is an implementation of FormatterRegistry suitable for +most environments. This implementation may be configured programmatically or +declaratively as a Spring bean using `FormattingConversionServiceFactoryBean`. Because +this implementation also implements `ConversionService`, it can be directly configured +for use with Spring's DataBinder and the Spring Expression Language (SpEL). + +Review the FormatterRegistry SPI below: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + package org.springframework.format; + + public interface FormatterRegistry extends ConverterRegistry { + + void addFormatterForFieldType(Class fieldType, Printer printer, Parser parser); + + void addFormatterForFieldType(Class fieldType, Formatter formatter); + + void addFormatterForFieldType(Formatter formatter); + + void addFormatterForAnnotation(AnnotationFormatterFactory factory); + + } +---- + +As shown above, Formatters can be registered by fieldType or annotation. + +The FormatterRegistry SPI allows you to configure Formatting rules centrally, instead of +duplicating such configuration across your Controllers. For example, you might want to +enforce that all Date fields are formatted a certain way, or fields with a specific +annotation are formatted in a certain way. With a shared FormatterRegistry, you define +these rules once and they are applied whenever formatting is needed. + + + +[[format-FormatterRegistrar-SPI]] +==== FormatterRegistrar SPI +The FormatterRegistrar is an SPI for registering formatters and converters through the +FormatterRegistry: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + package org.springframework.format; + + public interface FormatterRegistrar { + + void registerFormatters(FormatterRegistry registry); + + } +---- + +A FormatterRegistrar is useful when registering multiple related converters and +formatters for a given formatting category, such as Date formatting. It can also be +useful where declarative registration is insufficient. For example when a formatter +needs to be indexed under a specific field type different from its own or when +registering a Printer/Parser pair. The next section provides more information on +converter and formatter registration. + + + +[[format-configuring-formatting-mvc]] +==== Configuring Formatting in Spring MVC +In a Spring MVC application, you may configure a custom ConversionService instance +explicitly as an attribute of the `annotation-driven` element of the MVC namespace. This +ConversionService will then be used anytime a type conversion is required during +Controller model binding. If not configured explicitly, Spring MVC will automatically +register default formatters and converters for common types such as numbers and dates. + +To rely on default formatting rules, no custom configuration is required in your Spring +MVC config XML: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + +---- + +With this one-line of configuration, default formatters for Numbers and Date types will +be installed, including support for the @NumberFormat and @DateTimeFormat annotations. +Full support for the Joda Time formatting library is also installed if Joda Time is +present on the classpath. + +To inject a ConversionService instance with custom formatters and converters registered, +set the conversion-service attribute and then specify custom converters, formatters, or +FormatterRegistrars as properties of the FormattingConversionServiceFactoryBean: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + + + + + + + + + + + + + + + + + + +---- + +[NOTE] +==== +See <> and the `FormattingConversionServiceFactoryBean` +for more information on when to use FormatterRegistrars. +==== + + + + +[[format-configuring-formatting-globaldatetimeformat]] +=== Configuring a global date & time format +By default, date and time fields that are not annotated with `@DateTimeFormat` are +converted from strings using the the `DateFormat.SHORT` style. If you prefer, you can +change this by defining your own global format. + +You will need to ensure that Spring does not register default formatters, and instead +you should register all formatters manually. Use the +`org.springframework.format.datetime.joda.JodaTimeFormatterRegistrar` or +`org.springframework.format.datetime.DateFormatterRegistrar` class depending on whether +you use the Joda Time library. + +For example, the following Java configuration will register a global ' `yyyyMMdd`' +format. This example does not depend on the Joda Time library: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Configuration + public class AppConfig { + + @Bean + public FormattingConversionService conversionService() { + + // Use the DefaultFormattingConversionService but do not register defaults + DefaultFormattingConversionService conversionService = new DefaultFormattingConversionService(false); + + // Ensure @NumberFormat is still supported + conversionService.addFormatterForFieldAnnotation(new NumberFormatAnnotationFormatterFactory()); + + // Register date conversion with a specific global format + DateFormatterRegistrar registrar = new DateFormatterRegistrar(); + registrar.setFormatter(new DateFormatter("yyyyMMdd")); + registrar.registerFormatters(conversionService); + + return conversionService; + } + } +---- + +If you prefer XML based configuration you can use a +`FormattingConversionServiceFactoryBean`. Here is the same example, this time using Joda +Time: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + + + + + + + + + + + + + +
+---- + +[NOTE] +==== +Joda Time provides separate distinct types to represent `date`, `time` and `date-time` +values. The `dateFormatter`, `timeFormatter` and `dateTimeFormatter` properties of the +`JodaTimeFormatterRegistrar` should be used to configure the different formats for each +type. The `DateTimeFormatterFactoryBean` provides a convenient way to create formatters. +==== + +If you are using Spring MVC remember to explicitly configure the conversion service that +is used. For Java based `@Configuration` this means extending the +`WebMvcConfigurationSupport` class and overriding the `mvcConversionService()` method. +For XML you should use the `'conversion-service'` attribute of the +`mvc:annotation-driven` element. See <> for details. + + + + +[[validation-beanvalidation]] +=== Spring Validation +Spring 3 introduces several enhancements to its validation support. First, the JSR-303 +Bean Validation API is now fully supported. Second, when used programmatically, Spring's +DataBinder can now validate objects as well as bind to them. Third, Spring MVC now has +support for declaratively validating `@Controller` inputs. + + + +[[validation-beanvalidation-overview]] +==== Overview of the JSR-303 Bean Validation API +JSR-303 standardizes validation constraint declaration and metadata for the Java +platform. Using this API, you annotate domain model properties with declarative +validation constraints and the runtime enforces them. There are a number of built-in +constraints you can take advantage of. You may also define your own custom constraints. + +To illustrate, consider a simple PersonForm model with two properties: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class PersonForm { + private String name; + private int age; + } +---- + +JSR-303 allows you to define declarative validation constraints against such properties: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class PersonForm { + + @NotNull + @Size(max=64) + private String name; + + @Min(0) + private int age; + + } +---- + +When an instance of this class is validated by a JSR-303 Validator, these constraints +will be enforced. + +For general information on JSR-303/JSR-349, see the http://beanvalidation.org/[Bean +Validation website]. For information on the specific capabilities of the default +reference implementation, see the https://www.hibernate.org/412.html[Hibernate +Validator] documentation. To learn how to setup a Bean Validation provider as a Spring +bean, keep reading. + + + +[[validation-beanvalidation-spring]] +==== Configuring a Bean Validation Provider +Spring provides full support for the Bean Validation API. This includes convenient +support for bootstrapping a JSR-303/JSR-349 Bean Validation provider as a Spring bean. +This allows for a `javax.validation.ValidatorFactory` or `javax.validation.Validator` to +be injected wherever validation is needed in your application. + +Use the `LocalValidatorFactoryBean` to configure a default Validator as a Spring bean: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + +---- + +The basic configuration above will trigger Bean Validation to initialize using its +default bootstrap mechanism. A JSR-303/JSR-349 provider, such as Hibernate Validator, +is expected to be present in the classpath and will be detected automatically. + + +[[validation-beanvalidation-spring-inject]] +===== Injecting a Validator +`LocalValidatorFactoryBean` implements both `javax.validation.ValidatorFactory` and +`javax.validation.Validator`, as well as Spring's +`org.springframework.validation.Validator`. You may inject a reference to either of +these interfaces into beans that need to invoke validation logic. + +Inject a reference to `javax.validation.Validator` if you prefer to work with the Bean +Validation API directly: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + import javax.validation.Validator; + + @Service + public class MyService { + + @Autowired + private Validator validator; +---- + +Inject a reference to `org.springframework.validation.Validator` if your bean requires +the Spring Validation API: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + import org.springframework.validation.Validator; + + @Service + public class MyService { + + @Autowired + private Validator validator; + + } +---- + + +[[validation-beanvalidation-spring-constraints]] +===== Configuring Custom Constraints +Each Bean Validation constraint consists of two parts. First, a `@Constraint` annotation +that declares the constraint and its configurable properties. Second, an implementation +of the `javax.validation.ConstraintValidator` interface that implements the constraint's +behavior. To associate a declaration with an implementation, each `@Constraint` annotation +references a corresponding ValidationConstraint implementation class. At runtime, a +`ConstraintValidatorFactory` instantiates the referenced implementation when the +constraint annotation is encountered in your domain model. + +By default, the `LocalValidatorFactoryBean` configures a `SpringConstraintValidatorFactory` +that uses Spring to create ConstraintValidator instances. This allows your custom +ConstraintValidators to benefit from dependency injection like any other Spring bean. + +Shown below is an example of a custom `@Constraint` declaration, followed by an associated +`ConstraintValidator` implementation that uses Spring for dependency injection: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Target({ElementType.METHOD, ElementType.FIELD}) + @Retention(RetentionPolicy.RUNTIME) + @Constraint(validatedBy=MyConstraintValidator.class) + public @interface MyConstraint { + } +---- + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + import javax.validation.ConstraintValidator; + + public class MyConstraintValidator implements ConstraintValidator { + + @Autowired; + private Foo aDependency; + + ... + } +---- + +As you can see, a ConstraintValidator implementation may have its dependencies +@Autowired like any other Spring bean. + + +[[validation-beanvalidation-spring-method]] +===== Spring-driven Method Validation +The method validation feature supported by Bean Validation 1.1, and as a custom +extension also by Hibernate Validator 4.3, can be integrated into a Spring context +through a `MethodValidationPostProcessor` bean definition: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + +---- + +In order to be eligible for Spring-driven method validation, all target classes need +to be annotated with Spring's `@Validated` annotation, optionally declaring the +validation groups to use. Check out the `MethodValidationPostProcessor` javadocs +for setup details with Hibernate Validator and Bean Validation 1.1 providers. + + +[[validation-beanvalidation-spring-other]] +===== Additional Configuration Options +The default `LocalValidatorFactoryBean` configuration should prove sufficient for most +cases. There are a number of configuration options for various Bean Validation +constructs, from message interpolation to traversal resolution. See the +`LocalValidatorFactoryBean` javadocs for more information on these options. + + + +[[validation-binder]] +==== Configuring a DataBinder +Since Spring 3, a DataBinder instance can be configured with a Validator. Once +configured, the Validator may be invoked by calling `binder.validate()`. Any validation +Errors are automatically added to the binder's BindingResult. + +When working with the DataBinder programmatically, this can be used to invoke validation +logic after binding to a target object: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + Foo target = new Foo(); + DataBinder binder = new DataBinder(target); + binder.setValidator(new FooValidator()); + + // bind to the target object + binder.bind(propertyValues); + + // validate the target object + binder.validate(); + + // get BindingResult that includes any validation errors + BindingResult results = binder.getBindingResult(); +---- + +A DataBinder can also be configured with multiple `Validator` instances via +`dataBinder.addValidators` and `dataBinder.replaceValidators`. This is useful when +combining globally configured Bean Validation with a Spring `Validator` configured +locally on a DataBinder instance. See <>. + + + +[[validation-mvc]] +==== Spring MVC 3 Validation +Beginning with Spring 3, Spring MVC has the ability to automatically validate +`@Controller` inputs. In previous versions it was up to the developer to manually invoke +validation logic. + + +[[validation-mvc-triggering]] +===== Triggering @Controller Input Validation +To trigger validation of a `@Controller` input, simply annotate the input argument as +++@Valid++: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Controller + public class MyController { + + @RequestMapping("/foo", method=RequestMethod.POST) + public void processFoo(**@Valid** Foo foo) { /* ... */ } +---- + +Spring MVC will validate a @Valid object after binding so-long as an appropriate +Validator has been configured. + +[NOTE] +==== +The @Valid annotation is part of the standard JSR-303 Bean Validation API, and is not a +Spring-specific construct. +==== + + +[[validation-mvc-configuring]] +===== Configuring a Validator for use by Spring MVC +The `Validator` instance invoked when a `@Valid` method argument is encountered may be +configured in two ways. First, you may call `binder.setValidator(Validator)` within a +++@Controller++'s `@InitBinder` callback. This allows you to configure a `Validator` +instance per `@Controller` class: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Controller + public class MyController { + + @InitBinder + protected void initBinder(WebDataBinder binder) { + binder.setValidator(new FooValidator()); + } + + @RequestMapping("/foo", method=RequestMethod.POST) + public void processFoo(@Valid Foo foo) { ... } + + } +---- + +Second, you may call `setValidator(Validator)` on the global `WebBindingInitializer`. This +allows you to configure a `Validator` instance across all `@Controller` classes. This can be +achieved easily by using the Spring MVC namespace: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + +---- + +To combine a global and a local validator, configure the global validator as shown above +and then add a local validator: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Controller + public class MyController { + + @InitBinder + protected void initBinder(WebDataBinder binder) { + binder.addValidators(new FooValidator()); + } + + } +---- + + +[[validation-mvc-jsr303]] +===== Configuring a JSR-303/JSR-349 Validator for use by Spring MVC +With Bean Validation, a single `javax.validation.Validator` instance typically validates +__all__ model objects that declare validation constraints. To configure such a JSR-303 +backed Validator with Spring MVC, simply add a Bean Validation provider, such as +Hibernate Validator, to your classpath. Spring MVC will detect it and automatically +enable Bean Validation support across all Controllers. + +The Spring MVC configuration required to enable Bean Validation support is shown below: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + +---- + +With this minimal configuration, anytime a `@Valid` `@Controller` input is encountered, it +will be validated by the Bean Validation provider. That provider, in turn, will enforce +any constraints declared against the input. Any ++ConstraintViolation++s will automatically +be exposed as errors in the `BindingResult` renderable by standard Spring MVC form tags. + + + + + diff --git a/src/asciidoc/view.adoc b/src/asciidoc/view.adoc new file mode 100644 index 000000000000..0a72e85ec853 --- /dev/null +++ b/src/asciidoc/view.adoc @@ -0,0 +1,2406 @@ +[[view]] +== View technologies + + + + +[[view-introduction]] +=== Introduction +One of the areas in which Spring excels is in the separation of view technologies from +the rest of the MVC framework. For example, deciding to use Velocity or XSLT in place of +an existing JSP is primarily a matter of configuration. This chapter covers the major +view technologies that work with Spring and touches briefly on how to add new ones. This +chapter assumes you are already familiar with <> which covers the +basics of how views in general are coupled to the MVC framework. + + + + +[[view-jsp]] +=== JSP & JSTL +Spring provides a couple of out-of-the-box solutions for JSP and JSTL views. Using JSP +or JSTL is done using a normal view resolver defined in the `WebApplicationContext`. +Furthermore, of course you need to write some JSPs that will actually render the view. + +[NOTE] +==== +Setting up your application to use JSTL is a common source of error, mainly caused by +confusion over the different servlet spec., JSP and JSTL version numbers, what they mean +and how to declare the taglibs correctly. The article +http://www.mularien.com/blog/2008/04/24/how-to-reference-and-use-jstl-in-your-web-application/[How +to Reference and Use JSTL in your Web Application] provides a useful guide to the common +pitfalls and how to avoid them. Note that as of Spring 3.0, the minimum supported +servlet version is 2.4 (JSP 2.0 and JSTL 1.1), which reduces the scope for confusion +somewhat. +==== + + + +[[view-jsp-resolver]] +==== View resolvers +Just as with any other view technology you're integrating with Spring, for JSPs you'll +need a view resolver that will resolve your views. The most commonly used view resolvers +when developing with JSPs are the `InternalResourceViewResolver` and the +`ResourceBundleViewResolver`. Both are declared in the `WebApplicationContext`: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + # And a sample properties file is uses (views.properties in WEB-INF/classes): + welcome.(class)=org.springframework.web.servlet.view.JstlView + welcome.url=/WEB-INF/jsp/welcome.jsp + + productList.(class)=org.springframework.web.servlet.view.JstlView + productList.url=/WEB-INF/jsp/productlist.jsp +---- + +As you can see, the `ResourceBundleViewResolver` needs a properties file defining the +view names mapped to 1) a class and 2) a URL. With a `ResourceBundleViewResolver` you +can mix different types of views using only one resolver. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + +---- + +The `InternalResourceBundleViewResolver` can be configured for using JSPs as described +above. As a best practice, we strongly encourage placing your JSP files in a directory +under the `'WEB-INF'` directory, so there can be no direct access by clients. + + + +[[view-jsp-jstl]] +==== 'Plain-old' JSPs versus JSTL +When using the Java Standard Tag Library you must use a special view class, the +`JstlView`, as JSTL needs some preparation before things such as the I18N features will +work. + + + +[[view-jsp-tags]] +==== Additional tags facilitating development +Spring provides data binding of request parameters to command objects as described in +earlier chapters. To facilitate the development of JSP pages in combination with those +data binding features, Spring provides a few tags that make things even easier. All +Spring tags have__HTML escaping__ features to enable or disable escaping of characters. + +The tag library descriptor (TLD) is included in the `spring-webmvc.jar`. Further +information about the individual tags can be found in the appendix entitled +<>. + + + +[[view-jsp-formtaglib]] +==== Using Spring's form tag library +As of version 2.0, Spring provides a comprehensive set of data binding-aware tags for +handling form elements when using JSP and Spring Web MVC. Each tag provides support for +the set of attributes of its corresponding HTML tag counterpart, making the tags +familiar and intuitive to use. The tag-generated HTML is HTML 4.01/XHTML 1.0 compliant. + +Unlike other form/input tag libraries, Spring's form tag library is integrated with +Spring Web MVC, giving the tags access to the command object and reference data your +controller deals with. As you will see in the following examples, the form tags make +JSPs easier to develop, read and maintain. + +Let's go through the form tags and look at an example of how each tag is used. We have +included generated HTML snippets where certain tags require further commentary. + + +[[view-jsp-formtaglib-configuration]] +===== Configuration +The form tag library comes bundled in `spring-webmvc.jar`. The library descriptor is +called `spring-form.tld`. + +To use the tags from this library, add the following directive to the top of your JSP +page: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + <%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %> +---- + +where `form` is the tag name prefix you want to use for the tags from this library. + + +[[view-jsp-formtaglib-formtag]] +===== The form tag + +This tag renders an HTML 'form' tag and exposes a binding path to inner tags for +binding. It puts the command object in the `PageContext` so that the command object can +be accessed by inner tags. __All the other tags in this library are nested tags of the +`form` tag__. + +Let's assume we have a domain object called `User`. It is a JavaBean with properties +such as `firstName` and `lastName`. We will use it as the form backing object of our +form controller which returns `form.jsp`. Below is an example of what `form.jsp` would +look like: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + +
First Name:Field is required.
Last Name:Field is required.
- -
+ + + + + + + + + + + +
First Name:
Last Name:
+ +
+ +---- + +The `firstName` and `lastName` values are retrieved from the command object placed in +the `PageContext` by the page controller. Keep reading to see more complex examples of +how inner tags are used with the `form` tag. + +The generated HTML looks like a standard form: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- +
+ + + + + + + + + + + + +
First Name:
Last Name:
+ +
+
+---- + +The preceding JSP assumes that the variable name of the form backing object is +`'command'`. If you have put the form backing object into the model under another name +(definitely a best practice), then you can bind the form to the named variable like so: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + + + + + + +
First Name:
Last Name:
+ +
+
+---- + + +[[view-jsp-formtaglib-inputtag]] +===== The input tag + +This tag renders an HTML 'input' tag using the bound value and type='text' by default. +For an example of this tag, see <>. Starting with Spring +3.1 you can use other types such HTML5-specific types like 'email', 'tel', 'date', and +others. + + +[[view-jsp-formtaglib-checkboxtag]] +===== The checkbox tag + +This tag renders an HTML 'input' tag with type 'checkbox'. + +Let's assume our `User` has preferences such as newsletter subscription and a list of +hobbies. Below is an example of the `Preferences` class: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class Preferences { + + private boolean receiveNewsletter; + private String[] interests; + private String favouriteWord; + + public boolean isReceiveNewsletter() { + return receiveNewsletter; + } + + public void setReceiveNewsletter(boolean receiveNewsletter) { + this.receiveNewsletter = receiveNewsletter; + } + + public String[] getInterests() { + return interests; + } + + public void setInterests(String[] interests) { + this.interests = interests; + } + + public String getFavouriteWord() { + return favouriteWord; + } + + public void setFavouriteWord(String favouriteWord) { + this.favouriteWord = favouriteWord; + } + } +---- + +The `form.jsp` would look like: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + <%-- Approach 1: Property is of type java.lang.Boolean --%> + + + + + + <%-- Approach 2: Property is of an array or of type java.util.Collection --%> + + + + + + <%-- Approach 3: Property is of type java.lang.Object --%> + + +
Subscribe to newsletter?:
Interests: + Quidditch: + Herbology: + Defence Against the Dark Arts: +
Favourite Word: + Magic: +
+
+---- + +There are 3 approaches to the `checkbox` tag which should meet all your checkbox needs. + +* Approach One - When the bound value is of type `java.lang.Boolean`, the + `input(checkbox)` is marked as 'checked' if the bound value is `true`. The `value` + attribute corresponds to the resolved value of the `setValue(Object)` value property. +* Approach Two - When the bound value is of type `array` or `java.util.Collection`, the + `input(checkbox)` is marked as 'checked' if the configured `setValue(Object)` value is + present in the bound `Collection`. +* Approach Three - For any other bound value type, the `input(checkbox)` is marked as + 'checked' if the configured `setValue(Object)` is equal to the bound value. + +Note that regardless of the approach, the same HTML structure is generated. Below is an +HTML snippet of some checkboxes: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + Interests: + + Quidditch: + + Herbology: + + Defence Against the Dark Arts: + + + +---- + +What you might not expect to see is the additional hidden field after each checkbox. +When a checkbox in an HTML page is __not__ checked, its value will not be sent to the +server as part of the HTTP request parameters once the form is submitted, so we need a +workaround for this quirk in HTML in order for Spring form data binding to work. The +`checkbox` tag follows the existing Spring convention of including a hidden parameter +prefixed by an underscore ("_") for each checkbox. By doing this, you are effectively +telling Spring that "__the checkbox was visible in the form and I want my object to +which the form data will be bound to reflect the state of the checkbox no matter what__". + + +[[view-jsp-formtaglib-checkboxestag]] +===== The checkboxes tag + +This tag renders multiple HTML 'input' tags with type 'checkbox'. + +Building on the example from the previous `checkbox` tag section. Sometimes you prefer +not to have to list all the possible hobbies in your JSP page. You would rather provide +a list at runtime of the available options and pass that in to the tag. That is the +purpose of the `checkboxes` tag. You pass in an `Array`, a `List` or a `Map` containing +the available options in the "items" property. Typically the bound property is a +collection so it can hold multiple values selected by the user. Below is an example of +the JSP using this tag: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + +
Interests: + <%-- Property is of an array or of type java.util.Collection --%> + +
+
+---- + +This example assumes that the "interestList" is a `List` available as a model attribute +containing strings of the values to be selected from. In the case where you use a Map, +the map entry key will be used as the value and the map entry's value will be used as +the label to be displayed. You can also use a custom object where you can provide the +property names for the value using "itemValue" and the label using "itemLabel". + + +[[view-jsp-formtaglib-radiobuttontag]] +===== The radiobutton tag + +This tag renders an HTML 'input' tag with type 'radio'. + +A typical usage pattern will involve multiple tag instances bound to the same property +but with different values. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + Sex: + + Male:
+ Female: + + +---- + + +[[view-jsp-formtaglib-radiobuttonstag]] +===== The radiobuttons tag + +This tag renders multiple HTML 'input' tags with type 'radio'. + +Just like the `checkboxes` tag above, you might want to pass in the available options as +a runtime variable. For this usage you would use the `radiobuttons` tag. You pass in an +`Array`, a `List` or a `Map` containing the available options in the "items" property. +In the case where you use a Map, the map entry key will be used as the value and the map +entry's value will be used as the label to be displayed. You can also use a custom +object where you can provide the property names for the value using "itemValue" and the +label using "itemLabel". + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + Sex: + + +---- + + +[[view-jsp-formtaglib-passwordtag]] +===== The password tag + +This tag renders an HTML 'input' tag with type 'password' using the bound value. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + Password: + + + + +---- + +Please note that by default, the password value is __not__ shown. If you do want the +password value to be shown, then set the value of the `'showPassword'` attribute to +true, like so. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + Password: + + + + +---- + + +[[view-jsp-formtaglib-selecttag]] +===== The select tag + +This tag renders an HTML 'select' element. It supports data binding to the selected +option as well as the use of nested `option` and `options` tags. + +Let's assume a `User` has a list of skills. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + Skills: + + +---- + +If the `User's` skill were in Herbology, the HTML source of the 'Skills' row would look +like: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + Skills: + + + + +---- + + +[[view-jsp-formtaglib-optiontag]] +===== The option tag + +This tag renders an HTML 'option'. It sets 'selected' as appropriate based on the bound +value. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + House: + + + + + + + + + +---- + +If the `User's` house was in Gryffindor, the HTML source of the 'House' row would look +like: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + House: + + + + +---- + + +[[view-jsp-formtaglib-optionstag]] +===== The options tag + +This tag renders a list of HTML 'option' tags. It sets the 'selected' attribute as +appropriate based on the bound value. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + Country: + + + + + + + +---- + +If the `User` lived in the UK, the HTML source of the 'Country' row would look like: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + Country: + + + + +---- + +As the example shows, the combined usage of an `option` tag with the `options` tag +generates the same standard HTML, but allows you to explicitly specify a value in the +JSP that is for display only (where it belongs) such as the default string in the +example: "-- Please Select". + +The `items` attribute is typically populated with a collection or array of item objects. +`itemValue` and `itemLabel` simply refer to bean properties of those item objects, if +specified; otherwise, the item objects themselves will be stringified. Alternatively, +you may specify a `Map` of items, in which case the map keys are interpreted as option +values and the map values correspond to option labels. If `itemValue` and/or `itemLabel` +happen to be specified as well, the item value property will apply to the map key and +the item label property will apply to the map value. + + +[[view-jsp-formtaglib-textAreatag]] +===== The textarea tag + +This tag renders an HTML 'textarea'. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + Notes: + + + +---- + + +[[view-jsp-formtaglib-hiddeninputtag]] +===== The hidden tag + +This tag renders an HTML 'input' tag with type 'hidden' using the bound value. To submit +an unbound hidden value, use the HTML `input` tag with type 'hidden'. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + +---- + +If we choose to submit the 'house' value as a hidden one, the HTML would look like: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + +---- + + +[[view-jsp-formtaglib-errorstag]] +===== The errors tag + +This tag renders field errors in an HTML 'span' tag. It provides access to the errors +created in your controller or those that were created by any validators associated with +your controller. + +Let's assume we want to display all error messages for the `firstName` and `lastName` +fields once we submit the form. We have a validator for instances of the `User` class +called `UserValidator`. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class UserValidator implements Validator { + + public boolean supports(Class candidate) { + return User.class.isAssignableFrom(candidate); + } + + public void validate(Object obj, Errors errors) { + ValidationUtils.rejectIfEmptyOrWhitespace(errors, "firstName", "required", "Field is required."); + ValidationUtils.rejectIfEmptyOrWhitespace(errors, "lastName", "required", "Field is required."); + } + } +---- + +The `form.jsp` would look like: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + <%-- Show errors for firstName field --%> + + + + + + + <%-- Show errors for lastName field --%> + + + + + +
First Name:
Last Name:
+ +
+
+---- + +If we submit a form with empty values in the `firstName` and `lastName` fields, this is +what the HTML would look like: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- +
+ + + + + <%-- Associated errors to firstName field displayed --%> + + + + + + + <%-- Associated errors to lastName field displayed --%> + + + + + +
First Name:Field is required.
Last Name:Field is required.
+ +
+
+---- + +What if we want to display the entire list of errors for a given page? The example below +shows that the `errors` tag also supports some basic wildcarding functionality. + +* `path="*"` - displays all errors +* `path="lastName"` - displays all errors associated with the `lastName` field +* if `path` is omitted - object errors only are displayed + +The example below will display a list of errors at the top of the page, followed by +field-specific errors next to the fields: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + + + + + + + + + +
First Name:
Last Name:
+ +
+
+---- + +The HTML would look like: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- +
+ Field is required.
Field is required.
+ + + + + + + + + + + + + + + + +---- + + +[[rest-method-conversion]] +===== HTTP Method Conversion +A key principle of REST is the use of the Uniform Interface. This means that all +resources (URLs) can be manipulated using the same four HTTP methods: GET, PUT, POST, +and DELETE. For each method, the HTTP specification defines the exact semantics. For +instance, a GET should always be a safe operation, meaning that is has no side effects, +and a PUT or DELETE should be idempotent, meaning that you can repeat these operations +over and over again, but the end result should be the same. While HTTP defines these +four methods, HTML only supports two: GET and POST. Fortunately, there are two possible +workarounds: you can either use JavaScript to do your PUT or DELETE, or simply do a POST +with the 'real' method as an additional parameter (modeled as a hidden input field in an +HTML form). This latter trick is what Spring's `HiddenHttpMethodFilter` does. This +filter is a plain Servlet Filter and therefore it can be used in combination with any +web framework (not just Spring MVC). Simply add this filter to your web.xml, and a POST +with a hidden _method parameter will be converted into the corresponding HTTP method +request. + +To support HTTP method conversion the Spring MVC form tag was updated to support setting +the HTTP method. For example, the following snippet taken from the updated Petclinic +sample + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + +

+
+---- + +This will actually perform an HTTP POST, with the 'real' DELETE method hidden behind a +request parameter, to be picked up by the `HiddenHttpMethodFilter`, as defined in +web.xml: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + + httpMethodFilter + org.springframework.web.filter.HiddenHttpMethodFilter + + + + httpMethodFilter + petclinic + +---- + +The corresponding `@Controller` method is shown below: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @RequestMapping(method = RequestMethod.DELETE) + public String deletePet(@PathVariable int ownerId, @PathVariable int petId) { + this.clinic.deletePet(petId); + return "redirect:/owners/" + ownerId; + } +---- + + +[[view-jsp-formtaglib-html5]] +===== HTML5 Tags +Starting with Spring 3, the Spring form tag library allows entering dynamic attributes, +which means you can enter any HTML5 specific attributes. + +In Spring 3.1, the form input tag supports entering a type attribute other than 'text'. +This is intended to allow rendering new HTML5 specific input types such as 'email', +'date', 'range', and others. Note that entering type='text' is not required since 'text' +is the default type. + + + + +[[view-tiles]] +=== Tiles +It is possible to integrate Tiles - just as any other view technology - in web +applications using Spring. The following describes in a broad way how to do this. + + +[NOTE] +==== +This section focuses on Spring's support for Tiles v3 in the +`org.springframework.web.servlet.view.tiles3` package. +==== + + +[[view-tiles-dependencies]] +==== Dependencies +To be able to use Tiles, you have to add a dependency on Tiles version 3.0.1 or higher +and http://tiles.apache.org/framework/dependency-management.html[its transitive dependencies] +to your project. + + +[[view-tiles-integrate]] +==== How to integrate Tiles +To be able to use Tiles, you have to configure it using files containing definitions +(for basic information on definitions and other Tiles concepts, please have a look at +http://tiles.apache.org[]). In Spring this is done using the `TilesConfigurer`. Have a +look at the following piece of example ApplicationContext configuration: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + /WEB-INF/defs/general.xml + /WEB-INF/defs/widgets.xml + /WEB-INF/defs/administrator.xml + /WEB-INF/defs/customer.xml + /WEB-INF/defs/templates.xml + + + +---- + +As you can see, there are five files containing definitions, which are all located in +the `'WEB-INF/defs'` directory. At initialization of the `WebApplicationContext`, the +files will be loaded and the definitions factory will be initialized. After that has +been done, the Tiles includes in the definition files can be used as views within your +Spring web application. To be able to use the views you have to have a `ViewResolver` +just as with any other view technology used with Spring. Below you can find two +possibilities, the `UrlBasedViewResolver` and the `ResourceBundleViewResolver`. + +You can specify locale specific Tiles definitions by adding an underscore and then +the locale. For example: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + /WEB-INF/defs/tiles.xml + /WEB-INF/defs/tiles_fr_FR.xml + + + +---- + +With this configuration, `tiles_fr_FR.xml` will be used for requests with the `fr_FR` locale, +and `tiles.xml` will be used by default. + +[NOTE] +==== +Since underscores are used to indicate locales, it is recommended to avoid using +them otherwise in the file names for Tiles definitions. +==== + + +[[view-tiles-url]] +===== UrlBasedViewResolver + +The `UrlBasedViewResolver` instantiates the given `viewClass` for each view it has to +resolve. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + +---- + + +[[view-tiles-resource]] +===== ResourceBundleViewResolver + +The `ResourceBundleViewResolver` has to be provided with a property file containing +viewnames and viewclasses the resolver can use: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + +---- + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + ... + welcomeView.(class)=org.springframework.web.servlet.view.tiles3.TilesView + welcomeView.url=welcome (this is the name of a Tiles definition) + + vetsView.(class)=org.springframework.web.servlet.view.tiles3.TilesView + vetsView.url=vetsView (again, this is the name of a Tiles definition) + + findOwnersForm.(class)=org.springframework.web.servlet.view.JstlView + findOwnersForm.url=/WEB-INF/jsp/findOwners.jsp + ... +---- + +As you can see, when using the `ResourceBundleViewResolver`, you can easily mix +different view technologies. + +Note that the `TilesView` class supports JSTL (the JSP Standard Tag Library) out of the +box. + + +[[view-tiles-preparer]] +===== SimpleSpringPreparerFactory and SpringBeanPreparerFactory + +As an advanced feature, Spring also supports two special Tiles `PreparerFactory` +implementations. Check out the Tiles documentation for details on how to use +`ViewPreparer` references in your Tiles definition files. + +Specify `SimpleSpringPreparerFactory` to autowire ViewPreparer instances based on +specified preparer classes, applying Spring's container callbacks as well as applying +configured Spring BeanPostProcessors. If Spring's context-wide annotation-config has +been activated, annotations in ViewPreparer classes will be automatically detected and +applied. Note that this expects preparer __classes__ in the Tiles definition files, just +like the default `PreparerFactory` does. + +Specify `SpringBeanPreparerFactory` to operate on specified preparer __names__ instead +of classes, obtaining the corresponding Spring bean from the DispatcherServlet's +application context. The full bean creation process will be in the control of the Spring +application context in this case, allowing for the use of explicit dependency injection +configuration, scoped beans etc. Note that you need to define one Spring bean definition +per preparer name (as used in your Tiles definitions). + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + /WEB-INF/defs/general.xml + /WEB-INF/defs/widgets.xml + /WEB-INF/defs/administrator.xml + /WEB-INF/defs/customer.xml + /WEB-INF/defs/templates.xml + + + + + + + +---- + + + + +[[view-velocity]] +=== Velocity & FreeMarker +http://velocity.apache.org[Velocity] and http://www.freemarker.org[FreeMarker] are two +templating languages that can be used as view technologies within Spring MVC +applications. The languages are quite similar and serve similar needs and so are +considered together in this section. For semantic and syntactic differences between the +two languages, see the http://www.freemarker.org[FreeMarker] web site. + + + +[[view-velocity-dependencies]] +==== Dependencies +Your web application will need to include `velocity-1.x.x.jar` or `freemarker-2.x.jar` +in order to work with Velocity or FreeMarker respectively and `commons-collections.jar` +is required for Velocity. Typically they are included in the `WEB-INF/lib` folder where +they are guaranteed to be found by a Java EE server and added to the classpath for your +application. It is of course assumed that you already have the `spring-webmvc.jar` in +your `'WEB-INF/lib'` directory too! If you make use of Spring's 'dateToolAttribute' or +'numberToolAttribute' in your Velocity views, you will also need to include the +`velocity-tools-generic-1.x.jar` + + + +[[view-velocity-contextconfig]] +==== Context configuration +A suitable configuration is initialized by adding the relevant configurer bean +definition to your `'*-servlet.xml'` as shown below: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + + + + +---- + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + + + + +---- + +[NOTE] +==== +For non web-apps add a `VelocityConfigurationFactoryBean` or a +`FreeMarkerConfigurationFactoryBean` to your application context definition file. +==== + + + +[[view-velocity-createtemplates]] +==== Creating templates +Your templates need to be stored in the directory specified by the `*Configurer` bean +shown above. This document does not cover details of creating templates for the two +languages - please see their relevant websites for information. If you use the view +resolvers highlighted, then the logical view names relate to the template file names in +similar fashion to `InternalResourceViewResolver` for JSP's. So if your controller +returns a ModelAndView object containing a view name of "welcome" then the resolvers +will look for the `/WEB-INF/freemarker/welcome.ftl` or `/WEB-INF/velocity/welcome.vm` +template as appropriate. + + + +[[view-velocity-advancedconfig]] +==== Advanced configuration +The basic configurations highlighted above will be suitable for most application +requirements, however additional configuration options are available for when unusual or +advanced requirements dictate. + + +[[view-velocity-example-velocityproperties]] +===== velocity.properties +This file is completely optional, but if specified, contains the values that are passed +to the Velocity runtime in order to configure velocity itself. Only required for +advanced configurations, if you need this file, specify its location on the +`VelocityConfigurer` bean definition above. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + +---- + +Alternatively, you can specify velocity properties directly in the bean definition for +the Velocity config bean by replacing the "configLocation" property with the following +inline properties. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + file + + org.apache.velocity.runtime.resource.loader.FileResourceLoader + + ${webapp.root}/WEB-INF/velocity + false + + + +---- + +Refer to the +{javadoc-baseurl}/org/springframework/ui/velocity/VelocityEngineFactory.html[API +documentation] for Spring configuration of Velocity, or the Velocity documentation for +examples and definitions of the `'velocity.properties'` file itself. + + +[[views-freemarker]] +===== FreeMarker +FreeMarker 'Settings' and 'SharedVariables' can be passed directly to the FreeMarker +`Configuration` object managed by Spring by setting the appropriate bean properties on +the `FreeMarkerConfigurer` bean. The `freemarkerSettings` property requires a +`java.util.Properties` object and the `freemarkerVariables` property requires a +`java.util.Map`. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + + + +---- + +See the FreeMarker documentation for details of settings and variables as they apply to +the `Configuration` object. + + + +[[view-velocity-forms]] +==== Bind support and form handling +Spring provides a tag library for use in JSP's that contains (amongst other things) a +`` tag. This tag primarily enables forms to display values from form +backing objects and to show the results of failed validations from a `Validator` in the +web or business tier. From version 1.1, Spring now has support for the same +functionality in both Velocity and FreeMarker, with additional convenience macros for +generating form input elements themselves. + + +[[view-bind-macros]] +===== The bind macros +A standard set of macros are maintained within the `spring-webmvc.jar` file for both +languages, so they are always available to a suitably configured application. + +Some of the macros defined in the Spring libraries are considered internal (private) but +no such scoping exists in the macro definitions making all macros visible to calling +code and user templates. The following sections concentrate only on the macros you need +to be directly calling from within your templates. If you wish to view the macro code +directly, the files are called spring.vm / spring.ftl and are in the packages +`org.springframework.web.servlet.view.velocity` or +`org.springframework.web.servlet.view.freemarker` respectively. + + +[[view-simple-binding]] +===== Simple binding +In your html forms (vm / ftl templates) that act as the 'formView' for a Spring form +controller, you can use code similar to the following to bind to field values and +display error messages for each input field in similar fashion to the JSP equivalent. +Note that the name of the command object is "command" by default, but can be overridden +in your MVC configuration by setting the 'commandName' bean property on your form +controller. Example code is shown below for the `personFormV` and `personFormF` views +configured earlier; + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + ... +
+ Name: + #springBind( "command.name" ) +
+ #foreach($error in $status.errorMessages) $error
#end +
+ ... + + + ... + +---- + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + <#import "/spring.ftl" as spring /> + + ... +
+ Name: + <@spring.bind "command.name" /> +
+ <#list spring.status.errorMessages as error> ${error}
+
+ ... + + + ... + +---- + +`#springBind` / `<@spring.bind>` requires a 'path' argument which consists of the name +of your command object (it will be 'command' unless you changed it in your +FormController properties) followed by a period and the name of the field on the command +object you wish to bind to. Nested fields can be used too such as +"command.address.street". The `bind` macro assumes the default HTML escaping behavior +specified by the ServletContext parameter `defaultHtmlEscape` in web.xml + +The optional form of the macro called `#springBindEscaped` / `<@spring.bindEscaped>` +takes a second argument and explicitly specifies whether HTML escaping should be used in +the status error messages or values. Set to true or false as required. Additional form +handling macros simplify the use of HTML escaping and these macros should be used +wherever possible. They are explained in the next section. + + +[[views-form-macros]] +===== Form input generation macros +Additional convenience macros for both languages simplify both binding and form +generation (including validation error display). It is never necessary to use these +macros to generate form input fields, and they can be mixed and matched with simple HTML +or calls direct to the spring bind macros highlighted previously. + +The following table of available macros show the VTL and FTL definitions and the +parameter list that each takes. + +[[views-macros-defs-tbl]] +.Table of macro definitions +[cols="3,1,1"] +|=== +| macro| VTL definition| FTL definition + +| **message** (output a string from a resource bundle based on the code parameter) +| #springMessage($code) +| <@spring.message code/> + +| **messageText** (output a string from a resource bundle based on the code parameter, + falling back to the value of the default parameter) +| #springMessageText($code $text) +| <@spring.messageText code, text/> + +| **url** (prefix a relative URL with the application's context root) +| #springUrl($relativeUrl) +| <@spring.url relativeUrl/> + +| **formInput** (standard input field for gathering user input) +| #springFormInput($path $attributes) +| <@spring.formInput path, attributes, fieldType/> + +| **formHiddenInput *** (hidden input field for submitting non-user input) +| #springFormHiddenInput($path $attributes) +| <@spring.formHiddenInput path, attributes/> + +| **formPasswordInput** * (standard input field for gathering passwords. Note that no + value will ever be populated in fields of this type) +| #springFormPasswordInput($path $attributes) +| <@spring.formPasswordInput path, attributes/> + +| **formTextarea** (large text field for gathering long, freeform text input) +| #springFormTextarea($path $attributes) +| <@spring.formTextarea path, attributes/> + +| **formSingleSelect** (drop down box of options allowing a single required value to be + selected) +| #springFormSingleSelect( $path $options $attributes) +| <@spring.formSingleSelect path, options, attributes/> + +| **formMultiSelect** (a list box of options allowing the user to select 0 or more values) +| #springFormMultiSelect($path $options $attributes) +| <@spring.formMultiSelect path, options, attributes/> + +| **formRadioButtons** (a set of radio buttons allowing a single selection to be made + from the available choices) +| #springFormRadioButtons($path $options $separator $attributes) +| <@spring.formRadioButtons path, options separator, attributes/> + +| **formCheckboxes** (a set of checkboxes allowing 0 or more values to be selected) +| #springFormCheckboxes($path $options $separator $attributes) +| <@spring.formCheckboxes path, options, separator, attributes/> + +| **formCheckbox** (a single checkbox) +| #springFormCheckbox($path $attributes) +| <@spring.formCheckbox path, attributes/> + +| **showErrors** (simplify display of validation errors for the bound field) +| #springShowErrors($separator $classOrStyle) +| <@spring.showErrors separator, classOrStyle/> +|=== + +* In FTL (FreeMarker), these two macros are not actually required as you can use the + normal `formInput` macro, specifying ' `hidden`' or ' `password`' as the value for the + `fieldType` parameter. + +The parameters to any of the above macros have consistent meanings: + +* path: the name of the field to bind to (ie "command.name") +* options: a Map of all the available values that can be selected from in the input + field. The keys to the map represent the values that will be POSTed back from the form + and bound to the command object. Map objects stored against the keys are the labels + displayed on the form to the user and may be different from the corresponding values + posted back by the form. Usually such a map is supplied as reference data by the + controller. Any Map implementation can be used depending on required behavior. For + strictly sorted maps, a `SortedMap` such as a `TreeMap` with a suitable Comparator may + be used and for arbitrary Maps that should return values in insertion order, use a + `LinkedHashMap` or a `LinkedMap` from commons-collections. +* separator: where multiple options are available as discreet elements (radio buttons or + checkboxes), the sequence of characters used to separate each one in the list (ie + "
"). +* attributes: an additional string of arbitrary tags or text to be included within the + HTML tag itself. This string is echoed literally by the macro. For example, in a + textarea field you may supply attributes as 'rows="5" cols="60"' or you could pass + style information such as 'style="border:1px solid silver"'. +* classOrStyle: for the showErrors macro, the name of the CSS class that the span tag + wrapping each error will use. If no information is supplied (or the value is empty) + then the errors will be wrapped in tags. + +Examples of the macros are outlined below some in FTL and some in VTL. Where usage +differences exist between the two languages, they are explained in the notes. + +[[views-form-macros-input]] +====== Input Fields +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + ... + Name: + #springFormInput("command.name" "")
+ #springShowErrors("
" "")
+---- + +The formInput macro takes the path parameter (command.name) and an additional attributes +parameter which is empty in the example above. The macro, along with all other form +generation macros, performs an implicit spring bind on the path parameter. The binding +remains valid until a new bind occurs so the showErrors macro doesn't need to pass the +path parameter again - it simply operates on whichever field a bind was last created for. + +The showErrors macro takes a separator parameter (the characters that will be used to +separate multiple errors on a given field) and also accepts a second parameter, this +time a class name or style attribute. Note that FreeMarker is able to specify default +values for the attributes parameter, unlike Velocity, and the two macro calls above +could be expressed as follows in FTL: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + <@spring.formInput "command.name"/> + <@spring.showErrors "
"/> +---- + +Output is shown below of the form fragment generating the name field, and displaying a +validation error after the form was submitted with no value in the field. Validation +occurs through Spring's Validation framework. + +The generated HTML looks like this: + +[source,jsp,indent=0] +[subs="verbatim,quotes"] +---- + Name: + +
+ required +
+
+---- + +The formTextarea macro works the same way as the formInput macro and accepts the same +parameter list. Commonly, the second parameter (attributes) will be used to pass style +information or rows and cols attributes for the textarea. + +[[views-form-macros-select]] +====== Selection Fields +Four selection field macros can be used to generate common UI value selection inputs in +your HTML forms. + +* formSingleSelect +* formMultiSelect +* formRadioButtons +* formCheckboxes + +Each of the four macros accepts a Map of options containing the value for the form +field, and the label corresponding to that value. The value and the label can be the +same. + +An example of radio buttons in FTL is below. The form backing object specifies a default +value of 'London' for this field and so no validation is necessary. When the form is +rendered, the entire list of cities to choose from is supplied as reference data in the +model under the name 'cityMap'. + +[source,jsp,indent=0] +[subs="verbatim,quotes"] +---- + ... + Town: + <@spring.formRadioButtons "command.address.town", cityMap, "" />

+---- + +This renders a line of radio buttons, one for each value in `cityMap` using the +separator "". No additional attributes are supplied (the last parameter to the macro is +missing). The cityMap uses the same String for each key-value pair in the map. The map's +keys are what the form actually submits as POSTed request parameters, map values are the +labels that the user sees. In the example above, given a list of three well known cities +and a default value in the form backing object, the HTML would be + +[source,jsp,indent=0] +[subs="verbatim,quotes"] +---- + Town: + London + Paris + New York +---- + +If your application expects to handle cities by internal codes for example, the map of +codes would be created with suitable keys like the example below. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + protected Map referenceData(HttpServletRequest request) throws Exception { + Map cityMap = new LinkedHashMap(); + cityMap.put("LDN", "London"); + cityMap.put("PRS", "Paris"); + cityMap.put("NYC", "New York"); + + Map m = new HashMap(); + m.put("cityMap", cityMap); + return m; + } +---- + +The code would now produce output where the radio values are the relevant codes but the +user still sees the more user friendly city names. + +[source,jsp,indent=0] +[subs="verbatim,quotes"] +---- + Town: + London + Paris + New York +---- + + +[[views-form-macros-html-escaping]] +===== HTML escaping and XHTML compliance +Default usage of the form macros above will result in HTML tags that are HTML 4.01 +compliant and that use the default value for HTML escaping defined in your web.xml as +used by Spring's bind support. In order to make the tags XHTML compliant or to override +the default HTML escaping value, you can specify two variables in your template (or in +your model where they will be visible to your templates). The advantage of specifying +them in the templates is that they can be changed to different values later in the +template processing to provide different behavior for different fields in your form. + +To switch to XHTML compliance for your tags, specify a value of 'true' for a +model/context variable named xhtmlCompliant: + +[source,jsp,indent=0] +[subs="verbatim,quotes"] +---- + ## for Velocity.. + #set($springXhtmlCompliant = true) + + <#-- for FreeMarker --> + <#assign xhtmlCompliant = true in spring> +---- + +Any tags generated by the Spring macros will now be XHTML compliant after processing +this directive. + +In similar fashion, HTML escaping can be specified per field: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + <#-- until this point, default HTML escaping is used --> + + <#assign htmlEscape = true in spring> + <#-- next field will use HTML escaping --> + <@spring.formInput "command.name" /> + + <#assign htmlEscape = false in spring> + <#-- all future fields will be bound with HTML escaping off --> +---- + + + + +[[view-xslt]] +=== XSLT +XSLT is a transformation language for XML and is popular as a view technology within web +applications. XSLT can be a good choice as a view technology if your application +naturally deals with XML, or if your model can easily be converted to XML. The following +section shows how to produce an XML document as model data and have it transformed with +XSLT in a Spring Web MVC application. + + + +[[view-xslt-firstwords]] +==== My First Words +This example is a trivial Spring application that creates a list of words in the +`Controller` and adds them to the model map. The map is returned along with the view +name of our XSLT view. See <> for details of Spring Web MVC's +`Controller` interface. The XSLT view will turn the list of words into a simple XML +document ready for transformation. + + +[[view-xslt-beandefs]] +===== Bean definitions +Configuration is standard for a simple Spring application. The dispatcher servlet config +file contains a reference to a `ViewResolver`, URL mappings and a single controller +bean... + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + +---- + +... that encapsulates our word generation logic. + + +[[view-xslt-controllercode]] +===== Standard MVC controller code +The controller logic is encapsulated in a subclass of `AbstractController`, with the +handler method being defined like so... + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + protected ModelAndView handleRequestInternal(HttpServletRequest request, + HttpServletResponse response) throws Exception { + + Map map = new HashMap(); + List wordList = new ArrayList(); + + wordList.add("hello"); + wordList.add("world"); + + map.put("wordList", wordList); + + return new ModelAndView("home", map); + } +---- + +So far we've done nothing that's XSLT specific. The model data has been created in the +same way as you would for any other Spring MVC application. Depending on the +configuration of the application now, that list of words could be rendered by JSP/JSTL +by having them added as request attributes, or they could be handled by Velocity by +adding the object to the `VelocityContext`. In order to have XSLT render them, they of +course have to be converted into an XML document somehow. There are software packages +available that will automatically 'domify' an object graph, but within Spring, you have +complete flexibility to create the DOM from your model in any way you choose. This +prevents the transformation of XML playing too great a part in the structure of your +model data which is a danger when using tools to manage the domification process. + + +[[view-xslt-subclassing]] +===== Convert the model data to XML +In order to create a DOM document from our list of words or any other model data, we +must subclass the (provided) +`org.springframework.web.servlet.view.xslt.AbstractXsltView` class. In doing so, we must +also typically implement the abstract method `createXsltSource(..)` method. The first +parameter passed to this method is our model map. Here's the complete listing of the +`HomePage` class in our trivial word application: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + package xslt; + + // imports omitted for brevity + + public class HomePage extends AbstractXsltView { + + protected Source createXsltSource(Map model, String rootName, + HttpServletRequest request, HttpServletResponse response) throws Exception { + + Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument(); + Element root = document.createElement(rootName); + + List words = (List) model.get("wordList"); + for (Iterator it = words.iterator(); it.hasNext();) { + String nextWord = (String) it.next(); + Element wordNode = document.createElement("word"); + Text textNode = document.createTextNode(nextWord); + wordNode.appendChild(textNode); + root.appendChild(wordNode); + } + return new DOMSource(root); + } + + } +---- + +A series of parameter name/value pairs can optionally be defined by your subclass which +will be added to the transformation object. The parameter names must match those defined +in your XSLT template declared with `defaultValue`. To specify the parameters, override the +`getParameters()` method of the `AbstractXsltView` class and return a `Map` of the +name/value pairs. If your parameters need to derive information from the current +request, you can override the `getParameters(HttpServletRequest request)` method instead. + + +[[view-xslt-viewdefinitions]] +===== Defining the view properties +The views.properties file (or equivalent xml definition if you're using an XML based +view resolver as we did in the Velocity examples above) looks like this for the one-view +application that is 'My First Words': + +[literal] +[subs="verbatim,quotes"] +---- +home.(class)=xslt.HomePage +home.stylesheetLocation=/WEB-INF/xsl/home.xslt +home.root=words +---- + +Here, you can see how the view is tied in with the `HomePage` class just written which +handles the model domification in the first property `'.(class)'`. The +`'stylesheetLocation'` property points to the XSLT file which will handle the XML +transformation into HTML for us and the final property `'.root'` is the name that will +be used as the root of the XML document. This gets passed to the `HomePage` class above +in the second parameter to the `createXsltSource(..)` method(s). + + +[[view-xslt-transforming]] +===== Document transformation +Finally, we have the XSLT code used for transforming the above document. As shown in the +above `'views.properties'` file, the stylesheet is called `'home.xslt'` and it lives in +the war file in the `'WEB-INF/xsl'` directory. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + Hello! + +

My First Words

+ + + +
+ + +
+
+ +
+---- + + + +[[view-xslt-summary]] +==== Summary +A summary of the files discussed and their location in the WAR file is shown in the +simplified WAR structure below. + +[literal] +[subs="verbatim,quotes"] +---- +ProjectRoot + | + +- WebContent + | + +- WEB-INF + | + +- classes + | | + | +- xslt + | | | + | | +- HomePageController.class + | | +- HomePage.class + | | + | +- views.properties + | + +- lib + | | + | +- spring-*.jar + | + +- xsl + | | + | +- home.xslt + | + +- frontcontroller-servlet.xml +---- + +You will also need to ensure that an XML parser and an XSLT engine are available on the +classpath. JDK 1.4 provides them by default, and most Java EE containers will also make +them available by default, but it's a possible source of errors to be aware of. + + + + +[[view-document]] +=== Document views (PDF/Excel) + + + +[[view-document-intro]] +==== Introduction +Returning an HTML page isn't always the best way for the user to view the model output, +and Spring makes it simple to generate a PDF document or an Excel spreadsheet +dynamically from the model data. The document is the view and will be streamed from the +server with the correct content type to (hopefully) enable the client PC to run their +spreadsheet or PDF viewer application in response. + +In order to use Excel views, you need to add the 'poi' library to your classpath, and +for PDF generation, the iText library. + + + +[[view-document-config]] +==== Configuration and setup +Document based views are handled in an almost identical fashion to XSLT views, and the +following sections build upon the previous one by demonstrating how the same controller +used in the XSLT example is invoked to render the same model as both a PDF document and +an Excel spreadsheet (which can also be viewed or manipulated in Open Office). + + +[[view-document-configviews]] +===== Document view definitions +First, let's amend the views.properties file (or xml equivalent) and add a simple view +definition for both document types. The entire file now looks like this with the XSLT +view shown from earlier: + +[literal] +[subs="verbatim,quotes"] +---- +home.(class)=xslt.HomePage +home.stylesheetLocation=/WEB-INF/xsl/home.xslt +home.root=words + +xl.(class)=excel.HomePage + +pdf.(class)=pdf.HomePage +---- + +__If you want to start with a template spreadsheet or a fillable PDF form to add your +model data to, specify the location as the 'url' property in the view definition__ + + +[[view-document-configcontroller]] +===== Controller code +The controller code we'll use remains exactly the same from the XSLT example earlier +other than to change the name of the view to use. Of course, you could be clever and +have this selected based on a URL parameter or some other logic - proof that Spring +really is very good at decoupling the views from the controllers! + + +[[view-document-configsubclasses]] +===== Subclassing for Excel views +Exactly as we did for the XSLT example, we'll subclass suitable abstract classes in +order to implement custom behavior in generating our output documents. For Excel, this +involves writing a subclass of +`org.springframework.web.servlet.view.document.AbstractExcelView` (for Excel files +generated by POI) or `org.springframework.web.servlet.view.document.AbstractJExcelView` +(for JExcelApi-generated Excel files) and implementing the `buildExcelDocument()` method. + +Here's the complete listing for our POI Excel view which displays the word list from the +model map in consecutive rows of the first column of a new spreadsheet: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + package excel; + + // imports omitted for brevity + + public class HomePage extends AbstractExcelView { + + protected void buildExcelDocument(Map model, HSSFWorkbook wb, HttpServletRequest req, + HttpServletResponse resp) throws Exception { + + HSSFSheet sheet; + HSSFRow sheetRow; + HSSFCell cell; + + // Go to the first sheet + // getSheetAt: only if wb is created from an existing document + // sheet = wb.getSheetAt(0); + sheet = wb.createSheet("Spring"); + sheet.setDefaultColumnWidth((short) 12); + + // write a text at A1 + cell = getCell(sheet, 0, 0); + setText(cell, "Spring-Excel test"); + + List words = (List) model.get("wordList"); + for (int i=0; i < words.size(); i++) { + cell = getCell(sheet, 2+i, 0); + setText(cell, (String) words.get(i)); + } + } + + } +---- + +And the following is a view generating the same Excel file, now using JExcelApi: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + package excel; + + // imports omitted for brevity + + public class HomePage extends AbstractJExcelView { + + protected void buildExcelDocument(Map model, WritableWorkbook wb, + HttpServletRequest request, HttpServletResponse response) throws Exception { + + WritableSheet sheet = wb.createSheet("Spring", 0); + + sheet.addCell(new Label(0, 0, "Spring-Excel test")); + + List words = (List) model.get("wordList"); + for (int i = 0; i < words.size(); i++) { + sheet.addCell(new Label(2+i, 0, (String) words.get(i))); + } + } + } +---- + +Note the differences between the APIs. We've found that the JExcelApi is somewhat more +intuitive, and furthermore, JExcelApi has slightly better image-handling capabilities. +There have been memory problems with large Excel files when using JExcelApi however. + +If you now amend the controller such that it returns `xl` as the name of the view ( +`return new ModelAndView("xl", map);`) and run your application again, you should find +that the Excel spreadsheet is created and downloaded automatically when you request the +same page as before. + + +[[view-document-configsubclasspdf]] +===== Subclassing for PDF views +The PDF version of the word list is even simpler. This time, the class extends +`org.springframework.web.servlet.view.document.AbstractPdfView` and implements the +`buildPdfDocument()` method as follows: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + package pdf; + + // imports omitted for brevity + + public class PDFPage extends AbstractPdfView { + + protected void buildPdfDocument(Map model, Document doc, PdfWriter writer, + HttpServletRequest req, HttpServletResponse resp) throws Exception { + List words = (List) model.get("wordList"); + for (int i=0; i + +
+---- + +Here we've configured an instance of the `ResourceBundleViewResolver` class that will +look for view mappings in the resource bundle with base name `views`. (The content of +this file is described in the next section.) + + +[[view-jasper-reports-configuration-views]] +===== Configuring the Views + +The Spring Framework contains five different `View` implementations for JasperReports, +four of which correspond to one of the four output formats supported by JasperReports, +and one that allows for the format to be determined at runtime: + +[[view-jasper-reports-configuration-views-classes]] +.JasperReports View classes +|=== +| Class Name| Render Format + +| `JasperReportsCsvView` +| CSV + +| `JasperReportsHtmlView` +| HTML + +| `JasperReportsPdfView` +| PDF + +| `JasperReportsXlsView` +| Microsoft Excel + +| `JasperReportsMultiFormatView` +| The view is <> +|=== + +Mapping one of these classes to a view name and a report file is a matter of adding the +appropriate entries in the resource bundle configured in the previous section as shown +here: + +[literal] +[subs="verbatim,quotes"] +---- +simpleReport.(class)=org.springframework.web.servlet.view.jasperreports.JasperReportsPdfView +simpleReport.url=/WEB-INF/reports/DataSourceReport.jasper +---- + +Here you can see that the view with name `simpleReport` is mapped to the +`JasperReportsPdfView` class, causing the output of this report to be rendered in PDF +format. The `url` property of the view is set to the location of the underlying report +file. + + +[[view-jasper-reports-configuration-report-files]] +===== About Report Files +JasperReports has two distinct types of report file: the design file, which has a +`.jrxml` extension, and the compiled report file, which has a `.jasper` extension. +Typically, you use the JasperReports Ant task to compile your `.jrxml` design file into +a `.jasper` file before deploying it into your application. With the Spring Framework +you can map either of these files to your report file and the framework will take care +of compiling the `.jrxml` file on the fly for you. You should note that after a `.jrxml` +file is compiled by the Spring Framework, the compiled report is cached for the lifetime +of the application. Thus, to make changes to the file you will need to restart your +application. + + +[[view-jasper-reports-configuration-multiformat-view]] +===== Using JasperReportsMultiFormatView + +The `JasperReportsMultiFormatView` allows for the report format to be specified at +runtime. The actual rendering of the report is delegated to one of the other +JasperReports view classes - the `JasperReportsMultiFormatView` class simply adds a +wrapper layer that allows for the exact implementation to be specified at runtime. + +The `JasperReportsMultiFormatView` class introduces two concepts: the format key and the +discriminator key. The `JasperReportsMultiFormatView` class uses the mapping key to look +up the actual view implementation class, and it uses the format key to lookup up the +mapping key. From a coding perspective you add an entry to your model with the format +key as the key and the mapping key as the value, for example: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public ModelAndView handleSimpleReportMulti(HttpServletRequest request, + HttpServletResponse response) throws Exception { + + String uri = request.getRequestURI(); + String format = uri.substring(uri.lastIndexOf(".") + 1); + + Map model = getModel(); + model.put("format", format); + + return new ModelAndView("simpleReportMulti", model); + + } +---- + +In this example, the mapping key is determined from the extension of the request URI and +is added to the model under the default format key: `format`. If you wish to use a +different format key then you can configure this using the `formatKey` property of the +`JasperReportsMultiFormatView` class. + +By default the following mapping key mappings are configured in +`JasperReportsMultiFormatView`: + +[[view-jasper-reports-configuration-multiformat-view-mappings]] +.JasperReportsMultiFormatView Default Mapping Key Mappings +|=== +| Mapping Key| View Class + +| csv +| `JasperReportsCsvView` + +| html +| `JasperReportsHtmlView` + +| pdf +| `JasperReportsPdfView` + +| xls +| `JasperReportsXlsView` +|=== + +So in the example above a request to URI /foo/myReport.pdf would be mapped to the +`JasperReportsPdfView` class. You can override the mapping key to view class mappings +using the `formatMappings` property of `JasperReportsMultiFormatView`. + + + +[[view-jasper-reports-model]] +==== Populating the ModelAndView + +In order to render your report correctly in the format you have chosen, you must supply +Spring with all of the data needed to populate your report. For JasperReports this means +you must pass in all report parameters along with the report datasource. Report +parameters are simple name/value pairs and can be added to the `Map` for your model as +you would add any name/value pair. + +When adding the datasource to the model you have two approaches to choose from. The +first approach is to add an instance of `JRDataSource` or a `Collection` type to the +model `Map` under any arbitrary key. Spring will then locate this object in the model +and treat it as the report datasource. For example, you may populate your model like so: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + private Map getModel() { + Map model = new HashMap(); + Collection beanData = getBeanData(); + model.put("myBeanData", beanData); + return model; + } +---- + +The second approach is to add the instance of `JRDataSource` or `Collection` under a +specific key and then configure this key using the `reportDataKey` property of the view +class. In both cases Spring will wrap instances of `Collection` in a +`JRBeanCollectionDataSource` instance. For example: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + private Map getModel() { + Map model = new HashMap(); + Collection beanData = getBeanData(); + Collection someData = getSomeData(); + model.put("myBeanData", beanData); + model.put("someData", someData); + return model; + } +---- + +Here you can see that two `Collection` instances are being added to the model. To ensure +that the correct one is used, we simply modify our view configuration as appropriate: + +[literal] +[subs="verbatim,quotes"] +---- +simpleReport.(class)=org.springframework.web.servlet.view.jasperreports.JasperReportsPdfView +simpleReport.url=/WEB-INF/reports/DataSourceReport.jasper +simpleReport.reportDataKey=myBeanData +---- + +Be aware that when using the first approach, Spring will use the first instance of +`JRDataSource` or `Collection` that it encounters. If you need to place multiple +instances of `JRDataSource` or `Collection` into the model you need to use the second +approach. + + + +[[view-jasper-reports-subreports]] +==== Working with Sub-Reports +JasperReports provides support for embedded sub-reports within your master report files. +There are a wide variety of mechanisms for including sub-reports in your report files. +The easiest way is to hard code the report path and the SQL query for the sub report +into your design files. The drawback of this approach is obvious: the values are +hard-coded into your report files reducing reusability and making it harder to modify +and update report designs. To overcome this you can configure sub-reports declaratively, +and you can include additional data for these sub-reports directly from your controllers. + + +[[view-jasper-reports-subreports-config-reports]] +===== Configuring Sub-Report Files +To control which sub-report files are included in a master report using Spring, your +report file must be configured to accept sub-reports from an external source. To do this +you declare a parameter in your report file like so: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + +---- + +Then, you define your sub-report to use this sub-report parameter: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + + +---- + +This defines a master report file that expects the sub-report to be passed in as an +instance of `net.sf.jasperreports.engine.JasperReports` under the parameter +`ProductsSubReport`. When configuring your Jasper view class, you can instruct Spring to +load a report file and pass it into the JasperReports engine as a sub-report using the +`subReportUrls` property: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + +---- + +Here, the key of the `Map` corresponds to the name of the sub-report parameter in the +report design file, and the entry is the URL of the report file. Spring will load this +report file, compiling it if necessary, and pass it into the JasperReports engine under +the given key. + + +[[view-jasper-reports-subreports-config-datasources]] +===== Configuring Sub-Report Data Sources +This step is entirely optional when using Spring to configure your sub-reports. If you +wish, you can still configure the data source for your sub-reports using static queries. +However, if you want Spring to convert data returned in your `ModelAndView` into +instances of `JRDataSource` then you need to specify which of the parameters in your +`ModelAndView` Spring should convert. To do this, configure the list of parameter names +using the `subReportDataKeys` property of your chosen view class: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + +---- + +Here, the key you supply __must__ correspond to both the key used in your `ModelAndView` +and the key used in your report design file. + + + +[[view-jasper-reports-exporter-parameters]] +==== Configuring Exporter Parameters +If you have special requirements for exporter configuration -- perhaps you want a +specific page size for your PDF report -- you can configure these exporter parameters +declaratively in your Spring configuration file using the `exporterParameters` property +of the view class. The `exporterParameters` property is typed as a `Map`. In your +configuration the key of an entry should be the fully-qualified name of a static field +that contains the exporter parameter definition, and the value of an entry should be the +value you want to assign to the parameter. An example of this is shown below: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + Footer by Spring! + </td><td width="50%">&nbsp; </td></tr> + </table></body></html> + + + + + +---- + +Here you can see that the `JasperReportsHtmlView` is configured with an exporter +parameter for `net.sf.jasperreports.engine.export.JRHtmlExporterParameter.HTML_FOOTER` +which will output a footer in the resulting HTML. + + + + +[[view-feeds]] +=== Feed Views +Both `AbstractAtomFeedView` and `AbstractRssFeedView` inherit from the base class +`AbstractFeedView` and are used to provide Atom and RSS Feed views respectfully. They +are based on java.net's https://rome.dev.java.net[ROME] project and are located in the +package `org.springframework.web.servlet.view.feed`. + +`AbstractAtomFeedView` requires you to implement the `buildFeedEntries()` method and +optionally override the `buildFeedMetadata()` method (the default implementation is +empty), as shown below. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class SampleContentAtomView extends AbstractAtomFeedView { + + @Override + protected void buildFeedMetadata(Map model, + Feed feed, HttpServletRequest request) { + // implementation omitted + } + + @Override + protected List buildFeedEntries(Map model, + HttpServletRequest request, HttpServletResponse response) throws Exception { + // implementation omitted + } + + } +---- + +Similar requirements apply for implementing `AbstractRssFeedView`, as shown below. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class SampleContentAtomView extends AbstractRssFeedView { + + @Override + protected void buildFeedMetadata(Map model, + Channel feed, HttpServletRequest request) { + // implementation omitted + } + + @Override + protected List buildFeedItems(Map model, + HttpServletRequest request, HttpServletResponse response) throws Exception { + // implementation omitted + } + + } +---- + +The `buildFeedItems()` and `buildFeedEntires()` methods pass in the HTTP request in case +you need to access the Locale. The HTTP response is passed in only for the setting of +cookies or other HTTP headers. The feed will automatically be written to the response +object after the method returns. + +For an example of creating an Atom view please refer to Alef Arendsen's Spring Team Blog +https://spring.io/blog/2009/03/16/adding-an-atom-view-to-an-application-using-spring-s-rest-support[entry]. + + + + +[[view-xml-marshalling]] +=== XML Marshalling View +The `MarshallingView` uses an XML `Marshaller` defined in the `org.springframework.oxm` +package to render the response content as XML. The object to be marshalled can be set +explicitly using `MarhsallingView`'s `modelKey` bean property. Alternatively, the view +will iterate over all model properties and marshal the first type that is supported +by the `Marshaller`. For more information on the functionality in the +`org.springframework.oxm` package refer to the chapter <>. + + + + +[[view-json-mapping]] +=== JSON Mapping View +The `MappingJackson2JsonView` uses the Jackson library's `ObjectMapper` to render the response +content as JSON. By default, the entire contents of the model map (with the exception of +framework-specific classes) will be encoded as JSON. For cases where the contents of the +map need to be filtered, users may specify a specific set of model attributes to encode +via the `RenderedAttributes` property. The `extractValueFromSingleKeyModel` property may +also be used to have the value in single-key models extracted and serialized directly +rather than as a map of model attributes. + +JSON mapping can be customized as needed through the use of Jackson's provided +annotations. When further control is needed, a custom `ObjectMapper` can be injected +through the `ObjectMapper` property for cases where custom JSON +serializers/deserializers need to be provided for specific types. + + + + +[[view-xml-mapping]] +=== XML Mapping View +The `MappingJackson2XmlView` uses the +https://github.com/FasterXML/jackson-dataformat-xml[Jackson XML extension]'s `XmlMapper` +to render the response content as XML. If the model contains multiples entries, the +object to be serialized should be set explicitly using `MappingJackson2XmlView`'s +`modelKey` bean property. If the model contains a single entry, it will be serialized +automatically. + +XML mapping can be customized as needed through the use of JAXB or Jackson's provided +annotations. When further control is needed, a custom `XmlMapper` can be injected +through the `ObjectMapper` property for cases where custom XML +serializers/deserializers need to be provided for specific types. + diff --git a/src/asciidoc/web-integration.adoc b/src/asciidoc/web-integration.adoc new file mode 100644 index 000000000000..76a68d74cf39 --- /dev/null +++ b/src/asciidoc/web-integration.adoc @@ -0,0 +1,250 @@ +[[web-integration]] +== Integrating with other web frameworks + + + + +[[intro]] +=== Introduction + +.Spring Web Flow +**** +Spring Web Flow (SWF) aims to be the best solution for the management of web application +page flow. + +SWF integrates with existing frameworks like Spring MVC and JSF, in both Servlet and +Portlet environments. If you have a business process (or processes) that would benefit +from a conversational model as opposed to a purely request model, then SWF may be the +solution. + +SWF allows you to capture logical page flows as self-contained modules that are reusable +in different situations, and as such is ideal for building web application modules that +guide the user through controlled navigations that drive business processes. + +For more information about SWF, consult the +http://projects.spring.io/spring-webflow/[Spring Web Flow website]. +**** + +This chapter details Spring's integration with third party web frameworks, such as +http://www.oracle.com/technetwork/java/javaee/javaserverfaces-139869.html[JSF]. + +One of the core value propositions of the Spring Framework is that of enabling +__choice__. In a general sense, Spring does not force one to use or buy into any +particular architecture, technology, or methodology (although it certainly recommends +some over others). This freedom to pick and choose the architecture, technology, or +methodology that is most relevant to a developer and their development team is +arguably most evident in the web area, where Spring provides its own web framework +(<>), while at the same time providing integration with a number of +popular third party web frameworks. This allows one to continue to leverage any and all +of the skills one may have acquired in a particular web framework such as JSF, while +at the same time being able to enjoy the benefits afforded by Spring in other areas such +as data access, declarative transaction management, and flexible configuration and +application assembly. + +Having dispensed with the woolly sales patter (c.f. the previous paragraph), the +remainder of this chapter will concentrate upon the meaty details of integrating your +favorite web framework with Spring. One thing that is often commented upon by developers +coming to Java from other languages is the seeming super-abundance of web frameworks +available in Java. There are indeed a great number of web frameworks in the Java space; +in fact there are far too many to cover with any semblance of detail in a single +chapter. This chapter thus picks four of the more popular web frameworks in Java, +starting with the Spring configuration that is common to all of the supported web +frameworks, and then detailing the specific integration options for each supported web +framework. + +[NOTE] +==== +Please note that this chapter does not attempt to explain how to use any of the +supported web frameworks. For example, if you want to use JSF for the presentation +layer of your web application, the assumption is that you are already familiar with +JSF itself. If you need further details about any of the supported web frameworks +themselves, please do consult <> at the end of this chapter. +==== + + + + +[[web-integration-common]] +=== Common configuration +Before diving into the integration specifics of each supported web framework, let us +first take a look at the Spring configuration that is __not__ specific to any one web +framework. (This section is equally applicable to Spring's own web framework, Spring +MVC.) + +One of the concepts (for want of a better word) espoused by (Spring's) lightweight +application model is that of a layered architecture. Remember that in a 'classic' +layered architecture, the web layer is but one of many layers; it serves as one of the +entry points into a server side application and it delegates to service objects +(facades) defined in a service layer to satisfy business specific (and +presentation-technology agnostic) use cases. In Spring, these service objects, any other +business-specific objects, data access objects, etc. exist in a distinct 'business +context', which contains __no__ web or presentation layer objects (presentation objects +such as Spring MVC controllers are typically configured in a distinct 'presentation +context'). This section details how one configures a Spring container (a +`WebApplicationContext`) that contains all of the 'business beans' in one's application. + +On to specifics: all that one need do is to declare a +{javadoc-baseurl}/org/springframework/web/context/ContextLoaderListener.html[`ContextLoaderListener`] +in the standard Java EE servlet `web.xml` file of one's web application, and add a +`contextConfigLocation` section (in the same file) that defines which +set of Spring XML configuration files to load. + +Find below the configuration: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + org.springframework.web.context.ContextLoaderListener + +---- + +Find below the configuration: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + contextConfigLocation + /WEB-INF/applicationContext*.xml + +---- + +If you don't specify the `contextConfigLocation` context parameter, the +`ContextLoaderListener` will look for a file called `/WEB-INF/applicationContext.xml` to +load. Once the context files are loaded, Spring creates a +{javadoc-baseurl}/org/springframework/web/context/WebApplicationContext.html[`WebApplicationContext`] +object based on the bean definitions and stores it in the `ServletContext` of the web +application. + +All Java web frameworks are built on top of the Servlet API, and so one can use the +following code snippet to get access to this 'business context' `ApplicationContext` +created by the `ContextLoaderListener`. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + WebApplicationContext ctx = WebApplicationContextUtils.getWebApplicationContext(servletContext); +---- + +The +{javadoc-baseurl}/org/springframework/web/context/support/WebApplicationContextUtils.html[`WebApplicationContextUtils`] +class is for convenience, so you don't have to remember the name of the `ServletContext` +attribute. Its __getWebApplicationContext()__ method will return `null` if an object +doesn't exist under the `WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE` +key. Rather than risk getting `NullPointerExceptions` in your application, it's better +to use the `getRequiredWebApplicationContext()` method. This method throws an exception +when the `ApplicationContext` is missing. + +Once you have a reference to the `WebApplicationContext`, you can retrieve beans by +their name or type. Most developers retrieve beans by name and then cast them to one of +their implemented interfaces. + +Fortunately, most of the frameworks in this section have simpler ways of looking up +beans. Not only do they make it easy to get beans from a Spring container, but they also +allow you to use dependency injection on their controllers. Each web framework section +has more detail on its specific integration strategies. + + + + +[[jsf]] +=== JavaServer Faces 1.2 +JavaServer Faces (JSF) is the JCP's standard component-based, event-driven web user +interface framework. As of Java EE 5, it is an official part of the Java EE umbrella. + +For a popular JSF runtime as well as for popular JSF component libraries, check out the +http://myfaces.apache.org/[Apache MyFaces project]. The MyFaces project also provides +common JSF extensions such as http://myfaces.apache.org/orchestra/[MyFaces Orchestra]: +a Spring-based JSF extension that provides rich conversation scope support. + +[NOTE] +==== +Spring Web Flow 2.0 provides rich JSF support through its newly established Spring Faces +module, both for JSF-centric usage (as described in this section) and for Spring-centric +usage (using JSF views within a Spring MVC dispatcher). Check out the +http://projects.spring.io/spring-webflow[Spring Web Flow website] for details! +==== + +The key element in Spring's JSF integration is the JSF `ELResolver` mechanism. + +[[jsf-springbeanfaceselresolver]] +==== SpringBeanFacesELResolver (JSF 1.2+) +`SpringBeanFacesELResolver` is a JSF 1.2 compliant `ELResolver` implementation, +integrating with the standard Unified EL as used by JSF 1.2 and JSP 2.1. Like +`SpringBeanVariableResolver`, it delegates to the Spring's 'business context' +`WebApplicationContext` __first__, then to the default resolver of the underlying JSF +implementation. + +Configuration-wise, simply define `SpringBeanFacesELResolver` in your JSF 1.2 +__faces-context.xml__ file: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + org.springframework.web.jsf.el.SpringBeanFacesELResolver + ... + + +---- + + +[[jsf-facescontextutils]] +==== FacesContextUtils +A custom `VariableResolver` works well when mapping one's properties to beans +in __faces-config.xml__, but at times one may need to grab a bean explicitly. The +{javadoc-baseurl}/org/springframework/web/jsf/FacesContextUtils.html[`FacesContextUtils`] +class makes this easy. It is similar to `WebApplicationContextUtils`, except that it +takes a `FacesContext` parameter rather than a `ServletContext` parameter. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + ApplicationContext ctx = FacesContextUtils.getWebApplicationContext(FacesContext.getCurrentInstance()); +---- + + + +[[struts]] +=== Apache Struts 2.x +Invented by Craig McClanahan, http://struts.apache.org[Struts] is an open source project +hosted by the Apache Software Foundation. At the time, it greatly simplified the +JSP/Servlet programming paradigm and won over many developers who were using proprietary +frameworks. It simplified the programming model, it was open source (and thus free as in +beer), and it had a large community, which allowed the project to grow and become popular +among Java web developers. + +Check out the Struts +https://struts.apache.org/release/2.3.x/docs/spring-plugin.html[Spring Plugin] for the +built-in Spring integration shipped with Struts. + + + +[[tapestry]] +=== Tapestry 5.x +From the http://tapestry.apache.org/[Tapestry homepage]: + +Tapestry is a "__Component oriented framework for creating dynamic, robust, +highly scalable web applications in Java.__" + +While Spring has its own <>, there are a number of unique +advantages to building an enterprise Java application using a combination of Tapestry +for the web user interface and the Spring container for the lower layers. + +For more information, check out Tapestry's dedicated +https://tapestry.apache.org/integrating-with-spring-framework.html[integration module for +Spring]. + + + +[[web-integration-resources]] +=== Further Resources +Find below links to further resources about the various web frameworks described in this +chapter. + +* The http://www.oracle.com/technetwork/java/javaee/javaserverfaces-139869.html[JSF] homepage +* The http://struts.apache.org/[Struts] homepage +* The http://tapestry.apache.org/[Tapestry] homepage + diff --git a/src/asciidoc/websocket.adoc b/src/asciidoc/websocket.adoc new file mode 100644 index 000000000000..ea3e0a12a0a6 --- /dev/null +++ b/src/asciidoc/websocket.adoc @@ -0,0 +1,2088 @@ +[[websocket]] +== WebSocket Support +This part of the reference documentation covers Spring Framework's support for +WebSocket-style messaging in web applications including use of STOMP as an +application level WebSocket sub-protocol. + +<> establishes a frame of mind in which to think about +WebSocket, covering adoption challenges, design considerations, and thoughts on +when it is a good fit. + +<> reviews the Spring WebSocket API on the +server-side while <> explains the SockJS protocol and shows +how to configure and use it. + +<> introduces the STOMP messaging protocol. +<> demonstrates how to configure STOMP support in Spring. +<> and the following sections explain how to +write annotated message handling methods, send messages, choose message broker +options, as well as work with the special "user" destinations. Finally, +<> lists three approaches to testing STOMP/WebSocket +applications. + + + +[[websocket-intro]] +=== Introduction +The WebSocket protocol http://tools.ietf.org/html/rfc6455[RFC 6455] defines an important +new capability for web applications: full-duplex, two-way communication between client +and server. It is an exciting new capability on the heels of a long history of +techniques to make the web more interactive including Java applets, XMLHttpRequest, +Adobe Flash, ActiveXObject, various Comet techniques, server-sent events, and others. + +A proper introduction of the WebSocket protocol is beyond the scope of this +document. At a minimum however it's important to understand that HTTP is used only for +the initial handshake, which relies on a mechanism built into HTTP to request +a protocol upgrade (or in this case a protocol switch) to which the server can respond with +HTTP status 101 (switching protocols) if it agrees. Assuming the handshake succeeds +the TCP socket underlying the HTTP upgrade request remains open and both client and +server can use it to send messages to each other. + +Spring Framework 4 includes a new `spring-websocket` module with comprehensive +WebSocket support. It is compatible with the Java WebSocket API standard +(http://jcp.org/en/jsr/detail?id=356[JSR-356]) +and also provides additional value-add as explained in the rest of the introduction. + + + +[[websocket-into-fallback-options]] +==== WebSocket Fallback Options +An important challenge to adoption is the lack of support for WebSocket in some +browsers. Notably the first Internet Explorer version to support WebSocket is +version 10 (see http://caniuse.com/websockets for support by browser versions). +Furthermore, some restrictive proxies +may be configured in ways that either preclude the attempt to do HTTP upgrade +or otherwise break connection after some time because it has remained opened +for too long. A good overview on this topic from Peter Lubbers is available in +the InfoQ article +http://www.infoq.com/articles/Web-Sockets-Proxy-Servers["How HTML5 Web Sockets Interact With Proxy Servers"]. + + +Therefore to build a WebSocket application today, fallback options are required +to simulate the WebSocket API where necessary. +Spring Framework provides such transparent fallback +options based on the https://github.com/sockjs/sockjs-protocol[SockJS protocol]. +These options can be enabled through configuration and do not require +modifying the application otherwise. + + + +[[websocket-intro-architecture]] +==== A Messaging Architecture +Aside from short-to-midterm adoption challenges, using WebSocket +brings up important design considerations that are important to recognize +early on, especially in contrast to what we know about building web applications today. + +Today REST is a widely accepted, understood, and supported +architecture for building web applications. It is an architecture that relies +on having many URLs (__nouns__), a handful of HTTP methods (__verbs__), and +other principles such as using hypermedia (__links__), remaining stateless, etc. + +By contrast a WebSocket application may use a single URL only for the +initial HTTP handshake. All messages thereafter share and flow on the +same TCP connection. This points to an entirely different, asynchronous, +event-driven, messaging architecture. One that is much closer +to traditional messaging applications (e.g. JMS, AMQP). + +Spring Framework 4 includes a new `spring-messaging` module with key +abstractions from the +http://projects.spring.io/spring-integration/[Spring Integration] project +such as `Message`, `MessageChannel`, `MessageHandler` and others that can serve as +a foundation for such a messaging architecture. The module also includes a +set of annotations for mapping messages to methods, similar to the Spring MVC +annotation based programming model. + + + +[[websocket-intro-sub-protocol]] +==== Sub-Protocol Support in WebSocket +WebSocket does imply a __messaging architecture__ but does not mandate the +use of any specific __messaging protocol__. It is a very thin layer over TCP +that transforms a stream of bytes into a stream of messages +(either text or binary) and not much more. It is up to applications +to interpret the meaning of a message. + +Unlike HTTP, which is an application-level protocol, in the WebSocket protocol +there is simply not enough information in an incoming message for a framework +or container to know how to route it or process it. Therefore WebSocket is arguably +too low level for anything but a very trivial application. It can be done, but +it will likely lead to creating a framework on top. This is comparable to how +most web applications today are written using a web framework rather than the +Servlet API alone. + +For this reason the WebSocket RFC defines the use of +http://tools.ietf.org/html/rfc6455#section-1.9[sub-protocols]. +During the handshake, client and server can use the header +`Sec-WebSocket-Protocol` to agree on a sub-protocol, i.e. a higher, application-level +protocol to use. The use of a sub-protocol is not required, but +even if not used, applications will still need to choose a message +format that both client and server can understand. That format can be custom, +framework-specific, or a standard messaging protocol. + +Spring Framework provides support for using +http://stomp.github.io/stomp-specification-1.2.html#Abstract[STOMP] -- a simple, messaging protocol +originally created for use in scripting languages with frames inspired +by HTTP. STOMP is widely support and well suited for use over +WebSocket and over the web. + + + +[[websocket-intro-when-to-use]] +==== Should I Use WebSocket? +With all the design considerations surrounding the use of WebSocket, it is +reasonable to ask when is it appropriate to use? + +The best fit for WebSocket is in web applications where client and +server need to exchange events at high frequency and at low latency. Prime +candidates include but are not limited to applications in finance, games, +collaboration, and others. Such applications are both very sensitive to time +delays and also need to exchange a wide variety of messages at high +frequency. + +For other application types, however, this may not be the case. +For example, a news or social feed that shows breaking news as they become +available may be perfectly okay with simple polling once every few minutes. +Here latency is important, but it is acceptable if the news takes a +few minutes to appear. + +Even in cases where latency is crucial, if the volume of messages is +relatively low (e.g. monitoring network failures) the use of +https://spring.io/blog/2012/05/08/spring-mvc-3-2-preview-techniques-for-real-time-updates[long polling] +should be considered as a relatively simple alternative that +works reliably and is comparable by efficiency (again assuming the volume of +messages is relatively low). + +It is the combination of both low latency and high frequency of messages that can make +the use of the WebSocket protocol critical. Even in such applications, +the choice remains whether all client-server +communication should be done through WebSocket messages as opposed to using +HTTP and REST? The answer is going to vary by application, however, it is likely +that some functionality may be exposed over both WebSocket and as a REST API in +order to provide clients with alternatives. Furthermore, a REST API call may need +to broadcast a message to interested clients connected via WebSocket. + +Spring Framework allows `@Controller` and `@RestController` classes to have both +HTTP request handling and WebSocket message handling methods. +Furthermore, a Spring MVC request handling method, or any application +method for that matter, can easily broadcast a message to all interested +WebSocket clients or to a specific user. + + + + +[[websocket-server]] +=== WebSocket API +The Spring Framework provides a WebSocket API designed to adapt to various WebSocket engines. +For example, it runs on JSR-356 runtimes such as Tomcat (7.0.47+), GlassFish (4.0+) and +WildFly (8.0+) but can also adapt to other WebSocket runtimes such as the Jetty (9.1+) +native WebSocket support. + +[NOTE] +==== +As explained in the <>, direct use of a +WebSocket API is too low level for applications -- until assumptions are made about the +format of a message there is little a framework can do to interpret messages or route +them via annotations. This is why applications should consider using a sub-protocol +and Spring's <> support. + +When using a higher level protocol, the details of the WebSocket API become less +relevant, much like the details of TCP communication are not exposed to applications +when using HTTP. Nevertheless this section covers the details of using WebSocket +directly. +==== + + + +[[websocket-server-handler]] +==== Create and Configure a WebSocketHandler +Creating a WebSocket server is as simple as implementing `WebSocketHandler` or more +likely extending either `TextWebSocketHandler` or `BinaryWebSocketHandler`: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + import org.springframework.web.socket.WebSocketHandler; + import org.springframework.web.socket.WebSocketSession; + import org.springframework.web.socket.TextMessage; + + public class MyHandler extends TextWebSocketHandler { + + @Override + public void handleTextMessage(WebSocketSession session, TextMessage message) { + // ... + } + + } +---- + +There is dedicated WebSocket Java-config and XML namespace support for mapping the above +WebSocket handler at a specific URL: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + import org.springframework.web.socket.config.annotation.EnableWebSocket; + import org.springframework.web.socket.config.annotation.WebSocketConfigurer; + import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry; + + @Configuration + @EnableWebSocket + public class WebSocketConfig implements WebSocketConfigurer { + + @Override + public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { + registry.addHandler(myHandler(), "/myHandler"); + } + + @Bean + public WebSocketHandler myHandler() { + return new MyHandler(); + } + + } +---- + +XML configuration equivalent: + +[source,xml,indent=0] +[subs="verbatim,quotes,attributes"] +---- + + + + + + + + + +---- + +The above is for use in Spring MVC applications and should be included in the +configuration of a <>. However, Spring's WebSocket +support does not depend on Spring MVC. It is relatively simple to integrate a `WebSocketHandler` +into other HTTP serving environments with the help of +{javadoc-baseurl}/org/springframework/web/socket/server/support/WebSocketHttpRequestHandler.html[WebSocketHttpRequestHandler]. + + + +[[websocket-server-handshake]] +==== Customizing the WebSocket Handshake +The easiest way to customize the initial HTTP WebSocket handshake request is through +a `HandshakeInterceptor`, which exposes "before" and "after" the handshake methods. +Such an interceptor can be used to preclude the handshake or to make any attributes +available to the `WebSocketSession`. For example, there is a built-in interceptor +for passing HTTP session attributes to the WebSocket session: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Configuration + @EnableWebSocket + public class WebSocketConfig implements WebSocketConfigurer { + + @Override + public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { + registry.addHandler(new MyHandler(), "/myHandler") + .addInterceptors(new HttpSessionHandshakeInterceptor()); + } + + } +---- + +And the XML configuration equivalent: + +[source,xml,indent=0] +[subs="verbatim,quotes,attributes"] +---- + + + + + + + + + + + + +---- + +A more advanced option is to extend the `DefaultHandshakeHandler` that performs +the steps of the WebSocket handshake, including validating the client origin, +negotiating a sub-protocol, and others. An application may also need to use this +option if it needs to configure a custom `RequestUpgradeStrategy` in order to +adapt to a WebSocket server engine and version that is not yet supported +(also see <> for more on this subject). +Both the Java-config and XML namespace make it possible to configure a custom +`HandshakeHandler`. + + + +[[websocket-server-decorators]] +==== WebSocketHandler Decoration +Spring provides a `WebSocketHandlerDecorator` base class that can be used to decorate +a `WebSocketHandler` with additional behavior. Logging and exception handling +implementations are provided and added by default when using the WebSocket Java-config +or XML namespace. The `ExceptionWebSocketHandlerDecorator` catches all uncaught +exceptions arising from any WebSocketHandler method and closes the WebSocket +session with status `1011` that indicates a server error. + + + +[[websocket-server-deployment]] +==== Deployment Considerations +The Spring WebSocket API is easy to integrate into a Spring MVC application where +the `DispatcherServlet` serves both HTTP WebSocket handshake as well as other +HTTP requests. It is also easy to integrate into other HTTP processing scenarios +by invoking `WebSocketHttpRequestHandler`. This is convenient and easy to +understand. However, special considerations apply with regards to JSR-356 runtimes. + +The Java WebSocket API (JSR-356) provides two deployment mechanisms. The first +involves a Servlet container classpath scan (Servlet 3 feature) at startup; and +the other is a registration API to use at Servlet container initialization. +Neither of these mechanism make it possible to use a single "front controller" +for all HTTP processing -- including WebSocket handshake and all other HTTP +requests -- such as Spring MVC's `DispatcherServlet`. + +This is a significant limitation of JSR-356 that Spring's WebSocket support +addresses by providing a server-specific `RequestUpgradeStrategy` even when +running in a JSR-356 runtime. At present such support is available on +Tomcat 7.0.47+, Jetty 9.1+, GlassFish 4.0+, and WildFly 8.0+. Additional support will be +added as more WebSocket runtimes become available. + +[NOTE] +==== +A request to overcome the above limitation in the Java WebSocket API has been +created and can be followed at +https://java.net/jira/browse/WEBSOCKET_SPEC-211[WEBSOCKET_SPEC-211]. +Also note that Tomcat and Jetty already provide native API alternatives that +makes it easy to overcome the limitation. We are hopeful that more servers +will follow their example regardless of when it is addressed in the +Java WebSocket API. +==== + +A secondary consideration is that Servlet containers with JSR-356 support +are expected to perform an SCI scan that can slow down application startup, +in some cases dramatically. If a significant impact is observed after an +upgrade to a Servlet container version with JSR-356 support, it should +be possible to selectively enable or disable web fragments (and SCI scanning) +through the use of an `` element in `web.xml`: + +[source,xml,indent=0] +[subs="verbatim,quotes,attributes"] +---- + + + + + +---- + +You can then selectively enable web fragments by name, such as Spring's own +`SpringServletContainerInitializer` that provides support for the Servlet 3 +Java initialization API, if required: + +[source,xml,indent=0] +[subs="verbatim,quotes,attributes"] +---- + + + + spring_web + + + +---- + +[[websocket-server-runtime-configuration]] +==== Configuring the WebSocket Engine + +Each underlying WebSocket engine exposes configuration properties that control +runtime characteristics such as the size of message buffer sizes, idle timeout, +and others. + +For Tomcat, WildFly, and Glassfish add a `ServletServerContainerFactoryBean` to your +WebSocket Java config: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Configuration + @EnableWebSocket + public class WebSocketConfig implements WebSocketConfigurer { + + @Bean + public ServletServerContainerFactoryBean createWebSocketContainer() { + ServletServerContainerFactoryBean container = new ServletServerContainerFactoryBean(); + container.setMaxTextMessageBufferSize(8192); + container.setMaxBinaryMessageBufferSize(8192); + return container; + } + + } +---- + +or WebSocket XML namespace: + +[source,xml,indent=0] +[subs="verbatim,quotes,attributes"] +---- + + + + + + + + +---- + +[NOTE] +==== +For client side WebSocket configuration, you should use `WebSocketContainerFactoryBean` +(XML) or `ContainerProvider.getWebSocketContainer()` (Java config). +==== + +For Jetty, you'll need to supply a pre-configured Jetty `WebSocketServerFactory` and plug +that into Spring's `DefaultHandshakeHandler` through your WebSocket Java config: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Configuration + @EnableWebSocket + public class WebSocketConfig implements WebSocketConfigurer { + + @Override + public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { + registry.addHandler(echoWebSocketHandler(), + "/echo").setHandshakeHandler(handshakeHandler()); + } + + @Bean + public DefaultHandshakeHandler handshakeHandler() { + + WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.SERVER); + policy.setInputBufferSize(8192); + policy.setIdleTimeout(600000); + + return new DefaultHandshakeHandler( + new JettyRequestUpgradeStrategy(new WebSocketServerFactory(policy))); + } + + } +---- + +or WebSocket XML namespace: + +[source,xml,indent=0] +[subs="verbatim,quotes,attributes"] +---- + + + + + + + + + + + + + + + + + + + + + + + + + + +---- + + + + +[[websocket-fallback]] +=== SockJS Fallback Options +As explained in the <>, WebSocket is not +supported in all browsers yet and may be precluded by restrictive network proxies. +This is why Spring provides fallback options that emulate the WebSocket API as close +as possible based on the https://github.com/sockjs/sockjs-protocol[SockJS protocol]. + +[[websocket-fallback-sockjs-overview]] +==== Overview of SockJS + +The goal of SockJS is to let applications use a WebSocket API but fall back to +non-WebSocket alternatives when necessary at runtime, i.e. without the need to +change application code. + +SockJS consists of: + +* The https://github.com/sockjs/sockjs-protocol[SockJS protocol] +defined in the form of executable +http://sockjs.github.io/sockjs-protocol/sockjs-protocol-0.3.3.html[narrated tests]. +* The https://github.com/sockjs/sockjs-client[SockJS JavaScript client] - a client library for use in browsers. +* SockJS server implementations including one in the Spring Framework `spring-websocket` module. +* As of 4.1 `spring-websocket` also provides a SockJS Java client. + +SockJS is designed for use in browsers. It goes to great lengths +to support a wide range of browser versions using a variety of techniques. +For the full list of SockJS transport types and browsers see the +https://github.com/sockjs/sockjs-client[SockJS client] page. Transports +fall in 3 general categories: WebSocket, HTTP Streaming, and HTTP Long Polling. +For an overview of these categories see +https://spring.io/blog/2012/05/08/spring-mvc-3-2-preview-techniques-for-real-time-updates/[this blog post]. + +The SockJS client begins by sending `"GET /info"` to +obtain basic information from the server. After that it must decide what transport +to use. If possible WebSocket is used. If not, in most browsers +there is at least one HTTP streaming option and if not then HTTP (long) +polling is used. + +All transport requests have the following URL structure: +---- +http://host:port/myApp/myEndpoint/{server-id}/{session-id}/{transport} +---- + +* `{server-id}` - useful for routing requests in a cluster but not used otherwise. +* `{session-id}` - correlates HTTP requests belonging to a SockJS session. +* `{transport}` - indicates the transport type, e.g. "websocket", "xhr-streaming", etc. + +The WebSocket transport needs only a single HTTP request to do the WebSocket handshake. +All messages thereafter are exchanged on that socket. + +HTTP transports require more requests. Ajax/XHR streaming for example relies on +one long-running request for server-to-client messages and additional HTTP POST +requests for client-to-server messages. Long polling is similar except it +ends the current request after each server-to-client send. + +SockJS adds minimal message framing. For example the server sends the letter +o+ +("open" frame) initially, messages are sent as +a["message1","message2"]+ +(JSON-encoded array), the letter +h+ ("heartbeat" frame) if no messages flow +for 25 seconds by default, and the letter +c+ ("close" frame) to close the session. + +To learn more run an example in a browser and watch HTTP requests. +The SockJS client allows fixing the list of transports so it is possible to +see each transport one at a time. The SockJS client also provides a debug flag +which enables helpful messages in the browser console. On the server side enable +TRACE logging for `org.springframework.web.socket`. +For even more detail refer to the SockJS protocol +http://sockjs.github.io/sockjs-protocol/sockjs-protocol-0.3.3.html[narrated test]. + + +[[websocket-fallback-sockjs-enable]] +==== Enable SockJS +SockJS is easy to enable through a configuration: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Configuration + @EnableWebSocket + public class WebSocketConfig implements WebSocketConfigurer { + + @Override + public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { + registry.addHandler(myHandler(), "/myHandler").withSockJS(); + } + + @Bean + public WebSocketHandler myHandler() { + return new MyHandler(); + } + + } +---- + +and the XML configuration equivalent: + +[source,xml,indent=0] +[subs="verbatim,quotes,attributes"] +---- + + + + + + + + + + +---- + +The above is for use in Spring MVC applications and should be included in the +configuration of a <>. However, Spring's WebSocket +and SockJS support does not depend on Spring MVC. It is relatively simple to +integrate into other HTTP serving environments with the help of +{javadoc-baseurl}/org/springframework/web/socket/sockjs/support/SockJsHttpRequestHandler.html[SockJsHttpRequestHandler]. + +On the browser side, applications can use the +https://github.com/sockjs/sockjs-client[sockjs-client] that emulates the W3C +WebSocket API and communicates with the server to select the best +transport option depending on the browser it's running in. Review the +https://github.com/sockjs/sockjs-client[sockjs-client] page and the list of +transport types supported by browser. The client also provides several +configuration options, for example, to specify which transports to include. + +[[websocket-fallback-xhr-vs-iframe]] +==== HTTP Streaming in IE 8, 9: Ajax/XHR vs IFrame + +Internet Explorer 8 and 9 are and will remain common for some time. They are +a key reason for having SockJS. This section covers important +considerations about running in those browsers. + +SockJS client supports Ajax/XHR streaming in IE 8, 9 via Microsoft's +http://blogs.msdn.com/b/ieinternals/archive/2010/05/13/xdomainrequest-restrictions-limitations-and-workarounds.aspx[XDomainRequest]. +That works across domains but does not support sending cookies. +Cookies are very often essential for Java applications. +However since the SockJS client can be used with many server +types (not just Java ones), it needs to know whether cookies do matter. +If so the SockJS client prefers Ajax/XHR for streaming or otherwise it +relies on a iframe-based technique. + +The very first `"/info"` request from the SockJS client is a request for +information that can influence the client's choice of transports. +One of those details is whether the server application relies on cookies, +e.g. for authentication purposes or clustering with sticky sessions. +Spring's SockJS support includes a property called `sessionCookieNeeded`. +It is enabled by default since most Java applications rely on the `JSESSIONID` +cookie. If your application does not need it, you can turn off this option +and the SockJS client should choose `xdr-streaming` in IE 8 and 9. + +If you do use an iframe-based transport, and in any case, it is good to know +that browsers can be instructed to block the use of iframes on a given page by +setting the HTTP response header `X-Frame-Options` to `DENY`, +`SAMEORIGIN`, or `ALLOW-FROM `. This is used to prevent +https://www.owasp.org/index.php/Clickjacking[clickjacking]. + +[NOTE] +==== +Spring Security 3.2+ provides support for setting `X-Frame-Options` on every +response. By default the Spring Security Java config sets it to `DENY`. +In 3.2 the Spring Security XML namespace does not set that header by default +but may be configured to do so, and in the future it may set it by default. + +See http://docs.spring.io/spring-security/site/docs/3.2.2.RELEASE/reference/htmlsingle/#headers[Section 7.1. "Default Security Headers"] +of the Spring Security documentation for details no how to configure the +setting of the `X-Frame-Options` header. You may also check or watch +https://jira.spring.io/browse/SEC-2501[SEC-2501] for additional background. +==== + +If your application adds the `X-Frame-Options` response header (as it should!) +and relies on an iframe-based transport, you will need to set the header value to +`SAMEORIGIN` or `ALLOW-FROM `. Along with that the Spring SockJS +support also needs to know the location of the SockJS client because it is loaded +from the iframe. By default the iframe is set to download the SockJS client +from a CDN location. It is a good idea to configure this option to +a URL from the same origin as the application. + +In Java config this can be done as shown below. The XML namespace provides a +similar option on the `` element: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Configuration + @EnableWebSocket + public class WebSocketConfig implements WebSocketConfigurer { + + @Override + public void registerStompEndpoints(StompEndpointRegistry registry) { + registry.addEndpoint("/portfolio").withSockJS() + .setClientLibraryUrl("http://localhost:8080/myapp/js/sockjs-client.js"); + } + + // ... + + } +---- + +[NOTE] +==== +During initial development, do enable the SockJS client `devel` mode that prevents +the browser from caching SockJS requests (like the iframe) that would otherwise +be cached. For details on how to enable it see the +https://github.com/sockjs/sockjs-client[SockJS client] page. +==== + +[[websocket-fallback-sockjs-heartbeat]] +==== Heartbeat Messages + +The SockJS protocol requires servers to send heartbeat messages to preclude proxies +from concluding a connection is hung. The Spring SockJS configuiration has a property +called `heartbeatTime` that can be used to customize the frequency. By default a +heartbeat is sent after 25 seconds assuming no other messages were sent on that +connection. This 25 seconds value is in line with the following +http://tools.ietf.org/html/rfc6202[IETF recommendation] for public Internet applications. + +[NOTE] +==== +When using STOMP over WebSocket/SockJS, if the STOMP client and server negotiate +heartbeats to be exchanged, the SockJS heartbeats are disabled. +==== + +The Spring SockJS support also allows configuring the `TaskScheduler` to use +for scheduling heartbeats tasks. The task scheduler is backed by a thread pool +with default settings based on the number of available processors. Applications +should consider customizing the settings according to their specific needs. + +[[websocket-fallback-sockjs-servlet3-async]] +==== Servlet 3 Async Requests + +HTTP streaming and HTTP long polling SockJS transports require a connection to remain +open longer than usual. For an overview of these techniques see +https://spring.io/blog/2012/05/08/spring-mvc-3-2-preview-techniques-for-real-time-updates/[this blog post]. + +In Servlet containers this is done through Servlet 3 async support that +allows exiting the Servlet container thread processing a request and continuing +to write to the response from another thread. + +A specific issue is the Servlet API does not provide notifications for a client +that has gone away, see https://java.net/jira/browse/SERVLET_SPEC-44[SERVLET_SPEC-44]. +However, Servlet containers raise an exception on subseqeunt attempts to write +to the response. Since Spring's SockJS Service support sever-sent heartbeats (every +25 seconds by default), that means a client disconnect is usually detected within that +time period or earlier if a message are sent more frequently. + +[NOTE] +==== +As a result network IO failures may occur simply because a client has disconnected, which +can fill the log with unnecessary stack traces. Spring makes a best effort to identify +such network failures that represent client disconnects (specific to each server) and log +a more minimal message using the dedicated log category `DISCONNECTED_CLIENT_LOG_CATEGORY` +defined in `AbstractSockJsSession`. If you need to see the stack traces, set that +log category to TRACE. +==== + +[[websocket-fallback-cors]] +==== CORS Headers for SockJS + +The SockJS protocol uses CORS for cross-domain support in the XHR streaming and +polling transports. Therefore CORS headers are added automatically unless the +presence of CORS headers in the response is detected. So if an application is +already configured to provide CORS support, e.g. through a Servlet Filter, +Spring's SockJsService will skip this part. + +The following is the list of headers and values expected by SockJS: + +* `"Access-Control-Allow-Origin"` - intitialized from the value of the "origin" request header or "*". +* `"Access-Control-Allow-Credentials"` - always set to `true`. +* `"Access-Control-Request-Headers"` - initialized from values from the equivalent request header. +* `"Access-Control-Allow-Methods"` - the HTTP methods a transport supports (see `TransportType` enum). +* `"Access-Control-Max-Age"` - set to 31536000 (1 year). + +For the exact implementation see `addCorsHeaders` in `AbstractSockJsService` as well +as the `TransportType` enum in the source code. + +Alternatively if the CORS configuration allows it consider excluding URLs with the +SockJS endpoint prefix thus letting Spring's SockJsService handle it. + + +[[websocket-fallback-sockjs-client]] +==== SockJS Client + +A SockJS Java client is provided in order to connect to remote SockJS endpoints without +using a browser. This can be especially useful when there is a need of bidirectional +communication between 2 servers over a public network, i.e. where network proxies may +preclude the use of the WebSocket protocol. A SockJS Java client is also very useful +for testing purposes for example to simulate a large number of concurrent users. + +The SockJS Java client supports the "websocket", "xhr-streaming", and "xhr-polling" +transports. The remaining ones only make sense for use in a browser. + +The `WebSocketTransport` can be configured with: + +* `StandardWebSocketClient` in a JSR-356 runtime +* `JettyWebSocketClient` using the Jetty 9+ native WebSocket API +* Any implementation of Spring's `WebSocketClient` + +An `XhrTransport` by definition supports both "xhr-streaming" and "xhr-polling" since +from a client perspective there is no difference other than in the URL used to connect +to the server. At present there are two implementations: + +* `RestTemplateXhrTransport` uses the RestTemplate for HTTP requests. +* `JettyXhrTransport` uses Jetty's HttpClient for HTTP requests. + +The example below shows how to create a SockJS client and connect to a SockJS endpoint: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + List transports = new ArrayList<>(2); + transports.add(new WebSocketTransport(StandardWebSocketClient())); + transports.add(new RestTemplateXhrTransport()); + + SockJsClient sockJsClient = new SockJsClient(transports); + sockJsClient.doHandshake(new MyWebSocketHandler(), "ws://example.com:8080/sockjs"); +---- + +[NOTE] +==== +SockJS uses JSON formatted arrays for messages. By default Jackson 2 is used and needs +to be on the classpath. Alternatively you can configure a custom implementation of +`SockJsMessageCodec` and configure it on the SockJsClient. +==== + +To use the SockJsClient for simulating a large number of concurrent users you will +need to configure the underlying HTTP client (for XHR transports) to allow a sufficient +number of connections and threads. For example with Jetty: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- +HttpClient jettyHttpClient = new HttpClient(); +jettyHttpClient.setMaxConnectionsPerDestination(1000); +jettyHttpClient.setExecutor(new QueuedThreadPool(1000)); +---- + +Consider also customizing these server-side SockJS related properties (see Javadoc for details): + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- +@Configuration +public class WebSocketConfig extends WebSocketMessageBrokerConfigurationSupport { + + @Override + public void registerStompEndpoints(StompEndpointRegistry registry) { + registry.addEndpoint("/sockjs").withSockJS() + .setStreamBytesLimit(512 * 1024) + .setHttpMessageCacheSize(1000) + .setDisconnectDelay(30 * 1000); + } + + // ... + +} +---- + + + + +[[websocket-stomp]] +=== STOMP Over WebSocket Messaging Architecture +The WebSocket protocol defines two main types of messages -- text and binary -- +but leaves their content undefined. Instead it's expected that client and +server may agree on using a sub-protocol, i.e. a higher-level protocol that defines +the message content. Using a sub-protocol is optional but either way client +and server both need to understand how to interpret messages. + + + +[[websocket-stomp-overview]] +==== Overview of STOMP +http://stomp.github.io/stomp-specification-1.2.html#Abstract[STOMP] is a simple +messaging protocol originally created for scripting languages (such as Ruby, Python and +Perl) to connect to enterprise message brokers. It is designed to address a +subset of commonly used patterns in messaging protocols. STOMP can be used over +any reliable 2-way streaming network protocol such as TCP and WebSocket. + +STOMP is a frame based protocol with frames modelled on HTTP. This is the +structure of a frame: + +---- +COMMAND +header1:value1 +header2:value2 + +Body^@ +---- + +For example, a client can use the +SEND+ command to send a message or the ++SUBSCRIBE+ command to express interest in receiving messages. Both of these commands +require a +"destination"+ header that indicates where to send a message to, or likewise +what to subscribe to. + +Here is an example of a client sending a request to buy stock shares: + +---- +SEND +destination:/queue/trade +content-type:application/json +content-length:44 + +{"action":"BUY","ticker":"MMM","shares",44}^@ +---- + +Here is an example of a client subscribing to receive stock quotes: +---- +SUBSCRIBE +id:sub-1 +destination:/topic/price.stock.* + +^@ +---- + +[NOTE] +==== +The meaning of a destination is intentionally left opaque in the STOMP spec. It can +be any string and it's entirely up to STOMP servers to define the semantics and +the syntax of the destinations that they support. It is very common however, for +destinations to be path-like strings where `"/topic/.."` implies publish-subscribe +(__one-to-many__) and `"/queue/"` to implies point-to-point (__one-to-one__) message +exchanges. +==== + +STOMP servers can use the +MESSAGE+ command to broadcast messages to all subscribers. +Here is an example of a server sending a stock quote to a subscribed client: + +---- +MESSAGE +message-id:nxahklf6-1 +subscription:sub-1 +destination:/topic/price.stock.MMM + +{"ticker":"MMM","price":129.45}^@ +---- + +[NOTE] +==== +It's important to know that a server cannot send unsolicited messages. +All messages from a server must be in response to a specific client subscription +and the +"subscription-id"+ header of the server message must match +the +"id"+ header of the client subscription. +==== + +The above overview is intended to provide the most basic understanding of the +STOMP protocol. It is recommended to review the protocol +http://stomp.github.io/stomp-specification-1.2.html[specification], which is +easy to follow and manageable in terms of size. + +The following summarizes the benefits for an application from using STOMP over WebSocket: + +* Standard message format +* Application-level protocol with support for common messaging patterns +* Client-side support, e.g. https://github.com/jmesnil/stomp-websocket[stomp.js], https://github.com/cujojs/msgs[msgs.js] +* The ability to interpret, route, and process messages on both client and server-side +* The option to plug a message broker -- RabbitMQ, ActiveMQ, many others -- to broadcast messages (explained later) + +Most importantly the use of STOMP (vs plain WebSocket) enables the Spring Framework +to provide a programming model for application-level use in the same way that +Spring MVC provides a programming model based on HTTP. + + + +[[websocket-stomp-enable]] +==== Enable STOMP over WebSocket +The Spring Framework provides support for using STOMP over WebSocket through +the +spring-messaging+ and +spring-websocket+ modules. It's easy to enable it. + +Here is an example of configuring a STOMP WebSocket endpoint with SockJS fallback +options. The endpoint is available for clients to connect to at URL path `/app/portfolio`: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker; + import org.springframework.web.socket.config.annotation.StompEndpointRegistry; + + @Configuration + @EnableWebSocketMessageBroker + public class WebSocketConfig implements WebSocketMessageBrokerConfigurer { + + @Override + public void configureMessageBroker(MessageBrokerRegistry config) { + config.setApplicationDestinationPrefixes("/app"); + config.enableSimpleBroker("/queue", "/topic"); + } + + @Override + public void registerStompEndpoints(StompEndpointRegistry registry) { + registry.addEndpoint("/portfolio").withSockJS(); + } + + // ... + + } +---- + +XML configuration equivalent: + +[source,xml,indent=0] +[subs="verbatim,quotes,attributes"] +---- + + + + + + + + ... + + + +---- + +On the browser side, a client might connect as follows using +https://github.com/jmesnil/stomp-websocket[stomp.js] and the +https://github.com/sockjs/sockjs-client[sockjs-client]: + +[source,javascript,indent=0] +[subs="verbatim,quotes"] +---- + var socket = new SockJS("/spring-websocket-portfolio/portfolio"); + var stompClient = Stomp.over(socket); + + stompClient.connect({}, function(frame) { + } +---- + +Or if connecting via WebSocket (without SockJS): + +[source,javascript,indent=0] +[subs="verbatim,quotes"] +---- + var socket = new WebSocket("/spring-websocket-portfolio/portfolio"); + var stompClient = Stomp.over(socket); + + stompClient.connect({}, function(frame) { + } +---- + +Note that the stompClient above does not need to specify a `login` and `passcode` headers. +Even if it did, they would be ignored, or rather overridden, on the server side. See the +sections <> and +<> for more information on authentication. + + +[[websocket-stomp-message-flow]] +==== Flow of Messages + +When a STOMP endpoint is configured, the Spring application acts as the STOMP broker +to connected clients. It handles incoming messages and sends messages back. +This section provides a big picture overview of how messages flow inside the application. + +The `spring-messaging` module contains a number of abstractions that originated in the +https://spring.io/spring-integration[Spring Integration] project and are intended +for use as building blocks in messaging applications: + +* {javadoc-baseurl}/org/springframework/messaging/Message.html[Message] -- +represents a message with headers and a payload. +* {javadoc-baseurl}/org/springframework/messaging/MessageHandler.html[MessageHandler] -- +a contract for handling a message. +* {javadoc-baseurl}/org/springframework/messaging/MessageChannel.html[MessageChannel] -- +a contract for sending a message enabling loose coupling between senders and receivers. +* {javadoc-baseurl}/org/springframework/messaging/SubscribableChannel.html[SubscribableChannel] -- +extends `MessageChannel` and sends messages to registered `MessageHandler` subscribers. +* {javadoc-baseurl}/org/springframework/messaging/support/ExecutorSubscribableChannel.html[ExecutorSubscribableChannel] -- +a concrete implementation of `SubscribableChannel` that can deliver messages +asynchronously through a thread pool. + +The provided STOMP over WebSocket config, both Java and XML, uses the above to +assemble a concrete message flow including the following 3 channels: + +* `"clientInboundChannel"` -- for messages from WebSocket clients. Every incoming +WebSocket message carrying a STOMP frame is sent through this channel. +* `"clientOutboundChannel"` -- for messages to WebSocket clients. Every outgoing +STOMP message from the broker is sent through this channel before getting sent +to a client's WebSocket session. +* `"brokerChannel"` -- for messages to the broker from within the application. +Every message sent from the application to the broker passes through this channel. + +Messages on the `"clientInboundChannel"` can flow to annotated +methods for application handling (e.g. a stock trade execution request) or can +be forwarded to the broker (e.g. client subscribing for stock quotes). +The STOMP destination is used for simple prefix-based routing. For example +the "/app" prefix could route messages to annotated methods while the "/topic" +and "/queue" prefixes could route messages to the broker. + +When a message-handling annotated method has a return type, its return +value is sent as the payload of a Spring Message to the `"brokerChannel"`. +The broker in turn broadcasts the message to clients. Sending a message +to a destination can also be done from anywhere in the application with +the help of a messaging template. For example a an HTTP POST handling method +can broadcast a message to connected clients or a service component may +periodically broadcast stock quotes. + +Below is a simple example to illustrate the flow of messages: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Configuration + @EnableWebSocketMessageBroker + public class WebSocketConfig implements WebSocketMessageBrokerConfigurer { + + @Override + public void registerStompEndpoints(StompEndpointRegistry registry) { + registry.addEndpoint("/portfolio"); + } + + @Override + public void configureMessageBroker(MessageBrokerRegistry registry) { + registry.setApplicationDestinationPrefixes("/app"); + registry.enableSimpleBroker("/topic"); + } + + } + + @Controller + public class GreetingController { + + @MessageMapping("/greeting") { + public String handle(String greeting) { + return "[" + getTimestamp() + ": " + greeting; + } + + } + +---- + +The following explains the message flow for the above exmaple: + +* WebSocket clients connect to the WebSocket endpoint at "/portfolio". +* Subscriptions to "/topic/greeting" pass through the "clientInboundChannel" +and are forwarded to the broker. +* Greetings sent to "/app/greeting" pass through the "clientInboundChannel" +and are forwarded to the `GreetingController`. The controller adds the current +time and the return value is passed through the "brokerChannel" as message +to "/topic/greeting" (destination is selected based on a convention but can be +overridden via `@SendTo`). +* The broker in turn broadcasts messages to subscribers and they pass through +the `"clientOutboundChannel"`. + +The next section provides more details on annotated methods including the +kinds of arguments and return values supported. + + + +[[websocket-stomp-handle-annotations]] +==== Annotation Message Handling + +The `@MessageMapping` annotation is supported on methods of `@Controller` classes. +It can be used for mapping methods to message destinations and can also be combined +with the type-level `@MessageMapping` for expressing shared mappings across all +annotated methods within a controller. + +By default destination mappings are treated as Ant-style, slash-separated, path +patterns, e.g. "/foo*", "/foo/**". etc. They can also contain template variables, +e.g. "/foo/{id}" that can then be referenced via `@DestinationVariable`-annotated +method arguments. + +[NOTE] +==== +Applications can also use dot-separated destinations (vs slash). +See <>. +==== + +The following method arguments are supported for `@MessageMapping` methods: + +* `Message` method argument to get access to the complete message being processed. +* `@Payload`-annotated argument for access to the payload of a message, converted with +a `org.springframework.messaging.converter.MessageConverter`. +The presence of the annotation is not required since it is assumed by default. +Payload method arguments annotated with Validation annotations (like `@Validated`) will +be subject to JSR-303 validation. +* `@Header`-annotated arguments for access to a specific header value along with +type conversion using an `org.springframework.core.convert.converter.Converter` +if necessary. +* `@Headers`-annotated method argument that must also be assignable to `java.util.Map` +for access to all headers in the message. +* `MessageHeaders` method argument for getting access to a map of all headers. +* `MessageHeaderAccessor`, `SimpMessageHeaderAccessor`, or `StompHeaderAccessor` +for access to headers via typed accessor methods. +* `@DestinationVariable`-annotated arguments for access to template +variables extracted from the message destination. Values will be converted to +the declared method argument type as necessary. +* `java.security.Principal` method arguments reflecting the user logged in at +the time of the WebSocket HTTP handshake. + +The return value from an `@MessageMapping` method is converted with a +`org.springframework.messaging.converter.MessageConverter` and used as the body +of a new message that is then sent, by default, to the `"brokerChannel"` with +the same destination as the client message but using the prefix "/topic" by +default. An `@SendTo` message level annotation can be used to specify any +other destination instead. + +An `@SubscribeMapping` annotation can also be used to map subscription requests +to `@Controller` methods. It is supported on the method level, but can also be +combined with a type level `@MessageMapping` annotation that expresses shared +mappings across all message handling methods within the same controller. + +By default the return value from an `@SubscribeMapping` method is sent as a +message directly back to the connected client and does not pass through the +broker. This is useful for implementing request-reply message interactions; for +example, to fetch application data when the application UI is being initialized. +Or alternatively an `@SubscribeMapping` method can be annotated with `@SendTo` +in which case the resulting message is sent to the `"brokerChannel"` using +the specified target destination. + + +[[websocket-stomp-handle-send]] +==== Sending Messages + +What if you wanted to send messages to connected clients from any part of the +application? Any application component can send messages to the `"brokerChannel"`. +The easiest way to do that is to have a `SimpMessagingTemplate` injected, and +use it to send messages. Typically it should be easy to have it injected by +type, for example: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Controller + public class GreetingController { + + private SimpMessagingTemplate template; + + @Autowired + public GreetingController(SimpMessagingTemplate template) { + this.template = template; + } + + @RequestMapping(value="/greetings", method=POST) + public void greet(String greeting) { + String text = "[" + getTimestamp() + "]:" + greeting; + this.template.convertAndSend("/topic/greetings", text); + } + + } +---- + +But it can also be qualified by its name "brokerMessagingTemplate" if another +bean of the same type exists. + + +[[websocket-stomp-handle-simple-broker]] +==== Simple Broker + +The built-in, simple, message broker handles subscription requests from clients, +stores them in memory, and broadcasts messages to connected clients with matching +destinations. The broker supports path-like destinations, including subscriptions +to Ant-style destination patterns. + +[NOTE] +==== +Applications can also use dot-separated destinations (vs slash). +See <>. +==== + + + + +[[websocket-stomp-handle-broker-relay]] +==== Full-Featured Broker + +The simple broker is great for getting started but supports only a subset of +STOMP commands (e.g. no acks, receipts, etc), relies on a simple message +sending loop, and is not suitable for clustering. Instead, applications can +upgrade to using a full-featured message broker. + +Check the STOMP documentation for your message broker of choice (e.g. +http://www.rabbitmq.com/stomp.html[RabbitMQ], +http://activemq.apache.org/stomp.html[ActiveMQ], or other), install and run the +broker with STOMP support enabled. Then enable the STOMP broker relay in the +Spring configuration instead of the simple broker. + +Below is example configuration that enables a full-featured broker: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Configuration + @EnableWebSocketMessageBroker + public class WebSocketConfig implements WebSocketMessageBrokerConfigurer { + + @Override + public void registerStompEndpoints(StompEndpointRegistry registry) { + registry.addEndpoint("/portfolio").withSockJS(); + } + + @Override + public void configureMessageBroker(MessageBrokerRegistry registry) { + registry.enableStompBrokerRelay("/topic", "/queue"); + registry.setApplicationDestinationPrefixes("/app"); + } + + } +---- + +XML configuration equivalent: + +[source,xml,indent=0] +[subs="verbatim,quotes,attributes"] +---- + + + + + + + + + + +---- + +The "STOMP broker relay" in the above configuration is a Spring +http://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/messaging/MessageHandler.html[MessageHandler] +that handles messages by forwarding them to an external message broker. +To do so it establishes TCP connections to the broker, forwards all +messages to it, and reversely forwards all messages received +from the broker to clients through their WebSocket sessions. Essentially +it acts as a "relay" forwarding messages in both directions. + +[NOTE] +==== +Please add a dependency on `org.projectreactor:reactor-net` for TCP connection management. +==== + +Furthermore, application components (e.g. HTTP request handling methods, +business services, etc) can also send messages to the broker relay, as described +in <>, in order to broadcast messages to +subscribed WebSocket clients. + +In effect, the broker relay enables robust and scalable message broadcasting. + +[[websocket-stomp-handle-broker-relay-configure]] +==== Connections To Full-Featured Broker + +A STOMP broker relay maintains a single "system" TCP connection to the broker. +This connection is used for messages originating from the server-side application +only, not for receiving messages. You can configure the STOMP credentials +for this connection, i.e. the STOMP frame `login` and `passcode` headers. This +is exposed in both the XML namespace and the Java config as the +++systemLogin++/++systemPasscode++ properties with default values ++guest++/++guest++. + +The STOMP broker relay also creates a separate TCP connection for every connected +WebSocket client. You can configure the STOMP credentials to use for all TCP +connections created on behalf of clients. This is exposed in both the XML namespace +and the Java config as the `clientLogin`/`clientPasscode` properties with default +values ++guest++/++guest++. + +[NOTE] +==== +The STOMP broker relay always sets the `login` and `passcode` headers on every CONNECT +frame it forwards to the broker on behalf of clients. Therefore WebSocket clients +need not set those headers, they will be ignored. As the following section explains +instead WebSocket clients should rely on HTTP authentication to protect the WebSocket +endpoint and establish the client identity. +==== + +The STOMP broker relay also sends and receives heartbeats to and from the message +broker over the "system" TCP connection. You can configure the intervals for sending +and receiving heartbeats (10 seconds each by default). If connectivity to the broker +is lost, the broker relay will continue to try to reconnect, every 5 seconds, +until it succeeds. + +[NOTE] +==== +A Spring bean can implement `ApplicationListener` in order +to receive notifications when the "system" connection to the broker is lost and +re-established. For example a Stock Quote service broadcasting stock quotes can +stop trying to send messages when there is no active "system" connection. +==== + +The STOMP broker relay can also be configured with a `virtualHost` property. +The value of this property will be set as the `host` header of every CONNECT frame +and may be useful for example in a cloud environment where the actual host to which +the TCP connection is established is different from the host providing the +cloud-based STOMP service. + +[[websocket-stomp-destination-separator]] +==== Using Dot as Separator in `@MessageMapping` Destinations + +Although slash-separated path patterns are familiar to web developers, in messaging +it is common to use "." as separator for example in the names of topics, queues, +exchanges, etc. Applications can also switch to using "." (dot) instead of "/" (slash) +as the separator in `@MessageMapping` mappings by configuring a custom `AntPathMatcher`. + +In Java config: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Configuration + @EnableWebSocketMessageBroker + public class WebsocketConfig extends AbstractWebSocketMessageBrokerConfigurer { + + // ... + + @Override + public void configureMessageBroker(MessageBrokerRegistry registry) { + registry.enableStompBrokerRelay("/queue/", "/topic/"); + registry.setApplicationDestinationPrefixes("/app"); + registry.setPathMatcher(new AntPathMatcher(".")); + } + + } +---- + +In XML config: + +[source,xml,indent=0] +[subs="verbatim,quotes,attributes"] +---- + + + + + + + + + + + + +---- + +And below is a simple example to illustrate a controller with "." separator: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Controller + @MessageMapping("foo") + public class FooController { + + @MessageMapping("bar.{baz}") + public void handleBaz(@DestinationVariable String baz) { + } + + } +---- + +If the application prefix is set to "/app" then the foo method is effectively mapped to "/app/foo.bar.{baz}". + + + + +[[websocket-stomp-authentication]] +==== Authentication + +In a WebSocket-style application it is often useful to know who sent a message. +Therefore some form of authentication is needed to establish the user identity +and associate it with the current session. + +Existing Web applications already use HTTP based authentication. +For example Spring Security can secure the HTTP URLs of the application as usual. +Since a WebSocket session begins with an HTTP handshake, that means URLs mapped +to STOMP/WebSocket are already automatically protected and require authentication. +Moreover the page that opens the WebSocket connection is itself likely protected +and so by the time of the actual handshake, the user should have been authenticated. + +When a WebSocket handshake is made and a new WebSocket session created, +Spring's WebSocket support automatically transfers the `java.security.Principal` +from the HTTP request to the WebSocket session. After that every message flowing +through the application on that WebSocket session is enriched with +the user information. It's present in the message as a header. +Controller methods can access the current user by adding a method argument of +type `javax.security.Principal`. + +Note that even though the STOMP `CONNECT` frame has "login" and "passcode" headers +that can be used for authentication, Spring's STOMP WebSocket support ignores them +and currently expects users to have been authenticated already via HTTP. + +In some cases it may be useful to assign an identity to WebSocket session even +when the user has not formally authenticated. For example a mobile app might +assign some identity to anonymous users, perhaps based on geographical location. +The do that currently, an application can sub-class `DefaultHandshakeHandler` +and override the `determineUser` method. The custom handshake handler can then +be plugged in (see examples in <>). + + + +[[websocket-stomp-user-destination]] +==== User Destinations + +An application can send messages targeting a specific user. +Spring's STOMP support recognizes destinations prefixed with `"/user/"`. +For example, a client might subscribe to the destination `"/user/queue/position-updates"`. +This destination will be handled by the `UserDestinationMessageHandler` and +transformed into a destination unique to the user session, +e.g. `"/queue/position-updates-user123"`. This provides the convenience of subscribing +to a generically named destination while at the same time ensuring no collisions +with other users subscribing to the same destination so that each user can receive +unique stock position updates. + +On the sending side messages can be sent to a destination such as +`"/user/{username}/queue/position-updates"`, which in turn will be translated +by the `UserDestinationMessageHandler` into one or more destinations, one for each +session associated with the user. This allows any component within the application to +send messages targeting a specific user without necessarily knowing anything more +than their name and the generic destination. This is also supported through an +annotation as well as a messaging template. + +For example message-handling method can send messages to the user associated with +the message being handled through the `@SendToUser` annotation: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- +@Controller +public class PortfolioController { + + @MessageMapping("/trade") + @SendToUser("/queue/position-updates") + public TradeResult executeTrade(Trade trade, Principal principal) { + // ... + return tradeResult; + } +} +---- + +If the user has more than one sessions, by default all of the sessions subscribed +to the given destination are targeted. However sometimes, it may be necessary to +target only the session that sent the message being handled. This can be done by +setting the `broadcast` attribute to false, for example: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- +@Controller +public class MyController { + + @MessageMapping("/action") + public void handleAction() throws Exception{ + // raise MyBusinessException here + } + + @MessageExceptionHandler + @SendToUser(value="/queue/errors", broadcast=false) + public ApplicationError handleException(MyBusinessException exception) { + // ... + return appError; + } +} +---- + + +[NOTE] +==== +While user destinations generally imply an authenticated user, it isn't required +strictly. A WebSocket session that is not associated with an authenticated user +can subscribe to a user destination. In such cases the `@SendToUser` annotation +will behave exactly the same as with `broadcast=false`, i.e. targeting only the +session that sent the message being handled. +==== + +It is also possible to send a message to user destinations from any application +component by injecting the `SimpMessageTemplate` created by the Java config or +XML namespace, for example (the bean name is "brokerMessagingTemplate` if required +for qualification with `@Qualifier`): + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- +@Service +public class TradeServiceImpl implements TradeService { + + private final SimpMessageTemplate messagingTemplate; + + @Autowired + public TradeServiceImpl(SimpMessageTemplate messagingTemplate) { + this.messagingTemplate = messagingTemplate; + } + + // ... + + public void afterTradeExecuted(Trade trade) { + this.messagingTemplate.convertAndSendToUser( + trade.getUserName(), "/queue/position-updates", trade.getResult()); + } +} +---- + +[NOTE] +==== +When using user destinations with an external message broker, check the broker +documentation on how to manage inactive queues, so that when the user session is +over, all unique user queues are removed. For example, RabbitMQ creates auto-delete +queues when destinations like `/exchange/amq.direct/position-updates` are used. +So in that case the client could subscribe to `/user/exchange/amq.direct/position-updates`. +ActiveMQ has http://activemq.apache.org/delete-inactive-destinations.html[configuration options] +for purging inactive destinations. +==== + + + + +[[websocket-stomp-appplication-context-events]] +==== Listening To ApplicationContext Events and Intercepting Messages + +Several `ApplicationContext` events (listed below) are published and can be +received by implementing Spring's `ApplicationListener` interface. + +* `BrokerAvailabilityEvent` -- indicates when the broker becomes available/unavailable. +While the "simple" broker becomes available immediately on startup and remains so while +the application is running, the STOMP "broker relay" may lose its connection +to the full featured broker for example if the broker is restarted. The broker relay +has reconnect logic and will re-establish the "system" connection to the broker +when it comes back, hence this event is published whenever the state changes from connected +to disconnected and vice versa. Components using the `SimpMessagingTemplate` should +subscribe to this event and avoid sending messages at times when the broker is not +available. In any case they should be prepared to handle `MessageDeliveryException` +when sending a message. +* `SessionConnectEvent` -- published when a new STOMP CONNECT is received +indicating the start of a new client session. The event contains the message representing the +connect including the session id, user information (if any), and any custom headers the client +may have sent. This is useful for tracking client sessions. Components subscribed +to this event can wrap the contained message using `SimpMessageHeaderAccessor` or +`StompMessageHeaderAccessor`. +* `SessionConnectedEvent` -- published shortly after a `SessionConnectEvent` when the +broker has sent a STOMP CONNECTED frame in response to the CONNECT. At this point the +STOMP session can be considered fully established. +* `SessionSubscribeEvent` -- published when a new STOMP SUBSCRIBE is received. +* `SessionUnsubscribeEvent` -- published when a new STOMP UNSUBSCRIBE is received. +* `SessionDisconnectEvent` -- published when a STOMP session ends. The DISCONNECT may +have been sent from the client or it may also be automatically generated when the +WebSocket session is closed. In some cases this event may be published more than once +per session. Components should be idempotent to multiple disconnect events. + +[NOTE] +==== +When using a full-featured broker, the STOMP "broker relay" automatically reconnects the +"system" connection should the broker become temporarily unavailable. Client connections +however are not automatically reconnected. Assuming heartbeats are enabled, the client +will typically notice the broker is not responding within 10 seconds. Clients need to +implement their own reconnect logic. +==== + +Furthermore, an application can directly intercept every incoming and outgoing message by +registering a `ChannelInterceptor` on the respective message channel. For example +to intercept inbound messages: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Configuration + @EnableWebSocketMessageBroker + public class WebsocketConfig extends AbstractWebSocketMessageBrokerConfigurer { + + @Override + public void configureClientInboundChannel(ChannelRegistration registration) { + registration.setInterceptors(new MyChannelInterceptor()); + } + } +---- + +A custom `ChannelInterceptor` can extend the empty method base class +`ChannelInterceptorAdapter` and use `StompHeaderAccessor` or `SimpMessageHeaderAccessor` +to access information about the message. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class MyChannelInterceptor extends ChannelInterceptorAdapter { + + @Override + public Message preSend(Message message, MessageChannel channel) { + StompHeaderAccessor accessor = StompHeaderAccessor.wrap(message); + StompCommand command = accessor.getStompCommand(); + // ... + return message; + } + } +---- + + + +[[websocket-stomp-websocket-scope]] +==== WebSocket Scope + +Each WebSocket session has a map of attributes. The map is attached as a header to +inbound client messages and may be accessed from a controller method, for example: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- +@Controller +public class MyController { + + @MessageMapping("/action") + public void handle(SimpMessageHeaderAccessor headerAccessor) { + Map attrs = headerAccessor.getSessionAttributes(); + // ... + } +} +---- + +It is also possible to declare a Spring-managed bean in the `"websocket"` scope. +WebSocket-scoped beans can be injected into controllers and any channel interceptors +registered on the "clientInboundChannel". Those are typically singletons and live +longer than any individual WebSocket session. Therefore you will need to use a +scope proxy mode for WebSocket-scoped beans: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- +@Component +@Scope(value="websocket", proxyMode = ScopedProxyMode.TARGET_CLASS) +public class MyBean { + + @PostConstruct + public void init() { + // Invoked after dependencies injected + } + + // ... + + @PreDestroy + public void destroy() { + // Invoked when the WebSocket session ends + } +} + +@Controller +public class MyController { + + private final MyBean myBean; + + @Autowired + public MyController(MyBean myBean) { + this.myBean = myBean; + } + + @MessageMapping("/action") + public void handle() { + // this.myBean from the current WebSocket session + } +} +---- + +As with any custom scope, Spring initializes a new MyBean instance the first +time it is accessed from the controller and stores the instance in the WebSocket +session attributes. The same instance is returned subsequently until the session +ends. WebSocket-scoped beans will have all Spring lifecycle methods invoked as +shown in the examples above. + + + +[[websocket-stomp-configuration-performance]] +==== Configuration and Performance + +There is no silver bullet when it comes to performance. Many factors may +affect it including the size of messages, the volume, whether application +methods perform work that requires blocking, as well as external factors +such as network speed and others. The goal of this section is to provide +an overview of the available configuration options along with some thoughts +on how to reason about scaling. + +In a messaging application messages are passed through channels for asynchronous +executions backed by thread pools. Configuring such an application requires +good knowledge of the channels and the flow of messages. Therefore it is +recommended to review <>. + +The obvious place to start is to configure the thread pools backing the +`"clientInboundChannel"` and the `"clientOutboundChannel"`. By default both +are configured at twice the number of available processors. + +If the handling of messages in annotated methods is mainly CPU bound then the +number of threads for the `"clientInboundChannel"` should remain close to the +number of processors. If the work they do is more IO bound and requires blocking +or waiting on a database or other external system then the thread pool size +will need to be increased. + +[NOTE] +==== +`ThreadPoolExecutor` has 3 important properties. Those are the core and +the max thread pool size as well as the capacity for the queue to store +tasks for which there are no available threads. + +A common point of confusion is that configuring the core pool size (e.g. 10) +and max pool size (e.g. 20) results in a thread pool with 10 to 20 threads. +In fact if the capacity is left at its default value of Integer.MAX_VALUE +then the thread pool will never increase beyond the core pool size since +all additional tasks will be queued. + +Please review the Javadoc of `ThreadPoolExecutor` to learn how these +properties work and understand the various queuing strategies. +==== + +On the `"clientOutboundChannel"` side it is all about sending messages to WebSocket +clients. If clients are on a fast network then the number of threads should +remain close to the number of available processors. If they are slow or on +low bandwidth they will take longer to consume messages and put a burden on the +thread pool. Therefore increasing the thread pool size will be necessary. + +While the workload for the "clientInboundChannel" is possible to predict -- +after all it is based on what the application does -- how to configure the +"clientOutboundChannel" is harder as it is based on factors beyond +the control of the application. For this reason there are two additional +properties related to the sending of messages. Those are the `"sendTimeLimit"` +and the `"sendBufferSizeLimit"`. Those are used to configure how long a +send is allowed to take and how much data can be buffered when sending +messages to a client. + +The general idea is that at any given time only a single thread may be used +to send to a client. All additional messages meanwhile get buffered and you +can use these properties to decide how long sending a message is allowed to +take and how much data can be buffered in the mean time. Please review the +Javadoc of XML schema for this configuration for important additional details. + +Here is example configuration: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Configuration + @EnableWebSocketMessageBroker + public class WebSocketConfig implements WebSocketMessageBrokerConfigurer { + + @Override + public void configureWebSocketTransport(WebSocketTransportRegistration registration) { + registration.setSendTimeLimit(15 * 1000).setSendBufferSizeLimit(512 * 1024); + } + + // ... + + } +---- + +[source,xml,indent=0] +[subs="verbatim,quotes,attributes"] +---- + + + + + + + + +---- + +The WebSocket transport configuration shown above can also be used to configure the +maximum allowed size for incoming STOMP messages. Although in theory a WebSocket +message can be almost unlimited in size, in pracitce WebSocket servers impose +limits. For example 8K on Tomcat and 64K on Jetty. For this reason STOMP clients +such as stomp.js split larger STOMP messages at 16K boundaries and send them as +multiple WebSocket messages thus requiring the server to buffer and re-assemble. + +Spring's STOMP over WebSocket support does this so applications can configure the +maximum size for STOMP messages irrespective of WebSocket server specific message +sizes. Do keep in mind that the WebSocket message size will be automatically +adjusted if necessary to ensure they can carry 16K WebSocket messages at a +minimum. + +Here is example configuration: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Configuration + @EnableWebSocketMessageBroker + public class WebSocketConfig implements WebSocketMessageBrokerConfigurer { + + @Override + public void configureWebSocketTransport(WebSocketTransportRegistration registration) { + registration.setMessageSizeLimit(128 * 1024); + } + + // ... + + } +---- + +[source,xml,indent=0] +[subs="verbatim,quotes,attributes"] +---- + + + + + + + + +---- + +An important point about scaling is using multiple application instances. +Currently it is not possible to do that with the simple broker. +However when using a full-featured broker such as RabbitMQ, each application +instance connects to the broker and messages broadcast from one application +instance can be broadcast through the broker to WebSocket clients connected +through any other application instances. + + + +[[websocket-stomp-stats]] +==== Runtime Monitoring + +When using `@EnableWebSocketMessageBroker` or `` key +infrastructure components automatically gather stats and counters that provide +important insight into the internal state of the application. The configuration +also declares a bean of type `WebSocketMessageBrokerStats` that gathers all +available information in one place and by default logs it at INFO once +every 30 minutes. This bean can be exported to JMX through Spring's +`MBeanExporter` for viewing at runtime for example through JDK's jconsole. +Below is a summary of the available information. + +Client WebSocket Sessions:: + Current::: indicates how many client sessions there are + currently with the count further broken down by WebSocket vs HTTP + streaming and polling SockJS sessions. + Total::: indicates how many total sessions have been established. + Abnormally Closed::: + Connect Failures:::: these are sessions that got established but were + closed after not having received any messages within 60 seconds. This is + usually an indication of proxy or network issues. + Send Limit Exceeded:::: sessions closed after exceeding the configured send + timeout or the send buffer limits which can occur with slow clients + (see previous section). + Transport Errors:::: sessions closed after a transport error such as + failure to read or write to a WebSocket connection or + HTTP request/response. + STOMP Frames::: the total number of CONNECT, CONNECTED, and DISCONNECT frames + processed indicating how many clients connected on the STOMP level. Note that + the DISCONNECT count may be lower when sessions get closed abnormally or when + clients close without sending a DISCONNECT frame. +STOMP Broker Relay:: + TCP Connections::: indicates how many TCP connections on behalf of client + WebSocket sessions are established to the broker. This should be equal to the + number of client WebSocket sessions + 1 additional shared "system" connection + for sending messages from within the application. + STOMP Frames::: the total number of CONNECT, CONNECTED, and DISCONNECT frames + forwarded to or received from the broker on behalf of clients. Note that a + DISCONNECT frame is sent to the broker regardless of how the client WebSocket + session was closed. Therefore a lower DISCONNECT frame count is an indication + that the broker is pro-actively closing connections, may be because of a + heartbeat that didn't arrive in time, an invalid input frame, or other. +Client Inbound Channel:: stats from thread pool backing the "clientInboundChannel" + providing insight into the health of incoming message processing. Tasks queueing + up here is an indication the application may be too slow to handle messages. + If there I/O bound tasks (e.g. slow database query, HTTP request to 3rd party + REST API, etc) consider increasing the thread pool size. +Client Outbound Channel:: stats from the thread pool backing the "clientOutboundChannel" + providing insight into the health of broadcasting messages to clients. Tasks + queueing up here is an indication clients are too slow to consume messages. + One way to address this is to increase the thread pool size to accommodate the + number of concurrent slow clients expected. Another option is to reduce the + send timeout and send buffer size limits (see the previous section). +SockJS Task Scheduler:: stats from thread pool of the SockJS task scheduler which + is used to send heartbeats. Note that when heartbeats are negotiated on the + STOMP level the SockJS heartbeats are disabled. + +[[websocket-stomp-testing]] +==== Testing Annotated Controller Methods + +There are two main approaches to testing applications using Spring's STOMP over +WebSocket support. The first is to write server-side tests verifying the functionality +of controllers and their annotated message handling methods. The second is to write +full end-to-end tests that involve running a client and a server. + +The two approaches are not mutually exclusive. On the contrary each has a place +in an overall test strategy. Server-side tests are more focused and easier to write +and maintain. End-to-end integration tests on the other hand are more complete and +test much more but they're also more involved to write and maintain. + +The simplest form of server-side tests is to write controller unit tests. However +this is not useful enough since much of what a controller does depends on its +annotations. Pure unit tests simply can't test that. + +Ideally controllers under test should be invoked as they are at runtime, much like +the approach to testing controllers handling HTTP requests using the Spring MVC Test +framework. i.e. without running a Servlet container but relying on the Spring Framework +to invoke the annotated controllers. Just like with Spring MVC Test here there are two +two possible alternatives, either using a "context-based" or "standalone" setup: + +1. Load the actual Spring configuration with the help of the +Spring TestContext framework, inject "clientInboundChannel" as a test field, and +use it to send messages to be handled by controller methods. + +2. Manually set up the minimum Spring framework infrastructure required to invoke +controllers (namely the `SimpAnnotationMethodMessageHandler`) and pass messages for +controllers directly to it. + +Both of these setup scenarios are demonstrated in the +https://github.com/rstoyanchev/spring-websocket-portfolio/tree/master/src/test/java/org/springframework/samples/portfolio/web[tests for the stock portfolio] +sample application. + +The second approach is to create end-to-end integration tests. For that you will need +to run a WebSocket server in embedded mode and connect to it as a WebSocket client +sending WebSocket messages containing STOMP frames. +The https://github.com/rstoyanchev/spring-websocket-portfolio/tree/master/src/test/java/org/springframework/samples/portfolio/web[tests for the stock portfolio] +sample application also demonstrate this approach using Tomcat as the embedded +WebSocket server and a simple STOMP client for test purposes. diff --git a/src/asciidoc/xml-custom.adoc b/src/asciidoc/xml-custom.adoc new file mode 100644 index 000000000000..49cb64f66199 --- /dev/null +++ b/src/asciidoc/xml-custom.adoc @@ -0,0 +1,739 @@ +[[extensible-xml]] +== Extensible XML authoring + + + + +[[extensible-xml-introduction]] +=== Introduction +Since version 2.0, Spring has featured a mechanism for schema-based extensions to the +basic Spring XML format for defining and configuring beans. This section is devoted to +detailing how you would go about writing your own custom XML bean definition parsers and +integrating such parsers into the Spring IoC container. + +To facilitate the authoring of configuration files using a schema-aware XML editor, +Spring's extensible XML configuration mechanism is based on XML Schema. If you are not +familiar with Spring's current XML configuration extensions that come with the standard +Spring distribution, please first read the appendix entitled<>. + +Creating new XML configuration extensions can be done by following these (relatively) +simple steps: + +* <> an XML schema to describe your custom element(s). +* <> a custom `NamespaceHandler` implementation + (this is an easy step, don't worry). +* <> one or more `BeanDefinitionParser` implementations + (this is where the real work is done). +* <> the above artifacts with Spring (this too + is an easy step). + +What follows is a description of each of these steps. For the example, we will create an +XML extension (a custom XML element) that allows us to configure objects of the type +`SimpleDateFormat` (from the `java.text` package) in an easy manner. When we are done, +we will be able to define bean definitions of type `SimpleDateFormat` like this: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + +---- + +__(Don't worry about the fact that this example is very simple; much more detailed +examples follow afterwards. The intent in this first simple example is to walk you +through the basic steps involved.)__ + + + + +[[extensible-xml-schema]] +=== Authoring the schema +Creating an XML configuration extension for use with Spring's IoC container starts with +authoring an XML Schema to describe the extension. What follows is the schema we'll use +to configure `SimpleDateFormat` objects. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + + + + + + + + + + + +---- + +(The emphasized line contains an extension base for all tags that will be identifiable +(meaning they have an `id` attribute that will be used as the bean identifier in the +container). We are able to use this attribute because we imported the Spring-provided +`'beans'` namespace.) + +The above schema will be used to configure `SimpleDateFormat` objects, directly in an +XML application context file using the `` element. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + +---- + +Note that after we've created the infrastructure classes, the above snippet of XML will +essentially be exactly the same as the following XML snippet. In other words, we're just +creating a bean in the container, identified by the name `'dateFormat'` of type +`SimpleDateFormat`, with a couple of properties set. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + +---- + +[NOTE] +==== +The schema-based approach to creating configuration format allows for tight integration +with an IDE that has a schema-aware XML editor. Using a properly authored schema, you +can use autocompletion to have a user choose between several configuration options +defined in the enumeration. +==== + + + + +[[extensible-xml-namespacehandler]] +=== Coding a NamespaceHandler + +In addition to the schema, we need a `NamespaceHandler` that will parse all elements of +this specific namespace Spring encounters while parsing configuration files. The +`NamespaceHandler` should in our case take care of the parsing of the `myns:dateformat` +element. + +The `NamespaceHandler` interface is pretty simple in that it features just three methods: + +* `init()` - allows for initialization of the `NamespaceHandler` and will be called by + Spring before the handler is used +* `BeanDefinition parse(Element, ParserContext)` - called when Spring encounters a + top-level element (not nested inside a bean definition or a different namespace). This + method can register bean definitions itself and/or return a bean definition. +* `BeanDefinitionHolder decorate(Node, BeanDefinitionHolder, ParserContext)` - called + when Spring encounters an attribute or nested element of a different namespace. The + decoration of one or more bean definitions is used for example with + the<>. We'll start by + highlighting a simple example, without using decoration, after which we will show + decoration in a somewhat more advanced example. + +Although it is perfectly possible to code your own `NamespaceHandler` for the entire +namespace (and hence provide code that parses each and every element in the namespace), +it is often the case that each top-level XML element in a Spring XML configuration file +results in a single bean definition (as in our case, where a single `` +element results in a single `SimpleDateFormat` bean definition). Spring features a +number of convenience classes that support this scenario. In this example, we'll make +use the `NamespaceHandlerSupport` class: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + package org.springframework.samples.xml; + + import org.springframework.beans.factory.xml.NamespaceHandlerSupport; + + public class MyNamespaceHandler extends NamespaceHandlerSupport { + + public void init() { + **registerBeanDefinitionParser("dateformat", new SimpleDateFormatBeanDefinitionParser());** + } + + } +---- + +The observant reader will notice that there isn't actually a whole lot of parsing logic +in this class. Indeed... the `NamespaceHandlerSupport` class has a built in notion of +delegation. It supports the registration of any number of `BeanDefinitionParser` +instances, to which it will delegate to when it needs to parse an element in its +namespace. This clean separation of concerns allows a `NamespaceHandler` to handle the +orchestration of the parsing of __all__ of the custom elements in its namespace, while +delegating to `BeanDefinitionParsers` to do the grunt work of the XML parsing; this +means that each `BeanDefinitionParser` will contain just the logic for parsing a single +custom element, as we can see in the next step + + + + +[[extensible-xml-parser]] +=== BeanDefinitionParser + +A `BeanDefinitionParser` will be used if the `NamespaceHandler` encounters an XML +element of the type that has been mapped to the specific bean definition parser (which +is `'dateformat'` in this case). In other words, the `BeanDefinitionParser` is +responsible for parsing __one__ distinct top-level XML element defined in the schema. In +the parser, we'll have access to the XML element (and thus its subelements too) so that +we can parse our custom XML content, as can be seen in the following example: + +[source,java,indent=0] +---- + package org.springframework.samples.xml; + + import org.springframework.beans.factory.support.BeanDefinitionBuilder; + import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser; + import org.springframework.util.StringUtils; + import org.w3c.dom.Element; + + import java.text.SimpleDateFormat; + + public class SimpleDateFormatBeanDefinitionParser extends AbstractSingleBeanDefinitionParser { // <1> + + protected Class getBeanClass(Element element) { + return SimpleDateFormat.class; // <2> + } + + protected void doParse(Element element, BeanDefinitionBuilder bean) { + // this will never be null since the schema explicitly requires that a value be supplied + String pattern = element.getAttribute("pattern"); + bean.addConstructorArg(pattern); + + // this however is an optional property + String lenient = element.getAttribute("lenient"); + if (StringUtils.hasText(lenient)) { + bean.addPropertyValue("lenient", Boolean.valueOf(lenient)); + } + } + + } +---- + +<1> We use the Spring-provided `AbstractSingleBeanDefinitionParser` to handle a lot of +the basic grunt work of creating a __single__ `BeanDefinition`. + +<2> We supply the `AbstractSingleBeanDefinitionParser` superclass with the type that our +single `BeanDefinition` will represent. + +In this simple case, this is all that we need to do. The creation of our single +`BeanDefinition` is handled by the `AbstractSingleBeanDefinitionParser` superclass, as +is the extraction and setting of the bean definition's unique identifier. + + + + +[[extensible-xml-registration]] +=== Registering the handler and the schema +The coding is finished! All that remains to be done is to somehow make the Spring XML +parsing infrastructure aware of our custom element; we do this by registering our custom +`namespaceHandler` and custom XSD file in two special purpose properties files. These +properties files are both placed in a `'META-INF'` directory in your application, and +can, for example, be distributed alongside your binary classes in a JAR file. The Spring +XML parsing infrastructure will automatically pick up your new extension by consuming +these special properties files, the formats of which are detailed below. + + + +[[extensible-xml-registration-spring-handlers]] +==== 'META-INF/spring.handlers' + +The properties file called `'spring.handlers'` contains a mapping of XML Schema URIs to +namespace handler classes. So for our example, we need to write the following: + +[literal] +[subs="verbatim,quotes"] +---- +http\://www.mycompany.com/schema/myns=org.springframework.samples.xml.MyNamespaceHandler +---- + +__(The `':'` character is a valid delimiter in the Java properties format, and so the +`':'` character in the URI needs to be escaped with a backslash.)__ + +The first part (the key) of the key-value pair is the URI associated with your custom +namespace extension, and needs to __match exactly__ the value of the `'targetNamespace'` +attribute as specified in your custom XSD schema. + + + +[[extensible-xml-registration-spring-schemas]] +==== 'META-INF/spring.schemas' + +The properties file called `'spring.schemas'` contains a mapping of XML Schema locations +(referred to along with the schema declaration in XML files that use the schema as part +of the `'xsi:schemaLocation'` attribute) to __classpath__ resources. This file is needed +to prevent Spring from absolutely having to use a default `EntityResolver` that requires +Internet access to retrieve the schema file. If you specify the mapping in this +properties file, Spring will search for the schema on the classpath (in this case +`'myns.xsd'` in the `'org.springframework.samples.xml'` package): + +[literal] +[subs="verbatim,quotes"] +---- +http\://www.mycompany.com/schema/myns/myns.xsd=org/springframework/samples/xml/myns.xsd +---- + +The upshot of this is that you are encouraged to deploy your XSD file(s) right alongside +the `NamespaceHandler` and `BeanDefinitionParser` classes on the classpath. + + + + +[[extensible-xml-using]] +=== Using a custom extension in your Spring XML configuration +Using a custom extension that you yourself have implemented is no different from using +one of the 'custom' extensions that Spring provides straight out of the box. Find below +an example of using the custom `` element developed in the previous steps +in a Spring XML configuration file. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + + + + + + + +---- + + + + +[[extensible-xml-meat]] +=== Meatier examples +Find below some much meatier examples of custom XML extensions. + + + +[[extensible-xml-custom-nested]] +==== Nesting custom tags within custom tags +This example illustrates how you might go about writing the various artifacts required +to satisfy a target of the following configuration: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + + + + + +---- + +The above configuration actually nests custom extensions within each other. The class +that is actually configured by the above `` element is the `Component` +class (shown directly below). Notice how the `Component` class does __not__ expose a +setter method for the `'components'` property; this makes it hard (or rather impossible) +to configure a bean definition for the `Component` class using setter injection. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + package com.foo; + + import java.util.ArrayList; + import java.util.List; + + public class Component { + + private String name; + private List components = new ArrayList (); + + // mmm, there is no setter method for the 'components' + public void addComponent(Component component) { + this.components.add(component); + } + + public List getComponents() { + return components; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + } +---- + +The typical solution to this issue is to create a custom `FactoryBean` that exposes a +setter property for the `'components'` property. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + package com.foo; + + import org.springframework.beans.factory.FactoryBean; + + import java.util.List; + + public class ComponentFactoryBean implements FactoryBean { + + private Component parent; + private List children; + + public void setParent(Component parent) { + this.parent = parent; + } + + public void setChildren(List children) { + this.children = children; + } + + public Component getObject() throws Exception { + if (this.children != null && this.children.size() > 0) { + for (Component child : children) { + this.parent.addComponent(child); + } + } + return this.parent; + } + + public Class getObjectType() { + return Component.class; + } + + public boolean isSingleton() { + return true; + } + + } +---- + +This is all very well, and does work nicely, but exposes a lot of Spring plumbing to the +end user. What we are going to do is write a custom extension that hides away all of +this Spring plumbing. If we stick to <>, we'll start off by creating the XSD schema to define the structure of our +custom tag. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + + + + + + + + +---- + +We'll then create a custom `NamespaceHandler`. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + package com.foo; + + import org.springframework.beans.factory.xml.NamespaceHandlerSupport; + + public class ComponentNamespaceHandler extends NamespaceHandlerSupport { + + public void init() { + registerBeanDefinitionParser("component", new ComponentBeanDefinitionParser()); + } + + } +---- + +Next up is the custom `BeanDefinitionParser`. Remember that what we are creating is a +`BeanDefinition` describing a `ComponentFactoryBean`. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + package com.foo; + + import org.springframework.beans.factory.config.BeanDefinition; + import org.springframework.beans.factory.support.AbstractBeanDefinition; + import org.springframework.beans.factory.support.BeanDefinitionBuilder; + import org.springframework.beans.factory.support.ManagedList; + import org.springframework.beans.factory.xml.AbstractBeanDefinitionParser; + import org.springframework.beans.factory.xml.ParserContext; + import org.springframework.util.xml.DomUtils; + import org.w3c.dom.Element; + + import java.util.List; + + public class ComponentBeanDefinitionParser extends AbstractBeanDefinitionParser { + + protected AbstractBeanDefinition parseInternal(Element element, ParserContext parserContext) { + return parseComponentElement(element); + } + + private static AbstractBeanDefinition parseComponentElement(Element element) { + BeanDefinitionBuilder factory = BeanDefinitionBuilder.rootBeanDefinition(ComponentFactoryBean.class); + factory.addPropertyValue("parent", parseComponent(element)); + + List childElements = DomUtils.getChildElementsByTagName(element, "component"); + if (childElements != null && childElements.size() > 0) { + parseChildComponents(childElements, factory); + } + + return factory.getBeanDefinition(); + } + + private static BeanDefinition parseComponent(Element element) { + BeanDefinitionBuilder component = BeanDefinitionBuilder.rootBeanDefinition(Component.class); + component.addPropertyValue("name", element.getAttribute("name")); + return component.getBeanDefinition(); + } + + private static void parseChildComponents(List childElements, BeanDefinitionBuilder factory) { + ManagedList children = new ManagedList(childElements.size()); + for (Element element : childElements) { + children.add(parseComponentElement(element)); + } + factory.addPropertyValue("children", children); + } + + } +---- + +Lastly, the various artifacts need to be registered with the Spring XML infrastructure. + +[literal] +[subs="verbatim,quotes"] +---- +# in 'META-INF/spring.handlers' +http\://www.foo.com/schema/component=com.foo.ComponentNamespaceHandler +---- + +[literal] +[subs="verbatim,quotes"] +---- +# in 'META-INF/spring.schemas' +http\://www.foo.com/schema/component/component.xsd=com/foo/component.xsd +---- + + + +[[extensible-xml-custom-just-attributes]] +==== Custom attributes on 'normal' elements +Writing your own custom parser and the associated artifacts isn't hard, but sometimes it +is not the right thing to do. Consider the scenario where you need to add metadata to +already existing bean definitions. In this case you certainly don't want to have to go +off and write your own entire custom extension; rather you just want to add an +additional attribute to the existing bean definition element. + +By way of another example, let's say that the service class that you are defining a bean +definition for a service object that will (unknown to it) be accessing a clustered +http://jcp.org/en/jsr/detail?id=107[JCache], and you want to ensure that the named +JCache instance is eagerly started within the surrounding cluster: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + +---- + +What we are going to do here is create another `BeanDefinition` when the +`'jcache:cache-name'` attribute is parsed; this `BeanDefinition` will then initialize +the named JCache for us. We will also modify the existing `BeanDefinition` for the +`'checkingAccountService'` so that it will have a dependency on this new +JCache-initializing `BeanDefinition`. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + package com.foo; + + public class JCacheInitializer { + + private String name; + + public JCacheInitializer(String name) { + this.name = name; + } + + public void initialize() { + // lots of JCache API calls to initialize the named cache... + } + + } +---- + +Now onto the custom extension. Firstly, the authoring of the XSD schema describing the +custom attribute (quite easy in this case). + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + +---- + +Next, the associated `NamespaceHandler`. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + package com.foo; + + import org.springframework.beans.factory.xml.NamespaceHandlerSupport; + + public class JCacheNamespaceHandler extends NamespaceHandlerSupport { + + public void init() { + super.registerBeanDefinitionDecoratorForAttribute("cache-name", + new JCacheInitializingBeanDefinitionDecorator()); + } + + } +---- + +Next, the parser. Note that in this case, because we are going to be parsing an XML +attribute, we write a `BeanDefinitionDecorator` rather than a `BeanDefinitionParser`. + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + package com.foo; + + import org.springframework.beans.factory.config.BeanDefinitionHolder; + import org.springframework.beans.factory.support.AbstractBeanDefinition; + import org.springframework.beans.factory.support.BeanDefinitionBuilder; + import org.springframework.beans.factory.xml.BeanDefinitionDecorator; + import org.springframework.beans.factory.xml.ParserContext; + import org.w3c.dom.Attr; + import org.w3c.dom.Node; + + import java.util.ArrayList; + import java.util.Arrays; + import java.util.List; + + public class JCacheInitializingBeanDefinitionDecorator implements BeanDefinitionDecorator { + + private static final String[] EMPTY_STRING_ARRAY = new String[0]; + + public BeanDefinitionHolder decorate(Node source, BeanDefinitionHolder holder, + ParserContext ctx) { + String initializerBeanName = registerJCacheInitializer(source, ctx); + createDependencyOnJCacheInitializer(holder, initializerBeanName); + return holder; + } + + private void createDependencyOnJCacheInitializer(BeanDefinitionHolder holder, + String initializerBeanName) { + AbstractBeanDefinition definition = ((AbstractBeanDefinition) holder.getBeanDefinition()); + String[] dependsOn = definition.getDependsOn(); + if (dependsOn == null) { + dependsOn = new String[]{initializerBeanName}; + } else { + List dependencies = new ArrayList(Arrays.asList(dependsOn)); + dependencies.add(initializerBeanName); + dependsOn = (String[]) dependencies.toArray(EMPTY_STRING_ARRAY); + } + definition.setDependsOn(dependsOn); + } + + private String registerJCacheInitializer(Node source, ParserContext ctx) { + String cacheName = ((Attr) source).getValue(); + String beanName = cacheName + "-initializer"; + if (!ctx.getRegistry().containsBeanDefinition(beanName)) { + BeanDefinitionBuilder initializer = BeanDefinitionBuilder.rootBeanDefinition(JCacheInitializer.class); + initializer.addConstructorArg(cacheName); + ctx.getRegistry().registerBeanDefinition(beanName, initializer.getBeanDefinition()); + } + return beanName; + } + + } +---- + +Lastly, the various artifacts need to be registered with the Spring XML infrastructure. + +[literal] +[subs="verbatim,quotes"] +---- +# in 'META-INF/spring.handlers' +http\://www.foo.com/schema/jcache=com.foo.JCacheNamespaceHandler +---- + +[literal] +[subs="verbatim,quotes"] +---- +# in 'META-INF/spring.schemas' +http\://www.foo.com/schema/jcache/jcache.xsd=com/foo/jcache.xsd +---- + + + + +[[extensible-xml-resources]] +=== Further Resources +Find below links to further resources concerning XML Schema and the extensible XML +support described in this chapter. + +* The http://www.w3.org/TR/2004/REC-xmlschema-1-20041028/[XML Schema Part 1: Structures + Second Edition] +* The http://www.w3.org/TR/2004/REC-xmlschema-2-20041028/[XML Schema Part 2: Datatypes + Second Edition] + + diff --git a/src/asciidoc/xsd-configuration.adoc b/src/asciidoc/xsd-configuration.adoc new file mode 100644 index 000000000000..1f9311915be7 --- /dev/null +++ b/src/asciidoc/xsd-configuration.adoc @@ -0,0 +1,1179 @@ +[[xsd-config]] +== XML Schema-based configuration + + +[[xsd-config-introduction]] +=== Introduction +This appendix details the XML Schema-based configuration introduced in Spring 2.0 and +enhanced and extended in Spring 2.5 and 3.0. + +.DTD support? +**** +Authoring Spring configuration files using the older DTD style is still fully supported. + +Nothing will break if you forego the use of the new XML Schema-based approach to +authoring Spring XML configuration files. All that you lose out on is the opportunity to +have more succinct and clearer configuration. Regardless of whether the XML +configuration is DTD- or Schema-based, in the end it all boils down to the same object +model in the container (namely one or more `BeanDefinition` instances). +**** + +The central motivation for moving to XML Schema based configuration files was to make +Spring XML configuration easier. The __'classic'__ ``-based approach is good, but +its generic-nature comes with a price in terms of configuration overhead. + +From the Spring IoC containers point-of-view, __everything__ is a bean. That's great +news for the Spring IoC container, because if everything is a bean then everything can +be treated in the exact same fashion. The same, however, is not true from a developer's +point-of-view. The objects defined in a Spring XML configuration file are not all +generic, vanilla beans. Usually, each bean requires some degree of specific +configuration. + +Spring 2.0's new XML Schema-based configuration addresses this issue. The `` +element is still present, and if you wanted to, you could continue to write the __exact +same__ style of Spring XML configuration using only `` elements. The new XML +Schema-based configuration does, however, make Spring XML configuration files +substantially clearer to read. In addition, it allows you to express the intent of a +bean definition. + +The key thing to remember is that the new custom tags work best for infrastructure or +integration beans: for example, AOP, collections, transactions, integration with +3rd-party frameworks such as Mule, etc., while the existing bean tags are best suited to +application-specific beans, such as DAOs, service layer objects, validators, etc. + +The examples included below will hopefully convince you that the inclusion of XML Schema +support in Spring 2.0 was a good idea. The reception in the community has been +encouraging; also, please note the fact that this new configuration mechanism is totally +customisable and extensible. This means you can write your own domain-specific +configuration tags that would better represent your application's domain; the process +involved in doing so is covered in the appendix entitled <>. + + + + +[[xsd-config-body]] +=== XML Schema-based configuration + + + +[[xsd-config-body-referencing]] +==== Referencing the schemas +To switch over from the DTD-style to the new XML Schema-style, you need to make the +following change. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + +---- + +The equivalent file in the XML Schema-style would be... + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + +---- + +[NOTE] +==== +The `'xsi:schemaLocation'` fragment is not actually required, but can be included to +reference a local copy of a schema (which can be useful during development). +==== + +The above Spring XML configuration fragment is boilerplate that you can copy and paste +(!) and then plug `` definitions into like you have always done. However, the +entire point of switching over is to take advantage of the new Spring 2.0 XML tags since +they make configuration easier. The section entitled <> +demonstrates how you can start immediately by using some of the more common utility tags. + +The rest of this chapter is devoted to showing examples of the new Spring XML Schema +based configuration, with at least one example for every new tag. The format follows a +before and after style, with a __before__ snippet of XML showing the old (but still 100% +legal and supported) style, followed immediately by an __after__ example showing the +equivalent in the new XML Schema-based style. + + + +[[xsd-config-body-schemas-util]] +==== the util schema + +First up is coverage of the `util` tags. As the name implies, the `util` tags deal with +common, __utility__ configuration issues, such as configuring collections, referencing +constants, and suchlike. + +To use the tags in the `util` schema, you need to have the following preamble at the top +of your Spring XML configuration file; the text in the snippet below references the +correct schema so that the tags in the `util` namespace are available to you. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + +---- + + +[[xsd-config-body-schemas-util-constant]] +===== + +Before... + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + +---- + +The above configuration uses a Spring `FactoryBean` implementation, the +`FieldRetrievingFactoryBean`, to set the value of the `'isolation'` property on a bean +to the value of the `'java.sql.Connection.TRANSACTION_SERIALIZABLE'` constant. This is +all well and good, but it is a tad verbose and (unnecessarily) exposes Spring's internal +plumbing to the end user. + +The following XML Schema-based version is more concise and clearly expresses the +developer's intent (__'inject this constant value'__), and it just reads better. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + +---- + +[[xsd-config-body-schemas-util-frfb]] +====== Setting a bean property or constructor arg from a field value +http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/beans/factory/config/FieldRetrievingFactoryBean.html[`FieldRetrievingFactoryBean`] +is a `FactoryBean` which retrieves a `static` or non-static field value. It is typically +used for retrieving `public` `static` `final` constants, which may then be used to set a +property value or constructor arg for another bean. + +Find below an example which shows how a `static` field is exposed, by using the +http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/beans/factory/config/FieldRetrievingFactoryBean.html#setStaticField(java.lang.String)[`staticField`] +property: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + +---- + +There is also a convenience usage form where the `static` field is specified as the bean +name: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + +---- + +This does mean that there is no longer any choice in what the bean id is (so any other +bean that refers to it will also have to use this longer name), but this form is very +concise to define, and very convenient to use as an inner bean since the id doesn't have +to be specified for the bean reference: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + +---- + +It is also possible to access a non-static (instance) field of another bean, as +described in the API documentation for the +http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/beans/factory/config/FieldRetrievingFactoryBean.html[`FieldRetrievingFactoryBean`] +class. + +Injecting enum values into beans as either property or constructor arguments is very +easy to do in Spring, in that you don't actually have to __do__ anything or know +anything about the Spring internals (or even about classes such as the +`FieldRetrievingFactoryBean`). Let's look at an example to see how easy injecting an +enum value is; consider this JDK 5 enum: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + package javax.persistence; + + public enum PersistenceContextType { + + TRANSACTION, + EXTENDED + + } +---- + +Now consider a setter of type `PersistenceContextType`: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + package example; + + public class Client { + + private PersistenceContextType persistenceContextType; + + public void setPersistenceContextType(PersistenceContextType type) { + this.persistenceContextType = type; + } + + } +---- + +.. and the corresponding bean definition: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + +---- + +This works for classic type-safe emulated enums (on JDK 1.4 and JDK 1.3) as well; Spring +will automatically attempt to match the string property value to a constant on the enum +class. + + +[[xsd-config-body-schemas-util-property-path]] +===== + +Before... + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + + + + + +---- + +The above configuration uses a Spring `FactoryBean` implementation, the +`PropertyPathFactoryBean`, to create a bean (of type `int`) called `'testBean.age'` that +has a value equal to the `'age'` property of the `'testBean'` bean. + +After... + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + + + + + +---- + +The value of the `'path'` attribute of the `` tag follows the form +`'beanName.beanProperty'`. + +[[xsd-config-body-schemas-util-property-path-dependency]] +====== Using to set a bean property or constructor-argument + +`PropertyPathFactoryBean` is a `FactoryBean` that evaluates a property path on a given +target object. The target object can be specified directly or via a bean name. This +value may then be used in another bean definition as a property value or constructor +argument. + +Here's an example where a path is used against another bean, by name: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + // target bean to be referenced by name + + + + + + + + + + // will result in 11, which is the value of property 'spouse.age' of bean 'person' + + + + +---- + +In this example, a path is evaluated against an inner bean: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + + +---- + +There is also a shortcut form, where the bean name is the property path. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + +---- + +This form does mean that there is no choice in the name of the bean. Any reference to it +will also have to use the same id, which is the path. Of course, if used as an inner +bean, there is no need to refer to it at all: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + +---- + +The result type may be specifically set in the actual definition. This is not necessary +for most use cases, but can be of use for some. Please see the Javadocs for more info on +this feature. + + +[[xsd-config-body-schemas-util-properties]] +===== + +Before... + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + +---- + +The above configuration uses a Spring `FactoryBean` implementation, the +`PropertiesFactoryBean`, to instantiate a `java.util.Properties` instance with values +loaded from the supplied <> location). + +After... + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + +---- + + +[[xsd-config-body-schemas-util-list]] +===== + +Before... + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + pechorin@hero.org + raskolnikov@slums.org + stavrogin@gov.org + porfiry@gov.org + + + +---- + +The above configuration uses a Spring `FactoryBean` implementation, the +`ListFactoryBean`, to create a `java.util.List` instance initialized with values taken +from the supplied `'sourceList'`. + +After... + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + pechorin@hero.org + raskolnikov@slums.org + stavrogin@gov.org + porfiry@gov.org + +---- + +You can also explicitly control the exact type of `List` that will be instantiated and +populated via the use of the `'list-class'` attribute on the `` element. For +example, if we really need a `java.util.LinkedList` to be instantiated, we could use the +following configuration: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + jackshaftoe@vagabond.org + eliza@thinkingmanscrumpet.org + vanhoek@pirate.org + d'Arcachon@nemesis.org + +---- + +If no `'list-class'` attribute is supplied, a `List` implementation will be chosen by +the container. + + +[[xsd-config-body-schemas-util-map]] +===== + +Before... + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + + + + +---- + +The above configuration uses a Spring `FactoryBean` implementation, the +`MapFactoryBean`, to create a `java.util.Map` instance initialized with key-value pairs +taken from the supplied `'sourceMap'`. + +After... + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + +---- + +You can also explicitly control the exact type of `Map` that will be instantiated and +populated via the use of the `'map-class'` attribute on the `` element. For +example, if we really need a `java.util.TreeMap` to be instantiated, we could use the +following configuration: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + +---- + +If no `'map-class'` attribute is supplied, a `Map` implementation will be chosen by the +container. + + +[[xsd-config-body-schemas-util-set]] +===== + +Before... + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + pechorin@hero.org + raskolnikov@slums.org + stavrogin@gov.org + porfiry@gov.org + + + +---- + +The above configuration uses a Spring `FactoryBean` implementation, the +`SetFactoryBean`, to create a `java.util.Set` instance initialized with values taken +from the supplied `'sourceSet'`. + +After... + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + pechorin@hero.org + raskolnikov@slums.org + stavrogin@gov.org + porfiry@gov.org + +---- + +You can also explicitly control the exact type of `Set` that will be instantiated and +populated via the use of the `'set-class'` attribute on the `` element. For +example, if we really need a `java.util.TreeSet` to be instantiated, we could use the +following configuration: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + pechorin@hero.org + raskolnikov@slums.org + stavrogin@gov.org + porfiry@gov.org + +---- + +If no `'set-class'` attribute is supplied, a `Set` implementation will be chosen by the +container. + + + +[[xsd-config-body-schemas-jee]] +==== the jee schema + +The `jee` tags deal with Java EE (Java Enterprise Edition)-related configuration issues, +such as looking up a JNDI object and defining EJB references. + +To use the tags in the `jee` schema, you need to have the following preamble at the top +of your Spring XML configuration file; the text in the following snippet references the +correct schema so that the tags in the `jee` namespace are available to you. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + +---- + + +[[xsd-config-body-schemas-jee-jndi-lookup]] +===== (simple) + +Before... + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + +---- + +After... + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + +---- + + +[[xsd-config-body-schemas-jee-jndi-lookup-environment-single]] +===== (with single JNDI environment setting) + +Before... + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + bar + + + +---- + +After... + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + foo=bar + +---- + + +[[xsd-config-body-schemas-jee-jndi-lookup-evironment-multiple]] +===== (with multiple JNDI environment settings) + +Before... + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + bar + pong + + + +---- + +After... + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + foo=bar + ping=pong + + +---- + + +[[xsd-config-body-schemas-jee-jndi-lookup-complex]] +===== (complex) + +Before... + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + +---- + +After... + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + +---- + + +[[xsd-config-body-schemas-jee-local-slsb]] +===== (simple) + +The `` tag configures a reference to an EJB Stateless SessionBean. + +Before... + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + +---- + +After... + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + +---- + + +[[xsd-config-body-schemas-jee-local-slsb-complex]] +===== (complex) + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + +---- + +After... + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + +---- + + +[[xsd-config-body-schemas-jee-remote-slsb]] +===== + +The `` tag configures a reference to a `remote` EJB Stateless +SessionBean. + +Before... + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + + +---- + +After... + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + +---- + + + +[[xsd-config-body-schemas-lang]] +==== the lang schema + +The `lang` tags deal with exposing objects that have been written in a dynamic language +such as JRuby or Groovy as beans in the Spring container. + +These tags (and the dynamic language support) are comprehensively covered in the chapter +entitled <>. Please do consult that chapter for full details on this +support and the `lang` tags themselves. + +In the interest of completeness, to use the tags in the `lang` schema, you need to have +the following preamble at the top of your Spring XML configuration file; the text in the +following snippet references the correct schema so that the tags in the `lang` namespace +are available to you. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + +---- + + + +[[xsd-config-body-schemas-jms]] +==== the jms schema + +The `jms` tags deal with configuring JMS-related beans such as Spring's +<>. These tags are detailed in the section of the +<> entitled <>. Please do consult that chapter for full +details on this support and the `jms` tags themselves. + +In the interest of completeness, to use the tags in the `jms` schema, you need to have +the following preamble at the top of your Spring XML configuration file; the text in the +following snippet references the correct schema so that the tags in the `jms` namespace +are available to you. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + +---- + + + +[[xsd-config-body-schemas-tx]] +==== the tx (transaction) schema + +The `tx` tags deal with configuring all of those beans in Spring's comprehensive support +for transactions. These tags are covered in the chapter entitled <>. + +[TIP] +==== + +You are strongly encouraged to look at the `'spring-tx.xsd'` file that ships with the +Spring distribution. This file is (of course), the XML Schema for Spring's transaction +configuration, and covers all of the various tags in the `tx` namespace, including +attribute defaults and suchlike. This file is documented inline, and thus the +information is not repeated here in the interests of adhering to the DRY (Don't Repeat +Yourself) principle. +==== + +In the interest of completeness, to use the tags in the `tx` schema, you need to have +the following preamble at the top of your Spring XML configuration file; the text in the +following snippet references the correct schema so that the tags in the `tx` namespace +are available to you. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + +---- + +[NOTE] +==== +Often when using the tags in the `tx` namespace you will also be using the tags from the +`aop` namespace (since the declarative transaction support in Spring is implemented +using AOP). The above XML snippet contains the relevant lines needed to reference the +`aop` schema so that the tags in the `aop` namespace are available to you. +==== + + + +[[xsd-config-body-schemas-aop]] +==== the aop schema + +The `aop` tags deal with configuring all things AOP in Spring: this includes Spring's +own proxy-based AOP framework and Spring's integration with the AspectJ AOP framework. +These tags are comprehensively covered in the chapter entitled <>. + +In the interest of completeness, to use the tags in the `aop` schema, you need to have +the following preamble at the top of your Spring XML configuration file; the text in the +following snippet references the correct schema so that the tags in the `aop` namespace +are available to you. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + +---- + + + +[[xsd-config-body-schemas-context]] +==== the context schema + +The `context` tags deal with `ApplicationContext` configuration that relates to plumbing +- that is, not usually beans that are important to an end-user but rather beans that do +a lot of grunt work in Spring, such as `BeanfactoryPostProcessors`. The following +snippet references the correct schema so that the tags in the `context` namespace are +available to you. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + +---- + +[NOTE] +==== +The `context` schema was only introduced in Spring 2.5. +==== + + +[[xsd-config-body-schemas-context-pphc]] +===== + +This element activates the replacement of `${...}` placeholders, resolved against the +specified properties file (as a <>). This element is +a convenience mechanism that sets up a<> for you; if you need more control over the +`PropertyPlaceholderConfigurer`, just define one yourself explicitly. + + +[[xsd-config-body-schemas-context-ac]] +===== + +Activates the Spring infrastructure for various annotations to be detected in bean +classes: Spring's <> and +<>, as well as JSR 250's `@PostConstruct`, +`@PreDestroy` and `@Resource` (if available), and JPA's `@PersistenceContext` and +`@PersistenceUnit` (if available). Alternatively, you can choose to activate the +individual `BeanPostProcessors` for those annotations explicitly. + +[NOTE] +==== +This element does __not__ activate processing of Spring's +<> annotation. Use the +<`>> element for that purpose. +==== + + +[[xsd-config-body-schemas-context-component-scan]] +===== + +This element is detailed in <>. + + +[[xsd-config-body-schemas-context-ltw]] +===== + +This element is detailed in <>. + + +[[xsd-config-body-schemas-context-sc]] +===== + +This element is detailed in <>. + + +[[xsd-config-body-schemas-context-mbe]] +===== + +This element is detailed in <>. + + + +[[xsd-config-body-schemas-tool]] +==== the tool schema + +The `tool` tags are for use when you want to add tooling-specific metadata to your +custom configuration elements. This metadata can then be consumed by tools that are +aware of this metadata, and the tools can then do pretty much whatever they want with it +(validation, etc.). + +The `tool` tags are not documented in this release of Spring as they are currently +undergoing review. If you are a third party tool vendor and you would like to contribute +to this review process, then do mail the Spring mailing list. The currently supported +`tool` tags can be found in the file `'spring-tool.xsd'` in the +`'src/org/springframework/beans/factory/xml'` directory of the Spring source +distribution. + + + +[[xsd-config-body-schemas-jdbc]] +==== the jdbc schema + +The `jdbc` tags allow you to quickly configure an embedded database or initialize an +existing data source. These tags are documented in <> +and <> respectively. + +To use the tags in the `jdbc` schema, you need to have the following preamble at the top +of your Spring XML configuration file; the text in the following snippet references the +correct schema so that the tags in the `jdbc` namespace are available to you. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + +---- + + + +[[xsd-config-body-schemas-cache]] +==== the cache schema + +The `cache` tags can be used to enable support for Spring's `@CacheEvict`, `@CachePut` +and `@Caching` annotations. It it also supports declarative XML-based caching. See +<> and <> for details. + +To use the tags in the `cache` schema, you need to have the following preamble at the +top of your Spring XML configuration file; the text in the following snippet references +the correct schema so that the tags in the `cache` namespace are available to you. + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + +---- + + + +[[xsd-config-body-schemas-beans]] +==== the beans schema + +Last but not least we have the tags in the `beans` schema. These are the same tags that +have been in Spring since the very dawn of the framework. Examples of the various tags +in the `beans` schema are not shown here because they are quite comprehensively covered +in <> (and indeed in that entire <>). + +One thing that is new to the beans tags themselves in Spring 2.0 is the idea of +arbitrary bean metadata. In Spring 2.0 it is now possible to add zero or more key / +value pairs to `` XML definitions. What, if anything, is done with this extra +metadata is totally up to your own custom logic (and so is typically only of use if you +are writing your own custom tags as described in the appendix entitled +<>). + +Find below an example of the `` tag in the context of a surrounding `` +(please note that without any logic to interpret it the metadata is effectively useless +as-is). + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + ____ + + + + +---- + +In the case of the above example, you would assume that there is some logic that will +consume the bean definition and set up some caching infrastructure using the supplied +metadata. + +
First Name:Field is required.
Last Name:Field is required.
+ +