Spring Framework Reference Documentation PDF
Spring Framework Reference Documentation PDF
1 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
4.3.2.RELEASE
Copyright 2004-2016
Copies of this document may be made for your own use and for distribution to others, provided that
you do not charge any fee for such copies and further provided that each copy contains this Copyright
Notice, whether distributed in print or electronically.
Table of Contents
25/08/2016 12:10
2 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
3 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
7.4. Dependencies
7.4.1. Dependency Injection
Constructor-based dependency injection
25/08/2016 12:10
4 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
5 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
6 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
8. Resources
8.1. Introduction
8.2. The Resource interface
8.3. Built-in Resource implementations
8.3.1. UrlResource
8.3.2. ClassPathResource
8.3.3. FileSystemResource
8.3.4. ServletContextResource
8.3.5. InputStreamResource
8.3.6. ByteArrayResource
25/08/2016 12:10
7 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
8 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
9 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
10 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
11 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
IV. Testing
13. Introduction to Spring Testing
14. Unit Testing
14.1. Mock Objects
14.1.1. Environment
14.1.2. JNDI
14.1.3. Servlet API
14.1.4. Portlet API
25/08/2016 12:10
12 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
13 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Test-managed transactions
Enabling and disabling transactions
Transaction rollback and commit behavior
Programmatic transaction management
Executing code outside of a transaction
Configuring a transaction manager
Demonstration of all transaction-related annotations
15.5.8. Executing SQL scripts
Executing SQL scripts programmatically
Executing SQL scripts declaratively with @Sql
15.5.9. TestContext Framework support classes
Spring JUnit 4 Runner
Spring JUnit 4 Rules
JUnit 4 support classes
TestNG support classes
V. Data Access
17. Transaction Management
17.1. Introduction to Spring Framework transaction
management
17.2. Advantages of the Spring Frameworks transaction
support model
25/08/2016 12:10
14 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
15 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
16 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
20.3. Hibernate
20.3.1. SessionFactory setup in a Spring container
20.3.2. Implementing DAOs based on plain Hibernate API
20.3.3. Declarative transaction demarcation
20.3.4. Programmatic transaction demarcation
20.3.5. Transaction management strategies
20.3.6. Comparing container-managed and locally defined resources
20.3.7. Spurious application server warnings with Hibernate
20.4. JDO
20.4.1. PersistenceManagerFactory setup
20.4.2. Implementing DAOs based on the plain JDO API
20.4.3. Transaction management
20.4.4. JdoDialect
25/08/2016 12:10
17 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
20.5. JPA
20.5.1. Three options for JPA setup in a Spring environment
LocalEntityManagerFactoryBean
Obtaining an EntityManagerFactory from JNDI
LocalContainerEntityManagerFactoryBean
Dealing with multiple persistence units
20.5.2. Implementing DAOs based on plain JPA
20.5.3. Transaction Management
20.5.4. JpaDialect
21.6. Castor
21.6.1. CastorMarshaller
21.6.2. Mapping
XML Schema-based Configuration
21.7. XMLBeans
21.7.1. XmlBeansMarshaller
XML Schema-based Configuration
21.8. JiBX
21.8.1. JibxMarshaller
XML Schema-based Configuration
21.9. XStream
21.9.1. XStreamMarshaller
18 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
19 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
20 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
21 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Simple binding
Form input generation macros
HTML escaping and XHTML compliance
23.9. XSLT
23.9.1. My First Words
Bean definitions
Standard MVC controller code
Document transformation
25/08/2016 12:10
22 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
23.11. JasperReports
23.11.1. Dependencies
23.11.2. Configuration
Configuring the ViewResolver
Configuring the Views
About Report Files
Using JasperReportsMultiFormatView
23.11.3. Populating the ModelAndView
23.11.4. Working with Sub-Reports
Configuring Sub-Report Files
Configuring Sub-Report Data Sources
23.11.5. Configuring Exporter Parameters
25/08/2016 12:10
23 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25.5.2. ParameterHandlerMapping
25.5.3. PortletModeParameterHandlerMapping
25.5.4. Adding HandlerInterceptors
25.5.5. HandlerInterceptorAdapter
25.5.6. ParameterMappingInterceptor
25/08/2016 12:10
24 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
VII. Integration
28. Remoting and web services using Spring
28.1. Introduction
28.2. Exposing services using RMI
28.2.1. Exporting the service using the RmiServiceExporter
28.2.2. Linking in the service at the client
25/08/2016 12:10
25 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
28.6. JMS
28.6.1. Server-side configuration
28.6.2. Client-side configuration
28.7. AMQP
28.8. Auto-detection is not implemented for remote
interfaces
28.9. Considerations when choosing a technology
28.10. Accessing RESTful services on the Client
28.10.1. RestTemplate
Working with the URI
Dealing with request and response headers
Jackson JSON Views support
28.10.2. HTTP Message Conversion
StringHttpMessageConverter
FormHttpMessageConverter
ByteArrayHttpMessageConverter
MarshallingHttpMessageConverter
MappingJackson2HttpMessageConverter
MappingJackson2XmlHttpMessageConverter
SourceHttpMessageConverter
BufferedImageHttpMessageConverter
28.10.3. Async RestTemplate
25/08/2016 12:10
26 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
31. JMX
31.1. Introduction
31.2. Exporting your beans to JMX
31.2.1. Creating an MBeanServer
31.2.2. Reusing an existing MBeanServer
31.2.3. Lazy-initialized MBeans
31.2.4. Automatic registration of MBeans
31.2.5. Controlling the registration behavior
25/08/2016 12:10
27 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
32.5. Transactions
33. Email
33.1. Introduction
25/08/2016 12:10
28 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
33.2. Usage
33.2.1. Basic MailSender and SimpleMailMessage usage
33.2.2. Using the JavaMailSender and the MimeMessagePreparator
25/08/2016 12:10
29 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Refreshable beans
Inline dynamic language source files
Understanding Constructor Injection in the context of dynamiclanguage-backed beans
35.3.2. JRuby beans
35.3.3. Groovy beans
Customizing Groovy objects via a callback
35.3.4. BeanShell beans
35.4. Scenarios
35.4.1. Scripted Spring MVC Controllers
35.4.2. Scripted Validators
25/08/2016 12:10
30 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
VIII. Appendices
37. Migrating to Spring Framework 4.x
38. Spring Annotation Programming Model
39. Classic Spring Usage
39.1. Classic ORM usage
39.1.1. Hibernate
The HibernateTemplate
Implementing Spring-based DAOs without callbacks
25/08/2016 12:10
31 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
32 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
<jee:remote-slsb/>
41.2.4. the lang schema
41.2.5. the jms schema
41.2.6. the tx (transaction) schema
41.2.7. the aop schema
41.2.8. the context schema
<property-placeholder/>
<annotation-config/>
<component-scan/>
<load-time-weaver/>
<spring-configured/>
<mbean-export/>
41.2.9. the tool schema
41.2.10. the jdbc schema
41.2.11. the cache schema
41.2.12. the beans schema
25/08/2016 12:10
33 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
34 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
your enterprise-ready applications. However, Spring is modular, allowing you to use only
those parts that you need, without having to bring in the rest. You can use the IoC
container, with any web framework on top, but you can also use only the Hibernate
integration code or the JDBC abstraction layer. The Spring Framework supports
declarative transaction management, remote access to your logic through RMI or web
services, and various options for persisting your data. It offers a full-featured MVC
framework, and enables you to integrate AOP transparently into your software.
Spring is designed to be non-intrusive, meaning that your domain logic code generally
has no dependencies on the framework itself. In your integration layer (such as the data
access layer), some dependencies on the data access technology and the Spring
libraries will exist. However, it should be easy to isolate these dependencies from the rest
of your code base.
This document is a reference guide to Spring Framework features. If you have any
requests, comments, or questions on this document, please post them on the user
mailing list. Questions on the Framework itself should be asked on StackOverflow (see
https://spring.io/questions).
25/08/2016 12:10
35 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
36 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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.
2.2 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, Messaging, and Test, as shown in the following
diagram.
Figure 2.1. Overview of the Spring Framework
The following sections list the available modules for each feature along with their artifact
25/08/2016 12:10
37 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
names and the topics they cover. Artifact names correlate to artifact IDs used in
Dependency Management tools.
25/08/2016 12:10
38 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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 spring-aspects module provides integration with AspectJ.
The spring-instrument module provides class instrumentation support and
classloader implementations to be used in certain application servers. The
spring-instrument-tomcat module contains Springs instrumentation agent for
Tomcat.
2.2.3 Messaging
Spring Framework 4 includes a 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.
25/08/2016 12:10
39 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
2.2.5 Web
The Web layer consists of the spring-web , spring-webmvc , spring-websocket , and
spring-webmvc-portlet modules.
The spring-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 an HTTP client and the
web-related parts of Springs remoting support.
The spring-webmvc module (also known as the Web-Servlet module) contains Springs
model-view-controller (MVC) and REST Web Services implementation for web
applications. Springs MVC framework provides a clean separation between domain
model code and web forms and integrates with all of the other features of the Spring
Framework.
The spring-webmvc-portlet module (also known as the Web-Portlet module) provides
the MVC implementation to be used in a Portlet environment and mirrors the functionality
of the spring-webmvc module.
2.2.6 Test
The spring-test module supports the unit testing and integration testing of Spring
components with JUnit or TestNG. It provides consistent loading of Spring
ApplicationContext s and caching of those contexts. It also provides mock objects that
you can use to test your code in isolation.
25/08/2016 12:10
40 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Springs declarative transaction management features 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
Springs 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. Springs ORM support is integrated with JPA, Hibernate 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.
Figure 2.3. Spring middle-tier using a third-party web framework
25/08/2016 12:10
41 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
42 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
When you need to access existing code through web services, you can use Springs
Hessian- , Burlap- , Rmi- or JaxRpcProxyFactory classes. Enabling remote access
to existing applications is not difficult.
Figure 2.5. EJBs - Wrapping existing POJOs
25/08/2016 12:10
43 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
The Spring Framework also provides an access and abstraction layer 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.
25/08/2016 12:10
44 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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. springcore-4.3.2.RELEASE.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-*-<version>.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.
You will find bellow the list of Spring artifacts. For a more complete description of each
modules, see Section 2.2, Modules.
ArtifactId
Description
org.springframework spring-aop
org.springframework spring-aspects
org.springframework spring-beans
org.springframework spring-context
org.springframework spring-contextsupport
25/08/2016 12:10
45 de 1194
GroupId
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
ArtifactId
org.springframework spring-core
Description
Core utilities, used by many other
Spring modules
org.springframework spring-
expression
org.springframework springinstrument
org.springframework spring-
instrumenttomcat
org.springframework spring-jdbc
org.springframework spring-jms
org.springframework springmessaging
org.springframework spring-orm
org.springframework spring-oxm
Object/XML Mapping
org.springframework spring-test
org.springframework spring-tx
org.springframework spring-web
org.springframework spring-webmvc
org.springframework spring-webmvcportlet
25/08/2016 12:10
46 de 1194
GroupId
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
ArtifactId
org.springframework springwebsocket
Description
WebSocket and SockJS
implementations, including STOMP
support
Thats it. Note the scope can be declared as runtime if you dont need to compile against
Spring APIs, which is typically the case for basic dependency injection use cases.
25/08/2016 12:10
47 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
repository (e.g. for milestones or developer snapshots), you need to specify the repository
location in your Maven configuration. For full releases:
<repositories>
<repository>
<id>io.spring.repo.maven.release</id>
<url>http://repo.spring.io/release/</url>
<snapshots><enabled>false</enabled></snapshots>
</repository>
</repositories>
For milestones:
<repositories>
<repository>
<id>io.spring.repo.maven.milestone</id>
<url>http://repo.spring.io/milestone/</url>
<snapshots><enabled>false</enabled></snapshots>
</repository>
</repositories>
25/08/2016 12:10
48 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-framework-bom</artifactId>
<version>4.3.2.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
An added benefit of using the BOM is that you no longer need to specify the <version>
attribute when depending on Spring Framework artifacts:
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
</dependency>
<dependencies>
25/08/2016 12:10
49 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
If you prefer to use 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 :
<resolvers>
<ibiblio name="io.spring.repo.maven.release"
m2compatible="true"
root="http://repo.spring.io/release/"/>
</resolvers>
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 ):
<dependency org="org.springframework"
name="spring-core" rev="4.3.2.RELEASE" conf="compile->runtime"/>
2.3.2 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
25/08/2016 12:10
50 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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. Its 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 dont 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 thats important.
25/08/2016 12:10
51 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.3.2.RELEASE</version>
<exclusions>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
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.
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
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.3.2.RELEASE</version>
<exclusions>
25/08/2016 12:10
52 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<version>1.5.8</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.5.8</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.5.8</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.14</version>
</dependency>
</dependencies>
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 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.
Using Log4J
Many people use Log4j as a logging framework for configuration and management
purposes. Its efficient and well-established, and in fact its what we use at runtime when
we build and test Spring. Spring also provides some utilities for configuring and initializing
25/08/2016 12:10
53 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
54 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
container. That option isnt 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.
25/08/2016 12:10
55 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
56 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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.
25/08/2016 12:10
57 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
58 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
59 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
60 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
configuration and infrastructure abstraction; no changes are required to use the standard
annotations.
Spring 4.1 also improves its own caching abstraction significantly:
Caches can be resolved at runtime using a CacheResolver . 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 @CacheConfig class-level annotation allows common settings to be shared at
the 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 Cache interface as a new putIfAbsent
method has been added.
25/08/2016 12:10
61 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
62 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
package.
New application context events SessionSubscribeEvent and
SessionUnsubscribeEvent published when STOMP clients subscribe and
unsubscribe.
New "websocket" scope. See Section 26.4.14, WebSocket Scope.
@SendToUser can target only a single session and does not require an authenticated
user.
@MessageMapping methods can use dot "." instead of slash "/" as path separator.
See SPR-11660.
STOMP/WebSocket monitoring info collected and logged. See Section 26.4.16,
Runtime Monitoring.
Significantly optimized and improved logging that should remain very readable and
compact even at DEBUG level.
Optimized message creation including support for temporary message mutability and
avoiding automatic message id and timestamp creation. See Javadoc of
MessageHeaderAccessor .
Close STOMP/WebSocket connections that have no activity within 60 seconds after
the WebSocket session is established. See SPR-11884.
25/08/2016 12:10
63 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
64 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
aliases for annotation attributes. The new @AliasFor annotation can be used to
declare a pair of aliased attributes within a single annotation or to declare an alias
from one attribute in a custom composed annotation to an attribute in a
meta-annotation.
The following annotations have been retrofitted with @AliasFor support in order
to provide meaningful aliases for their value attributes: @Cacheable ,
@CacheEvict , @CachePut , @ComponentScan , @ComponentScan.Filter ,
@ImportResource , @Scope , @ManagedResource , @Header , @Payload ,
@SendToUser , @ActiveProfiles , @ContextConfiguration , @Sql ,
@TestExecutionListeners , @TestPropertySource , @Transactional ,
@ControllerAdvice , @CookieValue , @CrossOrigin , @MatrixVariable ,
@RequestHeader , @RequestMapping , @RequestParam , @RequestPart ,
@ResponseStatus , @SessionAttributes , @ActionMapping ,
@RenderMapping , @EventListener , @TransactionalEventListener .
For example, @ContextConfiguration from the spring-test module is now
declared as follows:
public @interface ContextConfiguration {
@AliasFor("locations")
String[] value() default {};
@AliasFor("value")
String[] locations() default {};
// ...
}
25/08/2016 12:10
65 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
66 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
67 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
the extension point can also be used to plug in any URI template library.
OkHTTP integration with the RestTemplate .
Custom baseUrl alternative for methods in MvcUriComponentsBuilder .
Serialization/deserialization exception messages are now logged at WARN level.
Default JSON prefix has been changed from "{} && " to the safer ")]}', " one.
New RequestBodyAdvice extension point and built-in implementation to support
Jacksons @JsonView on @RequestBody method arguments.
When using GSON or Jackson 2.6+, the handler method return type is used to
improve serialization of parameterized types like List<Foo> .
Introduced ScriptTemplateView as a JSR-223 based mechanism for scripted web
views, with a focus on JavaScript view templating on Nashorn (JDK 8).
25/08/2016 12:10
68 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
69 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
70 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
71 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
example).
@ModelAttribute allows preventing data binding via binding=false attribute
(see reference).
Consistent exposure of Errors and custom Throwables to MVC exception handlers.
Consistent charset handling in HTTP message converters, including a UTF-8 default
for multipart text content.
Static resource handling uses the configured ContentNegotiationManager for
media type determination.
RestTemplate and AsyncRestTemplate support strict URI variable encoding via
DefaultUriTemplateHandler .
AsyncRestTemplate supports request interception.
25/08/2016 12:10
72 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
73 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
The Spring Framework has its own AOP framework, which is conceptually easy to
understand, and which successfully addresses the 80% sweet spot of AOP requirements
in Java enterprise programming.
Coverage of Springs integration with AspectJ (currently the richest - in terms of features and certainly most mature AOP implementation in the Java enterprise space) is also
provided.
Chapter 7, The IoC container
Chapter 8, Resources
Chapter 9, Validation, Data Binding, and Type Conversion
Chapter 10, Spring Expression Language (SpEL)
Chapter 11, Aspect Oriented Programming with Spring
Chapter 12, Spring AOP APIs
25/08/2016 12:10
74 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
exclusively in this chapter in descriptions of Springs IoC container. For more information
on using the BeanFactory instead of the ApplicationContext, refer to Section 7.16,
The BeanFactory.
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.
25/08/2016 12:10
75 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
For information about using other forms of metadata with the Spring container, see:
Annotation-based configuration: Spring 2.5 introduced support for annotation-based
configuration metadata.
Java-based configuration: 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
25/08/2016 12:10
76 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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 <bean/> elements inside a top-level <beans/> 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
Springs integration with AspectJ to configure objects that have been created outside the
control of an IoC container. See Using AspectJ to dependency-inject domain objects with
Spring.
The following example shows the basic structure of XML-based configuration metadata:
<?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="..." class="...">
<!-- collaborators and configuration for this bean go here -->
</bean>
<bean id="..." class="...">
<!-- collaborators and configuration for this bean go here -->
</bean>
<!-- more bean definitions go here -->
</beans>
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 Dependencies for more
information.
25/08/2016 12:10
77 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
After you learn about Springs IoC container, you may want to know more
about Springs Resource abstraction, as described in Chapter 8,
Resources, 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 Section 8.7, Application contexts and Resource paths.
The following example shows the service layer objects (services.xml) configuration
file:
<?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">
<!-- services -->
The following example shows the data access objects daos.xml file:
<?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">
25/08/2016 12:10
78 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
class="org.springframework.samples.jpetstore.dao.jpa.JpaAccountDao">
<!-- additional collaborators and configuration for this bean go here -->
</bean>
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
25/08/2016 12:10
79 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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 <beans/> element, must be valid XML bean definitions
according to the Spring Schema.
25/08/2016 12:10
80 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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,
Springs integration with web frameworks provides for dependency injection for various
web framework classes such as controllers and JSF-managed beans.
Explained in
class
name
scope
constructor arguments
properties
autowiring mode
25/08/2016 12:10
81 de 1194
Property
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Explained in
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
ApplicationContexts 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.
25/08/2016 12:10
82 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
83 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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 <alias/> element to accomplish this.
<alias name="fromName" alias="toName"/>
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:
<alias name="subsystemA-dataSource" alias="subsystemB-dataSource"/>
<alias name="subsystemA-dataSource" alias="myApp-dataSource" />
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 Section 7.12.3, Using the @Bean annotation for details.
25/08/2016 12:10
84 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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 nested class.
For example, if you have a class called Foo in the com.example package, and
this Foo class has a static nested 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 nested class name
from the outer class name.
For details about the mechanism for supplying arguments to the constructor (if required)
25/08/2016 12:10
85 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Dependencies.
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
Dependencies and configuration in detail.
25/08/2016 12:10
86 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
One factory class can also hold more than one factory method as shown here:
<bean id="serviceLocator" class="examples.DefaultServiceLocator">
<!-- inject any dependencies required by this locator bean -->
</bean>
<bean id="clientService"
factory-bean="serviceLocator"
factory-method="createClientServiceInstance"/>
<bean id="accountService"
factory-bean="serviceLocator"
factory-method="createAccountServiceInstance"/>
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;
}
25/08/2016 12:10
87 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
This approach shows that the factory bean itself can be managed and configured through
dependency injection (DI). See Dependencies and configuration in detail.
7.4 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.
25/08/2016 12:10
88 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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 <constructor-arg/>
element.
25/08/2016 12:10
89 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
<beans>
<bean id="foo" class="x.y.Foo">
<constructor-arg ref="bar"/>
<constructor-arg ref="baz"/>
</bean>
<bean id="bar" class="x.y.Bar"/>
<bean id="baz" class="x.y.Baz"/>
</beans>
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
<value>true</value> , Spring cannot determine the type of the value, and so cannot
match by type without help. Consider the following class:
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;
}
}
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:
<bean id="exampleBean" class="examples.ExampleBean">
<constructor-arg type="int" value="7500000"/>
<constructor-arg type="java.lang.String" value="42"/>
</bean>
Use the index attribute to specify explicitly the index of constructor arguments. For
example:
25/08/2016 12:10
90 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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 cant compile your code with debug flag (or dont want to) you can use
@ConstructorProperties JDK annotation to explicitly name your constructor arguments.
The sample class would then have to look as follows:
package examples;
public class ExampleBean {
// Fields omitted
@ConstructorProperties({"years", "ultimateAnswer"})
public ExampleBean(int years, String ultimateAnswer) {
this.years = years;
this.ultimateAnswer = ultimateAnswer;
}
}
25/08/2016 12:10
91 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
92 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
93 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
94 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
<ref bean="anotherExampleBean"/>
</property>
<!-- setter injection using the neater ref attribute -->
<property name="beanTwo" ref="yetAnotherBean"/>
<property name="integerProperty" value="1"/>
</bean>
<bean id="anotherExampleBean" class="examples.AnotherBean"/>
<bean id="yetAnotherBean" class="examples.YetAnotherBean"/>
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:
<bean id="exampleBean" class="examples.ExampleBean">
<!-- constructor injection using the nested ref element -->
<constructor-arg>
<ref bean="anotherExampleBean"/>
</constructor-arg>
<!-- constructor injection using the neater ref attribute -->
<constructor-arg ref="yetAnotherBean"/>
<constructor-arg type="int" value="1"/>
</bean>
<bean id="anotherExampleBean" class="examples.AnotherBean"/>
25/08/2016 12:10
95 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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:
<bean id="exampleBean" class="examples.ExampleBean" factory-method="createInstance"
<constructor-arg ref="anotherExampleBean"/>
<constructor-arg ref="yetAnotherBean"/>
<constructor-arg value="1"/>
</bean>
<bean id="anotherExampleBean" class="examples.AnotherBean"/>
<bean id="yetAnotherBean" class="examples.YetAnotherBean"/>
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 (...);
25/08/2016 12:10
96 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
return eb;
}
}
The following example uses the p-namespace for even more succinct XML configuration.
<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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="myDataSource" class="org.apache.commons.dbcp.BasicDataSource"
25/08/2016 12:10
97 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
destroy-method="close"
p:driverClassName="com.mysql.jdbc.Driver"
p:url="jdbc:mysql://localhost:3306/mydb"
p:username="root"
p:password="masterkaoli"/>
</beans>
The preceding XML is more succinct; however, typos are discovered at runtime rather
than design time, unless you use an IDE such as IntelliJ IDEA or the 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:
<bean id="mappings"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"
<!-- typed as a java.util.Properties -->
<property name="properties">
<value>
jdbc.driver.className=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mydb
</value>
</property>
</bean>
The Spring container converts the text inside the <value/> 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 <value/> element over the value attribute style.
25/08/2016 12:10
98 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
The above bean definition snippet is exactly equivalent (at runtime) to the following
snippet:
<bean id="theTargetBean" class="..." />
<bean id="client" class="...">
<property name="targetName" value="theTargetBean" />
</bean>
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
prototype bean, this typo and the resulting exception may only be discovered long after
the container is deployed.
A common place (at least in versions earlier than Spring 2.0) where the <idref/>
element brings value is in the configuration of AOP interceptors in a ProxyFactoryBean
bean definition. Using <idref/> elements when you specify the interceptor names
prevents you from misspelling an interceptor id.
25/08/2016 12:10
99 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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.
<ref bean="someBean"/>
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.
<!-- in the parent context -->
<bean id="accountService" class="com.foo.SimpleAccountService">
<!-- insert dependencies as required as here -->
</bean>
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.
Inner beans
A <bean/> element inside the <property/> or <constructor-arg/> elements
defines a so-called inner bean.
<bean id="outer" class="...">
<!-- instead of using a reference to a target bean, simply define the target bean
<property name="target">
<bean class="com.example.Person"> <!-- this is the inner bean -->
<property name="name" value="Fiona Apple"/>
25/08/2016 12:10
100 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
An inner bean definition does not require a defined id or name; if specified, the container
does not use such a value as an identifier. The container also ignores the scope flag on
creation: 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 or to access them independently.
As a corner case, it is possible to receive destruction callbacks from a custom scope, e.g.
for a request-scoped inner bean contained within a singleton bean: The creation of the
inner bean instance will be tied to its containing bean, but destruction callbacks allow it to
participate in the request scopes lifecycle. This is not a common scenario; inner beans
typically simply share their containing beans scope.
Collections
In the <list/> , <set/> , <map/> , and <props/> elements, you set the properties and
arguments of the Java Collection types List , Set , Map , and Properties ,
respectively.
<bean id="moreComplexObject" class="example.ComplexObject">
<!-- results in a setAdminEmails(java.util.Properties) call -->
<property name="adminEmails">
<props>
<prop key="administrator">[email protected]</prop>
<prop key="support">[email protected]</prop>
<prop key="development">[email protected]</prop>
</props>
</property>
<!-- results in a setSomeList(java.util.List) call -->
<property name="someList">
<list>
<value>a list element followed by a reference</value>
<ref bean="myDataSource" />
</list>
</property>
<!-- results in a setSomeMap(java.util.Map) call -->
<property name="someMap">
<map>
<entry key="an entry" value="just some string"/>
<entry key ="a ref" value-ref="myDataSource"/>
</map>
25/08/2016 12:10
101 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
</property>
<!-- results in a setSomeSet(java.util.Set) call -->
<property name="someSet">
<set>
<value>just some string</value>
<ref bean="myDataSource" />
</set>
</property>
</bean>
The value of a map key or value, or a set value, can also again be any of the following
elements:
bean | ref | idref | list | set | map | props | value | null
Collection merging
The Spring container also supports the merging of collections. An application developer
can define a parent-style <list/> , <map/> , <set/> or <props/> element, and have
child-style <list/> , <map/> , <set/> or <props/> elements inherit and override
values from the parent collection. That is, the child collections values are the result of
merging the elements of the parent and child collections, with the childs 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 relevant section before
continuing.
The following example demonstrates collection merging:
<beans>
<bean id="parent" abstract="true" class="example.ComplexObject">
<property name="adminEmails">
<props>
<prop key="administrator">[email protected]</prop>
<prop key="support">[email protected]</prop>
</props>
</property>
</bean>
<bean id="child" parent="parent">
<property name="adminEmails">
<!-- the merge is specified on the child collection definition -->
<props merge="true">
<prop key="sales">[email protected]</prop>
<prop key="support">[email protected]</prop>
25/08/2016 12:10
102 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
</props>
</property>
</bean>
<beans>
Notice the use of the merge=true attribute on the <props/> 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 childs
adminEmails collection with the parents adminEmails collection.
[email protected]
[email protected]
[email protected]
The child Properties collections value set inherits all property elements from the
parent <props/> , and the childs value for the support value overrides the value in the
parent collection.
This merging behavior applies similarly to the <list/> , <map/> , and <set/> collection
types. In the specific case of the <list/> element, the semantics associated with the
List collection type, that is, the notion of an ordered collection of values, is
maintained; the parents values precede all of the child lists 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.
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 Springs 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 .
public class Foo {
25/08/2016 12:10
103 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
When the accounts property of the foo bean is prepared for injection, the generics
information about the element type of the strongly-typed Map<String, Float> is
available by reflection. Thus Springs 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.
25/08/2016 12:10
104 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
</property>
</bean>
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:
<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"
25/08/2016 12:10
105 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean name="john-classic" class="com.example.Person">
<property name="name" value="John Doe"/>
<property name="spouse" ref="jane"/>
</bean>
<bean name="john-modern"
class="com.example.Person"
p:name="John Doe"
p:spouse-ref="jane"/>
<bean name="jane" class="com.example.Person">
<property name="name" value="Jane Doe"/>
</bean>
</beans>
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 <property name="spouse" ref="jane"/> 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.
25/08/2016 12:10
106 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:c="http://www.springframework.org/schema/c"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="bar" class="x.y.Bar"/>
<bean id="baz" class="x.y.Baz"/>
<!-- traditional declaration -->
<bean id="foo" class="x.y.Foo">
<constructor-arg ref="bar"/>
<constructor-arg ref="baz"/>
<constructor-arg value="[email protected]"/>
</bean>
<!-- c-namespace declaration -->
<bean id="foo" class="x.y.Foo" c:bar-ref="bar" c:baz-ref="baz" c:email="
</beans>
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:
<!-- c-namespace index declaration -->
<bean id="foo" class="x.y.Foo" c:_0-ref="bar" c:_1-ref="baz"/>
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).
25/08/2016 12:10
107 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
as all components of the path except the final property name are not null . Consider the
following bean definition.
<bean id="foo" class="foo.Bar">
<property name="fred.bob.sammy" value="123" />
</bean>
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.
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:
<bean id="beanOne" class="ExampleBean" depends-on="manager,accountDao">
<property name="manager" ref="manager" />
</bean>
<bean id="manager" class="ManagerBean" />
<bean id="accountDao" class="x.y.jdbc.JdbcAccountDao" />
25/08/2016 12:10
108 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
shutdown order.
25/08/2016 12:10
109 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Explanation
(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
byType
25/08/2016 12:10
110 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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.
25/08/2016 12:10
111 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
112 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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 this blog entry.
25/08/2016 12:10
113 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
For this dynamic subclassing to work, the class that the Spring bean
container will subclass cannot be final , and the method to be
overridden cannot be final either.
Unit-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.
Concrete methods are also necessary for component scanning which
requires concrete classes to pick up.
A further key limitation is that lookup methods wont work with factory
methods and in particular not with @Bean methods in configuration
classes, since the container is not in charge of creating the instance in
that case and therefore cannot create a runtime-generated subclass on
the fly.
Finally, objects that have been the target of method injection cannot be
serialized.
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:
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:
25/08/2016 12:10
114 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
115 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
The bean definition to deploy the original class and specify the method override would
look like this:
<bean id="myValueCalculator" class="x.y.z.MyValueCalculator">
<!-- arbitrary method replacement -->
<replaced-method name="computeValue" replacer="replacementComputeValue">
<arg-type>String</arg-type>
</replaced-method>
</bean>
<bean id="replacementComputeValue" class="a.b.c.ReplacementComputeValue"/>
You can use one or more contained <arg-type/> elements within the
<replaced-method/> 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 :
java.lang.String
25/08/2016 12:10
116 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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.
Description
(Default) Scopes a single bean definition to a single object
instance per Spring IoC container.
prototype
request
session
25/08/2016 12:10
117 de 1194
Scope
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Description
ApplicationContext .
websocket
25/08/2016 12:10
118 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Springs 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:
<bean id="accountService" class="com.foo.DefaultAccountService"/>
<!-- the following is equivalent, though redundant (singleton scope is the default) -<bean id="accountService" class="com.foo.DefaultAccountService" scope="singleton"
25/08/2016 12:10
119 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
conversational state; it was just easier for this author to reuse the core of the singleton
diagram.
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 bean
post-processor, which holds a reference to beans that need to be cleaned up.
In some respects, the Spring containers 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
Section 7.6.1, Lifecycle callbacks.)
25/08/2016 12:10
120 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
121 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
<web-app>
...
<listener>
<listener-class>
org.springframework.web.context.request.RequestContextListener
</listener-class>
</listener>
...
</web-app>
Alternatively, if there are issues with your listener setup, consider using Springs
RequestContextFilter . The filter mapping depends on the surrounding web
application configuration, so you have to change it as appropriate.
<web-app>
...
<filter>
<filter-name>requestContextFilter</filter-name>
<filter-class>org.springframework.web.filter.RequestContextFilter</filter-clas
</filter>
<filter-mapping>
<filter-name>requestContextFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
...
</web-app>
Request scope
Consider the following XML configuration for a bean definition:
<bean id="loginAction" class="com.foo.LoginAction" scope="request"/>
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
25/08/2016 12:10
122 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Session scope
Consider the following XML configuration for a bean definition:
<bean id="userPreferences" class="com.foo.UserPreferences" scope="session"/>
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.
When using annotation-driven components or Java Config, the @SessionScope
annotation can be used to assign a component to the session scope.
@SessionScope
@Component
public class UserPreferences {
// ...
}
The globalSession scope is similar to the standard HTTP Session scope (described
25/08/2016 12:10
123 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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 globalSession 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 globalSession scope, the standard HTTP Session scope is used, and no
error is raised.
Application scope
Consider the following XML configuration for a bean definition:
<bean id="appPreferences" class="com.foo.AppPreferences" scope="application"
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' (for which there may be several in any given web application), and it
is actually exposed and therefore visible as a ServletContext attribute.
When using annotation-driven components or Java Config, the @ApplicationScope
annotation can be used to assign a component to the application scope.
@ApplicationScope
@Component
public class AppPreferences {
// ...
}
25/08/2016 12:10
124 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
You may also use <aop:scoped-proxy/> between beans that are scoped
as singleton , with the reference then going through an intermediate
proxy that is serializable and therefore able to re-obtain the target singleton
bean on deserialization.
When declaring <aop:scoped-proxy/> against a bean of scope
prototype , every method call on the shared proxy will lead to the creation
of a new target instance which the call is then being forwarded to.
Also, scoped proxies are not the only way to access beans from shorter
scopes in a lifecycle-safe fashion. You may also simply declare your
injection point (i.e. the constructor/setter argument or autowired field) as
ObjectFactory<MyTargetBean> , allowing for a getObject() call to
retrieve the current instance on demand every time it is needed - without
holding on to the instance or storing it separately.
The JSR-330 variant of this is called Provider , used with a
Provider<MyTargetBean> declaration and a corresponding get() call
for every retrieval attempt. See here for more details on JSR-330 overall.
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.
<?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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<!-- an HTTP Session-scoped bean exposed as a proxy -->
<bean id="userPreferences" class="com.foo.UserPreferences" scope="session"
<!-- instructs the container to proxy the surrounding bean -->
<aop:scoped-proxy/>
</bean>
<!-- a singleton-scoped bean injected with a proxy to the above bean -->
<bean id="userService" class="com.foo.SimpleUserService">
<!-- a reference to the proxied userPreferences bean -->
<property name="userPreferences" ref="userPreferences"/>
</bean>
</beans>
25/08/2016 12:10
125 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
bean definition (see the section called Choosing the type of proxy to create and
Chapter 41, XML Schema-based configuration). Why do definitions of beans scoped at
the request , session , globalSession and custom-scope levels require the
<aop:scoped-proxy/> element? Lets examine the following singleton bean definition
and contrast it with what you need to define for the aforementioned scopes (note that the
following userPreferences bean definition as it stands is incomplete).
<bean id="userPreferences" class="com.foo.UserPreferences" scope="session"/>
<bean id="userManager" class="com.foo.UserManager">
<property name="userPreferences" ref="userPreferences"/>
</bean>
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:
<bean id="userPreferences" class="com.foo.UserPreferences" scope="session">
<aop:scoped-proxy/>
</bean>
25/08/2016 12:10
126 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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 <aop:scoped-proxy/> 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.
<!-- DefaultUserPreferences implements the UserPreferences interface -->
<bean id="userPreferences" class="com.foo.DefaultUserPreferences" scope="session"
<aop:scoped-proxy proxy-target-class="false"/>
</bean>
<bean id="userManager" class="com.foo.UserManager">
<property name="userPreferences" ref="userPreferences"/>
</bean>
25/08/2016 12:10
127 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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 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).
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.
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.
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.
String getConversationId()
25/08/2016 12:10
128 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
You then create bean definitions that adhere to the scoping rules of your custom Scope :
<bean id="..." class="..." scope="thread">
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:
<?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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<bean class="org.springframework.beans.factory.config.CustomScopeConfigurer"
<property name="scopes">
<map>
<entry key="thread">
<bean class="org.springframework.context.support.SimpleThreadScope
</entry>
</map>
</property>
25/08/2016 12:10
129 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
</bean>
<bean id="bar" class="x.y.Bar" scope="thread">
<property name="name" value="Rick"/>
<aop:scoped-proxy/>
</bean>
<bean id="foo" class="x.y.Foo">
<property name="bar" ref="bar"/>
</bean>
</beans>
25/08/2016 12:10
130 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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:
void afterPropertiesSet() throws Exception;
25/08/2016 12:10
131 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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:
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 @PreDestroy
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
<bean/> . With Java config, you use the destroyMethod attribute of @Bean , see the
section called Receiving lifecycle callbacks. For example, the following definition:
<bean id="exampleInitBean" class="examples.ExampleBean" destroy-method="cleanup"
public class ExampleBean {
public void cleanup() {
// do some destruction work (like releasing pooled connections)
}
}
25/08/2016 12:10
132 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
133 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
134 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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
Any Spring-managed object may implement that interface. Then, when the
ApplicationContext itself receives start and stop signals, e.g. for a stop/restart
scenario at runtime, it will cascade those calls to all Lifecycle implementations defined
within that context. It does this by delegating to a LifecycleProcessor :
public interface LifecycleProcessor extends Lifecycle {
25/08/2016 12:10
135 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
void onRefresh();
void onClose();
}
25/08/2016 12:10
136 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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, its 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 callbacks run() method after that implementations
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:
25/08/2016 12:10
137 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
If you are using Springs 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 ConfigurableApplicationContext interface:
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public final class Boot {
public static void main(final String[] args) throws Exception {
ConfigurableApplicationContext 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...
}
}
25/08/2016 12:10
138 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
The callback is invoked after population of normal bean properties but before an
initialization callback such as InitializingBean afterPropertiesSet or a custom
init-method.
25/08/2016 12:10
139 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Injected
Explained in
Dependency
ApplicationContextAware
Declaring
Section 7.6.2,
ApplicationContext
ApplicationContextAware
and BeanNameAware
ApplicationEventPublisherAware
BeanClassLoaderAware
BeanFactoryAware
enclosing
Capabilities of the
ApplicationContext
ApplicationContext
Section 7.3.2,
Instantiating beans
Declaring
Section 7.6.2,
BeanFactory
ApplicationContextAware
and BeanNameAware
BeanNameAware
Section 7.6.2,
bean
ApplicationContextAware
and BeanNameAware
BootstrapContextAware
Resource adapter
BootstrapContext
the container runs in.
Typically available only
in JCA aware
ApplicationContext s
LoadTimeWeaverAware
Section 11.8.4,
processing class
25/08/2016 12:10
140 de 1194
Name
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Injected
Explained in
Dependency
MessageSourceAware
resolving messages
Capabilities of the
ApplicationContext
parametrization and
internationalization)
NotificationPublisherAware
PortletConfigAware
Section 31.7,
publisher
Notifications
Current
PortletConfig the
Framework
Current
PortletContext the
Framework
Chapter 8, Resources
low-level access to
resources
ServletConfigAware
Current
ServletConfig the
framework
Current
ServletContext the
framework
25/08/2016 12:10
141 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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.
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 parents property values.
A child bean definition inherits scope, constructor argument values, property values, and
method overrides from the parent, with the option to add new values. Any scope,
initialization method, destroy method, and/or static factory method settings that you
25/08/2016 12:10
142 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
The remaining settings are always taken from the child definition: depends on, autowire
mode, dependency check, singleton, 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:
<bean id="inheritedTestBeanWithoutClass" abstract="true">
<property name="name" value="parent"/>
<property name="age" value="1"/>
</bean>
<bean id="inheritsWithClass" class="org.springframework.beans.DerivedTestBean"
parent="inheritedTestBeanWithoutClass" init-method="initialize">
<property name="name" value="override"/>
<!-- age will inherit the value of 1 from the parent bean definition-->
</bean>
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 containers internal preInstantiateSingletons()
method ignores bean definitions that are defined as abstract.
25/08/2016 12:10
143 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
144 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
145 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
The following examples show how to write, register, and use BeanPostProcessor s in an
ApplicationContext .
25/08/2016 12:10
146 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
<lang:groovy id="messenger"
script-source="classpath:org/springframework/scripting/groovy/Messenger.gr
<lang:property name="message" value="Fiona Apple Is Just So Dreamy."
</lang:groovy>
<!-when the above bean (messenger) is instantiated, this custom
BeanPostProcessor implementation will output the fact to the system console
-->
<bean class="scripting.InstantiationTracingBeanPostProcessor"/>
</beans>
25/08/2016 12:10
147 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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 Section 7.8.1, Customizing
beans using a BeanPostProcessor). 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, BeanFactoryPostProcessor s 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
25/08/2016 12:10
148 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
149 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
The actual values come from another file in the standard Java Properties format:
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.
<context:property-placeholder location="classpath:com/foo/jdbc.properties"/>
25/08/2016 12:10
150 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
useful when you have to pick a particular implementation class at runtime. For example:
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfi
<property name="locations">
<value>classpath:com/foo/strategy.properties</value>
</property>
<property name="properties">
<value>custom.strategy.class=com.foo.DefaultStrategy</value>
</property>
</bean>
<bean id="serviceStrategy" class="${custom.strategy.class}"/>
If the class cannot be resolved at runtime to a valid class, resolution of the bean fails when it
to be created, which is during the preInstantiateSingletons() phase of an
ApplicationContext for a non-lazy-init bean.
For example:
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
foo.fred.bob.sammy=123
25/08/2016 12:10
151 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
i. the sammy property of the bob property of the fred property of the foo bean is
set to the scalar value 123 .
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.
25/08/2016 12:10
152 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
153 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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):
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<context:annotation-config/>
</beans>
7.9.1 @Required
The @Required annotation applies to bean property setter methods, as in the following
example:
public class SimpleMovieLister {
25/08/2016 12:10
154 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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.
7.9.2 @Autowired
JSR 330s @Inject annotation can be used in place of Springs
@Autowired annotation in the examples below. See here for more details.
25/08/2016 12:10
155 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
As expected, you can also apply the @Autowired annotation to "traditional" setter
methods:
public class SimpleMovieLister {
private MovieFinder movieFinder;
@Autowired
public void setMovieFinder(MovieFinder movieFinder) {
this.movieFinder = movieFinder;
}
// ...
}
You can also apply the annotation to methods with arbitrary names and/or multiple
arguments:
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 fields as well and even mix it with constructors:
public class MovieRecommender {
private final CustomerPreferenceDao customerPreferenceDao;
25/08/2016 12:10
156 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
@Autowired
private MovieCatalog movieCatalog;
@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:
public class MovieRecommender {
@Autowired
private MovieCatalog[] movieCatalogs;
// ...
}
Even typed Maps can be autowired as long as the expected key type is String . The
25/08/2016 12:10
157 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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.
public class SimpleMovieLister {
private MovieFinder movieFinder;
@Autowired(required=false)
public void setMovieFinder(MovieFinder movieFinder) {
this.movieFinder = movieFinder;
}
// ...
}
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.
@Autowireds 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.
25/08/2016 12:10
158 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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.
public class MovieRecommender {
@Autowired
private ApplicationContext context;
public MovieRecommender() {
}
// ...
}
25/08/2016 12:10
159 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
@Bean
@Primary
public MovieCatalog firstMovieCatalog() { ... }
@Bean
public MovieCatalog secondMovieCatalog() { ... }
// ...
}
With such configuration, the following MovieRecommender will be autowired with the
firstMovieCatalog .
public class MovieRecommender {
@Autowired
private MovieCatalog movieCatalog;
// ...
}
25/08/2016 12:10
160 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
25/08/2016 12:10
161 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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:annotation-config/>
<bean class="example.SimpleMovieCatalog">
<qualifier value="main"/>
<!-- inject any dependencies required by this bean -->
</bean>
<bean class="example.SimpleMovieCatalog">
<qualifier value="action"/>
<!-- inject any dependencies required by this bean -->
</bean>
<bean id="movieRecommender" class="example.MovieRecommender"/>
</beans>
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<MovieCatalog> . 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<MovieCatalog> annotated with @Qualifier("action") .
25/08/2016 12:10
162 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
You can create your own custom qualifier annotations. Simply define an annotation and
provide the @Qualifier annotation within your definition:
@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
25/08/2016 12:10
163 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
String value();
}
Then you can provide the custom qualifier on autowired fields and parameters:
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
<qualifier/> tags as sub-elements of the <bean/> 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.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<context:annotation-config/>
<bean class="example.SimpleMovieCatalog">
<qualifier type="Genre" value="Action"/>
<!-- inject any dependencies required by this bean -->
</bean>
<bean class="example.SimpleMovieCatalog">
25/08/2016 12:10
164 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
In Section 7.10, Classpath scanning and managed components, you will see an
annotation-based alternative to providing the qualifier metadata in XML. Specifically, see
Section 7.10.8, Providing qualifier metadata with annotations.
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:
@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface Offline {
}
You can also define custom qualifier annotations that accept named attributes in addition
25/08/2016 12:10
165 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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:
@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface MovieQualifier {
String genre();
Format format();
}
The fields to be autowired are annotated with the custom qualifier and include values for
both attributes: genre and format .
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;
// ...
}
25/08/2016 12:10
166 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
demonstrates that bean meta attributes may be used instead of the <qualifier/>
sub-elements. If available, the <qualifier/> and its attributes take precedence, but the
autowiring mechanism falls back on the values provided within the <meta/> tags if no
such qualifier is present, as in the last two bean definitions in the following example.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<context:annotation-config/>
<bean class="example.SimpleMovieCatalog">
<qualifier type="MovieQualifier">
<attribute key="format" value="VHS"/>
<attribute key="genre" value="Action"/>
</qualifier>
<!-- inject any dependencies required by this bean -->
</bean>
<bean class="example.SimpleMovieCatalog">
<qualifier type="MovieQualifier">
<attribute key="format" value="VHS"/>
<attribute key="genre" value="Comedy"/>
</qualifier>
<!-- inject any dependencies required by this bean -->
</bean>
<bean class="example.SimpleMovieCatalog">
<meta key="format" value="DVD"/>
<meta key="genre" value="Action"/>
<!-- inject any dependencies required by this bean -->
</bean>
<bean class="example.SimpleMovieCatalog">
<meta key="format" value="BLURAY"/>
<meta key="genre" value="Comedy"/>
<!-- inject any dependencies required by this bean -->
</bean>
</beans>
25/08/2016 12:10
167 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Assuming that beans above implement a generic interface, i.e. Store<String> and
Store<Integer> , you can @Autowire the Store interface and the generic will be
used as a qualifier:
@Autowired
private Store<String> s1; // <String> qualifier, injects the stringStore bean
@Autowired
private Store<Integer> s2; // <Integer> qualifier, injects the integerStore bean
Generic qualifiers also apply when autowiring Lists, Maps and Arrays:
// Inject all Store beans as long as they have an <Integer> generic
// Store<String> beans will not appear in this list
@Autowired
private List<Store<Integer>> s;
7.9.6 CustomAutowireConfigurer
The CustomAutowireConfigurer is a BeanFactoryPostProcessor that enables you
to register your own custom qualifier annotation types even if they are not annotated with
Springs @Qualifier annotation.
25/08/2016 12:10
168 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
class="org.springframework.beans.factory.annotation.CustomAutowireConfigurer"
<property name="customQualifierTypes">
<set>
<value>example.CustomQualifier</value>
</set>
</property>
</bean>
7.9.7 @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:
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
25/08/2016 12:10
169 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
bean property name. So the following example is going to have the bean with name
"movieFinder" injected into its setter method:
public class SimpleMovieLister {
private MovieFinder movieFinder;
@Resource
public void setMovieFinder(MovieFinder movieFinder) {
this.movieFinder = movieFinder;
}
}
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 Springs SimpleJndiBeanFactory
explicitly. However, it is recommended that you rely on the default behavior
and simply use Springs 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 .
public class MovieRecommender {
@Resource
private CustomerPreferenceDao customerPreferenceDao;
@Resource
private ApplicationContext context;
public MovieRecommender() {
25/08/2016 12:10
170 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
// ...
}
25/08/2016 12:10
171 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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.
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.
7.10.2 Meta-annotations
Many of the annotations provided by Spring can be used as meta-annotations in your
25/08/2016 12:10
172 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
173 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
@Service
@SessionScope(proxyMode = ScopedProxyMode.INTERFACES)
public class SessionScopedUserService implements UserService {
// ...
}
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/semicolon/space-separated list that includes the parent package of each class.)
@Configuration
@ComponentScan(basePackages = "org.example")
public class AppConfig {
...
}
25/08/2016 12:10
174 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
for concision, the above may have used the value attribute of the
annotation, i.e. ComponentScan("org.example")
25/08/2016 12:10
175 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Example Expression
Description
Type
annotation
org.example.SomeAnnotation
(default)
assignable
org.example.SomeClass
aspectj
org.example..*Service+
regex
org\.example\.Default.*
custom
org.example.MyTypeFilter
org.springframework.core.type .TypeFilt
interface.
The following example shows the configuration ignoring all @Repository annotations
and using "stub" repositories instead.
25/08/2016 12:10
176 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
@Configuration
@ComponentScan(basePackages = "org.example",
includeFilters = @Filter(type = FilterType.REGEX, pattern = ".*Stub.*Repositor
excludeFilters = @Filter(Repository.class))
public class AppConfig {
...
}
25/08/2016 12:10
177 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
}
}
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.
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:
@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(spouse);
tb.setCountry(country);
return tb;
}
@Bean
private TestBean privateInstance() {
return new TestBean("privateInstance", i++);
25/08/2016 12:10
178 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
}
@Bean
@RequestScope
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 #{ <expression> } . 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 but rather go through the
container in order to provide the usual lifecycle management and proxying of Spring
beans even when referring to other beans via programmatic calls to @Bean methods. In
contrast, invoking a method or field in an @Bean method within a plain @Component
class has standard Java semantics, with no special CGLIB processing or other
constraints applying.
25/08/2016 12:10
179 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
180 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
If you do not want to rely on the default bean-naming strategy, you can
provide a custom bean-naming strategy. First, implement the
BeanNameGenerator interface, and be sure to include a default no-arg
constructor. Then, provide the fully-qualified class name when configuring
the scanner:
@Configuration
@ComponentScan(basePackages = "org.example", nameGenerator = MyNameGenerator.class)
public class AppConfig {
...
}
<beans>
<context:component-scan base-package="org.example"
name-generator="org.example.MyNameGenerator" />
</beans>
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.
For details on web-specific scopes, see Section 7.5.4, Request, session, global session,
application, and WebSocket scopes.
To provide a custom strategy for scope resolution rather than relying on the
25/08/2016 12:10
181 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
@Configuration
@ComponentScan(basePackages = "org.example", scopeResolver = MyScopeResolver.class)
public class AppConfig {
...
}
<beans>
<context:component-scan base-package="org.example"
scope-resolver="org.example.MyScopeResolver" />
</beans>
When using certain non-singleton scopes, it may be necessary to generate proxies for the
scoped objects. The reasoning is described in the section called Scoped beans as
dependencies. 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:
@Configuration
@ComponentScan(basePackages = "org.example", scopedProxy = ScopedProxyMode.INTERFACES)
public class AppConfig {
...
}
<beans>
<context:component-scan base-package="org.example"
scoped-proxy="interfaces" />
</beans>
25/08/2016 12:10
182 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
183 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
As with @Autowired , it is possible to use @Inject at the field level, method level and
constructor-argument level. Furthermore, you may declare your injection point as a
Provider , allowing for on-demand access to beans of shorter scopes or lazy access to
other beans through a Provider.get() call. As a variant of the example above:
import javax.inject.Inject;
import javax.inject.Provider;
public class SimpleMovieLister {
private Provider<MovieFinder> movieFinder;
public void listMovies() {
this.movieFinder.get().findMovies(...);
...
}
}
If you would like to use a qualified name for the dependency that should be injected, you
should use the @Named annotation as follows:
import javax.inject.Inject;
import javax.inject.Named;
public class SimpleMovieLister {
25/08/2016 12:10
184 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
It is very common to use @Component without specifying a name for the component.
@Named can be used in a similar fashion:
import javax.inject.Inject;
import javax.inject.Named;
@Named
public class SimpleMovieLister {
private MovieFinder movieFinder;
@Inject
public void setMovieFinder(MovieFinder movieFinder) {
25/08/2016 12:10
185 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
}
// ...
}
When using @Named , it is possible to use component scanning in the exact same way as
when using Spring annotations:
@Configuration
@ComponentScan(basePackages = "org.example")
public class AppConfig {
...
}
javax.inject.*
@Inject
@Component
@Named
@Scope("singleton") @Singleton
25/08/2016 12:10
186 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Spring
javax.inject.*
@Qualifier
@Qualifier /
javax.inject.Qualifier is just a
@Named
@Value
no equivalent
@Required
no equivalent
@Lazy
no equivalent
ObjectFactory
Provider
javax.inject.Provider is a direct
alternative to Springs ObjectFactory ,
just with a shorter get() method
name. It can also be used in
combination with Springs @Autowired
or with non-annotated constructors and
setter methods.
25/08/2016 12:10
187 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
initializes a new object to be managed by the Spring IoC container. For those familiar with
Springs <beans/> XML configuration the @Bean annotation plays the same role as the
<bean/> 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:
@Configuration
public class AppConfig {
@Bean
public MyService myService() {
return new MyServiceImpl();
}
}
The AppConfig class above would be equivalent to the following Spring <beans/>
XML:
<beans>
<bean id="myService" class="com.acme.services.MyServiceImpl"/>
</beans>
25/08/2016 12:10
188 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Java-based configuration.
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:
public static void main(String[] args) {
ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.
MyService myService = ctx.getBean(MyService.class);
myService.doStuff();
}
The above assumes that MyServiceImpl , Dependency1 and Dependency2 use Spring
25/08/2016 12:10
189 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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:
25/08/2016 12:10
190 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
<web-app>
<!-- Configure ContextLoaderListener to use AnnotationConfigWebApplicationContext
instead of the default XmlWebApplicationContext -->
<context-param>
<param-name>contextClass</param-name>
<param-value>
org.springframework.web.context.support.AnnotationConfigWebApplicationCont
</param-value>
</context-param>
<!-- Bootstrap the root application context as usual using ContextLoaderListener <listener>
<listener-class>org.springframework.web.context.ContextLoaderListener
</listener>
<!-- Declare a Spring MVC DispatcherServlet as usual -->
<servlet>
<servlet-name>dispatcher</servlet-name>
25/08/2016 12:10
191 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-clas
<!-- Configure DispatcherServlet to use AnnotationConfigWebApplicationContext
instead of the default XmlWebApplicationContext -->
<init-param>
<param-name>contextClass</param-name>
<param-value>
org.springframework.web.context.support.AnnotationConfigWebApplication
</param-value>
</init-param>
<!-- Again, config locations must consist of one or more comma- or space-delim
and fully-qualified @Configuration classes -->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>com.acme.web.MvcConfig</param-value>
</init-param>
</servlet>
<!-- map all requests for /app/* to the dispatcher servlet -->
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/app/*</url-pattern>
</servlet-mapping>
</web-app>
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 methods 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:
@Configuration
public class AppConfig {
@Bean
public TransferService transferService() {
25/08/2016 12:10
192 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Bean dependencies
A @Bean annotated method can have an arbitrary number of parameters describing the
dependencies required to build that bean. For instance if our TransferService requires
an AccountRepository we can materialize that dependency via a method parameter:
@Configuration
public class AppConfig {
@Bean
public TransferService transferService(AccountRepository accountRepository) {
return new TransferServiceImpl(accountRepository);
}
}
25/08/2016 12:10
193 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
By default, beans defined using Java config that have a public close or
shutdown method are automatically enlisted with a destruction callback. If
you have a public close or shutdown method and you do not wish for it
to be called when the container shuts down, simply add
@Bean(destroyMethod="") to your bean definition to disable the default
(inferred) mode.
You may want to do that by default for a resource that you acquire via JNDI
as its lifecycle is managed outside the application. In particular, make sure
to always do it for a DataSource as it is known to be problematic on Java
EE application servers.
@Bean(destroyMethod="")
25/08/2016 12:10
194 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Also, with @Bean methods, you will typically choose to use programmatic
JNDI lookups: either using Springs
JndiTemplate / JndiLocatorDelegate helpers or straight JNDI
InitialContext usage, but not the JndiObjectFactoryBean variant
which would force you to declare the return type as the FactoryBean type
instead of the actual target type, making it harder to use for cross-reference
calls in other @Bean methods that intend to refer to the provided resource
here.
Of course, in the case of Foo above, it would be equally as valid to call the init()
method directly during construction:
@Configuration
public class AppConfig {
@Bean
public Foo foo() {
Foo foo = new Foo();
foo.init();
return foo;
}
// ...
}
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!
25/08/2016 12:10
195 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
@Configuration
public class MyConfiguration {
@Bean
@Scope("prototype")
public Encryptor encryptor() {
// ...
}
}
25/08/2016 12:10
196 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
@Bean(name = "myFoo")
public Foo foo() {
return new Foo();
}
}
Bean aliasing
As discussed in Section 7.3.1, Naming beans, 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.
@Configuration
public class AppConfig {
@Bean(name = { "dataSource", "subsystemA-dataSource", "subsystemB-dataSource" })
public DataSource dataSource() {
// instantiate, configure and return DataSource bean...
}
}
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 @Description annotation can be used:
@Configuration
public class AppConfig {
@Bean
@Description("Provides a basic example of a bean")
public Foo foo() {
return new Foo();
}
}
25/08/2016 12:10
197 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
In the example above, the foo bean receives a reference to bar via constructor
injection.
25/08/2016 12:10
198 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
@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();
}
}
}
25/08/2016 12:10
199 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
return clientService;
}
@Bean
public ClientService clientService2() {
ClientServiceImpl clientService = new ClientServiceImpl();
clientService.setClientDao(clientDao());
return clientService;
}
@Bean
public ClientDao clientDao() {
return new ClientDaoImpl();
}
}
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
25/08/2016 12:10
200 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Much as the <import/> element is used within Spring XML files to aid in modularizing
configurations, the @Import annotation allows for loading @Bean definitions from
another configuration class:
@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:
public static void main(String[] args) {
ApplicationContext ctx = new AnnotationConfigApplicationContext(ConfigB.
// 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.
25/08/2016 12:10
201 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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. As we already discussed, @Bean method can
have an arbitrary number of parameters describing the bean dependencies. Lets
consider a more real-world scenario with several @Configuration classes, each
depending on beans declared in the others:
@Configuration
public class ServiceConfig {
@Bean
public TransferService transferService(AccountRepository accountRepository) {
return new TransferServiceImpl(accountRepository);
}
}
@Configuration
public class RepositoryConfig {
@Bean
public AccountRepository accountRepository(DataSource dataSource) {
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.
// everything wires up across configuration classes...
TransferService transferService = ctx.getBean(TransferService.class);
transferService.transfer(100.00, "A123", "C456");
}
25/08/2016 12:10
202 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
There is another way to achieve the same result. Remember that @Configuration
classes are ultimately just another bean in the container: This means that they can take
advantage of @Autowired and @Value injection etc just like any other bean!
Make sure that the dependencies you inject that way are of the simplest
kind only. @Configuration classes are processed quite early during the
initialization of the context and forcing a dependency to be injected this way
may lead to unexpected early initialization. Whenever possible, resort to
parameter-based injection as in the example above.
Also, be particularly careful with BeanPostProcessor and
BeanFactoryPostProcessor definitions via @Bean . Those should usually
be declared as static @Bean methods, not triggering the instantiation of
their containing configuration class. Otherwise, @Autowired and @Value
wont work on the configuration class itself since it is being created as a
bean instance too early.
@Configuration
public class ServiceConfig {
@Autowired
private AccountRepository accountRepository;
@Bean
public TransferService transferService() {
return new TransferServiceImpl(accountRepository);
}
}
@Configuration
public class RepositoryConfig {
private final DataSource dataSource;
@Autowired
public RepositoryConfig(DataSource dataSource) {
this.dataSource = dataSource;
}
@Bean
public AccountRepository accountRepository() {
return new JdbcAccountRepository(dataSource);
}
25/08/2016 12:10
203 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
}
@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.
// everything wires up across configuration classes...
TransferService transferService = ctx.getBean(TransferService.class);
transferService.transfer(100.00, "A123", "C456");
}
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? Its
not explicit in the code, and this may be just fine. Remember that the 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:
@Configuration
public class ServiceConfig {
25/08/2016 12:10
204 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
@Autowired
private RepositoryConfig repositoryConfig;
@Bean
public TransferService transferService() {
// navigate 'through' the config class to the @Bean method!
return new TransferServiceImpl(repositoryConfig.accountRepository());
}
}
25/08/2016 12:10
205 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
@Configuration
@Import({ServiceConfig.class, DefaultRepositoryConfig.class}) // import the concrete c
public class SystemTestConfig {
@Bean
public DataSource dataSource() {
// return DataSource
}
}
public static void main(String[] args) {
ApplicationContext ctx = new AnnotationConfigApplicationContext(SystemTestConfig.
TransferService transferService = ctx.getBean(TransferService.class);
transferService.transfer(100.00, "A123", "C456");
}
25/08/2016 12:10
206 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
if (attrs != null) {
for (Object value : attrs.get("value")) {
if (context.getEnvironment().acceptsProfiles(((String[]) value))) {
return true;
}
}
return false;
}
}
return true;
}
25/08/2016 12:10
207 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
@Bean
public AccountRepository accountRepository() {
return new JdbcAccountRepository(dataSource);
}
@Bean
public TransferService transferService() {
return new TransferService(accountRepository());
}
}
system-test-config.xml:
<beans>
<!-- enable processing of annotations such as @Autowired and @Configuration -->
<context:annotation-config/>
<context:property-placeholder location="classpath:/com/acme/jdbc.properties"
<bean class="com.acme.AppConfig"/>
<bean class="org.springframework.jdbc.datasource.DriverManagerDataSource"
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
</beans>
jdbc.properties:
jdbc.url=jdbc:hsqldb:hsql://localhost/xdb
jdbc.username=sa
jdbc.password=
25/08/2016 12:10
208 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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 dont need to explicitly declare
<context:annotation-config/> , because <context:component-scan/> enables
the same functionality.
system-test-config.xml:
<beans>
<!-- picks up and registers AppConfig as a bean definition -->
<context:component-scan base-package="com.acme"/>
<context:property-placeholder location="classpath:/com/acme/jdbc.properties"
<bean class="org.springframework.jdbc.datasource.DriverManagerDataSource"
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
</beans>
25/08/2016 12:10
209 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
@Value("${jdbc.username}")
private String username;
@Value("${jdbc.password}")
private String password;
@Bean
public DataSource dataSource() {
return new DriverManagerDataSource(url, username, password);
}
}
properties-config.xml
<beans>
<context:property-placeholder location="classpath:/com/acme/jdbc.properties"
</beans>
jdbc.properties
jdbc.url=jdbc:hsqldb:hsql://localhost/xdb
jdbc.username=sa
jdbc.password=
25/08/2016 12:10
210 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
from them.
Lets 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 servers JNDI directory. Our dataSource bean now looks like this:
@Bean(destroyMethod="")
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 <import/>
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.
25/08/2016 12:10
211 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
@Profile
The @Profile annotation allows you 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:
@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();
}
}
@Configuration
@Profile("production")
public class JndiDataConfig {
@Bean(destroyMethod="")
public DataSource dataSource() throws Exception {
Context ctx = new InitialContext();
return (DataSource) ctx.lookup("java:comp/env/jdbc/datasource");
}
}
As mentioned before, with @Bean methods, you will typically choose to use
programmatic JNDI lookups: either using Springs
JndiTemplate / JndiLocatorDelegate helpers or the straight JNDI
InitialContext usage shown above, but not the
JndiObjectFactoryBean variant which would force you to declare the
return type as the FactoryBean type.
25/08/2016 12:10
212 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
@Profile can also be declared at the method level to include only one particular bean of
a configuration class:
@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");
}
}
25/08/2016 12:10
213 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
It is also possible to avoid that split and nest <beans/> elements within the same file:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jdbc="http://www.springframework.org/schema/jdbc"
25/08/2016 12:10
214 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
xmlns:jee="http://www.springframework.org/schema/jee"
xsi:schemaLocation="...">
<!-- other bean definitions -->
<beans profile="dev">
<jdbc:embedded-database id="dataSource">
<jdbc:script location="classpath:com/bank/config/sql/schema.sql"
<jdbc:script location="classpath:com/bank/config/sql/test-data.sql"
</jdbc:embedded-database>
</beans>
<beans profile="production">
<jee:jndi-lookup id="dataSource" jndi-name="java:comp/env/jdbc/datasource"
</beans>
</beans>
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.
Activating a profile
Now that we have updated our configuration, we still need to instruct Spring 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 Environment API which is available via an
ApplicationContext :
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.getEnvironment().setActiveProfiles("dev");
ctx.register(SomeConfig.class, StandaloneDataConfig.class, JndiDataConfig.class
ctx.refresh();
25/08/2016 12:10
215 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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:
ctx.getEnvironment().setActiveProfiles("profile1", "profile2");
Default profile
The default profile represents the profile that is enabled by default. Consider the
following:
@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 the default profile can be changed using setDefaultProfiles() on the
Environment or declaratively using the spring.profiles.default property.
25/08/2016 12:10
216 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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 PropertySource objects. A PropertySource is a
simple abstraction over any source of key-value pairs, and Springs
StandardEnvironment is configured with two PropertySource objectsone
representing the set of JVM system properties (a la System.getProperties() ) and one
representing the set of system environment variables (a la System.getenv() ).
Most importantly, the entire mechanism is configurable. Perhaps you have a custom
source of properties that youd like to integrate into this search. No problemsimply
25/08/2016 12:10
217 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
implement and instantiate your own PropertySource and add it to the set of
PropertySources for the current Environment :
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 MutablePropertySources API exposes a
number of methods that allow for precise manipulation of the set of property sources.
7.13.4 @PropertySource
The @PropertySource annotation provides a convenient and declarative mechanism for
adding a PropertySource to Springs 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".
@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;
}
}
25/08/2016 12:10
218 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
@Bean
public TestBean testBean() {
TestBean testBean = new TestBean();
testBean.setName(env.getProperty("testbean.name"));
return testBean;
}
}
25/08/2016 12:10
219 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
220 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
HierarchicalBeanFactory interface.
25/08/2016 12:10
221 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
<property name="basenames">
<list>
<value>format</value>
<value>exceptions</value>
<value>windows</value>
</list>
</property>
</bean>
</beans>
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
# in format.properties
message=Alligators rock!
# in exceptions.properties
argument.required=The {0} argument is required.
25/08/2016 12:10
222 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
<beans>
The resulting output from the invocation of the execute() method will be
The userDao argument is required.
25/08/2016 12:10
223 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
The resulting output from the running of the above program will be
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 contexts MessageSource when the bean is created and configured.
25/08/2016 12:10
224 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Explanation
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
ContextStoppedEvent
ContextClosedEvent
25/08/2016 12:10
225 de 1194
Event
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Explanation
"Closed" here means that all singleton beans are
destroyed. A closed context reaches its end of life;
it cannot be refreshed or restarted.
RequestHandledEvent
You can also create and publish your own custom events. This example demonstrates a
simple class that extends Springs ApplicationEvent base class:
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...
}
25/08/2016 12:10
226 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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; youre 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:
public class BlackListNotifier implements ApplicationListener<BlackListEvent> {
private String notificationAddress;
public void setNotificationAddress(String notificationAddress) {
this.notificationAddress = notificationAddress;
}
public void onApplicationEvent(BlackListEvent event) {
// notify appropriate parties via notificationAddress...
}
}
25/08/2016 12:10
227 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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 Springs
ApplicationEventMulticaster interface.
The following example shows the bean definitions used to register and configure each of
the classes above:
<bean id="emailService" class="example.EmailService">
<property name="blackList">
<list>
<value>[email protected]</value>
<value>[email protected]</value>
<value>[email protected]</value>
</list>
</property>
</bean>
<bean id="blackListNotifier" class="example.BlackListNotifier">
<property name="notificationAddress" value="[email protected]"/>
</bean>
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.
25/08/2016 12:10
228 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
As you can see above, the method signature actually infer which even type it listens to.
This also works for nested generics as long as the actual event resolves the generics
parameter you would filter on.
If your method should listen to several events or if you want to define it with no parameter
at all, the event type(s) can also be specified on the annotation itself:
@EventListener({ContextStartedEvent.class, ContextRefreshedEvent.class})
public void handleContextStart() {
}
It is also possible to add additional runtime filtering via the condition attribute of the
annotation that defines a SpEL expression that should match to actually invoke the
method for a particular event.
For instance, our notifier can be rewritten to be only invoked if the test attribute of the
event is equal to foo :
@EventListener(condition = "#event.test == 'foo'")
public void processBlackListEvent(BlackListEvent event) {
// notify appropriate parties via notificationAddress...
}
Each SpEL expression evaluates again a dedicated context. The next table lists the
items made available to the context so one can use them for conditional event
processing:
25/08/2016 12:10
229 de 1194
Name
Location
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Description
Example
event
root object
#root.event
args
root object
#root.args[0]
evaluation
name
context
notation as an
alias).
Note that #root.event allows you to access to the underlying event, even if your
method signature actually refers to an arbitrary object that was published.
If you need to publish an event as the result of processing another, just change the
method signature to return the event that should be published, something like:
@EventListener
public ListUpdateEvent handleBlackListEvent(BlackListEvent event) {
// notify appropriate parties via notificationAddress and
// then publish a ListUpdateEvent...
}
This new method will publish a new ListUpdateEvent for every BlackListEvent
handled by the method above. If you need to publish several events, just return a
Collection of events instead.
Asynchronous Listeners
If you want a particular listener to process events asynchronously, simply reuse the
regular @Async support:
@EventListener
25/08/2016 12:10
230 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
@Async
public void processBlackListEvent(BlackListEvent event) {
// BlackListEvent is processed in a separate thread
}
Ordering Listeners
If you need the listener to be invoked before another one, just add the @Order
annotation to the method declaration:
@EventListener
@Order(42)
public void processBlackListEvent(BlackListEvent event) {
// notify appropriate parties via notificationAddress...
}
Generic Events
You may also use generics to further define the structure of your event. Consider an
EntityCreatedEvent<T> where T is the type of the actual entity that got created. You
can create the following listener definition to only receive EntityCreatedEvent for a
Person :
@EventListener
public void onPersonCreated(EntityCreatedEvent<Person> event) {
...
}
Due to type erasure, this will only work if the event that is fired resolves the generic
parameter(s) on which the event listener filters on (that is something like
class PersonCreatedEvent extends EntityCreatedEvent<Person> { } ).
In certain circumstances, this may become quite tedious if all events follow the same
structure (as it should be the case for the event above). In such a case, you can
implement ResolvableTypeProvider to guide the framework beyond what the runtime
25/08/2016 12:10
231 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
This works not only for ApplicationEvent but any arbitrary object that
youd send as an event.
25/08/2016 12:10
232 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/daoContext.xml /WEB-INF/applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-cl
</listener>
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".
25/08/2016 12:10
233 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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 platforms JMX server - all through Springs standard transaction
management and JNDI and JMX support facilities. Application components can also
interact with the application servers JCA WorkManager through Springs TaskExecutor
abstraction.
Check out the JavaDoc of the 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 "METAINF/ra.xml" deployment descriptor (as shown in SpringContextResourceAdapter s
JavaDoc) and the corresponding Spring XML bean definition file(s) (typically "METAINF/applicationContext.xml"), and drop the resulting RAR file into your application
servers deployment directory.
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.
25/08/2016 12:10
234 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
BeanFactory
ApplicationContext
Bean instantiation/wiring
Yes
Yes
Automatic BeanPostProcessor
No
Yes
No
Yes
registration
Automatic
BeanFactoryPostProcessor
registration
25/08/2016 12:10
235 de 1194
Feature
Convenient MessageSource
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
BeanFactory
ApplicationContext
No
Yes
No
Yes
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
BeanFactoryPostProcessor s and BeanPostProcessor s. These mechanisms
implement important functionality such as property placeholder replacement and AOP.
25/08/2016 12:10
236 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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 ContextSingletonBeanFactoryLocator locator that is described in this
Spring team blog entry.
[1]
[2]
See Background
See Section 7.4.1, Dependency Injection
8. Resources
8.1 Introduction
Javas 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
25/08/2016 12:10
237 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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
25/08/2016 12:10
238 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
8.3.1 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
25/08/2016 12:10
239 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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 doesnt recognize the
prefix, it will assume the this is just a standard URL string, and will create a
UrlResource .
8.3.2 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.
8.3.3 FileSystemResource
This is a Resource implementation for java.io.File handles. It obviously supports
resolution as a File , and as a URL .
8.3.4 ServletContextResource
This is a Resource implementation for ServletContext resources, interpreting relative
paths within the relevant web applications 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 its expanded and on the filesystem like this, or accessed
directly from the JAR or somewhere else like a DB (its conceivable) is actually dependent
on the Servlet container.
25/08/2016 12:10
240 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
8.3.5 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.
8.3.6 ByteArrayResource
This is a Resource implementation for a given byte array. It creates a
ByteArrayInputStream for the given byte array.
Its useful for loading content from any given byte array, without having to resort to a
single-use InputStreamResource .
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 doesnt 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:
Resource template = ctx.getResource("some/resource/path/myTemplate.txt");
25/08/2016 12:10
241 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Similarly, one can force a UrlResource to be used by specifying any of the standard
java.net.URL prefixes:
Resource template = ctx.getResource("file:///some/resource/path/myTemplate.txt"
Resource template = ctx.getResource("http://myhost.com/resource/path/myTemplate.txt"
The following table summarizes the strategy for converting String s to Resource s:
Example
Explanation
classpath:
classpath:com/myapp/config.xml
file:
file:///data/config.xml
http:
http://myserver/logo.png
Loaded as a URL .
(none)
/data/config.xml
[1]
25/08/2016 12:10
242 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
243 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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).
<property name="template" value="classpath:some/resource/path/myTemplate.txt"
<property name="template" value="file:///some/resource/path/myTemplate.txt"/>
The bean definitions will be loaded from the classpath, as a ClassPathResource will be
used. But if you create a FileSystemXmlApplicationContext as follows:
ApplicationContext ctx =
new FileSystemXmlApplicationContext("conf/appContext.xml");
The bean definition will be loaded from a filesystem location, in this case relative to the
25/08/2016 12:10
244 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
i. 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.
25/08/2016 12:10
245 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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. Its not
possible to use the classpath*: prefix to construct an actual Resource , as a resource
points to just one resource at a time.
Ant-style Patterns
When the path location contains an Ant-style pattern, for example:
/WEB-INF/*-context.xml
com/mycompany/**/applicationContext.xml
file:C:/some/path/*-context.xml
classpath:com/mycompany/**/applicationContext.xml
i. 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.
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.
25/08/2016 12:10
246 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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.
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.
25/08/2016 12:10
247 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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
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
com/mycompany/package1/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.
As are the following: (Even though it would make sense for them to be different, as one
case is relative and the other absolute.)
FileSystemXmlApplicationContext ctx = ...;
25/08/2016 12:10
248 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
ctx.getResource("some/resource/path/myTemplate.txt");
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.
// actual context type doesn't matter, the Resource will always be UrlResource
ctx.getResource("file:///some/resource/path/myTemplate.txt");
25/08/2016 12:10
249 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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.
Springs 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.
Were 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
25/08/2016 12:10
250 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
251 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
/**
* This Validator validates Customer instances, and any subclasses of Customer too
*/
public boolean supports(Class clazz) {
return Customer.class.isAssignableFrom(clazz);
}
Validation errors are reported to the Errors object passed to the validator. In case of
Spring Web MVC you can use <spring:bind/> 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.
25/08/2016 12:10
252 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
the code youve 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 MessageCodesResolver and
DefaultMessageCodesResolver , respectively.
25/08/2016 12:10
253 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Explanation
Indicates the property name corresponding to the
methods getName() or isName() and
setName(..)
account.name
account[2]
account[COMPANYNAME]
Below youll find some examples of working with the BeanWrapper to get and set
properties.
(This next section is not vitally important to you if youre not planning to work with the
BeanWrapper directly. If youre 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:
public class Company {
private String name;
private Employee managingDirector;
25/08/2016 12:10
254 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
The following code snippets show some examples of how to retrieve and manipulate
some of the properties of instantiated Companies and Employees :
BeanWrapper company = new BeanWrapperImpl(new Company());
// setting the company name..
company.setPropertyValue("name", "Some Company Inc.");
// ... can also be done like this:
25/08/2016 12:10
255 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
256 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Explanation
Editor for byte arrays. Strings will simply be
converted to their corresponding byte
representations. Registered by default by
BeanWrapperImpl .
ClassEditor
CustomBooleanEditor
CustomCollectionEditor
CustomDateEditor
CustomNumberEditor
FileEditor
InputStreamEditor
25/08/2016 12:10
257 de 1194
Class
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Explanation
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
PatternEditor
PropertiesEditor
StringTrimmerEditor
URLEditor
25/08/2016 12:10
258 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
FooEditor class to be recognized and used as the PropertyEditor for Foo -typed
properties.
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 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.
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.
public class FooBeanInfo extends SimpleBeanInfo {
public PropertyDescriptor[] getPropertyDescriptors() {
try {
final PropertyEditor numberPE = new CustomNumberEditor(Integer.class
PropertyDescriptor ageDescriptor = new PropertyDescriptor("age", Foo.
public PropertyEditor createPropertyEditor(Object bean) {
return numberPE;
};
};
return new PropertyDescriptor[] { ageDescriptor };
}
catch (IntrospectionException ex) {
throw new Error(ex.toString());
}
}
}
25/08/2016 12:10
259 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
260 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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:
<bean id="sample" class="example.DependsOnExoticType">
<property name="type" value="aNameForExoticType"/>
</bean>
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
25/08/2016 12:10
261 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Finally, and in a bit of a departure from the focus of this chapter, for those of you using
Springs MVC web framework, using PropertyEditorRegistrars in conjunction with
data-binding Controllers (such as SimpleFormController ) can be very convenient.
25/08/2016 12:10
262 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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.
25/08/2016 12:10
263 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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:
package org.springframework.core.convert.support;
final class StringToInteger implements Converter<String, Integer> {
public Integer convert(String source) {
return Integer.valueOf(source);
}
}
9.5.2 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 :
package org.springframework.core.convert.converter;
public interface ConverterFactory<S, R> {
<T extends R> Converter<S, T> getConverter(Class<T> targetType);
}
25/08/2016 12:10
264 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
the range of classes you can convert to. Then implement getConverter(Class<T>), where
T is a subclass of R.
Consider the StringToEnum ConverterFactory as an example:
package org.springframework.core.convert.support;
final class StringToEnumConverterFactory implements ConverterFactory<String, Enum> {
public <T extends Enum> Converter<String, T> getConverter(Class<T> targetType) {
return new StringToEnumConverter(targetType);
}
9.5.3 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.
package org.springframework.core.convert.converter;
public interface GenericConverter {
public Set<ConvertiblePair> getConvertibleTypes();
25/08/2016 12:10
265 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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 a static valueOf method, is defined on the target class.
ConditionalGenericConverter is the union of the GenericConverter and
ConditionalConverter interfaces that allows you to define such custom matching
criteria:
public interface ConditionalGenericConverter
extends GenericConverter, ConditionalConverter {
boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType);
}
266 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
The ConversionService defines a unified API for executing type conversion logic at
runtime. Converters are often executed behind this facade interface:
package org.springframework.core.convert;
public interface ConversionService {
boolean canConvert(Class<?> sourceType, Class<?> targetType);
<T> T convert(Object source, Class<T> targetType);
boolean canConvert(TypeDescriptor sourceType, TypeDescriptor targetType);
To register a default ConversionService with Spring, add the following bean definition with
id conversionService :
25/08/2016 12:10
267 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
class="org.springframework.context.support.ConversionServiceFactoryBean"
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
25/08/2016 12:10
268 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
instance, you need to provide a formal definition of the source and target types.
Fortunately, TypeDescriptor provides various options to make that straightforward:
DefaultConversionService cs = new DefaultConversionService();
List<Integer> input = ....
cs.convert(input,
TypeDescriptor.forObject(input), // List<Integer> type descriptor
TypeDescriptor.collection(List.class, TypeDescriptor.valueOf(String.class
25/08/2016 12:10
269 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
java.lang.Long. Use the Formatter SPI when youre 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.
Where Formatter extends from the Printer and Parser building-block interfaces:
public interface Printer<T> {
String print(T fieldValue, Locale locale);
}
import java.text.ParseException;
public interface Parser<T> {
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 Joda Time library.
Consider DateFormatter as an example Formatter implementation:
25/08/2016 12:10
270 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
package org.springframework.format.datetime;
public final class DateFormatter implements Formatter<Date> {
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;
}
}
25/08/2016 12:10
271 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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:
public final class NumberFormatAnnotationFormatterFactory
implements AnnotationFormatterFactory<NumberFormat> {
public Set<Class<?>> getFieldTypes() {
return new HashSet<Class<?>>(asList(new Class<?>[] {
Short.class, Integer.class, Long.class, Float.class,
Double.class, BigDecimal.class, BigInteger.class }));
}
public Printer<Number> getPrinter(NumberFormat annotation, Class<?> fieldType) {
return configureFormatterFrom(annotation, fieldType);
}
public Parser<Number> getParser(NumberFormat annotation, Class<?> fieldType) {
return configureFormatterFrom(annotation, fieldType);
}
private Formatter<Number> 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();
}
25/08/2016 12:10
272 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
}
}
}
25/08/2016 12:10
273 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
274 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
275 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
http://www.springframework.org/schema/beans/spring-beans.xsd>
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 Section 22.16.3, Conversion and Formatting
for details.
25/08/2016 12:10
276 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
JSR-303 allows you to define declarative validation constraints against such properties:
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 Bean Validation website. For
information on the specific capabilities of the default reference implementation, see the
Hibernate Validator documentation. To learn how to setup a Bean Validation provider as a
Spring bean, keep reading.
25/08/2016 12:10
277 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
application.
Use the LocalValidatorFactoryBean to configure a default Validator as a Spring
bean:
<bean id="validator"
class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean"
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.
Injecting a Validator
LocalValidatorFactoryBean implements both
javax.validation.ValidatorFactory and javax.validation.Validator , as well
as Springs 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:
import javax.validation.Validator;
@Service
public class MyService {
@Autowired
private Validator validator;
25/08/2016 12:10
278 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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
constraints 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:
@Target({ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy=MyConstraintValidator.class)
public @interface MyConstraint {
}
import javax.validation.ConstraintValidator;
public class MyConstraintValidator implements ConstraintValidator {
@Autowired;
private Foo aDependency;
...
}
25/08/2016 12:10
279 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
<bean class="org.springframework.validation.beanvalidation.MethodValidationPostProcess
In order to be eligible for Spring-driven method validation, all target classes need to be
annotated with Springs @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.
280 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
281 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
282 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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.
ExpressionParser parser = new SpelExpressionParser();
// invokes 'getBytes().length'
Expression exp = parser.parseExpression("'Hello World'.bytes.length");
int length = (Integer) exp.getValue();
25/08/2016 12:10
283 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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.
// 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:
/ 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
25/08/2016 12:10
284 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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.
As a final introductory example, the use of a boolean operator is shown using the Inventor
object in the previous example.
Expression exp = parser.parseExpression("name == 'Nikola Tesla'");
boolean result = exp.getValue(context, Boolean.class); // evaluates to true
Type Conversion
25/08/2016 12:10
285 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
286 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
// Turn on:
// - auto null reference initialization
// - auto collection growing
SpelParserConfiguration config = new SpelParserConfiguration(true,true);
ExpressionParser parser = new SpelExpressionParser(config);
Expression expression = parser.parseExpression("list[3]");
Demo demo = new Demo();
Object o = expression.getValue(demo);
// demo.list will now be a real collection of 4 entries
// Each entry is a new empty String
25/08/2016 12:10
287 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
iterations, it was taking 75ms to evaluate using only the interpreter and just 3ms using the
compiled version of the expression.
Compiler configuration
The compiler is not turned on by default, but there are two ways to turn it on. It can be
turned on using the parser configuration process discussed earlier or via a system
property when SpEL usage is embedded inside another component. This section
discusses both of these options.
Is is important to understand that there are a few modes the compiler can operate in,
captured in an enum ( org.springframework.expression.spel.SpelCompilerMode ).
The modes are as follows:
OFF - The compiler is switched off; this is the default.
IMMEDIATE - In immediate mode the expressions are compiled as soon as possible.
This is typically after the first interpreted evaluation. If the compiled expression fails
(typically due to a type changing, as described above) then the caller of the
expression evaluation will receive an exception.
MIXED - In mixed mode the expressions silently switch between interpreted and
compiled mode over time. After some number of interpreted runs they will switch to
compiled form and if something goes wrong with the compiled form (like a type
changing, as described above) then the expression will automatically switch back to
interpreted form again. Sometime later it may generate another compiled form and
switch to it. Basically the exception that the user gets in IMMEDIATE mode is instead
handled internally.
IMMEDIATE mode exists because MIXED mode could cause issues for expressions that
have side effects. If a compiled expression blows up after partially succeeding it may
have already done something that has affected the state of the system. If this has
happened the caller may not want it to silently re-run in interpreted mode since part of the
expression may be running twice.
After selecting a mode, use the SpelParserConfiguration to configure the parser:
25/08/2016 12:10
288 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
When specifying the compiler mode it is also possible to specify a classloader (passing
null is allowed). Compiled expressions will be defined in a child classloader created under
any that is supplied. It is important to ensure if a classloader is specified it can see all the
types involved in the expression evaluation process. If none is specified then a default
classloader will be used (typically the context classloader for the thread that is running
during expression evaluation).
The second way to configure the compiler is for use when SpEL is embedded inside
some other component and it may not be possible to configure via a configuration object.
In these cases it is possible to use a system property. The property
spring.expression.compiler.mode can be set to one of the SpelCompilerMode
enum values ( off , immediate , or mixed ).
Compiler limitations
With Spring Framework 4.1 the basic compilation framework is in place. However, the
framework does not yet support compiling every kind of expression. The initial focus has
been on the common expressions that are likely to be used in performance critical
contexts. These kinds of expression cannot be compiled at the moment:
expressions involving assignment
expressions relying on the conversion service
expressions using custom resolvers or accessors
expressions using selection or projection
More and more types of expression will be compilable in the future.
25/08/2016 12:10
289 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
You can also refer to other bean properties by name, for example.
<bean id="numberGuess" class="org.spring.samples.NumberGuess">
<property name="randomNumber" value="#{ T(java.lang.Math).random() * 100.0 }"
<!-- other properties -->
</bean>
<bean id="shapeGuess" class="org.spring.samples.ShapeGuess">
<property name="initialShapeSeed" value="#{ numberGuess.randomNumber }"/>
<!-- other properties -->
</bean>
25/08/2016 12:10
290 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Autowired methods and constructors can also use the @Value annotation.
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;
}
// ...
}
public class MovieRecommender {
private String defaultLocale;
private CustomerPreferenceDao customerPreferenceDao;
@Autowired
25/08/2016 12:10
291 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Numbers support the use of the negative sign, exponential notation, and decimal points.
By default real numbers are parsed using Double.parseDouble().
25/08/2016 12:10
292 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Teslas year of birth and Pupins city of birth the following expressions are used.
// 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.
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.
// Officer's Dictionary
Inventor pupin = parser.parseExpression("Officers['president']").getValue(
societyContext, Inventor.class);
// evaluates to "Idvor"
String city = parser.parseExpression("Officers['president'].PlaceOfBirth.City"
societyContext, String.class);
// setting values
parser.parseExpression("Officers['advisors'][0].PlaceOfBirth.Country").setValue(
societyContext, "Croatia");
25/08/2016 12:10
293 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
{} 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.
{:} 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.
25/08/2016 12:10
294 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
10.5.6 Methods
Methods are invoked using typical Java programming syntax. You may also invoke
methods on literals. Varargs are also supported.
// 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);
10.5.7 Operators
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.
// 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.
In addition to standard relational operators SpEL supports the instanceof and regular
expression based matches operator.
// evaluates to false
boolean falseValue = parser.parseExpression(
"'xyz' instanceof T(Integer.class)").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);
25/08/2016 12:10
295 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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.
Logical operators
The logical operators that are supported are and, or, and not. Their use is demonstrated
below.
// -- AND -// evaluates to false
boolean falseValue = parser.parseExpression("true and false").getValue(Boolean.
// evaluates to true
String expression = "isMember('Nikola Tesla') and isMember('Mihajlo Pupin')"
boolean trueValue = parser.parseExpression(expression).getValue(societyContext, Boolea
// -- OR -// evaluates to true
boolean trueValue = parser.parseExpression("true or false").getValue(Boolean.
// evaluates to true
String expression = "isMember('Nikola Tesla') or isMember('Albert Einstein')"
boolean trueValue = parser.parseExpression(expression).getValue(societyContext, Boolea
// -- 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, Boole
Mathematical operators
25/08/2016 12:10
296 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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.
// 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.
// Division
int minusTwo = parser.parseExpression("6 / -3").getValue(Integer.class); // -2
double one = parser.parseExpression("8.0 / 4e0 / 2").getValue(Double.class);
// 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
10.5.8 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 .
Inventor inventor = new Inventor();
StandardEvaluationContext inventorContext = new StandardEvaluationContext(inventor);
parser.parseExpression("Name").setValue(inventorContext, "Alexander Seovic2"
// alternatively
25/08/2016 12:10
297 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
10.5.9 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.
Class dateClass = parser.parseExpression("T(java.util.Date)").getValue(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);
10.5.10 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).
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);
10.5.11 Variables
Variables can be referenced in the expression using the syntax #variableName .
Variables are set using the method setVariable on the StandardEvaluationContext .
Inventor tesla = new Inventor("Nikola Tesla", "Serbian");
StandardEvaluationContext context = new StandardEvaluationContext(tesla);
25/08/2016 12:10
298 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
10.5.12 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.
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.
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));
25/08/2016 12:10
299 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
}
return backwards.toString();
}
}
This method is then registered with the evaluation context and can be used within an
expression string.
ExpressionParser parser = new SpelExpressionParser();
StandardEvaluationContext context = new StandardEvaluationContext();
context.registerFunction("reverseString",
StringUtils.class.getDeclaredMethod("reverseString", new Class[] { String.
String helloWorldReversed = parser.parseExpression(
"#reverseString('hello')").getValue(context, String.class);
To access a factory bean itself, the bean name should instead be prefixed with a (&)
symbol.
ExpressionParser parser = new SpelExpressionParser();
StandardEvaluationContext context = new StandardEvaluationContext();
context.setBeanResolver(new MyBeanResolver());
25/08/2016 12:10
300 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
In this case, the boolean false results in returning the string value 'falseExp'. A more
realistic example is shown below.
parser.parseExpression("Name").setValue(societyContext, "IEEE");
societyContext.setVariable("queryName", "Nikola Tesla");
Also see the next section on the Elvis operator for an even shorter syntax for the ternary
operator.
Instead you can use the Elvis operator, named for the resemblance to Elvis' hair style.
ExpressionParser parser = new SpelExpressionParser();
String name = parser.parseExpression("name?:'Unknown'").getValue(String.class
System.out.println(name); // 'Unknown'
25/08/2016 12:10
301 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
The Elvis operator can be used to apply default values in expressions, e.g.
in an @Value expression:
@Value("#{systemProperties['pop3.port'] ?: 25}")
25/08/2016 12:10
302 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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:
List<Inventor> list = (List<Inventor>) 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.
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 $[] .
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.
25/08/2016 12:10
303 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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.
public class TemplateParserContext implements ParserContext {
public String getExpressionPrefix() {
return "#{";
}
public String getExpressionSuffix() {
return "}";
}
public boolean isTemplate() {
return true;
}
}
25/08/2016 12:10
304 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
305 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
}
public void setInventions(String[] inventions) {
this.inventions = inventions;
}
public String[] getInventions() {
return inventions;
}
}
PlaceOfBirth.java
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;
}
}
25/08/2016 12:10
306 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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<Inventor> members = new ArrayList<Inventor>();
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;
}
}
307 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
308 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
309 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
310 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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 Frameworks 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 the following chapter for a discussion of
the Spring AOP APIs.
25/08/2016 12:10
311 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
See Section 11.4, Choosing which AOP declaration style to use for a more
complete discussion of the whys and wherefores of each style.
Using the AspectJ compiler and weaver enables use of the full AspectJ
language, and is discussed in Section 11.8, Using AspectJ with Spring
applications.
25/08/2016 12:10
312 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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 AspectJs 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.
This assumes that you are using schema support as described in Chapter 41, XML
Schema-based configuration. See Section 41.2.7, the aop schema for how to import the
tags in the aop namespace.
25/08/2016 12:10
313 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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.
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 Springs component
scanner).
25/08/2016 12:10
314 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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' :
@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 AspectJs pointcut language, see
the AspectJ Programming Guide (and for extensions, the 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.
The full AspectJ pointcut language supports additional pointcut designators that are
not supported in Spring. These are:
call, get, set, preinitialization, staticinitialization, initialization, handle
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
25/08/2016 12:10
315 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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 ).
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:
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,
25/08/2016 12:10
316 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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 and therefore not available for aspects declared
in the @Aspect model.
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 Springs 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.
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.
25/08/2016 12:10
317 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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.*.*(..))")
25/08/2016 12:10
318 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
/**
* 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:
<aop:config>
<aop:advisor
pointcut="com.xyz.someapp.SystemArchitecture.businessService()"
advice-ref="tx-advice"/>
</aop:config>
<tx:advice id="tx-advice">
<tx:attributes>
<tx:method name="*" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
Examples
Spring AOP users are likely to use the execution pointcut designator the most often.
The format of an execution expression is:
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
25/08/2016 12:10
319 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
name pattern. If specifying a declaring type pattern then include a trailing . to join it to
the name pattern component. 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 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:
execution(public * *(..))
any join point (method execution only in Spring AOP) within the service package:
within(com.xyz.service.*)
any join point (method execution only in Spring AOP) within the service package or a
sub-package:
within(com.xyz.service..*)
any join point (method execution only in Spring AOP) where the proxy implements
the AccountService interface:
this(com.xyz.service.AccountService)
25/08/2016 12:10
320 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
'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:
target(com.xyz.service.AccountService)
'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 :
args(java.io.Serializable)
'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.
'@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:
25/08/2016 12:10
321 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
'@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:
@annotation(org.springframework.transaction.annotation.Transactional)
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:
@args(com.xyz.security.Classified)
'@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 :
bean(tradeService)
any join point (method execution only in Spring AOP) on Spring beans having names
that match the wildcard expression *Service :
bean(*Service)
25/08/2016 12:10
322 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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.
Before advice
Before advice is declared in an aspect using the @Before annotation:
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
25/08/2016 12:10
323 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
@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:
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() {
// ...
}
}
25/08/2016 12:10
324 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
members as well, all inside the same aspect. Were 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:
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 afterreturning advice.
25/08/2016 12:10
325 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
// ...
}
}
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.
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).
25/08/2016 12:10
326 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
// ...
}
}
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. dont 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.
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 (Dont worry if this doesnt 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.
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.ProceedingJoinPoint;
25/08/2016 12:10
327 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
@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.
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. Well see how to make argument and other
contextual values available to the advice body in a moment. First lets take a look at how
to write generic advice that can find out about the method the advice is currently advising.
25/08/2016 12:10
328 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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:
@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:
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:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Auditable {
AuditCode value();
}
25/08/2016 12:10
329 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
And then the advice that matches the execution of @Auditable methods:
@Before("com.xyz.lib.Pointcuts.anyPublicMethod() && @annotation(auditable)")
public void audit(Auditable auditable) {
AuditCode code = auditable.value();
// ...
}
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:
@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, its worth
pointing out that this wont work for generic collections. So you cannot define a pointcut
like this:
@Before("execution(* ..Sample+.sampleGenericCollectionMethod(*)) && args(param)")
public void beforeSampleMethod(Collection<MyType> 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.
25/08/2016 12:10
330 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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:
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
25/08/2016 12:10
331 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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.
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.
In many cases you will be doing this binding anyway (as in the example above).
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"
25/08/2016 12:10
332 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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.
11.2.5 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.)
@Aspect
public class UsageTracking {
@DeclareParents(value="com.xzy.myapp.service.*+", defaultImpl=DefaultUsageTracked.
public static UsageTracked mixin;
25/08/2016 12:10
333 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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:
UsageTracked usageTracked = (UsageTracked) context.getBean("myService");
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 AspectJs 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. Lets look at an example, and then well explain how it works.
@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
25/08/2016 12:10
334 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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.
11.2.7 Example
Now that you have seen how all the constituent parts work, lets 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 dont need to go back to the user for conflict resolution), wed
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. Heres how the basic aspect implementation looks:
@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()")
25/08/2016 12:10
335 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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 were 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:
<aop:aspectj-autoproxy/>
To refine the aspect so that it only retries idempotent operations, we might define an
Idempotent annotation:
@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:
25/08/2016 12:10
336 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
337 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
<aop:config>
<aop:aspect id="myAspect" ref="aBean">
...
</aop:aspect>
</aop:config>
<bean id="aBean" class="...">
...
</bean>
The bean backing the aspect (" `aBean`" in this case) can of course be configured and
dependency injected just like any other Spring bean.
Note that the pointcut expression itself is using the same AspectJ pointcut expression
language as described in Section 11.2, @AspectJ support. 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:
<aop:config>
<aop:pointcut id="businessService"
expression="com.xyz.myapp.SystemArchitecture.businessService()"/>
</aop:config>
25/08/2016 12:10
338 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
<aop:config>
<aop:aspect id="myAspect" ref="aBean">
<aop:pointcut id="businessService"
expression="execution(* com.xyz.myapp.service.*.*(..))"/>
...
</aop:aspect>
</aop:config>
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:
<aop:config>
<aop:aspect id="myAspect" ref="aBean">
<aop:pointcut id="businessService"
expression="execution(* com.xyz.myapp.service.*.*(..)) && this(ser
<aop:before pointcut-ref="businessService" method="monitor"/>
...
</aop:aspect>
</aop:config>
The advice must be declared to receive the collected join point context by including
parameters of the matching names:
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:
<aop:config>
<aop:aspect id="myAspect" ref="aBean">
25/08/2016 12:10
339 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
<aop:pointcut id="businessService"
expression="execution(* com.xyz.myapp.service.*.*(..)) **and** this(servic
<aop:before pointcut-ref="businessService" method="monitor"/>
...
</aop:aspect>
</aop:config>
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.
Before advice
Before advice runs before a matched method execution. It is declared inside an
<aop:aspect> using the <aop:before> element.
<aop:aspect id="beforeExample" ref="aBean">
<aop:before
pointcut-ref="dataAccessOperation"
method="doAccessCheck"/>
...
</aop:aspect>
25/08/2016 12:10
340 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
...
</aop:aspect>
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.
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:
<aop:aspect id="afterReturningExample" ref="aBean">
<aop:after-returning
pointcut-ref="dataAccessOperation"
returning="retVal"
method="doAccessCheck"/>
...
</aop:aspect>
The doAccessCheck method must declare a parameter named retVal . The type of this
25/08/2016 12:10
341 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
parameter constrains matching in the same way as described for @AfterReturning. For
example, the method signature may be declared as:
public void doAccessCheck(Object retVal) {...
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:
<aop:aspect id="afterThrowingExample" ref="aBean">
<aop:after-throwing
pointcut-ref="dataAccessOperation"
throwing="dataAccessEx"
method="doRecoveryActions"/>
...
</aop:aspect>
25/08/2016 12:10
342 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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; dont 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
the section called Around advice for notes on calling proceed with an Object[] .
<aop:aspect id="aroundExample" ref="aBean">
<aop:around
pointcut-ref="businessService"
method="doBasicProfiling"/>
...
</aop:aspect>
25/08/2016 12:10
343 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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 the section called Advice parameters 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 the section called Determining argument
names. For example:
<aop:before
pointcut="com.xyz.lib.Pointcuts.anyPublicMethod() and @annotation(auditable)"
method="audit"
arg-names="auditable"/>
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:
25/08/2016 12:10
344 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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
StopWatch clock = new StopWatch("Profiling for '" + name + "' and '"
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:
<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"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/sch
http://www.springframework.org/schema/aop http://www.springframework.org/schem
<!-- this is the object that will be proxied by Spring's AOP infrastructure -->
<bean id="fooService" class="x.y.service.DefaultFooService"/>
<!-- this is the actual advice itself -->
<bean id="profiler" class="x.y.SimpleProfiler"/>
<aop:config>
<aop:aspect ref="profiler">
<aop:pointcut id="theExecutionOfSomeFooServiceMethod"
expression="execution(* x.y.service.FooService.getFoo(String,int))
and args(name, age)"/>
<aop:around pointcut-ref="theExecutionOfSomeFooServiceMethod"
method="profile"/>
</aop:aspect>
</aop:config>
25/08/2016 12:10
345 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
</beans>
If we had the following driver script, we would get output something like this on standard
output:
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);
}
}
StopWatch 'Profiling for 'Pengo' and '12'': running time (millis) = 0
----------------------------------------ms
%
Task name
----------------------------------------00000 ? execution(getFoo)
Advice ordering
When multiple advice needs to execute at the same join point (executing method) the
ordering rules are as described in the section called Advice ordering. 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.
11.3.4 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.)
25/08/2016 12:10
346 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
<aop:declare-parents
types-matching="com.xzy.myapp.service.*+"
implement-interface="com.xyz.myapp.service.tracking.UsageTracked"
default-impl="com.xyz.myapp.service.tracking.DefaultUsageTracked"/>
<aop:before
pointcut="com.xyz.myapp.SystemArchitecture.businessService()
and this(usageTracked)"
method="recordUsage"/>
</aop:aspect>
The class backing the usageTracking bean would contain the method:
public void recordUsage(UsageTracked usageTracked) {
usageTracked.incrementUseCount();
}
11.3.6 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 Section 12.3.2, Advice types in
Spring. Advisors can take advantage of AspectJ pointcut expressions though.
Spring supports the advisor concept with the <aop:advisor> element. You will most
25/08/2016 12:10
347 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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.
11.3.7 Example
Lets see how the concurrent locking failure retry example from Section 11.2.7, Example
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 dont need to go back to the user for conflict resolution), wed
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, well need to use around advice so that we can
call proceed multiple times. Heres how the basic aspect implementation looks (its just a
regular Java class using the schema support):
public class ConcurrentOperationExecutor implements Ordered {
25/08/2016 12:10
348 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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.
This class is identical to the one used in the @AspectJ example, but with
the annotations removed.
25/08/2016 12:10
349 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
<aop:config>
<aop:aspect id="concurrentOperationRetry" ref="concurrentOperationExecutor"
<aop:pointcut id="idempotentOperation"
expression="execution(* com.xyz.myapp.service.*.*(..))"/>
<aop:around
pointcut-ref="idempotentOperation"
method="doConcurrentOperation"/>
</aop:aspect>
</aop:config>
<bean id="concurrentOperationExecutor"
class="com.xyz.myapp.service.impl.ConcurrentOperationExecutor">
<property name="maxRetries" value="3"/>
<property name="order" value="100"/>
</bean>
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:
@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:
<aop:pointcut id="idempotentOperation"
expression="execution(* com.xyz.myapp.service.*.*(..)) and
@annotation(com.xyz.myapp.service.Idempotent)"/>
25/08/2016 12:10
350 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
351 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
- 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:
@Pointcut(execution(* get*()))
public void propertyAccess() {}
@Pointcut(execution(org.xyz.Account+ *(..))
public void operationReturningAnAccount() {}
@Pointcut(propertyAccess() && operationReturningAnAccount())
public void accountPropertyAccess() {}
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.
25/08/2016 12:10
352 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
To force CGLIB proxying when using the @AspectJ autoproxy support, set the
'proxy-target-class' attribute of the <aop:aspectj-autoproxy> element to true :
<aop:aspectj-autoproxy proxy-target-class="true"/>
25/08/2016 12:10
353 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
<aop:config/> elements will force the use of CGLIB proxies for all three
of them.
If you invoke a method on an object reference, the method is invoked directly on that
object reference, as can be seen below.
25/08/2016 12:10
354 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
}
}
Things change slightly when the reference that client code has is a proxy. Consider the
following diagram and code snippet.
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
25/08/2016 12:10
355 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
because it is so horrendous. You can (choke!) totally tie the logic within your class to
Spring AOP by doing this:
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:
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.
25/08/2016 12:10
356 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
// you can also add existing aspect instances, the type of the object supplied must be
factory.addAspect(usageTracker);
// now get the proxy object...
MyInterfaceType proxy = factory.getProxy();
25/08/2016 12:10
357 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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:
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 prototypescoped) with the same name as the fully-qualified type name (
com.xyz.myapp.domain.Account ). Since the default name for a bean is the fullyqualified name of its type, a convenient way to declare the prototype definition is simply to
omit the id attribute:
<bean class="com.xyz.myapp.domain.Account" scope="prototype">
<property name="fundsTransferService" ref="fundsTransferService"/>
</bean>
If you want to explicitly specify the name of the prototype bean definition to use, you can
do so directly in the annotation:
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.
25/08/2016 12:10
358 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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:
@Configurable(preConstruction=true)
You can find out more information about the language semantics of the
various pointcut types in AspectJ in this appendix of the 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 AspectJ
Development Environment Guide) or load-time weaving (see Section 11.8.4, Load-time
25/08/2016 12:10
359 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
If you prefer XML based configuration, the Spring context namespace defines a
convenient context:spring-configured element:
<context:spring-configured/>
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.
<bean id="myService"
class="com.xzy.myapp.service.MyService"
depends-on="org.springframework.beans.factory.aspectj.AnnotationBeanConfigurer
<!-- ... -->
</bean>
25/08/2016 12:10
360 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
@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.
25/08/2016 12:10
361 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
want to use the Spring Frameworks 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 Javas 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 of any visibility
may be annotated, including private methods. Annotating non-public 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 dont 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 fullyqualified class names:
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);
25/08/2016 12:10
362 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
363 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
A first example
Let us assume that you are an application developer who has been tasked with
25/08/2016 12:10
364 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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.
Here is the profiling aspect. Nothing too fancy, just a quick-and-dirty time-based profiler,
using the @AspectJ-style of aspect declaration.
package foo;
import
import
import
import
import
import
org.aspectj.lang.ProceedingJoinPoint;
org.aspectj.lang.annotation.Aspect;
org.aspectj.lang.annotation.Around;
org.aspectj.lang.annotation.Pointcut;
org.springframework.util.StopWatch;
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.
25/08/2016 12:10
365 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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.
package foo;
25/08/2016 12:10
366 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
import org.springframework.context.support.ClassPathXmlApplicationContext;
public final class Main {
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml"
EntitlementCalculationService entitlementCalculationService
= (EntitlementCalculationService) ctx.getBean("entitlementCalculationServi
// 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:
java -javaagent:C:/projects/foo/lib/global/spring-instrument.jar foo.Main
The -javaagent is a flag for specifying and enabling 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 :) )
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.
package foo;
import org.springframework.context.support.ClassPathXmlApplicationContext;
25/08/2016 12:10
367 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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.
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.
'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 referred to that resource. (I appreciate that
this section is brief, but the aop.xml file is 100% AspectJ - there is no Spring-specific
25/08/2016 12:10
368 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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.)
Spring configuration
The key component in Springs 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.
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.
25/08/2016 12:10
369 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
@Configuration
@EnableLoadTimeWeaving
public class AppConfig {
}
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).
LoadTimeWeaver
implementation
WebLogicLoadTimeWeaver
GlassFishLoadTimeWeaver
TomcatLoadTimeWeaver
JBossLoadTimeWeaver
25/08/2016 12:10
370 de 1194
Runtime Environment
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
LoadTimeWeaver
implementation
WildFly
Running in IBMs WebSphere
WebSphereLoadTimeWeaver
InstrumentationLoadTimeWeaver
InstrumentationSavingAgent (java
-javaagent:path/to/spring-instrument.jar)
Fallback, expecting the underlying
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:
@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 <context:load-time-weaver/>
element:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
25/08/2016 12:10
371 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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:load-time-weaver
weaver-class="org.springframework.instrument.classloading.ReflectiveLoadTi
</beans>
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 Springs 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.
XML Value
Explanation
Value
ENABLED
on
DISABLED
off
AUTODETECT
autodetect
25/08/2016 12:10
372 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Environment-specific configuration
This last section contains any additional settings and configuration that you will need
when using Springs LTW support in environments such as application servers and web
containers.
Tomcat
Historically, Apache Tomcat's default class loader did not support class transformation
which is why Spring provides an enhanced implementation that addresses this need.
Named TomcatInstrumentableClassLoader , the loader works on Tomcat 6.0 and
above.
25/08/2016 12:10
373 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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 documentation for more details
about available context locations.
Alternatively, consider the use of the Spring-provided generic VM agent, to be specified in
Tomcats launch script (see above). This will make instrumentation available to all
deployed web applications, no matter what ClassLoader they happen to run on.
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).
25/08/2016 12:10
374 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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 Jetty) does not have (or does not support) a dedicated LTW.
12.2.1 Concepts
Springs pointcut model enables pointcut reuse independent of advice types. Its possible
to target different advice using the same pointcut.
The org.springframework.aop.Pointcut interface is the central interface, used to
25/08/2016 12:10
375 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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:
public interface ClassFilter {
boolean matches(Class clazz);
}
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.
25/08/2016 12:10
376 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Static pointcuts
Static pointcuts are based on method and target class, and cannot take into account the
methods arguments. Static pointcuts are sufficient - and best - for most usages. Its
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.
Lets consider some static pointcut implementations included with Spring.
25/08/2016 12:10
377 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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:
<bean id="settersAndAbsquatulatePointcut"
class="org.springframework.aop.support.JdkRegexpMethodPointcut">
<property name="patterns">
<list>
<value>.*set.*</value>
<value>.*absquatulate</value>
</list>
</property>
</bean>
Attribute-driven pointcuts
An important type of static pointcut is a metadata-driven pointcut. This uses the values of
25/08/2016 12:10
378 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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.
25/08/2016 12:10
379 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
You can use custom pointcuts with any advice type in Spring 1.0 RC2 and above.
25/08/2016 12:10
380 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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 invocations result: the return value of the join point.
A simple MethodInterceptor implementation looks as follows:
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 MethodInvocations 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 dont want to do this without good reason!
25/08/2016 12:10
381 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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. (Springs API design would allow
for field before advice, although the usual objects apply to field interception and its
unlikely that Spring will ever implement it).
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:
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;
}
}
Throws advice
25/08/2016 12:10
382 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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:
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):
public class RemoteThrowsAdvice implements ThrowsAdvice {
public void afterThrowing(RemoteException ex) throws Throwable {
// Do something with remote exception
}
}
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.
public static class CombinedThrowsAdvice implements ThrowsAdvice {
public void afterThrowing(RemoteException ex) throws Throwable {
// Do something with remote exception
}
25/08/2016 12:10
383 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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:
public class CountingAfterReturningAdvice implements AfterReturningAdvice {
private int count;
25/08/2016 12:10
384 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
}
}
This advice doesnt change the execution path. If it throws an exception, this will be
thrown up the interceptor chain instead of the return value.
Introduction advice
Spring treats introduction advice as a special kind of interception advice.
Introduction requires an IntroductionAdvisor , and an IntroductionInterceptor ,
implementing the following interface:
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:
public interface IntroductionAdvisor extends Advisor, IntroductionInfo {
ClassFilter getClassFilter();
void validateInterfaces() throws IllegalArgumentException;
}
public interface IntroductionInfo {
Class[] getInterfaces();
}
25/08/2016 12:10
385 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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, well 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. Its 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
25/08/2016 12:10
386 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
for introduction, so we dont 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.
25/08/2016 12:10
387 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
public LockMixinAdvisor() {
super(new LockMixin(), Lockable.class);
}
}
The Spring AOP support also uses factory beans under the covers.
25/08/2016 12:10
388 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
12.5.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 ProxyFactoryBeans 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.
25/08/2016 12:10
389 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
no longer allowed. This is useful both as a slight optimization and for those cases
when you dont 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 isnt supplied, a CGLIB
proxy for the target class will be used (but see also Section 12.5.3, JDK- and
CGLIB-based proxies).
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 cant 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 Section 12.5.6, Using 'global'
advisors.
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 .
25/08/2016 12:10
390 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
If the class of a target object that is to be proxied (hereafter simply referred to as the
target class) doesnt 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 isnt 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.
25/08/2016 12:10
391 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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.
You might be wondering why the list doesnt hold bean references. The
reason for this is that if the ProxyFactoryBeans 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 its necessary to be able to obtain an instance of the prototype
25/08/2016 12:10
392 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
The "person" bean definition above can be used in place of a Person implementation, as
follows:
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:
<bean id="personUser" class="com.mycompany.PersonUser">
<property name="person"><ref bean="person"/></property>
</bean>
The PersonUser class in this example would expose a property of type Person. As far
as its 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).
Its 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:
<bean id="myAdvisor" class="com.mycompany.MyAdvisor">
<property name="someProperty" value="Custom string property value"/>
</bean>
25/08/2016 12:10
393 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
This has the advantage that theres 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. Theres 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.
25/08/2016 12:10
394 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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:
<bean id="proxy" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="target" ref="service"/>
<property name="interceptorNames">
<list>
<value>global*</value>
</list>
</property>
</bean>
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.
<bean id="myService" parent="txProxyTemplate">
<property name="target">
<bean class="org.springframework.samples.MyServiceImpl">
</bean>
</property>
</bean>
25/08/2016 12:10
395 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Note that in the example above, we have explicitly marked the parent bean definition as
abstract by using the abstract attribute, as described previously, 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.
25/08/2016 12:10
396 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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.
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.
25/08/2016 12:10
397 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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, its possible to add or remove advisors or interceptors even once a proxy has
been created. The only restriction is that its 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:
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));
25/08/2016 12:10
398 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Its questionable whether its 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.
25/08/2016 12:10
399 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
BeanNameAutoProxyCreator
The BeanNameAutoProxyCreator class is a BeanPostProcessor that automatically
creates AOP proxies for beans with names matching literal values or wildcards.
<bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator"
<property name="beanNames" value="jdk*,onlyJdk"/>
<property name="interceptorNames">
<list>
<value>myInterceptor</value>
</list>
</property>
</bean>
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
advisors 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
25/08/2016 12:10
400 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreato
<bean class="org.springframework.transaction.interceptor.TransactionAttributeSourceAdv
<property name="transactionInterceptor" ref="transactionInterceptor"/>
</bean>
<bean id="customAdvisor" class="com.mycompany.MyAdvisor"/>
<bean id="businessObject1" class="com.mycompany.BusinessObject1">
<!-- Properties omitted -->
</bean>
<bean id="businessObject2" class="com.mycompany.BusinessObject2"/>
25/08/2016 12:10
401 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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 .
<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreato
<bean class="org.springframework.transaction.interceptor.TransactionAttributeSourceAdv
<property name="transactionInterceptor" ref="transactionInterceptor"/>
</bean>
<bean id="transactionInterceptor"
class="org.springframework.transaction.interceptor.TransactionInterceptor"
<property name="transactionManager" ref="transactionManager"/>
<property name="transactionAttributeSource">
<bean class="org.springframework.transaction.interceptor.AttributesTransaction
<property name="attributes" ref="attributes"/>
</bean>
</property>
25/08/2016 12:10
402 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreato
<bean class="org.springframework.transaction.interceptor.TransactionAttributeSourceAdv
<property name="transactionInterceptor" ref="transactionInterceptor"/>
</bean>
<bean id="transactionInterceptor"
class="org.springframework.transaction.interceptor.TransactionInterceptor"
<property name="transactionManager" ref="transactionManager"/>
<property name="transactionAttributeSource">
<bean class="org.springframework.transaction.annotation.AnnotationTransactionA
</property>
</bean>
25/08/2016 12:10
403 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
404 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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).
Lets look at the standard target sources provided with Spring, and how you can use
them.
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.
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 doesnt add any advice - and its not necessary to add advice to
25/08/2016 12:10
405 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
arbitrary advice.
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
25/08/2016 12:10
406 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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 isnt necessary to specify interceptors to use pooling.
If you want only pooling, and no other advice, dont set the interceptorNames property at
all.
Its 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.
Youll need to define an advisor like this:
Simpler pooling is available using auto-proxying. Its possible to set the TargetSources
used by any auto-proxy creator.
25/08/2016 12:10
407 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Theres 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.
25/08/2016 12:10
408 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
409 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
14.1.2 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
25/08/2016 12:10
410 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
411 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
412 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
413 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
414 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
may affect future tests. Also, many operationssuch as inserting or modifying persistent
datacannot 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 tests application context.
If you want a transaction to commitunusual, but occasionally useful when you want a
particular test to populate or modify the databasethe TestContext framework can be
instructed to cause the transaction to commit instead of roll back via the @Commit
annotation.
See transaction management with the TestContext framework.
25/08/2016 12:10
415 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
15.4 Annotations
15.4.1 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.
@BootstrapWith
@BootstrapWith is a class-level annotation that is used to configure how the Spring
TestContext Framework is bootstrapped. Specifically, @BootstrapWith is used to
specify a custom TestContextBootstrapper . Consult the Bootstrapping the
TestContext framework section for further details.
@ContextConfiguration
@ContextConfiguration defines class-level metadata that is used to determine how to
25/08/2016 12:10
416 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
417 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
@WebAppConfiguration
@WebAppConfiguration is 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 tests
WebApplicationContext .
@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.
@ContextConfiguration
@WebAppConfiguration("classpath:test-web-resources")
public class WebAppTests {
// class body...
}
@ContextHierarchy
@ContextHierarchy is 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.
25/08/2016 12:10
418 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
@ContextHierarchy({
@ContextConfiguration("/parent-config.xml"),
@ContextConfiguration("/child-config.xml")
})
public class ContextHierarchyTests {
// class body...
}
@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 the section called Context hierarchies
and the @ContextHierarchy javadocs for further examples.
@ActiveProfiles
@ActiveProfiles is a class-level annotation that is used to declare which bean
definition profiles should be active when loading an ApplicationContext for an
integration test.
@ContextConfiguration
@ActiveProfiles("dev")
public class DeveloperTests {
// class body...
}
@ContextConfiguration
@ActiveProfiles({"dev", "integration"})
public class DeveloperIntegrationTests {
// class body...
}
25/08/2016 12:10
419 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
See the section called Context configuration with environment profiles and the
@ActiveProfiles javadocs for examples and further details.
@TestPropertySource
@TestPropertySource is a class-level annotation that is used to configure the locations
of properties files and inlined properties to be added to the set of PropertySources in
the Environment for an ApplicationContext loaded for an integration test.
Test property sources have higher precedence than those loaded from the operating
systems 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.
@ContextConfiguration
@TestPropertySource("/test.properties")
public class MyIntegrationTests {
// class body...
}
@DirtiesContext
@DirtiesContext indicates that the underlying Spring ApplicationContext has been
dirtied during the execution of a test (i.e., modified or corrupted in some mannerfor
example, by changing the state of a singleton bean) and should be closed. When an
application context is marked dirty, it is removed from the testing frameworks cache and
25/08/2016 12:10
420 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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 class or class hierarchy. In such scenarios, the ApplicationContext is
marked as dirty before or after any such annotated method as well as before or after the
current test class, depending on the configured methodMode and classMode .
The following examples explain when the context would be dirtied for various
configuration scenarios:
Before the current test class, when declared on a class with class mode set to
BEFORE_CLASS .
@DirtiesContext(classMode = BEFORE_CLASS)
public class FreshContextTests {
// some tests that require a new Spring container
}
After the current test class, when declared on a class with class mode set to
AFTER_CLASS (i.e., the default class mode).
@DirtiesContext
public class ContextDirtyingTests {
// some tests that result in the Spring container being dirtied
}
Before each test method in the current test class, when declared on a class with
class mode set to BEFORE_EACH_TEST_METHOD.
@DirtiesContext(classMode = BEFORE_EACH_TEST_METHOD)
public class FreshContextTests {
// some tests that require a new Spring container
}
After each test method in the current test class, when declared on a class with class
mode set to AFTER_EACH_TEST_METHOD.
@DirtiesContext(classMode = AFTER_EACH_TEST_METHOD)
public class ContextDirtyingTests {
// some tests that result in the Spring container being dirtied
}
Before the current test, when declared on a method with the method mode set to
BEFORE_METHOD
25/08/2016 12:10
421 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
@DirtiesContext(methodMode = BEFORE_METHOD)
@Test
public void testProcessWhichRequiresFreshAppCtx() {
// some logic that requires a new Spring container
}
After the current test, when declared on a method with the method mode set to
AFTER_METHOD (i.e., the default method mode).
@DirtiesContext
@Test
public void testProcessWhichDirtiesAppCtx() {
// some logic that results in the Spring container being dirtied
}
For further details regarding the EXHAUSTIVE and CURRENT_LEVEL algorithms see the
DirtiesContext.HierarchyMode javadocs.
25/08/2016 12:10
422 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
@TestExecutionListeners
@TestExecutionListeners defines class-level metadata for configuring the
TestExecutionListener implementations that should be registered with the
TestContextManager . Typically, @TestExecutionListeners is used in conjunction
with @ContextConfiguration .
@ContextConfiguration
@TestExecutionListeners({CustomTestExecutionListener.class, AnotherTestExecutionListen
public class CustomTestExecutionListenerTests {
// class body...
}
@Commit
@Commit indicates that the transaction for a transactional test method should be
committed after the test method has completed. @Commit can be used as a direct
replacement for @Rollback(false) in order to more explicitly convey the intent of the
code. Analogous to @Rollback , @Commit may also be declared as a class-level or
method-level annotation.
@Commit
@Test
public void testProcessWithoutRollback() {
// ...
}
@Rollback
@Rollback indicates whether the transaction for a transactional test method should be
rolled back after the test method has completed. If true , the transaction is rolled back;
otherwise, the transaction is committed (see also @Commit ). Rollback semantics for
integration tests in the Spring TestContext Framework default to true even if
@Rollback is not explicitly declared.
When declared as a class-level annotation, @Rollback defines the default rollback
semantics for all test methods within the test class hierarchy. When declared as a
method-level annotation, @Rollback defines rollback semantics for the specific test
method, potentially overriding class-level @Rollback or @Commit semantics.
25/08/2016 12:10
423 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
@Rollback(false)
@Test
public void testProcessWithoutRollback() {
// ...
}
@BeforeTransaction
@BeforeTransaction indicates that the annotated void method should be executed
before a transaction is started for test methods configured to run within a transaction via
Springs @Transactional annotation. As of Spring Framework 4.3,
@BeforeTransaction methods are not required to be public and may be declared on
Java 8 based interface default methods.
@BeforeTransaction
void beforeTransaction() {
// logic to be executed before a transaction is started
}
@AfterTransaction
@AfterTransaction indicates that the annotated void method should be executed
after a transaction is ended for test methods configured to run within a transaction via
Springs @Transactional annotation. As of Spring Framework 4.3,
@AfterTransaction methods are not required to be public and may be declared on
Java 8 based interface default methods.
@AfterTransaction
void afterTransaction() {
// logic to be executed after a transaction has ended
}
@Sql
@Sql is used to annotate a test class or test method to configure SQL scripts to be
executed against a given database during integration tests.
@Test
@Sql({"/test-schema.sql", "/test-user-data.sql"})
public void userTest {
// execute code that relies on the test schema and test data
}
25/08/2016 12:10
424 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
See the section called Executing SQL scripts declaratively with @Sql for further details.
@SqlConfig
@SqlConfig defines metadata that is used to determine how to parse and execute SQL
scripts configured via the @Sql annotation.
@Test
@Sql(
scripts = "/test-user-data.sql",
config = @SqlConfig(commentPrefix = "`", separator = "@@")
)
public void userTest {
// execute code that relies on the test data
}
@SqlGroup
@SqlGroup is a container annotation that aggregates several @Sql annotations.
@SqlGroup can be used natively, declaring several nested @Sql annotations, or it can
be used in conjunction with Java 8s support for repeatable annotations, where @Sql can
simply be declared several times on the same class or method, implicitly generating this
container annotation.
@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
}
25/08/2016 12:10
425 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
@IfProfileValue
@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. Otherwise, the test will be disabled and effectively
ignored.
@IfProfileValue can be applied at the class level, the method level, or both.
Class-level usage of @IfProfileValue takes precedence over method-level usage for
any methods within that class or its subclasses. Specifically, a test is enabled if it is
enabled both at the class level and at the method level; the absence of
@IfProfileValue means the test is implicitly enabled. This is analogous to the
semantics of JUnit 4s @Ignore annotation, except that the presence of @Ignore
always disables a test.
25/08/2016 12:10
426 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
@ProfileValueSourceConfiguration
@ProfileValueSourceConfiguration is a 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.
@ProfileValueSourceConfiguration(CustomProfileValueSource.class)
public class CustomProfileValueSourceTests {
// class body...
}
@Timed
@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.
@Timed(millis=1000)
public void testProcessWithOneSecondTimeout() {
// some logic that should not take longer than 1 second to execute
}
25/08/2016 12:10
427 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
@Repeat
@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.
@Repeat(10)
@Test
public void testProcessRepeatedly() {
// ...
}
25/08/2016 12:10
428 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
@Repeat
@Timed
@IfProfileValue
@ProfileValueSourceConfiguration
For example, if we discover that we are repeating the following configuration across our
JUnit 4 based test suite
@RunWith(SpringRunner.class)
@ContextConfiguration({"/app-config.xml", "/test-data-access-config.xml"})
@ActiveProfiles("dev")
@Transactional
public class OrderRepositoryTests { }
@RunWith(SpringRunner.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:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@ContextConfiguration({"/app-config.xml", "/test-data-access-config.xml"})
@ActiveProfiles("dev")
@Transactional
public @interface TransactionalDevTest { }
429 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
TestContext
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
SmartContextLoader to load an ApplicationContext if requested.
25/08/2016 12:10
430 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
TestContextManager
TestContextManager is the main entry point into the Spring TestContext Framework,
which manages a single TestContext and signals events to each registered
TestExecutionListener at well-defined test execution points:
prior to any before class or before all methods of a particular testing framework
test instance post-processing
prior to any before or before each methods of a particular testing framework
after any after or after each methods of a particular testing framework
after any after class or after all methods of a particular testing framework
TestExecutionListener
TestExecutionListener defines the API for reacting to test execution events published
by the TestContextManager with which the listener is registered. See Section 15.5.3,
TestExecutionListener configuration.
Context Loaders
ContextLoader is a strategy interface that was 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 support.
SmartContextLoader is an 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
25/08/2016 12:10
431 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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.
25/08/2016 12:10
432 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
433 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Ordering TestExecutionListeners
When the TestContext framework discovers default TestExecutionListener s via the
aforementioned SpringFactoriesLoader mechanism, the instantiated listeners are
sorted using Springs AnnotationAwareOrderComparator which honors Springs
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.
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.
@ContextConfiguration
@TestExecutionListeners({
MyCustomTestExecutionListener.class,
ServletTestExecutionListener.class,
DirtiesContextBeforeModesTestExecutionListener.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 releasefor example, SqlScriptsTestExecutionListener was introduced
in Spring Framework 4.1, and DirtiesContextBeforeModesTestExecutionListener
25/08/2016 12:10
434 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
435 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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, Groovy scripts, annotated classes (typically @Configuration
classes), or context initializers using Springs @ContextConfiguration annotation.
Alternatively, you can implement and configure your own custom SmartContextLoader
25/08/2016 12:10
436 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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" .
package com.example;
@RunWith(SpringRunner.class)
25/08/2016 12:10
437 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
@RunWith(SpringRunner.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" .
package com.example;
@RunWith(SpringRunner.class)
// ApplicationContext will be loaded from
// "classpath:com/example/MyTestContext.groovy"
@ContextConfiguration
public class MyTest {
25/08/2016 12:10
438 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
// class body...
}
25/08/2016 12:10
439 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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 nested 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 nested 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 nested configuration class if desired.
@RunWith(SpringRunner.class)
// ApplicationContext will be loaded from the
// static nested 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
}
}
25/08/2016 12:10
440 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
441 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
It is also possible to omit the declaration of XML configuration files, Groovy scripts, or
annotated classes in @ContextConfiguration entirely and instead declare only
ApplicationContextInitializer classes which are then responsible for registering
beans in the contextfor example, by programmatically loading bean definitions from
XML files or configuration classes.
@RunWith(SpringRunner.class)
// ApplicationContext will be initialized by EntireAppInitializer
// which presumably registers beans in the context
@ContextConfiguration(initializers = EntireAppInitializer.class)
public class MyTest {
// class body...
}
25/08/2016 12:10
442 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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".
@RunWith(SpringRunner.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...
}
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 Springs Ordered interface or are annotated with Springs @Order
annotation or the standard @Priority annotation.
@RunWith(SpringRunner.class)
25/08/2016 12:10
443 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Lets take a look at some examples with XML configuration and @Configuration
classes.
<!-- app-config.xml -->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xmlns:jee="http://www.springframework.org/schema/jee"
xsi:schemaLocation="...">
<bean id="transferService"
class="com.bank.service.internal.DefaultTransferService">
<constructor-arg ref="accountRepository"/>
<constructor-arg ref="feePolicy"/>
</bean>
<bean id="accountRepository"
class="com.bank.repository.internal.JdbcAccountRepository">
<constructor-arg ref="dataSource"/>
25/08/2016 12:10
444 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
</bean>
<bean id="feePolicy"
class="com.bank.service.internal.ZeroFeePolicy"/>
<beans profile="dev">
<jdbc:embedded-database id="dataSource">
<jdbc:script
location="classpath:com/bank/config/sql/schema.sql"/>
<jdbc:script
location="classpath:com/bank/config/sql/test-data.sql"/>
</jdbc:embedded-database>
</beans>
<beans profile="production">
<jee:jndi-lookup id="dataSource" jndi-name="java:comp/env/jdbc/datasource"
</beans>
<beans profile="default">
<jdbc:embedded-database id="dataSource">
<jdbc:script
location="classpath:com/bank/config/sql/schema.sql"/>
</jdbc:embedded-database>
</beans>
</beans>
package com.bank.service;
@RunWith(SpringRunner.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
}
}
25/08/2016 12:10
445 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
446 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
@Profile("default")
public class DefaultDataConfig {
@Bean
public DataSource dataSource() {
return new EmbeddedDatabaseBuilder()
.setType(EmbeddedDatabaseType.HSQL)
.addScript("classpath:com/bank/config/sql/schema.sql")
.build();
}
}
@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();
}
}
package com.bank.service;
@RunWith(SpringRunner.class)
@ContextConfiguration(classes = {
TransferServiceConfig.class,
StandaloneDataConfig.class,
JndiDataConfig.class,
DefaultDataConfig.class})
@ActiveProfiles("dev")
public class TransferServiceTest {
@Autowired
private TransferService transferService;
25/08/2016 12:10
447 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
@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 .
package com.bank.service;
@RunWith(SpringRunner.class)
@ContextConfiguration(classes = {
TransferServiceConfig.class,
StandaloneDataConfig.class,
JndiDataConfig.class,
DefaultDataConfig.class})
@ActiveProfiles("dev")
public abstract class AbstractIntegrationTest {
}
package com.bank.service;
25/08/2016 12:10
448 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
449 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
450 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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"
@ContextConfiguration
@TestPropertySource(properties = {"timezone = GMT", "port: 4242"})
public class MyIntegrationTests {
// class body...
}
25/08/2016 12:10
451 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Test property sources have higher precedence than those loaded from the operating
systems 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.
@ContextConfiguration
@TestPropertySource(
locations = "/test.properties",
properties = {"timezone = GMT", "port: 4242"}
)
public class MyIntegrationTests {
// class body...
}
25/08/2016 12:10
452 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
locations.
@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.
@TestPropertySource(properties = "key1 = value1")
@ContextConfiguration
public class BaseTest {
// ...
}
@TestPropertySource(properties = "key2 = value2")
@ContextConfiguration
public class ExtendedTest extends BaseTest {
// ...
}
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 tests 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 youre familiar
with the directory structure of a web application in a Maven project, youll know that
25/08/2016 12:10
453 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
"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 Springs classpath:
prefix.
Please note that Springs testing support for WebApplicationContexts is on par with its
support for standard ApplicationContexts . When testing with a
WebApplicationContext you are free to declare XML configuration files, Groovy
scripts, or @Configuration classes via @ContextConfiguration . You are of course
also free to use any other test annotations such as @ActiveProfiles ,
@TestExecutionListeners , @Sql , @Rollback , etc.
The following examples demonstrate some of the various configuration options for
loading a WebApplicationContext .
Conventions.
@RunWith(SpringRunner.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 frameworks 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.
@RunWith(SpringRunner.class)
// file system resource
25/08/2016 12:10
454 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
@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.
@RunWith(SpringRunner.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.
To provide comprehensive web testing support, Spring 3.2 introduced a
ServletTestExecutionListener that is enabled by default. When testing against a
WebApplicationContext this TestExecutionListener sets up default thread-local state
via Spring Webs 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
25/08/2016 12:10
455 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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.
@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;
//...
}
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
25/08/2016 12:10
456 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
457 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Since Spring Framework 4.3, the size of the context cache is bounded with a default
maximum size of 32. Whenever the maximum size is reached, a least recently used
(LRU) eviction policy is used to evict and close stale contexts. The maximum size can be
configured from the command line or a build script by setting a JVM system property
named spring.test.context.cache.maxSize . As an alternative, the same property
can be set programmatically via the SpringProperties API.
Since having a large number of application contexts loaded within a given test suite can
cause the suite to take an unnecessarily long time to execute, it is often beneficial to
know exactly how many contexts have been loaded and cached. To view the statistics for
the underlying context cache, simply set the log level for the
org.springframework.test.context.cache logging category to DEBUG .
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 objectyou can
annotate your test class or test method with @DirtiesContext (see the discussion of
@DirtiesContext in Section 15.4.1, Spring Testing Annotations). 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
DirtiesContextBeforeModesTestExecutionListener and the
DirtiesContextTestExecutionListener which are enabled by default.
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 Springs ContextLoaderListener and a
child WebApplicationContext loaded via Springs 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.
Since 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.
25/08/2016 12:10
458 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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 4 based examples demonstrate common configuration scenarios for
integration tests that require the use of context hierarchies.
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).
@RunWith(SpringRunner.class)
@WebAppConfiguration
@ContextHierarchy({
@ContextConfiguration(classes = TestAppConfig.class),
@ContextConfiguration(classes = WebConfig.class)
})
public class ControllerIntegrationTests {
@Autowired
private WebApplicationContext wac;
// ...
}
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.
@RunWith(SpringRunner.class)
25/08/2016 12:10
459 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
@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 {}
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 the name
attribute in @ContextConfiguration 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"} .
@RunWith(SpringRunner.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 {}
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 the
inheritLocations flag in @ContextConfiguration 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" .
@RunWith(SpringRunner.class)
@ContextHierarchy({
@ContextConfiguration(name = "parent", locations = "/app-config.xml"),
25/08/2016 12:10
460 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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 autowiring by type, 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") .
25/08/2016 12:10
461 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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
Goals 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.
The first code listing shows a JUnit 4 based implementation of the test class that uses
@Autowired for field injection.
@RunWith(SpringRunner.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.
@RunWith(SpringRunner.class)
// specifies the Spring configuration to load for this test fixture
25/08/2016 12:10
462 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
The preceding code listings use the same XML context file referenced by the
@ContextConfiguration annotation (that is, repository-config.xml ), which looks
like this:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- this bean will be injected into the HibernateTitleRepositoryTests class -->
<bean id="titleRepository" class="com.foo.repository.hibernate.HibernateTitleRepos
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
If you are extending from a Spring-provided test base class that happens to use @Autowired
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 overr
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.
// ...
25/08/2016 12:10
463 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
@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
of type matches to a specific bean. Its value is matched against <qualifier> declarations
within the corresponding <bean> 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).
25/08/2016 12:10
464 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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
25/08/2016 12:10
465 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
framework.
Session-scoped bean configuration.
<beans>
<bean id="userService"
class="com.example.SimpleUserService"
c:userPreferences-ref="userPreferences" />
<bean id="userPreferences"
class="com.example.UserPreferences"
c:theme="#{session.getAttribute('theme')}"
scope="session">
<aop:scoped-proxy />
</bean>
</beans>
25/08/2016 12:10
466 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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
transaction propagation for details).
25/08/2016 12:10
467 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
rollback and commit behavior, 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
Section 15.7, PetClinic Example for an additional example.
@RunWith(SpringRunner.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);
}
25/08/2016 12:10
468 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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 @Commit and @Rollback annotations. See the corresponding entries in the
annotation support section for further details.
25/08/2016 12:10
469 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
470 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
@ContextConfiguration
@Transactional(transactionManager = "txMgr")
@Commit
public class FictitiousTransactionalTest {
@BeforeTransaction
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 @Commit setting
@Rollback
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
void verifyFinalDatabaseState() {
// logic to verify the final state after transaction has rolled back
}
}
When you test application code that manipulates the state of a Hibernate session
or JPA persistence context, make sure to flush the underlying unit of work within
test methods that execute that code. Failing to flush the underlying unit of work 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 any ORM frameworks that maintain an in-memory unit of work.
// ...
@Autowired
25/08/2016 12:10
471 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
SessionFactory sessionFactory;
@Transactional
@Test // no expected exception!
public void falsePositive() {
updateEntityInHibernateSession();
// False positive: an exception will be thrown once the Hibernate
// Session is finally flushed (i.e., in production code)
}
@Transactional
@Test(expected = ...)
public void updateWithSessionFlush() {
updateEntityInHibernateSession();
// Manual flush is required to avoid false positive in test
sessionFactory.getCurrentSession().flush();
}
// ...
Or for JPA:
// ...
@PersistenceContext
EntityManager entityManager;
@Transactional
@Test // no expected exception!
public void falsePositive() {
updateEntityInJpaPersistenceContext();
// False positive: an exception will be thrown once the JPA
// EntityManager is finally flushed (i.e., in production code)
}
@Transactional
@Test(expected = ...)
public void updateWithEntityManagerFlush() {
updateEntityInJpaPersistenceContext();
// Manual flush is required to avoid false positive in test
entityManager.flush();
}
// ...
25/08/2016 12:10
472 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
org.springframework.test.context.junit4.AbstractTransactionalJUnit4SpringConte
org.springframework.test.context.testng.AbstractTransactionalTestNGSpringConte
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 .
25/08/2016 12:10
473 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
474 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
@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
}
}
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.
25/08/2016 12:10
475 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
@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
}
25/08/2016 12:10
476 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
477 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
478 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
@RunWith(SpringRunner.class)
@TestExecutionListeners({})
public class SimpleTest {
@Test
public void testMethod() {
// execute test logic...
}
}
25/08/2016 12:10
479 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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(SpringRunner.class)
or Springs JUnit rules.
25/08/2016 12:10
480 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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.
25/08/2016 12:10
481 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
The Spring MVC Test framework provides first class support for testing Spring MVC code
using a fluent API that can be used with JUnit, TestNG, or any other testing framework.
Its built on the Servlet API mock objects from the spring-test module and hence does
not use a running Servlet container. It uses the DispatcherServlet to provide full
Spring MVC runtime behavior and provides support for loading actual Spring
configuration with the TestContext framework in addition to a standalone mode in which
controllers may be instantiated manually and tested one at a time.
Spring MVC Test also provides client-side support for testing code that uses the
RestTemplate . Client-side tests mock the server responses and also do not use a
running server.
Spring Boot provides an option to write full, end-to-end integration tests that
include a running server. If this is your goal please have a look at the Spring
Boot reference page. For more information on the differences between
out-of-container and end-to-end integration tests, see the section called
Differences between Out-of-Container and End-to-End Integration Tests.
25/08/2016 12:10
482 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
@RunWith(SpringRunner.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(
.andExpect(status().isOk())
.andExpect(content().contentType("application/json"))
.andExpect(jsonPath("$.name").value("Lee"));
}
}
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
25/08/2016 12:10
483 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
(e.g. IntelliJ) may not require any additional configuration. Just check the support for code
completion on static members.
Setup Options
There are two main options for creating an instance of MockMvc . The first is to load
Spring MVC configuration through the TestContext framework, which loads the Spring
configuration and injects a WebApplicationContext into the test to use to build a
MockMvc instance:
@RunWith(SpringRunner.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 is to simply create a controller instance manually without loading Spring
configuration. Instead basic default configuration, roughly comparable to that of the MVC
JavaConfig or the MVC namespace, is automatically created and can be customized to a
degree:
public class MyWebTests {
private MockMvc mockMvc;
@Before
public void setup() {
this.mockMvc = MockMvcBuilders.standaloneSetup(new AccountController()).build(
}
// ...
25/08/2016 12:10
484 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
You can then inject the mock service into the test in order set up and verify expectations:
@RunWith(SpringRunner.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 doesnt involve loading Spring configuration. Such tests are more focused on 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 specific behavior or to debug an issue.
Just like with any "integration vs. unit testing" debate, there is no right or wrong answer.
However, using the "standaloneSetup" does imply the need for additional
"webAppContextSetup" tests in order to verify your Spring MVC configuration.
25/08/2016 12:10
485 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Performing Requests
Its easy to perform requests using any HTTP method:
mockMvc.perform(post("/hotels/{id}", 42).accept(MediaType.APPLICATION_JSON));
You can also perform file upload requests that internally use
MockMultipartHttpServletRequest so that there is no actual parsing of a multipart
request but rather you have to set it up:
mockMvc.perform(fileUpload("/doc").file("a1", "ABC".getBytes("UTF-8")));
Or you can add Servlet request parameters representing either query of form parameters:
mockMvc.perform(get("/hotels").param("foo", "bar"));
If application code relies on Servlet request parameters and doesnt check the query
string explicitly (as is most often the case) then it doesnt matter which option you use.
Keep in mind however that query params provided with the URI template will be decoded
while request parameters provided through the param() method are expected to
already be decoded.
In most cases its 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:
mockMvc.perform(get("/app/main/hotels/{id}").contextPath("/app").servletPath(
Looking at the above example, it would be cumbersome to set the contextPath and
servletPath with every performed request. Instead you can set up default request
properties:
public class MyWebTests {
private MockMvc mockMvc;
@Before
25/08/2016 12:10
486 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
The above properties will affect every request performed through the MockMvc instance.
If the same property is also specified on a given request, it overrides the default value.
That is why the HTTP method and URI in the default request dont matter since they must
be specified on every request.
Defining Expectations
Expectations can be defined by appending one or more .andExpect(..) calls after
performing a request:
mockMvc.perform(get("/accounts/1")).andExpect(status().isOk());
Many times when writing tests, its useful to dump the results of the performed request.
This can be done as follows, where print() is a static import from
MockMvcResultHandlers :
mockMvc.perform(post("/persons"))
.andDo(print())
.andExpect(status().isOk())
25/08/2016 12:10
487 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
.andExpect(model().attributeHasErrors("person"));
As long as request processing does not cause an unhandled exception, the print()
method will print all the available result data to System.out . Spring Framework 4.2
introduced a log() method and two additional variants of the print() method, one
that accepts an OutputStream and one that accepts a Writer . For example, invoking
print(System.err) will print the result data to System.err ; while invoking
print(myWriter) will print the result data to a custom writer. If you would like to have
the result data logged instead of printed, simply invoke the log() method which will log
the result data as a single DEBUG message under the
org.springframework.test.web.servlet.result logging category.
In some cases, you may want to get direct access to the result and verify something that
cannot be verified otherwise. This can be achieved by appending .andReturn() after all
other expectations:
If all tests repeat the same expectations you can set up common expectations once when
building the MockMvc instance:
standaloneSetup(new SimpleController())
.alwaysExpect(status().isOk())
.alwaysExpect(content().contentType("application/json;charset=UTF-8"))
.build()
Note that common expectations are always applied and cannot be overridden without
creating a separate MockMvc instance.
When JSON response content contains hypermedia links created with Spring HATEOAS,
the resulting links can be verified using JsonPath expressions:
mockMvc.perform(get("/people").accept(MediaType.APPLICATION_JSON))
.andExpect(jsonPath("$.links[?(@.rel == 'self')].href").value("http://localhost:80
When XML response content contains hypermedia links created with Spring HATEOAS,
the resulting links can be verified using XPath expressions:
25/08/2016 12:10
488 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Filter Registrations
When setting up a MockMvc instance, you can register one or more Servlet Filter
instances:
Registered filters will be invoked through via the MockFilterChain from spring-test ,
and the last filter will delegate to the DispatcherServlet .
25/08/2016 12:10
489 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
490 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
web application that supports CRUD operations on a Message object. The application
also supports paging through all messages. How would you go about testing it?
With Spring MVC Test, we can easily test if we are able to create a Message .
MockHttpServletRequestBuilder createMessage = post("/messages/")
.param("summary", "Spring Rocks")
.param("text", "In case you didn't know, Spring Rocks!");
mockMvc.perform(createMessage)
.andExpect(status().is3xxRedirection())
.andExpect(redirectedUrl("/messages/123"));
What if we want to test our form view that allows us to create the message? For example,
assume our form looks like the following snippet:
<form id="messageForm" action="/messages/" method="post">
<div class="pull-right"><a href="/messages/">Messages</a></div>
<label for="summary">Summary</label>
<input type="text" class="required" id="summary" name="summary" value="" />
<label for="text">Message</label>
<textarea id="text" name="text"></textarea>
<div class="form-actions">
<input type="submit" value="Create" />
</div>
</form>
How do we ensure that our form will produce the correct request to create a new
message? A naive attempt would look like this:
mockMvc.perform(get("/messages/form"))
.andExpect(xpath("//input[@name='summary']").exists())
.andExpect(xpath("//textarea[@name='text']").exists());
This test has some obvious drawbacks. If we update our controller to use the parameter
message instead of text , our form test would continue to pass even though the HTML
form is out of synch with the controller. To resolve this we can combine our two tests.
String summaryParamName = "summary";
String textParamName = "text";
mockMvc.perform(get("/messages/form"))
.andExpect(xpath("//input[@name='" + summaryParamName + "']"
.andExpect(xpath("//textarea[@name='" + textParamName + "']"
25/08/2016 12:10
491 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
This would reduce the risk of our test incorrectly passing, but there are still some
problems.
What if we have multiple forms on our page? Admittedly we could update our xpath
expressions, but they get more complicated the more factors we take into account
(Are the fields the correct type? Are the fields enabled? etc.).
Another issue is that we are doing double the work we would expect. We must first
verify the view, and then we submit the view with the same parameters we just
verified. Ideally this could be done all at once.
Finally, there are some things that we still cannot account for. For example, what if
the form has JavaScript validation that we wish to test as well?
The overall problem is that testing a web page does not involve a single interaction.
Instead, it is a combination of how the user interacts with a web page and how that web
page interacts with other resources. For example, the result of a form view is used as the
input to a user for creating a message. In addition, our form view may potentially utilize
additional resources which impact the behavior of the page, such as JavaScript
validation.
25/08/2016 12:10
492 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
key constraints.
Testing can become slow since each test would need to ensure that the database is
in the correct state.
Since our database needs to be in a specific state, we cannot run tests in parallel.
Performing assertions on things like auto-generated ids, timestamps, etc. can be
difficult.
These challenges do not mean that we should abandon end-to-end integration testing
altogether. Instead, we can reduce the number of end-to-end integration tests by
refactoring our detailed tests to use mock services which will execute much faster, more
reliably, and without side effects. We can then implement a small number of true
end-to-end integration tests that validate simple workflows to ensure that everything
works together properly.
25/08/2016 12:10
493 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
MockMvcWebClientBuilder as follows.
@Autowired
WebApplicationContext context;
WebClient webClient;
@Before
public void setup() {
webClient = MockMvcWebClientBuilder
.webAppContextSetup(context)
.build();
}
This will ensure that any URL referencing localhost as the server will be directed to
our MockMvc instance without the need for a real HTTP connection. Any other URL will
be requested using a network connection as normal. This allows us to easily test the use
of CDNs.
The default context path is "" . Alternatively, we can specify the context
path as illustrated in the section called Advanced
MockMvcWebClientBuilder.
Once we have a reference to the HtmlPage , we can then fill out the form and submit it to
create a message.
HtmlForm form = createMsgFormPage.getHtmlElementById("messageForm");
HtmlTextInput summaryInput = createMsgFormPage.getHtmlElementById("summary");
25/08/2016 12:10
494 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Finally, we can verify that a new message was created successfully. The following
assertions use the AssertJ library.
assertThat(newMessagePage.getUrl().toString()).endsWith("/messages/123");
String id = newMessagePage.getHtmlElementById("id").getTextContent();
assertThat(id).isEqualTo("123");
String summary = newMessagePage.getHtmlElementById("summary").getTextContent();
assertThat(summary).isEqualTo("Spring Rocks");
String text = newMessagePage.getHtmlElementById("text").getTextContent();
assertThat(text).isEqualTo("In case you didn't know, Spring Rocks!");
This improves on our MockMvc test in a number of ways. First we no longer have to
explicitly verify our form and then create a request that looks like the form. Instead, we
request the form, fill it out, and submit it, thereby significantly reducing the overhead.
Another important factor is that HtmlUnit uses the Mozilla Rhino engine to evaluate
JavaScript. This means that we can test the behavior of JavaScript within our pages as
well!
Refer to the HtmlUnit documentation for additional information about using HtmlUnit.
Advanced MockMvcWebClientBuilder
In the examples so far, we have used MockMvcWebClientBuilder in the simplest way
possible, by building a WebClient based on the WebApplicationContext loaded for
us by the Spring TestContext Framework. This approach is repeated here.
@Autowired
WebApplicationContext context;
WebClient webClient;
@Before
public void setup() {
webClient = MockMvcWebClientBuilder
.webAppContextSetup(context)
.build();
}
25/08/2016 12:10
495 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
WebClient webClient;
@Before
public void setup() {
webClient = MockMvcWebClientBuilder
// demonstrates applying a MockMvcConfigurer (Spring Security)
.webAppContextSetup(context, springSecurity())
// for illustration only - defaults to ""
.contextPath("")
// By default MockMvc is used for localhost only;
// the following will use MockMvc for example.com and example.org as w
.useMockMvcForHosts("example.com","example.org")
.build();
}
As an alternative, we can perform the exact same setup by configuring the MockMvc
instance separately and supplying it to the MockMvcWebClientBuilder as follows.
MockMvc mockMvc = MockMvcBuilders
.webAppContextSetup(context)
.apply(springSecurity())
.build();
webClient = MockMvcWebClientBuilder
.mockMvcSetup(mockMvc)
// for illustration only - defaults to ""
.contextPath("")
// By default MockMvc is used for localhost only;
// the following will use MockMvc for example.com and example.org as w
.useMockMvcForHosts("example.com","example.org")
.build();
This is more verbose, but by building the WebClient with a MockMvc instance we have
the full power of MockMvc at our fingertips.
25/08/2016 12:10
496 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Suppose we need to ensure that a message is created properly. The tests involve finding
the HTML form input elements, filling them out, and making various assertions.
This approach results in numerous, separate tests because we want to test error
conditions as well. For example, we want to ensure that we get an error if we fill out only
part of the form. If we fill out the entire form, the newly created message should be
displayed afterwards.
If one of the fields were named "summary", then we might have something like the
following repeated in multiple places within our tests.
HtmlTextInput summaryInput = currentPage.getHtmlElementById("summary");
summaryInput.setValueAttribute(summary);
So what happens if we change the id to "smmry"? Doing so would force us to update all
of our tests to incorporate this change! Of course, this violates the DRY Principle; so we
should ideally extract this code into its own method as follows.
public HtmlPage createMessage(HtmlPage currentPage, String summary, String text) {
setSummary(currentPage, summary);
// ...
}
public void setSummary(HtmlPage currentPage, String summary) {
HtmlTextInput summaryInput = currentPage.getHtmlElementById("summary"
summaryInput.setValueAttribute(summary);
}
This ensures that we do not have to update all of our tests if we change the UI.
We might even take this a step further and place this logic within an Object that
represents the HtmlPage we are currently on.
public class CreateMessagePage {
25/08/2016 12:10
497 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Formerly, this pattern is known as the Page Object Pattern. While we can certainly do this
with HtmlUnit, WebDriver provides some tools that we will explore in the following
sections to make this pattern much easier to implement.
25/08/2016 12:10
498 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
WebDriver driver;
@Before
public void setup() {
driver = MockMvcHtmlUnitDriverBuilder
.webAppContextSetup(context)
.build();
}
This will ensure that any URL referencing localhost as the server will be directed to
our MockMvc instance without the need for a real HTTP connection. Any other URL will
be requested using a network connection as normal. This allows us to easily test the use
of CDNs.
We can then fill out the form and submit it to create a message.
ViewMessagePage viewMessagePage =
page.createMessage(ViewMessagePage.class, expectedSummary, expectedText);
This improves on the design of our HtmlUnit test by leveraging the Page Object Pattern.
As we mentioned in the section called Why WebDriver and MockMvc?, we can use the
Page Object Pattern with HtmlUnit, but it is much easier with WebDriver. Lets take a look
at our new CreateMessagePage implementation.
public class CreateMessagePage
extends AbstractPage {
25/08/2016 12:10
499 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
@FindBy(css = "input[type=submit]")
private WebElement submit;
public CreateMessagePage(WebDriver driver) {
super(driver);
}
The first thing you will notice is that CreateMessagePage extends the
AbstractPage . We wont go over the details of AbstractPage , but in summary it
contains common functionality for all of our pages. For example, if our application
has a navigational bar, global error messages, etc., this logic can be placed in a
shared location.
The next thing you will notice is that we have a member variable for each of the
parts of the HTML page that we are interested in. These are of type WebElement .
WebDriver 's PageFactory allows us to remove a lot of code from the HtmlUnit
version of CreateMessagePage by automatically resolving each WebElement . The
PageFactory#initElements(WebDriver,Class<T>) method will automatically resolve
each WebElement by using the field name and looking it up by the id or name of
the element within the HTML page.
We can use the @FindBy annotation to override the default lookup behavior. Our
example demonstrates how to use the @FindBy annotation to look up our submit
button using a css selector, input[type=submit].
Finally, we can verify that a new message was created successfully. The following
assertions use the FEST assertion library.
assertThat(viewMessagePage.getMessage()).isEqualTo(expectedMessage);
assertThat(viewMessagePage.getSuccess()).isEqualTo("Successfully created a new message
25/08/2016 12:10
500 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Advanced MockMvcHtmlUnitDriverBuilder
In the examples so far, we have used MockMvcHtmlUnitDriverBuilder in the simplest
way possible, by building a WebDriver based on the WebApplicationContext loaded
for us by the Spring TestContext Framework. This approach is repeated here.
@Autowired
WebApplicationContext context;
WebDriver driver;
@Before
public void setup() {
driver = MockMvcHtmlUnitDriverBuilder
.webAppContextSetup(context)
.build();
}
25/08/2016 12:10
501 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
@Before
public void setup() {
driver = MockMvcHtmlUnitDriverBuilder
// demonstrates applying a MockMvcConfigurer (Spring Security)
.webAppContextSetup(context, springSecurity())
// for illustration only - defaults to ""
.contextPath("")
// By default MockMvc is used for localhost only;
// the following will use MockMvc for example.com and example.org as w
.useMockMvcForHosts("example.com","example.org")
.build();
}
As an alternative, we can perform the exact same setup by configuring the MockMvc
instance separately and supplying it to the MockMvcHtmlUnitDriverBuilder as follows.
MockMvc mockMvc = MockMvcBuilders
.webAppContextSetup(context)
.apply(springSecurity())
.build();
driver = MockMvcHtmlUnitDriverBuilder
.mockMvcSetup(mockMvc)
// for illustration only - defaults to ""
.contextPath("")
// By default MockMvc is used for localhost only;
// the following will use MockMvc for example.com and example.org as w
.useMockMvcForHosts("example.com","example.org")
.build();
This is more verbose, but by building the WebDriver with a MockMvc instance we have
the full power of MockMvc at our fingertips.
25/08/2016 12:10
502 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Geb is backed by WebDriver, so it offers many of the same benefits that we get from
WebDriver. However, Geb makes things even easier by taking care of some of the
boilerplate code for us.
This will ensure that any URL referencing localhost as the server will be directed to
our MockMvc instance without the need for a real HTTP connection. Any other URL will
be requested using a network connection as normal. This allows us to easily test the use
of CDNs.
We can then fill out the form and submit it to create a message.
when:
form.summary = expectedSummary
form.text = expectedMessage
submit.click(ViewMessagePage)
Any unrecognized method calls or property accesses/references that are not found will be
forwarded to the current page object. This removes a lot of the boilerplate code we
25/08/2016 12:10
503 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
As with direct WebDriver usage, this improves on the design of our HtmlUnit test by
leveraging the Page Object Pattern. As mentioned previously, we can use the Page
Object Pattern with HtmlUnit and WebDriver, but it is even easier with Geb. Lets take a
look at our new Groovy-based CreateMessagePage implementation.
class CreateMessagePage extends Page {
static url = 'messages/form'
static at = { assert title == 'Messages : Create'; true }
static content = {
submit { $('input[type=submit]') }
form { $('form') }
errors(required:false) { $('label.error, .alert-error')?.text() }
}
}
The first thing you will notice is that our CreateMessagePage extends Page . We wont
go over the details of Page , but in summary it contains common functionality for all of our
pages. The next thing you will notice is that we define a URL in which this page can be
found. This allows us to navigate to the page as follows.
to CreateMessagePage
We also have an at closure that determines if we are at the specified page. It should
return true if we are on the correct page. This is why we can assert that we are on the
correct page as follows.
then:
at CreateMessagePage
errors.contains('This field is required.')
Next we create a content closure that specifies all the areas of interest within the page.
We can use a jQuery-ish Navigator API to select the content we are interested in.
Finally, we can verify that a new message was created successfully.
then:
at ViewMessagePage
success == 'Successfully created a new message'
id
date
25/08/2016 12:10
504 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
summary == expectedSummary
message == expectedMessage
For further details on how to get the most out of Geb, consult The Book of Geb users
manual.
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 request to "/greeting" and want to return a 200 response with "text/plain"
content. We could define as additional expected requests and stub responses as needed.
When expected requests and stub responses are defined, the RestTemplate can be
used in client-side code as usual. At the end of testing mockServer.verify() can be
used to verify that all expectations have been satisfied.
By default requests are expected in the order in which expectations were declared. You
can set the ignoreExpectOrder option when building the server in which case all
expectations are checked (in order) to find a match for a given request. That means
requests are allowed to come in any order. Here is an example:
server = MockRestServiceServer.bindTo(restTemplate).ignoreExpectOrder(true).build();
Even with unordered requests by default each request is allowed to execute once only.
The expect method provides an overloaded variant that accepts an ExpectedCount
argument that specifies a count range, e.g. once , manyTimes , max , min , between ,
and so on. Here is an example:
25/08/2016 12:10
505 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Note that when ignoreExpectOrder is not set (the default), and therefore requests are
expected in order of declaration, then that order only applies to the first of any expected
request. For example if "/foo" is expected 2 times followed by "/bar" 3 times, then there
should be a request to "/foo" before there is a request to "/bar" but aside from that
subsequent "/foo" and "/bar" requests can come at any time.
As an alternative to all of the above the client-side test support also provides a
ClientHttpRequestFactory implementation that can be configured into a
RestTemplate to bind it to a MockMvc instance. That allows processing requests using
actual server-side logic but without running a server. Here is an example:
MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build();
this.restTemplate = new RestTemplate(new MockMvcClientHttpRequestFactory(mockMvc));
// Test code that uses the above RestTemplate ...
mockServer.verify();
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.
506 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
The PetClinic application, available on GitHub, illustrates several features of the Spring
TestContext Framework in a JUnit 4 environment. Most test functionality is included in the
AbstractClinicTests , for which a partial listing is shown below:
import static org.junit.Assert.assertEquals;
// import ...
@ContextConfiguration
public abstract class AbstractClinicTests extends AbstractTransactionalJUnit4SpringCon
@Autowired
protected Clinic clinic;
@Test
public void getVets() {
Collection<Vet> 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 variablethe application object being testedis 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
25/08/2016 12:10
507 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
database within the test fixture set up of your test casesagain, 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 .
@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
variablespopulated by Dependency Injection, naturallysuch 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 <jee:jndi-lookup> 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
25/08/2016 12:10
508 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
509 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
510 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Transaction bound event describes how you could use application events within a
transaction.
25/08/2016 12:10
511 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
512 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
513 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
514 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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:
public interface TransactionStatus extends SavepointManager {
boolean isNewTransaction();
boolean hasSavepoint();
void setRollbackOnly();
boolean isRollbackOnly();
void flush();
boolean isCompleted();
}
25/08/2016 12:10
515 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
If you use JTA in a Java EE container then you use a container DataSource , obtained
through JNDI, in conjunction with Springs JtaTransactionManager . This is what the
JTA and JNDI lookup version would look like:
<?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:jee="http://www.springframework.org/schema/jee"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/jee
http://www.springframework.org/schema/jee/spring-jee.xsd">
<jee:jndi-lookup id="dataSource" jndi-name="jdbc/jpetstore"/>
The JtaTransactionManager does not need to know about the DataSource , or any
other specific resources, because it uses the containers global transaction management
infrastructure.
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.
25/08/2016 12:10
516 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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.
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
25/08/2016 12:10
517 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
transactions are managed merely by changing configuration, even if that change means
moving from local to global transactions or vice versa.
25/08/2016 12:10
518 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
17.4.3 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.
25/08/2016 12:10
519 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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 <tx:tags/> as simply defining TransactionProxyFactoryBean beans on
your behalf.
The concept of rollback rules is important: they enable you to specify which exceptions
25/08/2016 12:10
520 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
(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 anapplication 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.
25/08/2016 12:10
521 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
522 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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.
<!-- from the file 'context.xml' -->
<?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">
<!-- this is the service object that we want to make transactional -->
<bean id="fooService" class="x.y.service.DefaultFooService"/>
<!-- the transactional advice (what 'happens'; see the <aop:advisor/> bean below)
25/08/2016 12:10
523 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
<!-- ensure that the above transactional advice runs for any execution
of an operation defined by the FooService interface -->
<aop:config>
<aop:pointcut id="fooServiceOperation" expression="execution(* x.y.service.Foo
<aop:advisor advice-ref="txAdvice" pointcut-ref="fooServiceOperation"
</aop:config>
Examine the preceding configuration. You want to make a service object, the
fooService bean, transactional. The transaction semantics to apply are encapsulated in
the <tx:advice/> definition. The <tx:advice/> 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 <tx:advice/> tag is set to the name of the
PlatformTransactionManager bean that is going to drive the transactions, in this case,
the txManager bean.
25/08/2016 12:10
524 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
The <aop:config/> 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 <aop:pointcut/> element is an AspectJ pointcut
expression; see Chapter 11, Aspect Oriented Programming with Spring 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:
<aop:config>
<aop:pointcut id="fooServiceMethods" expression="execution(* x.y.service.*.*(..))"
<aop:advisor advice-ref="txAdvice" pointcut-ref="fooServiceMethods"/>
</aop:config>
In this example it is assumed that all your service interfaces are defined in
the x.y.service package; see Chapter 11, Aspect Oriented Programming
with Spring for more details.
Now that weve 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:
public final class Boot {
25/08/2016 12:10
525 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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.)
25/08/2016 12:10
526 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
that a transactions 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 Frameworks 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 Frameworks 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.
<tx:advice id="txAdvice" transaction-manager="txManager">
<tx:attributes>
<tx:method name="get*" read-only="true" rollback-for="NoProductInStockException"
<tx:method name="*"/>
</tx:attributes>
</tx:advice>
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 Frameworks transaction
infrastructure to commit the attendant transaction even in the face of an unhandled
InstrumentNotFoundException .
<tx:advice id="txAdvice">
<tx:attributes>
<tx:method name="updateStock" no-rollback-for="InstrumentNotFoundException"
<tx:method name="*"/>
</tx:attributes>
</tx:advice>
<tx:advice id="txAdvice">
<tx:attributes>
<tx:method name="*" rollback-for="Throwable" no-rollback-for="InstrumentNotFoundEx
</tx:attributes>
25/08/2016 12:10
527 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
</tx:advice>
You can also indicate a required rollback programmatically. Although very simple, this
process is quite invasive, and tightly couples your code to the Spring Frameworks
transaction infrastructure:
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.
25/08/2016 12:10
528 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
<aop:config>
<aop:pointcut id="serviceOperation"
expression="execution(* x.y.service..*Service.*(..))"/>
<aop:advisor pointcut-ref="serviceOperation" advice-ref="txAdvice"/>
</aop:config>
<!-- these two beans will be transactional... -->
<bean id="fooService" class="x.y.service.DefaultFooService"/>
<bean id="barService" class="x.y.service.extras.SimpleBarService"/>
The following example shows how to configure two distinct beans with totally different
transactional settings.
<?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">
<aop:config>
25/08/2016 12:10
529 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
expression="execution(* x.y.service.*Service.*(..))"/>
<aop:pointcut id="noTxServiceOperation"
expression="execution(* x.y.service.ddl.DefaultDdlManager.*(..))"
<!-- this bean will also be transactional, but with totally different transactiona
<bean id="anotherFooService" class="x.y.service.ddl.DefaultDdlManager"/>
<tx:advice id="defaultTxAdvice">
<tx:attributes>
<tx:method name="get*" read-only="true"/>
<tx:method name="*"/>
</tx:attributes>
</tx:advice>
<tx:advice id="noTxAdvice">
<tx:attributes>
<tx:method name="*" propagation="NEVER"/>
</tx:attributes>
</tx:advice>
25/08/2016 12:10
530 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
You can change these default settings; the various attributes of the <tx:method/> tags
that are nested within <tx:advice/> and <tx:attributes/> tags are summarized
below:
Required?
Default
Yes
Description
No
isolation
No
DEFAULT
timeout
No
-1
read-only
No
false
rollback-for
No
com.foo.MyBusinessException,ServletEx
no-rollback-for
No
com.foo.MyBusinessException,ServletEx
25/08/2016 12:10
531 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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:
<!-- from the file 'context.xml' -->
<?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">
<!-- this is the service object that we want to make transactional -->
<bean id="fooService" class="x.y.service.DefaultFooService"/>
25/08/2016 12:10
532 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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
25/08/2016 12:10
533 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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.
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 . Also, the proxy must be fully
initialized to provide the expected behaviour so you should not rely on this
feature in your initialization code, i.e. @PostConstruct .
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.
Annotation Attribute
N/A (See
Default
transactionManager
TransactionManagementConfigurer
javadocs)
mode
mode
proxy
25/08/2016 12:10
534 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
XML Attribute
Annotation Attribute
proxy-target-class
proxyTargetClass
Default
false
25/08/2016 12:10
535 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
XML Attribute
Annotation Attribute
order
order
Default
Ordered.LOWEST_PRECED
25/08/2016 12:10
536 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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.
@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
}
}
@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:
25/08/2016 12:10
537 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Type
String
Description
Optional qualifier
specifying the
transaction manager to
be used.
propagation
enum: Propagation
Optional propagation
setting.
isolation
enum: Isolation
readOnly
boolean
Read/write vs.
read-only transaction
timeout
Transaction timeout.
granularity)
rollbackFor
Array of Class
Optional array of
derived from
Throwable.
rollbackForClassName
noRollbackFor
Classes must be
of exception classes
derived from
Throwable.
rollback.
Array of Class
Optional array of
derived from
25/08/2016 12:10
538 de 1194
Property
noRollbackForClassName
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Type
Description
of exception classes
derived from
Throwable.
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, WebLogics 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 .
could be combined with the following transaction manager bean declarations in the
application context.
<tx:annotation-driven/>
25/08/2016 12:10
539 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
</bean>
In this case, the two methods on TransactionalService will run under separate
transaction managers, differentiated by the "order" and "account" qualifiers. The default
<tx:annotation-driven> target bean name transactionManager will still be used if
no specifically qualified PlatformTransactionManager bean is found.
Here we have used the syntax to define the transaction manager qualifier, but could also
have included propagation behavior, rollback rules, timeouts etc.
25/08/2016 12:10
540 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Required
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 transactions 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
25/08/2016 12:10
541 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
RequiresNew
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 transactions rollback
status.
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
Springs DataSourceTransactionManager .
25/08/2016 12:10
542 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
This chapter is not concerned with explaining AOP in any great detail
(except as it applies to transactions). See Chapter 11, Aspect Oriented
Programming with Spring 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 the
section called Advice ordering. .
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());
}
25/08/2016 12:10
543 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
return returnValue;
}
}
<?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="fooService" class="x.y.service.DefaultFooService"/>
<aop:config>
<!-- this advice will execute around the transactional advice -->
<aop:aspect id="profilingAspect" ref="profiler">
<aop:pointcut id="serviceMethodWithReturnValue"
expression="execution(!void x.y..*Service.*(..))"/>
<aop:around method="profile" pointcut-ref="serviceMethodWithReturnValu
</aop:aspect>
</aop:config>
25/08/2016 12:10
544 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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.
<?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="fooService" class="x.y.service.DefaultFooService"/>
<aop:config>
<aop:pointcut id="entryPointMethod" expression="execution(* x.y..*Service.*(..
<!-- will execute after the profiling advice (c.f. the order attribute) -->
<aop:advisor advice-ref="txAdvice" pointcut-ref="entryPointMethod" __order
<!-- order value is higher than the profiling aspect -->
<aop:aspect id="profilingAspect" ref="profiler">
<aop:pointcut id="serviceMethodWithReturnValue"
expression="execution(!void x.y..*Service.*(..))"/>
<aop:around method="profile" pointcut-ref="serviceMethodWithReturnValue"
</aop:aspect>
</aop:config>
<tx:advice id="txAdvice" transaction-manager="txManager">
<tx:attributes>
<tx:method name="get*" read-only="true"/>
<tx:method name="*"/>
25/08/2016 12:10
545 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
</tx:attributes>
</tx:advice>
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 beans order property so
that it is higher than the transactional advices order value.
You configure additional aspects in similar fashion.
// configure the AnnotationTransactionAspect to use it; this must be done before execu
AnnotationTransactionAspect.aspectOf().setTransactionManager(txManager);
25/08/2016 12:10
546 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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 Javas rule that annotations on interfaces are
not inherited.
25/08/2016 12:10
547 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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 .
public class SimpleService implements Service {
// single TransactionTemplate shared amongst all methods in this instance
private final TransactionTemplate transactionTemplate;
Code within the callback can roll the transaction back by calling the setRollbackOnly()
method on the supplied TransactionStatus object:
25/08/2016 12:10
548 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
protected void doInTransactionWithoutResult(TransactionStatus status) {
try {
updateOperation1();
updateOperation2();
} catch (SomeBusinessExeption ex) {
status.setRollbackOnly();
}
}
});
25/08/2016 12:10
549 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
550 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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.
25/08/2016 12:10
551 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
552 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
553 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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.
25/08/2016 12:10
554 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
555 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
If you are using the classic Hibernate APIs than you can inject the SessionFactory:
@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 .
@Repository
public class JdbcMovieFinder implements MovieFinder {
private JdbcTemplate jdbcTemplate;
@Autowired
public void init(DataSource dataSource) {
this.jdbcTemplate = new JdbcTemplate(dataSource);
}
// ...
}
Please see the specific coverage of each persistence technology for details
on how to configure the application context to take advantage of these
annotations.
25/08/2016 12:10
556 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Spring
You
X
Handle transactions.
The Spring Framework takes care of all the low-level details that can make JDBC such a
tedious API to develop with.
25/08/2016 12:10
557 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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 doesnt 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.
25/08/2016 12:10
558 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
559 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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.
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).
Querying (SELECT)
Here is a simple query for getting the number of rows in a relation:
int rowCount = this.jdbcTemplate.queryForObject("select count(*) from t_actor"
25/08/2016 12:10
560 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
If the last two snippets of code actually existed in the same application, it would make
sense to remove the duplication present in the two RowMapper anonymous inner
classes, and extract them out into a single class (typically a static nested class) that
can then be referenced by DAO methods as needed. For example, it may be better to
write the last code snippet as follows:
public List<Actor> findAllActors() {
return this.jdbcTemplate.query( "select first_name, last_name from t_actor"
}
private static final class ActorMapper implements RowMapper<Actor> {
public Actor mapRow(ResultSet rs, int rowNum) throws SQLException {
Actor actor = new Actor();
actor.setFirstName(rs.getString("first_name"));
actor.setLastName(rs.getString("last_name"));
return actor;
}
}
25/08/2016 12:10
561 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
The following example invokes a simple stored procedure. More sophisticated stored
procedure support is covered later.
this.jdbcTemplate.update(
"call SUPPORT.REFRESH_ACTORS_SUMMARY(?)",
Long.valueOf(unionId));
25/08/2016 12:10
562 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
DAO classes; the JdbcTemplate is created in the setter for the DataSource . This leads
to DAOs that look in part like the following:
public class JdbcCorporateEventDao implements CorporateEventDao {
private JdbcTemplate jdbcTemplate;
public void setDataSource(DataSource dataSource) {
this.jdbcTemplate = new JdbcTemplate(dataSource);
}
// JDBC-backed implementations of the methods on the CorporateEventDao follow...
}
25/08/2016 12:10
563 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
The corresponding XML configuration file would look like the following:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!-- Scans within the base package of the application for @Component classes to co
<context:component-scan base-package="org.springframework.docs.test" />
If you are using Springs 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
25/08/2016 12:10
564 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
19.2.2 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.
// 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"
Notice the use of the named parameter notation in the value assigned to the sql
variable, and the corresponding value that is plugged into the namedParameters
variable (of type MapSqlParameterSource ).
Alternatively, you can pass along named parameters and their corresponding values to a
NamedParameterJdbcTemplate instance by using the Map -based style.The remaining
methods exposed by the NamedParameterJdbcOperations and implemented by the
NamedParameterJdbcTemplate class follow a similar pattern and are not covered here.
The following example shows the use of the Map -based style.
// some JDBC-backed DAO class...
private NamedParameterJdbcTemplate namedParameterJdbcTemplate;
public void setDataSource(DataSource dataSource) {
25/08/2016 12:10
565 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Integ
25/08/2016 12:10
566 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
}
// 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_
19.2.3 SQLExceptionTranslator
SQLExceptionTranslator is an interface to be implemented by classes that can
translate between SQLExceptions and Springs 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
25/08/2016 12:10
567 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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
25/08/2016 12:10
568 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
// create a custom translator and set the DataSource for the default translation l
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 .
25/08/2016 12:10
569 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
In addition to the single result query methods, several methods return a list with an entry
for each row that the query returned. The most generic method is queryForList(..)
which returns a List where each entry is a Map with each entry in the map representing
the column value for that row. If you add a method to the above example to retrieve a list
of all the rows, it would look like this:
private JdbcTemplate jdbcTemplate;
25/08/2016 12:10
570 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
571 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
following example works on Oracle but may not work on other platforms:
final String INSERT_SQL = "insert into my_test (name) values(?)";
final String name = "Rob";
KeyHolder keyHolder = new GeneratedKeyHolder();
jdbcTemplate.update(
new PreparedStatementCreator() {
public PreparedStatement createPreparedStatement(Connection connection)
PreparedStatement ps = connection.prepareStatement(INSERT_SQL, new
ps.setString(1, name);
return ps;
}
},
keyHolder);
// keyHolder.getKey() now contains the generated key
25/08/2016 12:10
572 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
The following examples show the basic connectivity and configuration for DBCP and
C3P0. To learn about more options that help control the pooling features, see the product
documentation for the respective connection pooling implementations.
DBCP configuration:
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method=
<property name="driverClassName" value="${jdbc.driverClassName}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
<context:property-placeholder location="jdbc.properties"/>
C3P0 configuration:
25/08/2016 12:10
573 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
19.3.2 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 .
19.3.3 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.
19.3.4 AbstractDataSource
AbstractDataSource is an abstract base class for Springs 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.
19.3.5 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
25/08/2016 12:10
574 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
19.3.6 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 .
19.3.7 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.
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, its 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 .
19.3.8 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
25/08/2016 12:10
575 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
19.3.9 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.
25/08/2016 12:10
576 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
If you are processing a stream of updates or reading from a file, then you might have a
25/08/2016 12:10
577 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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.
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:
25/08/2016 12:10
578 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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.
25/08/2016 12:10
579 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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 arrays length indicates the number of batches executed and the second level
arrays length indicates the number of updates in that batch. The number of updates in
each batch should be 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.
25/08/2016 12:10
580 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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.
25/08/2016 12:10
581 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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 executeAndReturnKey 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 executeAndReturnKeyHolder method.
25/08/2016 12:10
582 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
.usingColumns("first_name", "last_name")
.usingGeneratedKeyColumns("id");
}
public void add(Actor actor) {
Map<String, Object> parameters = new HashMap<String, Object>(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.
25/08/2016 12:10
583 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
As you can see, the configuration is the same; only the executing code has to change to
use these alternative input classes.
25/08/2016 12:10
584 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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 dont have to create a subclass and
you dont 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.
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
25/08/2016 12:10
585 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
The code you write for the execution of the call involves creating an
SqlParameterSource containing the IN parameter. Its 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 LinkedCaseInsensitiveMap . 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 . Here is an
example of this configuration:
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
25/08/2016 12:10
586 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Explicit declarations are necessary if the database you use is not a Springsupported 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.
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)
);
}
25/08/2016 12:10
587 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
The execution and end results of the two examples are the same; this one specifies all
details explicitly rather than relying on metadata.
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.
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.
25/08/2016 12:10
588 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
589 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
The execute method used returns a String containing the return value from the function
call.
To call this procedure you declare the RowMapper . Because the class you want to map to
follows the JavaBean rules, you can use a BeanPropertyRowMapper that is created by
passing in the required class to map to in the newInstance method.
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",
BeanPropertyRowMapper.newInstance(Actor.class));
}
public List getActorsList() {
Map m = procReadAllActors.execute(new HashMap<String, Object>(0));
25/08/2016 12:10
590 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
}
// ... 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.
Many Spring developers believe that the various RDBMS operation classes
described below (with the exception of the StoredProcedure 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.
19.6.1 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 .
19.6.2 MappingSqlQuery
25/08/2016 12:10
591 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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.
public class ActorMappingQuery extends MappingSqlQuery<Actor> {
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.
private ActorMappingQuery actorMappingQuery;
@Autowired
public void setDataSource(DataSource dataSource) {
this.actorMappingQuery = new ActorMappingQuery(dataSource);
}
public Customer getCustomer(Long id) {
return actorMappingQuery.findObject(id);
}
25/08/2016 12:10
592 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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.
public List<Actor> searchForActors(int age, String namePattern) {
List<Actor> actors = actorSearchMappingQuery.execute(age, namePattern);
return actors;
}
19.6.3 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 its simply called execute . However, you dont have to subclass the SqlUpdate
class since it can easily be parameterized by setting SQL and declaring parameters.
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) {
25/08/2016 12:10
593 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
19.6.4 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.
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
25/08/2016 12:10
594 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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.
import
import
import
import
java.sql.Types;
java.util.Date;
java.util.HashMap;
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();
}
25/08/2016 12:10
595 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
The following example of a StoredProcedure has two output parameters (in this case,
Oracle REF cursors).
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
declareParameter(new SqlOutParameter("genres", OracleTypes.CURSOR, new
compile();
}
public Map<String, Object> execute() {
// again, this sproc has no input parameters, so an empty Map is supplied
return super.execute(new HashMap<String, Object>());
}
}
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 :
import org.springframework.jdbc.core.RowMapper;
import java.sql.ResultSet;
import java.sql.SQLException;
import com.foo.domain.Title;
25/08/2016 12:10
596 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
The GenreMapper class maps a ResultSet to a Genre domain object for each row in
the supplied ResultSet .
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:
import
import
import
import
oracle.jdbc.OracleTypes;
org.springframework.jdbc.core.SqlOutParameter;
org.springframework.jdbc.core.SqlParameter;
org.springframework.jdbc.object.StoredProcedure;
import javax.sql.DataSource;
import
import
import
import
java.sql.Types;
java.util.Date;
java.util.HashMap;
java.util.Map;
25/08/2016 12:10
597 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
598 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
values.
25/08/2016 12:10
599 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Now its time to read the LOB data from the database. Again, you use a JdbcTemplate
with the same instance variable lobHandler and a reference to a
DefaultLobHandler .
25/08/2016 12:10
600 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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. Oracles 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.
25/08/2016 12:10
601 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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.
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)
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 .
final Long[] ids = new Long[] {1L, 2L};
SqlTypeValue value = new AbstractSqlTypeValue() {
protected Object createTypeValue(Connection conn, int sqlType, String typeName)
ArrayDescriptor arrayDescriptor = new ArrayDescriptor(typeName, conn);
ARRAY idArray = new ARRAY(arrayDescriptor, conn, ids);
return idArray;
25/08/2016 12:10
602 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
}
};
The preceding configuration creates an embedded HSQL database populated with SQL
from schema.sql and test-data.sql resources in the root of the classpath. In
addition, as a best practice, the embedded database will be assigned a uniquely
generated name. The embedded database is made available to the Spring container as a
bean of type javax.sql.DataSource which can then be injected into data access
objects as needed.
25/08/2016 12:10
603 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Consult the Javadoc for EmbeddedDatabaseBuilder for further details on all supported
options.
The EmbeddedDatabaseBuilder can also be used to create an embedded database
using Java Config like in the following example.
@Configuration
public class DataSourceConfig {
@Bean
public DataSource dataSource() {
return new EmbeddedDatabaseBuilder()
.generateUniqueName(true)
.setType(H2)
.setScriptEncoding("UTF-8")
.ignoreFailedDrops(true)
.addScript("schema.sql")
.addScripts("user_data.sql", "country_data.sql")
.build();
}
}
25/08/2016 12:10
604 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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 .
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 you are using the builder API, call
the setType(EmbeddedDatabaseType) method with EmbeddedDatabaseType.DERBY .
25/08/2016 12:10
605 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
606 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
type.
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
jira.spring.io.
The example above executes the two scripts specified against the database: the first
script creates a schema, and the second populates tables with a test data set. 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 you are executing the
scripts against a database that already has test data in it. The likelihood of accidentally
deleting data is reduced by following the common pattern (as shown above) of creating
the tables first and then inserting the datathe first step will fail if the tables already
exist.
However, to gain more control over the creation and deletion of existing data, the XML
namespace provides a few additional options. The first is a 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), for example:
25/08/2016 12:10
607 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
<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, for example:
<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 executed
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 doesnt 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 DROP statements,
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).
Each statement should be separated by ; or a new line if the ; character is not present
at all in the script. You can control that globally or script by script, for example:
<jdbc:initialize-database data-source="dataSource" separator="@@">
<jdbc:script location="classpath:com/foo/sql/db-schema.sql" separator=";"
<jdbc:script location="classpath:com/foo/sql/db-test-data-1.sql"/>
<jdbc:script location="classpath:com/foo/sql/db-test-data-2.sql"/>
</jdbc:initialize-database>
In this example, the two test-data scripts use @@ as statement separator and only the
db-schema.sql uses ; . This configuration specifies that the default separator is @@
and override that default for the db-schema script.
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.
25/08/2016 12:10
608 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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 DataSource instance and executes the scripts
provided in its initialization callback (analogous to an init-method in an XML bean
definition, a @PostConstruct method in a component, or the afterPropertiesSet()
method in a component that implements 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 data from the database on application
startup.
To get around this issue you have 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 include:
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
include:
Rely on the default behavior of the Spring BeanFactory , 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 in XML configuration 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.
the parent context contains the DataSource , and child context contains the
business components). This structure is common in Spring web applications but can
25/08/2016 12:10
609 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
610 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
(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
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.
25/08/2016 12:10
611 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
The major goal of Springs 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 Springs
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.
25/08/2016 12:10
612 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
When you use Hibernate, JPA, or JDO in a DAO, you must decide how to handle the
persistence technologys 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 technologys 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:
@Repository
public class ProductDaoImpl implements ProductDao {
// class body here...
}
<beans>
20.3 Hibernate
We will start with a coverage of Hibernate 5 in a Spring environment, using it to
25/08/2016 12:10
613 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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.
As of Spring 4.0, Spring requires Hibernate 3.6 or later. Note that the
Hibernate team stopped supporting Hibernate 3 years ago and even
phased out support for Hibernate 4.x in late 2015. We therefore recommend
Hibernate 5.1 and higher from a 2016+ perspective.
25/08/2016 12:10
614 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
</property>
</bean>
</beans>
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
Hibernates CaveatEmptor sample application. (In general, do not keep any resources in
static variables unless absolutely necessary.)
25/08/2016 12:10
615 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
The above DAO follows the dependency injection pattern: it fits nicely into a Spring IoC
container, just as it would if coded against Springs 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:
<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 Hibernates 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, Springs LocalSessionFactoryBean supports Hibernates
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 Springs
JtaTransactionManager , EJB container managed transactions (CMTs), or JTA.
In summary: you can implement DAOs based on the plain Hibernate API, while still being
able to participate in Spring-managed transactions.
25/08/2016 12:10
616 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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:
<?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.hibernate5.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>
25/08/2016 12:10
617 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
</tx:advice>
<bean id="myProductService" class="product.SimpleProductService">
<property name="productDao" ref="myProductDao"/>
</bean>
</beans>
25/08/2016 12:10
618 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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.
<?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.hibernate5.HibernateTransactionManager"
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
<tx:annotation-driven/>
<bean id="myProductService" class="product.SimpleProductService">
<property name="productDao" ref="myProductDao"/>
</bean>
</beans>
25/08/2016 12:10
619 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
620 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
621 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
</property>
</bean>
<bean id="mySessionFactory2"
class="org.springframework.orm.hibernate5.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>
25/08/2016 12:10
622 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
623 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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
Springs 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
25/08/2016 12:10
624 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
625 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
20.4 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.
25/08/2016 12:10
626 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
627 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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:
<beans>
<bean id="myPmfProxy"
class="org.springframework.orm.jdo.TransactionAwarePersistenceManagerFacto
<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:
public class ProductDaoImpl implements ProductDao {
private PersistenceManagerFactory persistenceManagerFactory;
public void setPersistenceManagerFactory(PersistenceManagerFactory pmf) {
this.persistenceManagerFactory = pmf;
}
25/08/2016 12:10
628 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
With such DAOs that rely on active transactions, it is recommended that you enforce
active transactions through turning off
TransactionAwarePersistenceManagerFactoryProxys `allowCreate flag:
<beans>
<bean id="myPmfProxy"
class="org.springframework.orm.jdo.TransactionAwarePersistenceManagerFacto
<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 JDOs 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 Springs DataAccessException (if desired).
25/08/2016 12:10
629 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
To execute service operations within transactions, you can use Springs common
declarative transaction facilities. For example:
<?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>
25/08/2016 12:10
630 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
20.4.4 JdoDialect
As an advanced feature, both LocalPersistenceManagerFactoryBean and
JdoTransactionManager support a custom JdoDialect that can be passed into the
jdoDialect bean property. 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 Springs JDO support.
20.5 JPA
The Spring JPA, available under the org.springframework.orm.jpa package, offers
comprehensive support for the 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.
LocalEntityManagerFactoryBean
25/08/2016 12:10
631 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
<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 providerspecific, 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.
Use this option when deploying to a Java EE 5 server. Check your servers
documentation on how to deploy a custom JPA provider into your server,
allowing for a different provider than the servers default.
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.
25/08/2016 12:10
632 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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 servers 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.
LocalContainerEntityManagerFactoryBean
<beans>
<bean id="myEmf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFac
<property name="dataSource" ref="someDataSource"/>
<property name="loadTimeWeaver">
<bean class="org.springframework.instrument.classloading.InstrumentationLo
</property>
</bean>
</beans>
25/08/2016 12:10
633 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
634 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
<context:load-time-weaver/>
<bean id="emf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBe
...
</bean>
However, if needed, one can manually specify a dedicated weaver through the
loadTimeWeaver property:
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.
25/08/2016 12:10
635 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
636 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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:
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 :
<beans>
25/08/2016 12:10
637 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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:
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();
}
}
25/08/2016 12:10
638 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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.
To execute service operations within transactions, you can use Springs common
declarative transaction facilities. For example:
<?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"
25/08/2016 12:10
639 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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.Produ
<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>
20.5.4 JpaDialect
As an advanced feature JpaTransactionManager and subclasses of
AbstractEntityManagerFactoryBean support a custom JpaDialect , to be passed
into the jpaDialect bean property. 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
25/08/2016 12:10
640 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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 Springs JPA support.
25/08/2016 12:10
641 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
21.2.1 Marshaller
Spring abstracts all marshalling operations behind the
org.springframework.oxm.Marshaller interface, the main methods of which is listed
below.
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.
25/08/2016 12:10
642 de 1194
Result
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
implementation
DOMResult
org.w3c.dom.Node
SAXResult
org.xml.sax.ContentHandler
StreamResult
java.io.File , java.io.OutputStream , or
java.io.Writer
21.2.2 Unmarshaller
Similar to the Marshaller , there is the org.springframework.oxm.Unmarshaller
interface.
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.
Source
implementation
DOMSource
org.w3c.dom.Node
25/08/2016 12:10
643 de 1194
Source
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
implementation
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 .
21.2.3 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:
25/08/2016 12:10
644 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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.
import
import
import
import
import
java.io.FileInputStream;
java.io.FileOutputStream;
java.io.IOException;
javax.xml.transform.stream.StreamResult;
javax.xml.transform.stream.StreamSource;
import
import
import
import
org.springframework.context.ApplicationContext;
org.springframework.context.support.ClassPathXmlApplicationContext;
org.springframework.oxm.Marshaller;
org.springframework.oxm.Unmarshaller;
25/08/2016 12:10
645 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
FileOutputStream os = null;
try {
os = new FileOutputStream(FILE_NAME);
this.marshaller.marshal(settings, new StreamResult(os));
} finally {
if (os != null) {
os.close();
}
}
}
<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
Marshaller
Unmarshaller
25/08/2016 12:10
646 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
21.5 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 Section 21.2, Marshaller and
Unmarshaller. The corresponding integration classes reside in the
org.springframework.oxm.jaxb package.
25/08/2016 12:10
647 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
21.5.1 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:
<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>
Alternatively, the list of classes to bind can be provided to the marshaller via the
class-to-be-bound child tag:
<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>
Description
Required
25/08/2016 12:10
648 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Attribute
Description
Required
id
no
contextPath
no
21.6 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 Castor web site. The Spring integration
classes reside in the org.springframework.oxm.castor package.
21.6.1 CastorMarshaller
As with JAXB, the CastorMarshaller implements both the Marshaller and
Unmarshaller interface. It can be wired up as follows:
<beans>
<bean id="castorMarshaller" class="org.springframework.oxm.castor.CastorMarshaller
...
</beans>
21.6.2 Mapping
Although it is possible to rely on Castors 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 Castor XML Mapping.
The mapping can be set using the mappingLocation resource property, indicated below
with a classpath resource.
<beans>
<bean id="castorMarshaller" class="org.springframework.oxm.castor.CastorMarshaller
<property name="mappingLocation" value="classpath:mapping.xml" />
</bean>
</beans>
25/08/2016 12:10
649 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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
no
encoding
no
XML
target-class
no
no
no
21.7 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.
25/08/2016 12:10
650 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
21.7.1 XmlBeansMarshaller
The XmlBeansMarshaller implements both the Marshaller and Unmarshaller
interfaces. It can be configured as follows:
<beans>
Description
Required
id
no
options
no
21.8 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
25/08/2016 12:10
651 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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 JiBX web site. The Spring integration classes
reside in the org.springframework.oxm.jibx package.
21.8.1 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:
<beans>
<bean id="jibxFlightsMarshaller" class="org.springframework.oxm.jibx.JibxMarshalle
<property name="targetClass">org.springframework.oxm.jibx.Flights</property>
</bean>
...
</beans>
Description
Required
id
no
target-class
yes
bindingName
no
25/08/2016 12:10
652 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
21.9 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 XStream web site. The Spring integration
classes reside in the org.springframework.oxm.xstream package.
21.9.1 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 analias map,
which consists of string aliases mapped to classes:
<beans>
<bean id="xstreamMarshaller" class="org.springframework.oxm.xstream.XStreamMarshal
<property name="aliases">
<props>
<prop key="Flight">org.springframework.oxm.xstream.Flight</prop>
</props>
</property>
</bean>
...
</beans>
By default, XStream allows for arbitrary classes to be unmarshalled, which can result in secu
external sources (i.e. the Web), as this can result in security vulnerabilities. If you do use the
This will make sure that only the registered classes are eligible for unmarshalling.
Additionally, you can register custom converters to make sure that only your supported class
unmarshalled. You might want to add a CatchAllConverter as the last converter in the list
to converters that explicitly support the domain classes that should be supported. As a result
XStream converters with lower priorities and possible security vulnerabilities do not get invok
25/08/2016 12:10
653 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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.
25/08/2016 12:10
654 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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
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
Section 11.6.1, 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. Springs 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 do not need to
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.
Springs 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.
655 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
656 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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 Chapter 43, spring JSP Tag Library
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 Chapter 44, spring-form JSP Tag Library
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 Section 7.5.4, Request, session, global session, application, and
WebSocket scopes
25/08/2016 12:10
657 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
The DispatcherServlet is an actual Servlet (it inherits from the HttpServlet base
class), and as such is declared in your web application. You need to map requests that
you want the DispatcherServlet to handle, by using a URL mapping. Here is a
standard Java EE Servlet configuration in a Servlet 3.0+ environment:
public class MyWebApplicationInitializer implements WebApplicationInitializer {
25/08/2016 12:10
658 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
In the preceding example, all requests starting with /example will be handled by the
DispatcherServlet instance named 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 interface named
AbstractAnnotationConfigDispatcherServletInitializer makes it even easier to
register the DispatcherServlet by simply specifying its servlet mapping and listing
configuration classes - its even the recommended way to set up your Spring MVC
application. See Code-based Servlet container initialization for more details.
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:
Below is the web.xml equivalent of the above code based example:
<web-app>
<servlet>
<servlet-name>example</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-clas
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>example</servlet-name>
<url-pattern>/example/*</url-pattern>
</servlet-mapping>
</web-app>
25/08/2016 12:10
659 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Upon initialization of a DispatcherServlet , Spring MVC looks for a file named [servletname]-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):
<web-app>
<servlet>
<servlet-name>golfing</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-clas
<load-on-startup>1</load-on-startup>
25/08/2016 12:10
660 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
</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.
Figure 22.3. Single root context in Spring Web MVC
25/08/2016 12:10
661 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
<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-clas
<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>
</web-app>
25/08/2016 12:10
662 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
@Override
protected String[] getServletMappings() {
return new String[] { "/golfing/*" };
}
}
Explanation
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
HandlerExceptionResolver
ViewResolver
25/08/2016 12:10
663 de 1194
Bean type
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Explanation
LocaleResolver &
LocaleContextResolver
ThemeResolver
MultipartResolver
FlashMapManager
25/08/2016 12:10
664 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
665 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
web.xml file. See the following table for the list of supported parameters.
Explanation
Class that implements WebApplicationContext ,
which instantiates the context used by this Servlet.
By default, the XmlWebApplicationContext is
used.
contextConfigLocation
namespace
25/08/2016 12:10
666 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
@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.
25/08/2016 12:10
667 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
668 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
In the above example, @RequestMapping is used in a number of places. The first usage
is on the type (class) level, which indicates that all handler methods in 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 add() 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 the section called URI Template Patterns).
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 :
@Controller
public class ClinicController {
private final Clinic clinic;
@Autowired
public ClinicController(Clinic clinic) {
this.clinic = clinic;
}
@RequestMapping("/")
public void welcomeHandler() {
25/08/2016 12:10
669 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
}
@RequestMapping("/vets")
public ModelMap vetsHandler() {
return new ModelMap(this.clinic.getVets());
}
}
The above example does not specify GET vs. PUT , POST , and so forth, because
@RequestMapping maps all HTTP methods by default. Use
@RequestMapping(method=GET) or @GetMapping to narrow the mapping.
25/08/2016 12:10
670 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
@GetMapping("/{day}")
public Map<String, Appointment> getForDay(@PathVariable @DateTimeFormat(iso=ISO.DA
return appointmentBook.getAppointmentsForDay(day);
}
@GetMapping("/new")
public AppointmentForm getNewForm() {
return new AppointmentForm();
}
@PostMapping
public String add(@Valid AppointmentForm appointment, BindingResult result) {
if (result.hasErrors()) {
return "appointments/new";
}
appointmentBook.addAppointment(appointment);
return "redirect:/appointments";
}
}
25/08/2016 12:10
671 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
672 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
@GetMapping("/owners/{ownerId}")
public String findOwner(@PathVariable String ownerId, Model model) {
Owner owner = ownerService.findOwner(ownerId);
model.addAttribute("owner", owner);
return "displayOwner";
}
To process the @PathVariable annotation, Spring MVC needs to find the matching URI temp
variable by name. You can specify it in the annotation:
@GetMapping("/owners/{ownerId}")
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 compiled with debugging information or the -parameters
compiler flag on Java 8, Spring MVC will match the method argument name to the URI temp
variable name:
@GetMapping("/owners/{ownerId}")
public String findOwner(@PathVariable String ownerId, Model model) {
// implementation omitted
}
25/08/2016 12:10
673 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
annotations. As a result the findPet() method can be invoked with a URL such as
/owners/42/pets/21 .
@Controller
@RequestMapping("/owners/{ownerId}")
public class RelativePathUriTemplateController {
@RequestMapping("/pets/{petId}")
public void findPet(@PathVariable String ownerId, @PathVariable String petId, Mode
// 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 the section called Method Parameters And Type Conversion
and the section called Customizing WebDataBinder initialization.
@RequestMapping("/spring-web/{symbolicName:[a-z-]+}-{version:\\d\\.\\d\\.\\d}{extensio
public void handle(@PathVariable String version, @PathVariable String extension) {
// ...
}
Path Patterns
In addition to URI templates, the @RequestMapping annotation and all composed
@RequestMapping variants also support 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} ).
25/08/2016 12:10
674 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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
doesnt 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 Section 22.16.11, Path Matching in the section on
configuring Spring MVC).
25/08/2016 12:10
675 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
676 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Matrix Variables
The URI specification 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 "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":
// GET /pets/42;q=11;r=22
@GetMapping("/pets/{petId}")
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:
25/08/2016 12:10
677 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
// GET /owners/42;q=11/pets/21;q=22
@GetMapping("/owners/{ownerId}/pets/{petId}")
public void findPet(
@MatrixVariable(name="q", pathVar="ownerId") int q1,
@MatrixVariable(name="q", pathVar="petId") int q2) {
// q1 == 11
// q2 == 22
}
@GetMapping("/owners/{ownerId}/pets/{petId}")
public void findPet(
@MatrixVariable MultiValueMap<String, String> matrixVars,
@MatrixVariable(pathVar="petId"") MultiValueMap<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 .
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 Advanced Customizations with MVC Java
Config section describes how the RequestMappingHandlerMapping can be
25/08/2016 12:10
678 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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 .
<?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>
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.
25/08/2016 12:10
679 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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:
@GetMapping(path = "/pets/{petId}", produces = MediaType.APPLICATION_JSON_UTF8_VALUE
@ResponseBody
public Pet getPet(@PathVariable String petId, Model model) {
// implementation omitted
}
Be aware that the media type specified in the produces condition can also
optionally specify a character set. For example, in the code snippet above
we specify the same media type than the default one configured in
MappingJackson2HttpMessageConverter , including the UTF-8 charset.
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 . Also consider using constants provided in MediaType such as
APPLICATION_JSON_VALUE and APPLICATION_JSON_UTF8_VALUE .
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.
25/08/2016 12:10
680 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
The same can be done to test for request header presence/absence or to match based
on a specific request header value:
@Controller
@RequestMapping("/owners/{ownerId}")
public class RelativePathUriTemplateController {
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.
25/08/2016 12:10
681 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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 /
LocaleContextResolver in an MVC environment.
java.util.TimeZone (Java 6+) / java.time.ZoneId (on Java 8) for the time
25/08/2016 12:10
682 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
LocaleContextResolver .
java.io.InputStream / java.io.Reader for access to the requests content. This
value is the raw InputStream/Reader as exposed by the Servlet API.
java.io.OutputStream / java.io.Writer for generating the responses 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
the section called URI Template Patterns.
@MatrixVariable annotated parameters for access to name-value pairs located in
URI path segments. See the section called Matrix Variables.
@RequestParam annotated parameters for access to specific Servlet request
parameters. Parameter values are converted to the declared method argument type.
See the section called Binding request parameters to method parameters with
@RequestParam.
@RequestHeader annotated parameters for access to specific Servlet request HTTP
headers. Parameter values are converted to the declared method argument type.
See the section called Mapping request header attributes with the @RequestHeader
annotation.
@RequestBody annotated parameters for access to the HTTP request body.
Parameter values are converted to the declared method argument type using
HttpMessageConverter s. See the section called Mapping the request body with
the @RequestBody annotation.
@RequestPart annotated parameters for access to the content of a
"multipart/form-data" request part. See Section 22.10.5, Handling a file upload
request from programmatic clients and Section 22.10, Springs multipart (file
upload) support.
@SessionAttribute annotated parameters for access to existing, permanent
session attributes (e.g. user authentication object) as opposed to model attributes
temporarily stored in the session as part of a controller workflow via
@SessionAttributes .
@RequestAttribute annotated parameters for access to request attributes.
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 the section called Using 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
25/08/2016 12:10
683 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
@PostMapping
public String processSubmit(@ModelAttribute("pet") Pet pet, Model model, BindingResult
Note, that there is a Model parameter in between Pet and BindingResult . To get this
working you have to reorder the parameters as follows:
@PostMapping
public String processSubmit(@ModelAttribute("pet") Pet pet, BindingResult result
@RequestParam
25/08/2016 12:10
684 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
685 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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.
A ResponseBodyEmitter can be returned to write multiple objects to the response
asynchronously; also supported as the body within a ResponseEntity .
An SseEmitter can be returned to write Server-Sent Events to the response
asynchronously; also supported as the body within a ResponseEntity .
A StreamingResponseBody can be returned to write to the response OutputStream
asynchronously; also supported as the body within a ResponseEntity .
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.
25/08/2016 12:10
686 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
687 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandl
<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"
Also see Section 22.16.1, Enabling the MVC Java Config or the MVC XML
Namespace for information on configuring message converters and a
validator through the MVC namespace or the MVC Java config.
25/08/2016 12:10
688 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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 Message Converters.
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:
@RequestMapping("/something")
public ResponseEntity<String> handle(HttpEntity<byte[]> requestEntity) throws
String requestHeader = requestEntity.getHeaders().getFirst("MyRequestHeader"
byte[] requestBody = requestEntity.getBody();
// do something with request header and body
25/08/2016 12:10
689 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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 Message Converters.
@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.
25/08/2016 12:10
690 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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 the section called Advising
controllers with @ControllerAdvice and @RestControllerAdvice section for more details.
25/08/2016 12:10
691 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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 the
section called Using @SessionAttributes to store model attributes in the HTTP
session between requests.
It may already be in the model due to an @ModelAttribute method in the same
controlleras 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 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:
@PutMapping("/accounts/{account}")
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
namesincluding query string parameters and form fieldsto 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
Chapter 9, Validation, Data Binding, and Type Conversion. Customizing the data binding
process for a controller level is covered in the section called Customizing
WebDataBinder initialization.
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:
@PostMapping("/owners/{ownerId}/pets/{petId}/edit")
public String processSubmit(@ModelAttribute("pet") Pet pet, BindingResult result) {
if (result.hasErrors()) {
25/08/2016 12:10
692 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
return "petForm";
}
// ...
}
With a BindingResult you can check if errors were found in which case its common to
render the same form where the errors can be shown with the help of Springs <errors>
form tag.
Note that in some cases it may be useful to gain access to an attribute in the model
without data binding. For such cases you may inject the Model into the controller or
alternatively use the binding flag on the annotation:
@ModelAttribute
public AccountForm setUpForm() {
return new AccountForm();
}
@ModelAttribute
public Account findAccount(@PathVariable String accountId) {
return accountRepository.findOne(accountId);
}
@PostMapping("update")
public String update(@Valid AccountUpdateForm form, BindingResult result,
@ModelAttribute(binding=false) Account account) {
// ...
}
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:
@PostMapping("/owners/{ownerId}/pets/{petId}/edit")
public String processSubmit(@ModelAttribute("pet") Pet pet, BindingResult result) {
new PetValidator().validate(pet, result);
if (result.hasErrors()) {
return "petForm";
}
// ...
25/08/2016 12:10
693 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Or you can have validation invoked automatically by adding the JSR-303 @Valid
annotation:
@PostMapping("/owners/{ownerId}/pets/{petId}/edit")
public String processSubmit(@Valid @ModelAttribute("pet") Pet pet, BindingResult resul
if (result.hasErrors()) {
return "petForm";
}
// ...
}
See Section 9.8, Spring Validation and Chapter 9, Validation, Data Binding, and Type
Conversion for details on how to configure and use validation.
25/08/2016 12:10
694 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
@RequestMapping("/")
public String handle(@SessionAttribute User user) {
// ...
}
For use cases that require adding or removing session attributes consider injecting
org.springframework.web.context.request.WebRequest or
javax.servlet.http.HttpSession into the controller method.
For temporary storage of model attributes in the session as part of a controller workflow
consider using SessionAttributes as described in the section called Using
@SessionAttributes to store model attributes in the HTTP session between requests.
<filter>
<filter-name>httpPutFormFilter</filter-name>
<filter-class>org.springframework.web.filter.HttpPutFormContentFilter</filter-clas
</filter>
<filter-mapping>
25/08/2016 12:10
695 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
<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.
The following code sample demonstrates how to get the value of the JSESSIONID
cookie:
@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 the section called Method Parameters And Type Conversion.
This annotation is supported for annotated handler methods in Servlet and Portlet
environments.
25/08/2016 12:10
696 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
localhost:8080
text/html,application/xhtml+xml,application/xml;q=0.9
fr,en-gb;q=0.7,en;q=0.3
gzip,deflate
ISO-8859-1,utf-8;q=0.7,*;q=0.7
300
The following code sample demonstrates how to get the value of the Accept-Encoding
and Keep-Alive headers:
@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 the
section called Method Parameters And Type Conversion.
When an @RequestHeader annotation is used on a Map<String, String> ,
MultiValueMap<String, String> , or HttpHeaders argument, the map is populated
with all header values.
This annotation is supported for annotated handler methods in Servlet and Portlet
environments.
25/08/2016 12:10
697 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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 the section called Customizing WebDataBinder initialization) or
by registering Formatters with the FormattingConversionService (see Section 9.6,
Spring Field Formatting).
@InitBinder
protected void initBinder(WebDataBinder binder) {
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
dateFormat.setLenient(false);
binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, false
}
// ...
}
25/08/2016 12:10
698 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandl
<property name="cacheSeconds" value="0"/>
<property name="webBindingInitializer">
<bean class="org.springframework.samples.petclinic.web.ClinicBindingInitialize
</property>
</bean>
25/08/2016 12:10
699 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
700 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
}
}
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;
}
}
Note that despite @JsonView allowing for more than one class to be
specified, the use on a controller method is only supported with exactly one
class argument. Consider the use of a composite interface if you need to
enable multiple views.
For controllers relying on view resolution, simply add the serialization view class to the
model:
@Controller
public class UserController extends AbstractController {
@GetMapping("/user")
public String getUser(Model model) {
model.addAttribute("user", new User("eric", "7!jd#h23"));
model.addAttribute(JsonView.class.getName(), User.WithoutPasswordView.
25/08/2016 12:10
701 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
return "userView";
}
}
For controllers relying on view resolution, JSONP is automatically enabled when the
request has a query parameter named jsonp or callback . Those names can be
customized through jsonpParameterNames property.
25/08/2016 12:10
702 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
This may be difficult to understand without any knowledge of the Servlet 3.0
asynchronous request processing features. It would certainly help to read up on that.
Here are a few basic facts about the underlying mechanism:
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 to allow processing to
complete later.
The call to request.startAsync() returns AsyncContext which can be used for
further control over async processing. For example it provides the method
dispatch , that is similar to a forward from the Servlet API except it allows an
application to resume request processing on a Servlet container thread.
The ServletRequest provides access to the current DispatcherType that can be
used to distinguish between processing the initial request, an async dispatch, a
forward, and other dispatcher types.
With the above in mind, the following is the sequence of events for async request
processing with a Callable :
Controller returns a Callable .
Spring MVC starts asynchronous processing and submits the Callable to a
TaskExecutor for processing in a separate thread.
The DispatcherServlet and all Filters exit the Servlet container thread but the
25/08/2016 12:10
703 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
704 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
HTTP Streaming
A controller method can use DeferredResult and Callable to produce its return
value asynchronously and that can be used to implement techniques such as long polling
where the server can push an event to the client as soon as possible.
What if you wanted to push multiple events on a single HTTP response? This is a
technique related to "Long Polling" that is known as "HTTP Streaming". Spring MVC
makes this possible through the ResponseBodyEmitter return value type which can be
used to send multiple Objects, instead of one as is normally the case with
@ResponseBody , where each Object sent is written to the response with an
HttpMessageConverter .
Here is an example of that:
@RequestMapping("/events")
public ResponseBodyEmitter handle() {
ResponseBodyEmitter emitter = new ResponseBodyEmitter();
// Save the emitter somewhere..
return emitter;
}
// In some other thread
emitter.send("Hello once");
// and again later on
emitter.send("Hello again");
// and done at some point
emitter.complete();
ResponseBodyEmitter
25/08/2016 12:10
705 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Events. Server-sent events is a just another variation on the same "HTTP Streaming"
technique except events pushed from the server are formatted according to the W3C
Server-Sent Events specification.
Server-Sent Events can be used for their intended purpose, that is to push events from
the server to clients. It is quite easy to do in Spring MVC and requires simply returning a
value of type SseEmitter .
Note however that Internet Explorer does not support Server-Sent Events and that for
more advanced web application messaging scenarios such as online games,
collaboration, financial applicatinos, and others its better to consider Springs WebSocket
support that includes SockJS-style WebSocket emulation falling back to a very wide
range of browsers (including Internet Explorer) and also higher-level messaging patterns
for interacting with clients through a publish-subscribe model within a more messagingcentric architecture. For further background on this see the following blog post.
25/08/2016 12:10
706 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
<filter>
<filter-name>Spring OpenEntityManagerInViewFilter</filter-name>
<filter-class>org.springframework.~.OpenEntityManagerInViewFilter</filter-clas
<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>
25/08/2016 12:10
707 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
708 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
<beans>
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingH
<property name="interceptors">
<bean class="example.MyInterceptor"/>
</property>
</bean>
<beans>
25/08/2016 12:10
709 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
<beans>
<bean id="handlerMapping"
class="org.springframework.web.servlet.mvc.method.annotation.RequestMappin
<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>
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;
}
25/08/2016 12:10
710 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
As you can see, the Spring adapter class HandlerInterceptorAdapter makes it easier
to extend the HandlerInterceptor interface.
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 Section 22.16.1, Enabling the MVC
Java Config or the MVC XML Namespace.
Note that the postHandle method of HandlerInterceptor is not always ideally suited
for use with @ResponseBody and ResponseEntity methods. In such cases an
HttpMessageConverter writes to and commits the response before postHandle is
called which makes it impossible to change the response, for example to add a header.
Instead an application can implement ResponseBodyAdvice and either declare it as an
@ControllerAdvice bean or configure it directly on
RequestMappingHandlerAdapter .
711 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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 Chapter 23, View technologies 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.
Description
Abstract view resolver that caches
views. Often views need preparation
before they can be used; extending this
view resolver provides caching.
XmlViewResolver
ResourceBundleViewResolver
25/08/2016 12:10
712 de 1194
ViewResolver
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Description
the classpath. The default file name is
views.properties .
UrlBasedViewResolver
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 /
Convenient subclass of
FreeMarkerViewResolver
ContentNegotiatingViewResolver
25/08/2016 12:10
713 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
UrlBasedViewResolver . This view resolver translates a view name to a URL and hands
the request over to the RequestDispatcher to render the view.
<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 :
<bean id="viewResolver"
class="org.springframework.web.servlet.view.ResourceBundleViewResolver"
<property name="basename" value="views"/>
<property name="defaultParentView" value="parentView"/>
</bean>
25/08/2016 12:10
714 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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 .
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!
25/08/2016 12:10
715 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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
APIs 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.
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 Springs 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 in turn calls
HttpServletResponse.sendRedirect() to send an HTTP redirect to the client
browser.
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 the section called The redirect: prefix facilitates this decoupling.
25/08/2016 12:10
716 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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 @RequestMapping method can declare an argument of type
RedirectAttributes and use it to specify the exact attributes to make available to
RedirectView . If the method does redirect, the content of RedirectAttributes is
used. Otherwise the content of the 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
doesnt 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
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:
@PostMapping("/files/{path}")
public String upload(...) {
// ...
return "redirect:files/{path}";
}
Another way of passing data to the redirect target is via Flash Attributes. Unlike other
redirect attributes, flash attributes are saved in the HTTP session (and hence do not
appear in the URL). See Section 22.6, Using flash attributes for more information.
25/08/2016 12:10
717 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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.
Note that the controller handler is annotated with the @ResponseStatus , the annotation
value takes precedence over the response status set by RedirectView .
22.5.4 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 media types that it understands. For example, an HTTP
25/08/2016 12:10
718 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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:
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.
<bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver"
<property name="viewResolvers">
<list>
<bean class="org.springframework.web.servlet.view.BeanNameViewResolver"
<bean class="org.springframework.web.servlet.view.InternalResourceViewReso
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
</list>
25/08/2016 12:10
719 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
</property>
<property name="defaultViews">
<list>
<bean class="org.springframework.web.servlet.view.json.MappingJackson2Json
</list>
</property>
</bean>
<bean id="content" class="com.foo.samples.rest.SampleContentAtomView"/>
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.
@Controller
public class ContentController {
private List<SampleContent> contentList = new ArrayList<SampleContent>();
25/08/2016 12:10
720 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
@GetMapping("/content")
public ModelAndView getContent() {
ModelAndView mav = new ModelAndView();
mav.setViewName("content");
mav.addObject("sampleContentList", contentList);
return mav;
}
}
25/08/2016 12:10
721 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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 .
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:
UriComponents uriComponents = UriComponentsBuilder.newInstance()
.scheme("http").host("example.com").path("/hotels/{hotel}/bookings/{booking}"
.expand("42", "21")
.encode();
25/08/2016 12:10
722 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
.encode();
Alternatively, you may choose to copy a subset of the available information up to and
including the context path:
// Re-use host, port and context path
// Append "/accounts" to the path
In the above example we provided actual method argument values, in this case the long
25/08/2016 12:10
723 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
value 21, to be used as a path variable and inserted into the URL. Furthermore, we
provided the value 42 in order to fill in any remaining URI variables such as the "hotel"
variable inherited from the type-level request mapping. If the method had more
arguments you can supply null for arguments not needed for the URL. In general only
@PathVariable and @RequestParam arguments are relevant for constructing the URL.
There are additional ways to use MvcUriComponentsBuilder . For example you can use
a technique akin to mock testing through proxies to avoid referring to the controller
method by name (the example assumes static import of
MvcUriComponentsBuilder.on ):
UriComponents uriComponents = MvcUriComponentsBuilder
.fromMethodCall(on(BookingController.class).getBooking(21)).buildAndExpand(
URI uri = uriComponents.encode().toUri();
25/08/2016 12:10
724 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
class and the full method name. For example, the method getFoo in class
FooController is assigned the name "FC#getFoo". This strategy can be replaced or
customized by creating an instance of HandlerMethodMappingNamingStrategy and
plugging it into your RequestMappingHandlerMapping . The default strategy
implementation also looks at the name attribute on @RequestMapping and uses that if
present. That means if the default mapping name assigned conflicts with another (e.g.
overloaded methods) you can assign a name explicitly on the @RequestMapping .
The Spring JSP tag library provides a function called mvcUrl that can be used to
prepare links to controller methods based on this mechanism.
For example given:
@RequestMapping("/people/{id}/addresses")
public class PersonAddressController {
@RequestMapping("/{country}")
public HttpEntity getAddress(@PathVariable String country) { ... }
}
The above example relies on the mvcUrl JSP function declared in the Spring tag library
(i.e. META-INF/spring.tld). For more advanced cases (e.g. a custom base URL as
explained in the previous section), it is easy to define your own function, or use a custom
tag file, in order to use a specific instance of MvcUriComponentsBuilder with a custom
base URL.
25/08/2016 12:10
725 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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 Section 22.4.1, Intercepting requests with a HandlerInterceptor
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.
22.8.2 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
clients operating system. Note that this resolver does not support time zone information.
22.8.3 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 .
25/08/2016 12:10
726 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
<!-- in seconds. If set to -1, the cookie is not persisted (deleted when browser s
<property name="cookieMaxAge" value="100000"/>
</bean>
Default
classname +
Description
The name of the cookie
LOCALE
cookieMaxAge Integer.MAX_INT
cookiePath
22.8.4 SessionLocaleResolver
The SessionLocaleResolver allows you to retrieve Locale and TimeZone from the
session that might be associated with the users request. In contrast to
CookieLocaleResolver , this strategy stores locally chosen locale settings in the Servlet
containers HttpSession . As a consequence, those settings are just temporary for each
session and therefore lost when each session terminates.
Note that there is no direct relationship with external session management mechanisms
such as the Spring Session project. This SessionLocaleResolver will simply evaluate
and modify corresponding HttpSession attributes against the current
HttpServletRequest .
22.8.5 LocaleChangeInterceptor
25/08/2016 12:10
727 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
728 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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:
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%>
<html>
<head>
<link rel="stylesheet" href="<spring:theme code='styleSheet'/>" type
</head>
<body style="background=<spring:theme code='background'/>">
...
</body>
</html>
25/08/2016 12:10
729 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
as a LocaleResolver . It detects the theme to use for a particular request and can also
alter the requests theme. The following theme resolvers are provided by Spring:
Description
Selects a fixed theme, set using the
defaultThemeName property.
SessionThemeResolver
CookieThemeResolver
25/08/2016 12:10
730 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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.
<bean id="multipartResolver"
class="org.springframework.web.multipart.support.StandardServletMultipartResol
</bean>
731 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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:
<html>
<head>
<title>Upload a file please</title>
</head>
<body>
<h1>Please upload a file</h1>
<form method="post" action="/form" enctype="multipart/form-data">
<input type="text" name="name"/>
<input type="file" name="file"/>
<input type="submit"/>
</form>
</body>
</html>
The next step is to create a controller that handles the file upload. This controller is very
similar to a normal annotated @Controller , except that we use
MultipartHttpServletRequest or MultipartFile in the method parameters:
@Controller
public class FileUploadController {
@PostMapping("/form")
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
25/08/2016 12:10
732 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
733 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
734 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
22.11.2 @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
controller (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:
@Controller
public class SimpleController {
// @RequestMapping methods omitted ...
@ExceptionHandler(IOException.class)
public ResponseEntity<String> handleIOException(IOException ex) {
// prepare responseEntity
return responseEntity;
}
}
25/08/2016 12:10
735 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
value converted with message converters and written to the response stream.
BindException
ConversionNotSupportedException
HttpMediaTypeNotAcceptableException
HttpMediaTypeNotSupportedException
HttpMessageNotReadableException
HttpMessageNotWritableException
HttpRequestMethodNotSupportedException
MethodArgumentNotValidException
MissingServletRequestParameterException
MissingServletRequestPartException
25/08/2016 12:10
736 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Exception
NoHandlerFoundException
NoSuchRequestHandlingMethodException
TypeMismatchException
MissingPathVariableException
NoHandlerFoundException
25/08/2016 12:10
737 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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:
@Controller
public class ErrorController {
or in a JSP:
<%@ page contentType="application/json" pageEncoding="UTF-8"%>
{
status:<%=request.getAttribute("javax.servlet.error.status_code") %>,
reason:<%=request.getAttribute("javax.servlet.error.message") %>
}
25/08/2016 12:10
738 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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 Spring MVC
Showcase for an example.
Another option is to use a framework dedicated to Web Security. HDIV is one such
framework and integrates with Spring MVC.
Here is a snippet from the corresponding Spring Web MVC configuration file:
<bean class="org.springframework.web.servlet.mvc.support.ControllerClassNameHandlerMap
25/08/2016 12:10
739 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
740 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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 objects 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.
25/08/2016 12:10
741 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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).
25/08/2016 12:10
742 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
class="org.springframework.web.servlet.view.DefaultRequestToViewNameTransl
<bean class="x.y.RegistrationController">
<!-- inject dependencies as necessary -->
</bean>
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.
25/08/2016 12:10
743 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
header is mostly responsible for this, along with conditional headers such as
'Last-Modified' and 'ETag' .
The 'Cache-Control' HTTP response header advises private caches (e.g. browsers)
and public caches (e.g. proxies) on how they can cache HTTP responses for further
reuse.
An 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 .
This section describes the different choices available to configure HTTP caching in a
Spring Web MVC application.
25/08/2016 12:10
744 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**")
.addResourceLocations("/public-resources/")
.setCacheControl(CacheControl.maxAge(1, TimeUnit.HOURS).cachePublic())
}
}
And in XML:
<mvc:resources mapping="/resources/**" location="/public-resources/">
<mvc:cache-control max-age="3600" cache-public="true"/>
</mvc:resources>
25/08/2016 12:10
745 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
As described in the section called Using HttpEntity, controllers can interact with the
request/response using HttpEntity types. Controllers returning ResponseEntity can
include HTTP caching information in responses like this:
@GetMapping("/book/{id}")
public ResponseEntity<Book> showBook(@PathVariable Long id) {
Book book = findBook(id);
String version = book.getVersion();
return ResponseEntity
.ok()
.cacheControl(CacheControl.maxAge(30, TimeUnit.DAYS))
.eTag(version) // lastModified is also available
.body(book);
}
Doing this will not only include 'ETag' and 'Cache-Control' headers in the response,
it will also convert the response to an HTTP 304 Not Modified response with an
empty body if the conditional headers sent by the client match the caching information
set by the Controller.
An @RequestMapping method may also wish to support the same behavior. This can be
achieved as follows:
@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";
}
25/08/2016 12:10
746 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
<filter>
<filter-name>etagFilter</filter-name>
<filter-class>org.springframework.web.filter.ShallowEtagHeaderFilter</filter-class
<!-- Optional parameter that configures the filter to write weak ETags
<init-param>
<param-name>writeWeakETag</param-name>
<param-value>true</param-value>
25/08/2016 12:10
747 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
</init-param>
-->
</filter>
<filter-mapping>
<filter-name>etagFilter</filter-name>
<servlet-name>petclinic</servlet-name>
</filter-mapping>
See Section 22.15, Code-based Servlet container initialization for more details.
25/08/2016 12:10
748 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
749 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
@Override
protected Filter[] getServletFilters() {
return new Filter[] { new HiddenHttpMethodFilter(), new CharacterEncodingFilte
}
}
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 .
Finally, if you need to further customize the DispatcherServlet itself, you can override
the createDispatcherServlet method.
25/08/2016 12:10
750 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
751 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
752 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
ones:
1. DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES is
disabled.
2. MapperFeature.DEFAULT_VIEW_INCLUSION is disabled.
It also automatically registers the following well-known modules if they are
detected on the classpath:
1. jackson-datatype-jdk7: support for Java 7 types like
java.nio.file.Path .
2. jackson-datatype-joda: support for Joda-Time types.
3. jackson-datatype-jsr310: support for Java 8 Date & Time API types.
4. jackson-datatype-jdk8: support for other Java 8 types like Optional .
25/08/2016 12:10
753 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
<bean id="conversionService"
class="org.springframework.format.support.FormattingConversionServiceFacto
<property name="converters">
<set>
<bean class="org.example.MyConverter"/>
</set>
</property>
<property name="formatters">
<set>
<bean class="org.example.MyFormatter"/>
<bean class="org.example.MyAnnotationFormatterFactory"/>
</set>
</property>
<property name="formatterRegistrars">
<set>
<bean class="org.example.MyFormatterRegistrar"/>
</set>
</property>
</bean>
</beans>
25/08/2016 12:10
754 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
22.16.4 Validation
Spring provides a Validator interface that can be used for validation in all layers of an
application. In Spring MVC you can configure it for use as a global Validator instance,
to be used whenever an @Valid or @Validated controller method argument is
encountered, and/or as a local Validator within a controller through an @InitBinder
method. Global and local validator instances can be combined to provide composite
validation.
Spring also supports JSR-303/JSR-349 Bean Validation via
LocalValidatorFactoryBean which adapts the Spring
org.springframework.validation.Validator interface to the Bean Validation
javax.validation.Validator contract. This class can be plugged into Spring MVC as
a global validator as described next.
By default use of @EnableWebMvc or <mvc:annotation-driven> automatically
registers Bean Validation support in Spring MVC through the
LocalValidatorFactoryBean when a Bean Validation provider such as Hibernate
Validator is detected on the classpath.
25/08/2016 12:10
755 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {
@Override
public Validator getValidator(); {
// return "global" validator
}
}
and in XML:
<?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 validator="globalValidator"/>
</beans>
To combine global with local validation, simply add one or more local validator(s):
@Controller
public class MyController {
@InitBinder
protected void initBinder(WebDataBinder binder) {
binder.addValidators(new FooValidator());
}
}
With this minimal configuration any time an @Valid or @Validated method argument is
encountered, it will be validated by the configured validators. Any validation violations will
automatically be exposed as errors in the BindingResult accessible as a method
argument and also renderable in Spring MVC HTML views.
22.16.5 Interceptors
25/08/2016 12:10
756 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LocaleInterceptor());
registry.addInterceptor(new ThemeInterceptor()).addPathPatterns("/**"
registry.addInterceptor(new SecurityInterceptor()).addPathPatterns("/secure/*"
}
}
25/08/2016 12:10
757 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Below is an example of customizing content negotiation options through the MVC Java
config:
@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {
@Override
public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
configurer.mediaType("json", MediaType.APPLICATION_JSON);
}
}
If not using the MVC Java config or the MVC namespace, youll 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
ContentNegotiationManager , so you can use one shared 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
25/08/2016 12:10
758 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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.
25/08/2016 12:10
759 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
<mvc:view-resolvers>
<mvc:content-negotiation>
<mvc:default-views>
<bean class="org.springframework.web.servlet.view.json.MappingJackson2Json
</mvc:default-views>
</mvc:content-negotiation>
<mvc:jsp/>
</mvc:view-resolvers>
Note however that FreeMarker, Velocity, Tiles, Groovy Markup and script templates also
require configuration of the underlying view technology.
The MVC namespace provides dedicated elements. For example with FreeMarker:
<mvc:view-resolvers>
<mvc:content-negotiation>
<mvc:default-views>
<bean class="org.springframework.web.servlet.view.json.MappingJackson2Json
</mvc:default-views>
</mvc:content-negotiation>
<mvc:freemarker cache="false"/>
</mvc:view-resolvers>
<mvc:freemarker-configurer>
<mvc:template-loader-path location="/freemarker"/>
</mvc:freemarker-configurer>
25/08/2016 12:10
760 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**").addResourceLocations("/public-res
}
}
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:
@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**").addResourceLocations("/public-res
}
25/08/2016 12:10
761 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
And in XML:
<mvc:resources mapping="/resources/**" location="/public-resources/" cache-period
For more details, see HTTP caching support for static resources.
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:
@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:
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 applications resources. Support for versioned URLs is built into
the framework and can be enabled by configuring a resource chain on the resource
handler. The chain consists of one more ResourceResolver instances followed by one
or more ResourceTransformer instances. Together they can provide arbitrary
resolution and transformation of resources.
The built-in VersionResourceResolver can be configured with different strategies. For
example a FixedVersionStrategy can use a property, a date, or other as the version.
A ContentVersionStrategy uses an MD5 hash computed from the content of the
25/08/2016 12:10
762 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
XML example:
<mvc:resources mapping="/resources/**" location="/public-resources/">
<mvc:resource-chain>
<mvc:resource-cache/>
<mvc:resolvers>
<mvc:version-resolver>
<mvc:content-version-strategy patterns="/**"
</mvc:version-resolver>
</mvc:resolvers>
</mvc:resource-chain>
</mvc:resources>
In order for the above to work the application must also render URLs with versions. The
easiest way to do that is to configure the ResourceUrlEncodingFilter which wraps
the response and overrides its encodeURL method. This will work in JSPs, FreeMarker,
Velocity, and any other view technology that calls the response encodeURL method.
Alternatively, an application can also inject and use directly the ResourceUrlProvider
bean, which is automatically declared with the MVC Java config and the MVC
25/08/2016 12:10
763 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
namespace.
Webjars are also supported with WebJarsResourceResolver , which is automatically
registered when the "org.webjars:webjars-locator" library is on classpath. This
resolver allows the resource chain to resolve version agnostic libraries from HTTP GET
requests "GET /jquery/jquery.min.js" will return resource
"/jquery/1.2.0/jquery.min.js" . It also works by rewriting resource URLs in
templates
@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer config
configurer.enable();
}
}
Or in XML:
<mvc:default-servlet-handler/>
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
25/08/2016 12:10
764 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer config
configurer.enable("myCustomDefaultServlet");
}
}
Or in XML:
<mvc:default-servlet-handler default-servlet-name="myCustomDefaultServlet"/>
25/08/2016 12:10
765 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
//...
}
@Bean
public PathMatcher antPathMatcher() {
//...
}
}
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder()
.indentOutput(true)
.dateFormat(new SimpleDateFormat("yyyy-MM-dd"))
.modulesToInstall(new ParameterNamesModule());
converters.add(new MappingJackson2HttpMessageConverter(builder.build()));
25/08/2016 12:10
766 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
converters.add(new MappingJackson2XmlHttpMessageConverter(builder.xml().build(
}
}
<mvc:annotation-driven>
<mvc:message-converters>
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessag
<property name="objectMapper" ref="objectMapper"/>
</bean>
<bean class="org.springframework.http.converter.xml.MappingJackson2XmlHttpMess
<property name="objectMapper" ref="xmlMapper"/>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
25/08/2016 12:10
767 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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 thingsremove the @EnableWebMvc annotation in order to
prevent the import and then extend from DelegatingWebMvcConfiguration , a
subclass of WebMvcConfigurationSupport . Here is an example:
@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
}
}
25/08/2016 12:10
768 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
23.2 Thymeleaf
Thymeleaf is a good example of a view technology fitting perfectly in the MVC framework.
Support for this integration is not provided by the Spring team but by the Thymeleaf team
25/08/2016 12:10
769 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
itself.
Configuring Thymeleaf for Spring usually requires a few beans defined, like a
ServletContextTemplateResolver , a SpringTemplateEngine and a
ThymeleafViewResolver . Please refer to the Thymeleaf+Spring documentation section
for more details.
23.3.1 Configuration
Configuring the Groovy Markup Template Engine is quite easy:
@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {
@Override
public void configureViewResolvers(ViewResolverRegistry registry) {
registry.groovy();
}
@Bean
public GroovyMarkupConfigurer groovyMarkupConfigurer() {
GroovyMarkupConfigurer configurer = new GroovyMarkupConfigurer();
configurer.setResourceLoaderPath("/WEB-INF/");
return configurer;
}
}
25/08/2016 12:10
770 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
<mvc:groovy-configurer resource-loader-path="/WEB-INF/"/>
23.3.2 Example
Unlike traditional template engines, this one relies on a DSL that uses the builder syntax.
Here is a sample template for an HTML page:
yieldUnescaped '<!DOCTYPE html>'
html(lang:'en') {
head {
meta('http-equiv':'"Content-Type" content="text/html; charset=utf-8"'
title('My page')
}
body {
p('This is an example of HTML contents')
}
}
23.4.1 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
Springs 'dateToolAttribute' or 'numberToolAttribute' in your Velocity views, you will also
25/08/2016 12:10
771 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
<!-This bean sets up the Velocity environment for us based on a root path for templates.
Optionally, a properties file can be specified for more control over the Velocity
environment, but the defaults are pretty sane for file based template loading.
-->
<bean id="velocityConfig" class="org.springframework.web.servlet.view.velocity.Velocit
<property name="resourceLoaderPath" value="/WEB-INF/velocity/"/>
</bean>
<!-View resolvers can also be configured with ResourceBundles or XML files. If you need
different view resolving based on Locale, you have to use the resource bundle resolver
-->
<bean id="viewResolver" class="org.springframework.web.servlet.view.velocity.VelocityV
<property name="cache" value="true"/>
<property name="prefix" value=""/>
<property name="suffix" value=".vm"/>
</bean>
<!-View resolvers can also be configured with ResourceBundles or XML files. If you need
different view resolving based on Locale, you have to use the resource bundle resolver
-->
<bean id="viewResolver" class="org.springframework.web.servlet.view.freemarker.FreeMar
<property name="cache" value="true"/>
<property name="prefix" value=""/>
<property name="suffix" value=".ftl"/>
</bean>
25/08/2016 12:10
772 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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.
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.
25/08/2016 12:10
773 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
</bean>
Refer to the API documentation for Spring configuration of Velocity, or the Velocity
documentation for examples and definitions of the 'velocity.properties' file itself.
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 .
See the FreeMarker documentation for details of settings and variables as they apply to
the Configuration object.
25/08/2016 12:10
774 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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.
Simple binding
In your HTML forms (vm / ftl templates) which act as a form view for a Spring MVC
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. Example
code is shown below for the personFormV / personFormF views configured earlier:
<!-- velocity macros are automatically available -->
<html>
...
<form action="" method="POST">
Name:
#springBind("myModelObject.name")
<input type="text"
name="${status.expression}"
value="$!status.value"/><br>
#foreach($error in $status.errorMessages) <b>$error</b> <br> #end
<br>
...
<input type="submit" value="submit"/>
</form>
...
</html>
<!-- freemarker macros have to be imported into a namespace. We strongly
recommend sticking to 'spring' -->
<#import "/spring.ftl" as spring/>
<html>
...
<form action="" method="POST">
Name:
<@spring.bind "myModelObject.name"/>
<input type="text"
name="${spring.status.expression}"
value="${spring.status.value?html}"/><br>
<#list spring.status.errorMessages as error> <b>${error}</b> <br> </#list>
<br>
...
<input type="submit" value="submit"/>
25/08/2016 12:10
775 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
</form>
...
</html>
VTL definition
#springMessage($code)
FTL definition
<@spring.message code/>
string from a
resource bundle
based on the code
parameter)
messageText
(output a string from
a resource bundle
based on the code
parameter, falling
25/08/2016 12:10
776 de 1194
macro
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
VTL definition
FTL definition
#springUrl($relativeUrl)
<@spring.url relativeUrl/>
formInput (standard
#springFormInput($path
<@spring.formInput path,
$attributes)
attributes, fieldType/>
#springFormHiddenInput($path
<@spring.formHiddenInput
path, attributes/>
submitting non-user
input)
formPasswordInput #springFormPasswordInput($path <@spring.formPasswordInput
$attributes)
path, attributes/>
formTextarea (large
#springFormTextarea($path
<@spring.formTextarea path,
$attributes)
attributes/>
formSingleSelect
#springFormSingleSelect( $path
<@spring.formSingleSelect
$options $attributes)
formMultiSelect (a
#springFormMultiSelect($path
<@spring.formMultiSelect
$options $attributes)
* (standard input
field for gathering
passwords. Note
that no value will
ever be populated in
fields of this type)
gathering long,
freeform text input)
options allowing a
single required value
to be selected)
25/08/2016 12:10
777 de 1194
macro
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
VTL definition
FTL definition
values)
formRadioButtons
#springFormRadioButtons($path
<@spring.formRadioButtons
(a set of radio
buttons allowing a
attributes/>
single selection to be
made from the
available choices)
formCheckboxes (a #springFormCheckboxes($path
set of checkboxes
allowing 0 or more
<@spring.formCheckboxes
path, options, separator,
attributes/>
values to be
selected)
formCheckbox (a
#springFormCheckbox($path
<@spring.formCheckbox
single checkbox)
$attributes)
path, attributes/>
showErrors
#springShowErrors($separator
<@spring.showErrors
(simplify display of
$classOrStyle)
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.
25/08/2016 12:10
778 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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
"<br>").
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 <b></b> 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.
Input Fields
<!-- the Name field example from above using form macros in VTL -->
...
Name:
#springFormInput("command.name" "")<br>
#springShowErrors("<br>" "")<br>
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 doesnt 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:
<@spring.formInput "command.name"/>
<@spring.showErrors "<br>"/>
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 Springs Validation framework.
25/08/2016 12:10
779 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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.
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'.
...
Town:
<@spring.formRadioButtons "command.address.town", cityMap, ""/><br><br>
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 maps 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
Town:
25/08/2016 12:10
780 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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.
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.
Town:
<input type="radio" name="address.town" value="LDN">London</input>
<input type="radio" name="address.town" value="PRS" checked="checked">Paris</input>
<input type="radio" name="address.town" value="NYC">New York</input>
25/08/2016 12:10
781 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
this directive.
In similar fashion, HTML escaping can be specified per field:
<#-- 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 -->
25/08/2016 12:10
782 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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.
25/08/2016 12:10
783 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
compliant.
Unlike other form/input tag libraries, Springs 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.
Lets 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.
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:
<%@ 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.
25/08/2016 12:10
784 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
</td>
</tr>
</table>
</form:form>
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:
<form method="POST">
<table>
<tr>
<td>First Name:</td>
<td><input name="firstName" type="text" value="Harry"/></td>
</tr>
<tr>
<td>Last Name:</td>
<td><input name="lastName" type="text" value="Potter"/></td>
</tr>
<tr>
<td colspan="2">
<input type="submit" value="Save Changes"/>
</td>
</tr>
</table>
</form>
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:
<form:form modelAttribute="user">
<table>
<tr>
<td>First Name:</td>
<td><form:input path="firstName"/></td>
</tr>
<tr>
<td>Last Name:</td>
<td><form:input path="lastName"/></td>
</tr>
<tr>
<td colspan="2">
<input type="submit" value="Save Changes"/>
25/08/2016 12:10
785 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
</tr>
</table>
</form:form>
25/08/2016 12:10
786 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
<td>Interests:</td>
<%-- Approach 2: Property is of an array or of type java.util.Collection
<td>
Quidditch: <form:checkbox path="preferences.interests" value
Herbology: <form:checkbox path="preferences.interests" value
Defence Against the Dark Arts: <form:checkbox path="preferences.intere
</td>
</tr>
<tr>
<td>Favourite Word:</td>
<%-- Approach 3: Property is of type java.lang.Object --%>
<td>
Magic: <form:checkbox path="preferences.favouriteWord" value
</td>
</tr>
</table>
</form:form>
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.
25/08/2016 12:10
787 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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".
25/08/2016 12:10
788 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
</form:form>
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 entrys 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".
25/08/2016 12:10
789 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
<tr>
<td>Password:</td>
<td>
<form:password path="password"/>
</td>
</tr>
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.
<tr>
<td>Password:</td>
<td>
<form:password path="password" value="^76525bvHGq" showPassword="true"
</td>
</tr>
If the Users skill were in Herbology, the HTML source of the 'Skills' row would look like:
<tr>
<td>Skills:</td>
<td>
<select name="skills" multiple="true">
<option value="Potions">Potions</option>
<option value="Herbology" selected="selected">Herbology</option>
<option value="Quidditch">Quidditch</option>
</select>
</td>
</tr>
25/08/2016 12:10
790 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
This tag renders an HTML 'option'. It sets 'selected' as appropriate based on the bound
value.
<tr>
<td>House:</td>
<td>
<form:select path="house">
<form:option value="Gryffindor"/>
<form:option value="Hufflepuff"/>
<form:option value="Ravenclaw"/>
<form:option value="Slytherin"/>
</form:select>
</td>
</tr>
If the Users house was in Gryffindor, the HTML source of the 'House' row would look
like:
<tr>
<td>House:</td>
<td>
<select name="house">
<option value="Gryffindor" selected="selected">Gryffindor</option>
<option value="Hufflepuff">Hufflepuff</option>
<option value="Ravenclaw">Ravenclaw</option>
<option value="Slytherin">Slytherin</option>
</select>
</td>
</tr>
If the User lived in the UK, the HTML source of the 'Country' row would look like:
25/08/2016 12:10
791 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
<tr>
<td>Country:</td>
<td>
<select name="country">
<option value="-">--Please Select</option>
<option value="AT">Austria</option>
<option value="UK" selected="selected">United Kingdom</option>
<option value="US">United States</option>
</select>
</td>
</tr>
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.
If we choose to submit the 'house' value as a hidden one, the HTML would look like:
25/08/2016 12:10
792 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
793 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
</table>
</form:form>
If we submit a form with empty values in the firstName and lastName fields, this is
what the HTML would look like:
<form method="POST">
<table>
<tr>
<td>First Name:</td>
<td><input name="firstName" type="text" value=""/></td>
<%-- Associated errors to firstName field displayed --%>
<td><span name="firstName.errors">Field is required.</span></td>
</tr>
<tr>
<td>Last Name:</td>
<td><input name="lastName" type="text" value=""/></td>
<%-- Associated errors to lastName field displayed --%>
<td><span name="lastName.errors">Field is required.</span></td>
</tr>
<tr>
<td colspan="3">
<input type="submit" value="Save Changes"/>
</td>
</tr>
</table>
</form>
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 fieldspecific errors next to the fields:
<form:form>
<form:errors path="*" cssClass="errorBox"/>
<table>
<tr>
<td>First Name:</td>
<td><form:input path="firstName"/></td>
<td><form:errors path="firstName"/></td>
25/08/2016 12:10
794 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
</tr>
<tr>
<td>Last Name:</td>
<td><form:input path="lastName"/></td>
<td><form:errors path="lastName"/></td>
</tr>
<tr>
<td colspan="3">
<input type="submit" value="Save Changes"/>
</td>
</tr>
</table>
</form:form>
25/08/2016 12:10
795 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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 Springs
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
<form:form method="delete">
<p class="submit"><input type="submit" value="Delete Pet"/></p>
</form:form>
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:
<filter>
<filter-name>httpMethodFilter</filter-name>
<filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter</filter>
<filter-mapping>
<filter-name>httpMethodFilter</filter-name>
<servlet-name>petclinic</servlet-name>
</filter-mapping>
HTML5 Tags
Starting with Spring 3, the Spring form tag library allows entering dynamic attributes,
which means you can enter any HTML5 specific attributes.
25/08/2016 12:10
796 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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.
23.6.1 Dependencies
To be able to use script templates integration, you need to have available in your
classpath the script engine:
Nashorn Javascript engine is provided builtin with Java 8+. Using the latest update
release available is highly recommended.
Rhino Javascript engine is provided builtin with Java 6 and Java 7. Please notice that
using Rhino is not recommended since it does not support running most template
engines.
JRuby dependency should be added in order to get Ruby support.
Jython dependency should be added in order to get Python support.
You should also need to add dependencies for your script based template engine. For
example, for Javascript you can use WebJars to add Maven/Gradle dependencies in
order to make your javascript libraries available in the classpath.
25/08/2016 12:10
797 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
parameters like the script engine to use, the script files to load and what function should
be called to render the templates. This is done thanks to a ScriptTemplateConfigurer
bean and optional script files.
For example, in order to render Mustache templates thanks to the Nashorn Javascript
engine provided with Java 8+, you should declare the following configuration:
@Configuration
@EnableWebMvc
public class MustacheConfig extends WebMvcConfigurerAdapter {
@Override
public void configureViewResolvers(ViewResolverRegistry registry) {
registry.scriptTemplate();
}
@Bean
public ScriptTemplateConfigurer configurer() {
ScriptTemplateConfigurer configurer = new ScriptTemplateConfigurer();
configurer.setEngineName("nashorn");
configurer.setScripts("mustache.js");
configurer.setRenderObject("Mustache");
configurer.setRenderFunction("render");
return configurer;
}
}
25/08/2016 12:10
798 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
799 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
return configurer;
}
}
polyfill.js only defines the window object needed by Handlebars to run properly:
var window = {};
This basic render.js implementation compiles the template before using it. A
production ready implementation should also store and reused cached templates /
pre-compiled templates. This can be done on the script side, as well as any customization
you need (managing template engine configuration for example).
function render(template, model) {
var compiledTemplate = Handlebars.compile(template);
return compiledTemplate(model);
}
Check out Spring script templates unit tests (java, resources) for more configuration
examples.
23.8 Tiles
It is possible to integrate Tiles - just as any other view technology - in web applications
25/08/2016 12:10
800 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
23.8.1 Dependencies
To be able to use Tiles, you have to add a dependency on Tiles version 3.0.1 or higher
and its transitive dependencies to your project.
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:
25/08/2016 12:10
801 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
<value>/WEB-INF/defs/tiles.xml</value>
<value>/WEB-INF/defs/tiles_fr_FR.xml</value>
</list>
</property>
</bean>
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.
UrlBasedViewResolver
The UrlBasedViewResolver instantiates the given viewClass for each view it has to
resolve.
ResourceBundleViewResolver
The ResourceBundleViewResolver has to be provided with a property file containing
viewnames and viewclasses the resolver can use:
As you can see, when using the ResourceBundleViewResolver , you can easily mix
different view technologies.
25/08/2016 12:10
802 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Note that the TilesView class supports JSTL (the JSP Standard Tag Library) out of the
box.
23.9 XSLT
XSLT is a transformation language for XML and is popular as a view technology within
25/08/2016 12:10
803 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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.
Bean definitions
Configuration is standard for a simple Spring application. The MVC configuration has to
define a XsltViewResolver bean and regular MVC annotation configuration.
@EnableWebMvc
@ComponentScan
@Configuration
public class WebConfig extends WebMvcConfigurerAdapter {
@Bean
public XsltViewResolver xsltViewResolver() {
XsltViewResolver viewResolver = new XsltViewResolver();
viewResolver.setPrefix("/WEB-INF/xsl/");
viewResolver.setSuffix(".xslt");
return viewResolver;
}
}
25/08/2016 12:10
804 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
@RequestMapping("/")
public String home(Model model) throws Exception {
So far weve only created a DOM document and added it to the Model map. Note that you
can also load an XML file as a Resource and use it instead of a custom DOM document.
Of course, 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.
Next, XsltViewResolver will resolve the "home" XSLT template file and merge the
DOM document into it to generate our view.
Document transformation
Finally, the XsltViewResolver will resolve the "home" XSLT template file and merge the
DOM document into it to generate our view. As shown in the XsltViewResolver
configuration, XSLT templates live in the war file in the 'WEB-INF/xsl' directory and
end with a "xslt" file extension.
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
<xsl:output method="html" omit-xml-declaration="yes"/>
<xsl:template match="/">
25/08/2016 12:10
805 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
<html>
<head><title>Hello!</title></head>
<body>
<h1>My First Words</h1>
<ul>
<xsl:apply-templates/>
</ul>
</body>
</html>
</xsl:template>
<xsl:template match="word">
<li><xsl:value-of select="."/></li>
</xsl:template>
</xsl:stylesheet>
25/08/2016 12:10
806 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
In order to use Excel views, you need to add the 'poi' library to your classpath, and for
PDF generation, the iText library.
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
Controller code
The controller code well 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!
25/08/2016 12:10
807 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Heres 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:
package excel;
// imports omitted for brevity
public class HomePage extends AbstractExcelView {
And the following is a view generating the same Excel file, now using JExcelApi:
package excel;
// imports omitted for brevity
public class HomePage extends AbstractJExcelView {
protected void buildExcelDocument(Map model, WritableWorkbook wb,
HttpServletRequest request, HttpServletResponse response) throws
WritableSheet sheet = wb.createSheet("Spring", 0);
25/08/2016 12:10
808 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Note the differences between the APIs. Weve 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.
Once again, amend the controller to return the pdf view with
return new ModelAndView("pdf", map); , and reload the URL in your application.
This time a PDF document should appear listing each of the words in the model map.
25/08/2016 12:10
809 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
23.11 JasperReports
JasperReports ( http://jasperreports.sourceforge.net) is a powerful open-source reporting
engine that supports the creation of report designs using an easily understood XML file
format. JasperReports is capable of rendering reports in four different formats: CSV,
Excel, HTML and PDF.
23.11.1 Dependencies
Your application will need to include the latest release of JasperReports, which at the time
of writing was 0.6.1. JasperReports itself depends on the following projects:
BeanShell
Commons BeanUtils
Commons Collections
Commons Digester
Commons Logging
iText
POI
JasperReports also requires a JAXP compliant XML parser.
23.11.2 Configuration
To configure JasperReports views in your Spring container configuration you need to
define a ViewResolver to map view names to the appropriate view class depending on
which format you want your report rendered in.
25/08/2016 12:10
810 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Render Format
JasperReportsCsvView
CSV
JasperReportsHtmlView
HTML
JasperReportsPdfView
JasperReportsXlsView
Microsoft Excel
JasperReportsMultiFormatView
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:
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.
25/08/2016 12:10
811 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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:
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 Class
csv
JasperReportsCsvView
html
JasperReportsHtmlView
JasperReportsPdfView
xls
JasperReportsXlsView
25/08/2016 12:10
812 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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:
25/08/2016 12:10
813 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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.
<subreport>
<reportElement isPrintRepeatedValues="false" x="5" y="25" width="325"
height="20" isRemoveLineWhenBlank="true" backcolor="#ffcc99"/>
<subreportParameter name="City">
<subreportParameterExpression><![CDATA[$F{city}]]></subreportParameterExpressi
</subreportParameter>
<dataSourceExpression><![CDATA[$P{SubReportData}]]></dataSourceExpression>
<subreportExpression class="net.sf.jasperreports.engine.JasperReport">
<![CDATA[$P{ProductsSubReport}]]></subreportExpression>
</subreport>
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
25/08/2016 12:10
814 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
subReportUrls property:
<property name="subReportUrls">
<map>
<entry key="ProductsSubReport" value="/WEB-INF/reports/subReportChild.jrxml"
</map>
</property>
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.
Here, the key you supply must correspond to both the key used in your ModelAndView
and the key used in your report design file.
25/08/2016 12:10
815 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
<value>Footer by Spring!
</td><td width="50%">&nbsp; </td></tr>
</table></body></html>
</value>
</entry>
</map>
</property>
</bean>
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.
25/08/2016 12:10
816 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
@Override
protected void buildFeedMetadata(Map<String, Object> model,
Channel feed, HttpServletRequest request) {
// implementation omitted
}
@Override
protected List<Item> buildFeedItems(Map<String, Object> model,
HttpServletRequest request, HttpServletResponse response) throws
// implementation omitted
}
}
25/08/2016 12:10
817 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
818 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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.
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 Section 24.6,
Further Resources at the end of this chapter.
25/08/2016 12:10
819 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-cl
</listener>
25/08/2016 12:10
820 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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.
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 Spring Web Flow website for
details!
The key element in Springs JSF integration is the JSF ELResolver mechanism.
25/08/2016 12:10
821 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
24.3.2 FacesContextUtils
A custom VariableResolver works well when mapping ones properties to beans in
faces-config.xml, but at times one may need to grab a bean explicitly. The
FacesContextUtils class makes this easy. It is similar to
WebApplicationContextUtils , except that it takes a FacesContext parameter rather
than a ServletContext parameter.
25/08/2016 12:10
822 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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-286 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
25/08/2016 12:10
823 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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-286
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 .
25/08/2016 12:10
824 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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.
25/08/2016 12:10
825 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
<portlet-mode>view</portlet-mode>
</supports>
<portlet-info>
<title>Sample Portlet</title>
</portlet-info>
</portlet>
Explanation
handler
mapping(s)
controller(s)
25/08/2016 12:10
826 de 1194
Expression
view resolver
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Explanation
(Section 25.6, Views and resolving them) capable of
resolving view names to view definitions
multipart
resolver
handler
exception
resolver
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 :
1. 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.).
2. 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 Section 25.7, Multipart (file upload) support for further information about
multipart handling).
3. 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.
4. 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 Springs DispatcherPortlet by adding context parameters in the
portlet.xml file or portlet init-parameters. The possibilities are listed below.
25/08/2016 12:10
827 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Explanation
Class that implements WebApplicationContext ,
which will be used to instantiate the context used
by this portlet. If this parameter isnt specified, the
XmlPortletApplicationContext will be used.
contextConfigLocation
namespace
viewRendererUrl
<servlet>
<servlet-name>ViewRendererServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.ViewRendererServlet</servlet-class>
25/08/2016 12:10
828 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
</servlet>
<servlet-mapping>
<servlet-name>ViewRendererServlet</servlet-name>
<url-pattern>/WEB-INF/servlet/view</url-pattern>
</servlet-mapping>
25.4 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.
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;
25/08/2016 12:10
829 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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.
Explanation
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
renderWhenMinimized
25/08/2016 12:10
830 de 1194
Parameter
cacheSeconds
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Explanation
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.
25/08/2016 12:10
831 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
}
}
<bean id="sampleController" class="samples.SampleController">
<property name="cacheSeconds" value="120"/>
</bean>
The class above and the declaration in the web application context is all you need
besides setting up a handler mapping (see Section 25.5, Handler mappings) to get this
very simple controller working.
25/08/2016 12:10
832 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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 dont want to specify what views youre 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.
25.4.4 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:
This can be very valuable since you can then use interceptors to pre-process and
post-process requests going to these portlets. Since JSR-286 does not support any kind
of filter mechanism, this is quite handy. For example, this can be used to wrap the
25/08/2016 12:10
833 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
834 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25.5.1 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:
<bean class="org.springframework.web.portlet.handler.PortletModeHandlerMapping"
<property name="portletModeMap">
<map>
<entry key="view" value-ref="viewHandler"/>
<entry key="edit" value-ref="editHandler"/>
<entry key="help" value-ref="helpHandler"/>
</map>
</property>
</bean>
25.5.2 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:
<bean class="org.springframework.web.portlet.handler.ParameterHandlerMapping"
<property name="parameterMap">
<map>
<entry key="add" value-ref="addItemHandler"/>
<entry key="edit" value-ref="editItemHandler"/>
25/08/2016 12:10
835 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25.5.3 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:
<bean class="org.springframework.web.portlet.handler.PortletModeParameterHandlerMappin
<property name="portletModeParameterMap">
<map>
<entry key="view"> <!-- 'view' portlet mode -->
<map>
<entry key="add" value-ref="addItemHandler"/>
<entry key="edit" value-ref="editItemHandler"/>
<entry key="delete" value-ref="deleteItemHandler"/>
</map>
</entry>
<entry key="edit"> <!-- 'edit' portlet mode -->
<map>
<entry key="prefs" value-ref="prefsHandler"/>
<entry key="resetPrefs" value-ref="resetPrefsHandler"/>
</map>
</entry>
</map>
</property>
</bean>
25/08/2016 12:10
836 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25.5.5 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.
25.5.6 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
25/08/2016 12:10
837 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
838 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Any configured PortletMultipartResolver bean must have the following id (or name): "
<bean id="portletMultipartResolver"
class="org.springframework.web.portlet.multipart.CommonsPortletMultipartResolv
<!-- 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 . Be sure to use at least version 1.1 of Commons FileUpload
as previous versions do not support JSR-286 Portlet applications.
Now that you have seen how to set Portlet MVC up to handle multipart requests, lets 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
25/08/2016 12:10
839 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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 .
As you can see, weve created a field named "file" that matches the property of the bean
that holds the byte[] array. Furthermore weve 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 thats 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. Theres 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.
<bean id="portletMultipartResolver"
class="org.springframework.web.portlet.multipart.CommonsPortletMultipartResolv
<bean class="org.springframework.web.portlet.handler.PortletModeHandlerMapping"
<property name="portletModeMap">
<map>
<entry key="view" value-ref="fileUploadController"/>
</map>
</property>
25/08/2016 12:10
840 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
</bean>
<bean id="fileUploadController" class="examples.FileUploadController">
<property name="commandClass" value="examples.FileUploadBean"/>
<property name="formView" value="fileuploadform"/>
<property name="successView" value="confirmation"/>
</bean>
After that, create the controller and the actual class to hold the file property.
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
}
25/08/2016 12:10
841 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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:
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;
}
25/08/2016 12:10
842 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Of course, this last example only makes (logical) sense in the context of uploading a plain
text file (it wouldnt 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) objects class. In this case one does not need to register
any custom property editor because there is no type conversion to be performed.
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;
}
}
25/08/2016 12:10
843 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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.
<bean class="org.springframework.web.portlet.mvc.annotation.DefaultAnnotationHandl
<bean class="org.springframework.web.portlet.mvc.annotation.AnnotationMethodHandle
25/08/2016 12:10
844 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
</beans>
<context:component-scan base-package="org.springframework.samples.petportal.portle
// ...
</beans>
25/08/2016 12:10
845 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
The following is an example of a form controller from the PetPortal sample application
using this annotation:
@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) {
25/08/2016 12:10
846 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
// 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");
}
}
As of Spring 3.0, there are dedicated @ActionMapping and @RenderMapping (as well
as @ResourceMapping and @EventMapping ) annotations which can be used instead:
@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;
}
@RenderMapping // default (action=list)
public String showPetSites() {
25/08/2016 12:10
847 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
}
@RenderMapping(params = "action=add")
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";
}
@ActionMapping(params = "action=add")
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");
}
}
@ActionMapping(params = "action=delete")
public void removeSite(@RequestParam("site") String site, ActionResponse response)
this.petSites.remove(site);
response.setRenderParameter("action", "list");
}
}
25/08/2016 12:10
848 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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 requests content. This
will be the raw InputStream/Reader as exposed by the Portlet API.
java.io.OutputStream / java.io.Writer for generating the responses 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
25/08/2016 12:10
849 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
850 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
// ...
}
Parameters using this annotation are required by default, but you can specify that a
parameter is optional by setting @RequestParams `required attribute to false (e.g.,
@RequestParam(name="id", required=false) ).
The following code snippet shows these two usages of this annotation:
@Controller
@RequestMapping("EDIT")
@SessionAttributes("site")
public class PetSitesEditController {
// ...
@ModelAttribute("petSites")
public Properties getPetSites() {
return this.petSites;
25/08/2016 12:10
851 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
852 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
@InitBinder
protected void initBinder(WebDataBinder binder) {
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
dateFormat.setLenient(false);
binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, false
}
// ...
}
25/08/2016 12:10
853 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
The JSR-286 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.
25/08/2016 12:10
854 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
destinations. Finally, Section 26.4.17, Testing Annotated Controller Methods lists three
approaches to testing STOMP/WebSocket applications.
26.1 Introduction
The WebSocket protocol 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 to the WebSocket protocol is beyond the scope of this document. At
a minimum however its 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 (JSR-356)
and also provides additional value-add as explained in the rest of the introduction.
25/08/2016 12:10
855 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
856 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
protocol originally created for use in scripting languages with frames inspired by HTTP.
STOMP is widely supported and well suited for use over WebSocket and over the web.
25/08/2016 12:10
857 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
7.0.47+, Jetty 9.1+, GlassFish 4.1+, WebLogic 12.1.3+, and Undertow 1.0+ (and WildFly
8.0+). Additional support may be added as more WebSocket runtimes become available.
There is dedicated WebSocket Java-config and XML namespace support for mapping the
above WebSocket handler to a specific URL:
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 {
25/08/2016 12:10
858 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
registry.addHandler(myHandler(), "/myHandler");
}
@Bean
public WebSocketHandler myHandler() {
return new MyHandler();
}
}
The above is for use in Spring MVC applications and should be included in the
configuration of a DispatcherServlet. However, Springs 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 WebSocketHttpRequestHandler.
25/08/2016 12:10
859 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
registry.addHandler(new MyHandler(), "/myHandler")
.addInterceptors(new HttpSessionHandshakeInterceptor());
}
}
<websocket:handlers>
<websocket:mapping path="/myHandler" handler="myHandler"/>
<websocket:handshake-interceptors>
<bean class="org.springframework.web.socket.server.support.HttpSessionHand
</websocket:handshake-interceptors>
</websocket:handlers>
<bean id="myHandler" class="org.springframework.samples.MyHandler"/>
</beans>
25/08/2016 12:10
860 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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.
A request to overcome the above limitation in the Java WebSocket API has
been created and can be followed at 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 a ServletContainerInitializer (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 the
<absolute-ordering /> element in web.xml :
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
25/08/2016 12:10
861 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
xsi:schemaLocation="
http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">
<absolute-ordering/>
</web-app>
You can then selectively enable web fragments by name, such as Springs own
SpringServletContainerInitializer that provides support for the Servlet 3 Java
initialization API, if required:
<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">
<absolute-ordering>
<name>spring_web</name>
</absolute-ordering>
</web-app>
@Bean
public ServletServerContainerFactoryBean createWebSocketContainer() {
ServletServerContainerFactoryBean container = new ServletServerContainerFactor
container.setMaxTextMessageBufferSize(8192);
container.setMaxBinaryMessageBufferSize(8192);
return container;
}
25/08/2016 12:10
862 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
863 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
864 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
accept only same origin requests. It is also possible to allow all or a specified list of
origins. This check is mostly designed for browser clients. There is nothing preventing
other types of clients from modifying the Origin header value (see RFC 6454: The Web
Origin Concept for more details).
The 3 possible behaviors are:
Allow only same origin requests (default): in this mode, when SockJS is enabled, the
Iframe HTTP response header X-Frame-Options is set to SAMEORIGIN , and
JSONP transport is disabled since it does not allow to check the origin of a request.
As a consequence, IE6 and IE7 are not supported when this mode is enabled.
Allow a specified list of origins: each provided allowed origin must start with http://
or https:// . In this mode, when SockJS is enabled, both IFrame and JSONP
based transports are disabled. As a consequence, IE6 through IE9 are not supported
when this mode is enabled.
Allow all origins: to enable this mode, you should provide * as the allowed origin
value. In this mode, all transports are available.
WebSocket and SockJS allowed origins can be configured as shown bellow:
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").setAllowedOrigins("http://mydom
}
@Bean
public WebSocketHandler myHandler() {
return new MyHandler();
}
}
25/08/2016 12:10
865 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/websocket
http://www.springframework.org/schema/websocket/spring-websocket.xsd"
<websocket:handlers allowed-origins="http://mydomain.com">
<websocket:mapping path="/myHandler" handler="myHandler" />
</websocket:handlers>
<bean id="myHandler" class="org.springframework.samples.MyHandler"/>
</beans>
25/08/2016 12:10
866 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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"] (JSONencoded 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 the 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
narrated test.
25/08/2016 12:10
867 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
@Bean
public WebSocketHandler myHandler() {
return new MyHandler();
}
}
The above is for use in Spring MVC applications and should be included in the
configuration of a DispatcherServlet. However, Springs 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 SockJsHttpRequestHandler.
On the browser side, applications can use the sockjs-client (version 1.0.x) that emulates
the W3C WebSocket API and communicates with the server to select the best transport
option depending on the browser its running in. Review the 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.
25/08/2016 12:10
868 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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 <origin> . 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 via the <websocket:sockjs> element:
25/08/2016 12:10
869 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
@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"
}
// ...
}
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 SockJS
client page.
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.
25/08/2016 12:10
870 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
HTTP streaming and HTTP long polling SockJS transports require a connection to remain
open longer than usual. For an overview of these techniques see 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 that the Servlet API does not provide notifications for a client that has
gone away, see SERVLET_SPEC-44. However, Servlet containers raise an exception on
subsequent attempts to write to the response. Since Springs SockJS Service supports
sever-sent heartbeats (every 25 seconds by default), that means a client disconnect is
usually detected within that time period or earlier if messages are sent more frequently.
25/08/2016 12:10
871 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
872 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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:
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):
@Configuration
public class WebSocketConfig extends WebSocketMessageBrokerConfigurationSupport {
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/sockjs").withSockJS()
.setStreamBytesLimit(512 * 1024)
.setHttpMessageCacheSize(1000)
.setDisconnectDelay(30 * 1000);
}
// ...
}
25/08/2016 12:10
873 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
STOMP is a simple text-oriented messaging protocol that was 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 messaging patterns.
STOMP can be used over any reliable 2-way streaming network protocol such as TCP
and WebSocket. Although STOMP is a text-oriented protocol, the payload of messages
can be either text or binary.
STOMP is a frame based protocol whose frames are modeled on HTTP. The structure of
a STOMP frame:
COMMAND
header1:value1
header2:value2
Body^@
Clients can use the SEND or SUBSCRIBE commands to send or subscribe for messages
along with a "destination" header that describes what the message is about and who
should receive it. This enables a simple publish-subscribe mechanism that can be used to
send messages through the broker to other connected clients or to send messages to the
server to request that some work be performed.
When using Springs STOMP support, the Spring WebSocket application acts as the
STOMP broker to clients. Messages are routed to @Controller message-handling
methods or to a simple, in-memory broker that keeps track of subscriptions and
broadcasts messages to subscribed users. You can also configure Spring to work with a
dedicated STOMP broker (e.g. RabbitMQ, ActiveMQ, etc) for the actual broadcasting of
messages. In that case Spring maintains TCP connections to the broker, relays
messages to it, and also passes messages from it down to connected WebSocket clients.
Thus Spring web applications can rely on unified HTTP-based security, common
validation, and a familiar programming model message-handling work.
Here is an example of a client subscribing to receive stock quotes which the server may
emit periodically e.g. via a scheduled task sending messages through a
SimpMessagingTemplate to the broker:
SUBSCRIBE
id:sub-1
destination:/topic/price.stock.*
^@
Here is an example of a client sending a trade request, which the server may handle
25/08/2016 12:10
874 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
through an @MessageMapping method and later on, after the execution, broadcast a
trade confirmation message and details down to the client:
SEND
destination:/queue/trade
content-type:application/json
content-length:44
{"action":"BUY","ticker":"MMM","shares",44}^@
The meaning of a destination is intentionally left opaque in the STOMP spec. It can be
any string, and its 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/" 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}^@
It is 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 specification in full.
The benefits of using STOMP as a WebSocket sub-protocol:
No need to invent a custom message format
Use existing stomp.js client in the browser
Ability to route messages to based on destination
Option to use full-fledged message broker such as RabbitMQ, ActiveMQ, etc. for
broadcasting
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
25/08/2016 12:10
875 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
and in XML:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:websocket="http://www.springframework.org/schema/websocket"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/websocket
http://www.springframework.org/schema/websocket/spring-websocket.xsd"
<websocket:message-broker application-destination-prefix="/app">
<websocket:stomp-endpoint path="/portfolio">
<websocket:sockjs/>
25/08/2016 12:10
876 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
</websocket:stomp-endpoint>
<websocket:simple-broker prefix="/topic, /queue"/>
</websocket:message-broker>
</beans>
The "/app" prefix is arbitrary. You can pick any prefix. Its simply meant to
differentiate messages to be routed to message-handling methods to do
application work vs messages to be routed to the broker to broadcast to
subscribed clients.
The "/topic" and "/queue" prefixes depend on the broker in use. In the case
of the simple, in-memory broker the prefixes do not have any special
meaning; its merely a convention that indicates how the destination is used
(pub-sub targetting many subscribers or point-to-point messages typically
targeting an individual recipient). In the case of using a dedicated broker,
most brokers use "/topic" as a prefix for destinations with pub-sub
semantics and "/queue" for destinations with point-to-point semantics.
Check the STOMP page of the broker to see the destination semantics it
supports.
On the browser side, a client might connect as follows using stomp.js and the sockjsclient:
var socket = new SockJS("/spring-websocket-portfolio/portfolio");
var stompClient = Stomp.over(socket);
stompClient.connect({}, function(frame) {
}
Note that the stompClient above does not need to specify login and passcode
headers. Even if it did, they would be ignored, or rather overridden, on the server side.
See the sections Section 26.4.8, Connections To Full-Featured Broker and
Section 26.4.10, Authentication for more information on authentication.
25/08/2016 12:10
877 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
878 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
879 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
The following explains the message flow for the above example:
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 a 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.
25/08/2016 12:10
880 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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.
25/08/2016 12:10
881 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
882 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
But it can also be qualified by its name "brokerMessagingTemplate" if another bean of the
same type exists.
25/08/2016 12:10
883 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
@Override
public void configureMessageBroker(MessageBrokerRegistry registry) {
registry.enableStompBrokerRelay("/topic", "/queue");
registry.setApplicationDestinationPrefixes("/app");
}
}
The "STOMP broker relay" in the above configuration is a Spring 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 then forwards
all messages received from the broker to clients through their WebSocket sessions.
Essentially it acts as a "relay" that forwards messages in both directions.
25/08/2016 12:10
884 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
The STOMP broker relay always sets the login and passcode headers
on every CONNECT frame that 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.
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
25/08/2016 12:10
885 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
In XML config:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:websocket="http://www.springframework.org/schema/websocket"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/websocket
http://www.springframework.org/schema/websocket/spring-websocket.xsd">
<websocket:message-broker application-destination-prefix="/app" path-matcher
<websocket:stomp-endpoint path="/stomp" />
<websocket:simple-broker prefix="/topic, /queue"/>
</websocket:message-broker>
<bean id="pathMatcher" class="org.springframework.util.AntPathMatcher">
<constructor-arg index="0" value="." />
</bean>
</beans>
25/08/2016 12:10
886 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
@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}".
26.4.10 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 is created,
Springs WebSocket support automatically propagates 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.
Its 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, Springs 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 a WebSocket session even when
the user has not been 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
25/08/2016 12:10
887 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
If the user has more than one session, 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:
@Controller
public class MyController {
25/08/2016 12:10
888 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
@MessageMapping("/action")
public void handleAction() throws Exception{
// raise MyBusinessException here
}
@MessageExceptionHandler
@SendToUser(destinations="/queue/errors", broadcast=false)
public ApplicationError handleException(MyBusinessException exception) {
// ...
return appError;
}
}
25/08/2016 12:10
889 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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 . Similarly, ActiveMQ
has configuration options for purging inactive destinations.
25/08/2016 12:10
890 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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:
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {
@Override
public void configureClientInboundChannel(ChannelRegistration registration) {
registration.setInterceptors(new MyChannelInterceptor());
}
}
25/08/2016 12:10
891 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Once the session is established any payload can be sent and that will be serialized with
the configured MessageConverter :
session.send("/topic/foo", "payload");
25/08/2016 12:10
892 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
You can also subscribe to destinations. The subscribe methods require a handler for
messages on the subscription and return a Subscription handle that can be used to
unsubscribe. For each received message the handler can specify the target Object type
the payload should be deserialized to:
session.subscribe("/topic/foo", new StompFrameHandler() {
@Override
public Type getPayloadType(StompHeaders headers) {
return String.class;
}
@Override
public void handleFrame(StompHeaders headers, Object payload) {
// ...
}
});
The STOMP protocol also supports receipts where the client must add a "receipt" header
to which the server responds with a RECEIPT frame after the send or subscribe are
processed. To support this the StompSession offers setAutoReceipt(boolean) that
causes a "receipt" header to be added on every subsequent send or subscribe.
Alternatively you can also manually add a "receipt" header to the StompHeaders . Both
send and subscribe return an instance of Receiptable that can be used to register for
receipt success and failure callbacks. For this feature the client must be configured with a
TaskScheduler and the amount of time before a receipt expires (15 seconds by
default).
Note that StompSessionHandler itself is a StompFrameHandler which allows it to
handle ERROR frames in addition to the handleException callback for exceptions from
25/08/2016 12:10
893 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
including ConnectionLostException .
25/08/2016 12:10
894 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
@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.
25/08/2016 12:10
895 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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.
@Override
public void configureWebSocketTransport(WebSocketTransportRegistration registratio
registration.setSendTimeLimit(15 * 1000).setSendBufferSizeLimit(512 *
}
// ...
}
25/08/2016 12:10
896 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:websocket="http://www.springframework.org/schema/websocket"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/websocket
http://www.springframework.org/schema/websocket/spring-websocket.xsd"
<websocket:message-broker>
<websocket:transport send-timeout="15000" send-buffer-size="524288" />
<!-- ... -->
</websocket:message-broker>
</beans>
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 practice 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.
Springs 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:
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
@Override
public void configureWebSocketTransport(WebSocketTransportRegistration registratio
registration.setMessageSizeLimit(128 * 1024);
}
// ...
}
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:websocket="http://www.springframework.org/schema/websocket"
xsi:schemaLocation="
25/08/2016 12:10
897 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/websocket
http://www.springframework.org/schema/websocket/spring-websocket.xsd"
<websocket:message-broker>
<websocket:transport message-size="131072" />
<!-- ... -->
</websocket:message-broker>
</beans>
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.
25/08/2016 12:10
898 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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 didnt 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.
25/08/2016 12:10
899 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
900 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
27.1 Introduction
For security reasons, browsers prohibit AJAX calls to resources residing outside the
current origin. For example, as youre checking your bank account in one tab, you could
have the evil.com website open in another tab. The scripts from evil.com should not be
able to make AJAX requests to your bank API (e.g., withdrawing money from your
account!) using your credentials.
Cross-origin resource sharing (CORS) is a W3C specification implemented by most
browsers that allows you to specify in a flexible way what kind of cross domain requests
are authorized, instead of using some less secured and less powerful hacks like IFRAME
or JSONP.
As of Spring Framework 4.2, CORS is supported out of the box. CORS requests
(including preflight ones with an OPTIONS method) are automatically dispatched to the
various registered HandlerMapping s. They handle CORS preflight requests and
intercept CORS simple and actual requests thanks to a CorsProcessor implementation
(DefaultCorsProcessor by default) in order to add the relevant CORS response headers
(like Access-Control-Allow-Origin ) based on the CORS configuration you have
provided.
25/08/2016 12:10
901 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
In the above example CORS support is enabled for both the retrieve() and the
remove() handler methods, and you can also see how you can customize the CORS
configuration using @CrossOrigin attributes.
You can even use both controller-level and method-level CORS configurations; Spring will
then combine attributes from both annotations to create merged CORS configuration.
@CrossOrigin(maxAge = 3600)
@RestController
@RequestMapping("/account")
public class AccountController {
@CrossOrigin("http://domain2.com")
@RequestMapping("/{id}")
public Account retrieve(@PathVariable Long id) {
// ...
}
@RequestMapping(method = RequestMethod.DELETE, path = "/{id}")
public void remove(@PathVariable Long id) {
// ...
}
25/08/2016 12:10
902 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
27.3.1 JavaConfig
Enabling CORS for the whole application is as simple as:
@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**");
}
}
You can easily change any properties, as well as only apply this CORS configuration to a
specific path pattern:
@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/api/**")
.allowedOrigins("http://domain2.com")
.allowedMethods("PUT", "DELETE")
.allowedHeaders("header1", "header2", "header3")
.exposedHeaders("header1", "header2")
.allowCredentials(false).maxAge(3600);
}
}
25/08/2016 12:10
903 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
The following minimal XML configuration enables CORS for the /** path pattern with the
same default properties as with the aforementioned JavaConfig examples:
<mvc:cors>
<mvc:mapping path="/**" />
</mvc:cors>
25/08/2016 12:10
904 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
You need to ensure that CorsFilter is ordered before the other filters, see this blog
post about how to configure Spring Boot accordingly.
25/08/2016 12:10
905 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
906 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
We will start exposing the service to a remote client by using RMI and talk a bit about the
drawbacks of using RMI. Well then continue to show an example using Hessian as the
protocol.
25/08/2016 12:10
907 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
As you can see, were 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' . Well use the URL later
on to link in the service at the client side.
The servicePort property has been omitted (it defaults to 0). This means
that an anonymous port will be used to communicate with the service.
25/08/2016 12:10
908 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
}
// additional methods using the accountService
}
To link in the service on the client, well create a separate Spring container, containing the
simple object and the service linking configuration bits:
<bean class="example.SimpleObject">
<property name="accountService" ref="accountService"/>
</bean>
Thats 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 were linking it in using the RmiProxyFactoryBean .
25/08/2016 12:10
909 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
<url-pattern>/remoting/*</url-pattern>
</servlet-mapping>
Youre probably familiar with Springs DispatcherServlet principles and if so, you
know that now youll 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 Springs 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.
Now were 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
In the latter case, define a corresponding servlet for this exporter in 'web.xml' , with the
25/08/2016 12:10
910 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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.
<servlet>
<servlet-name>accountExporter</servlet-name>
<servlet-class>org.springframework.web.context.support.HttpRequestHandlerServlet
</servlet>
<servlet-mapping>
<servlet-name>accountExporter</servlet-name>
<url-pattern>/remoting/AccountService</url-pattern>
</servlet-mapping>
25/08/2016 12:10
911 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
for example. Usually, you dont use per-user security credentials here, but rather shared
credentials defined at the Hessian/BurlapProxyFactoryBean level (similar to a JDBC
DataSource ).
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"
<property name="interceptors" ref="authorizationInterceptor"/>
</bean>
<bean id="authorizationInterceptor"
class="org.springframework.web.servlet.handler.UserRoleAuthorizationIntercepto
<property name="authorizedRoles" value="administrator,operator"/>
</bean>
25/08/2016 12:10
912 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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 dispatchers
application context:
In addition, define a corresponding servlet for this exporter in 'web.xml' , with the
servlet name matching the bean name of the target exporter:
<servlet>
<servlet-name>accountExporter</servlet-name>
<servlet-class>org.springframework.web.context.support.HttpRequestHandlerServlet
</servlet>
<servlet-mapping>
<servlet-name>accountExporter</servlet-name>
<url-pattern>/remoting/AccountService</url-pattern>
</servlet-mapping>
If you are running outside of a servlet container and are using Oracles 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:
<bean name="accountExporter"
class="org.springframework.remoting.httpinvoker.SimpleHttpInvokerServiceExport
<property name="service" ref="accountService"/>
<property name="serviceInterface" value="example.AccountService"/>
</bean>
25/08/2016 12:10
913 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
<bean id="httpServer"
class="org.springframework.remoting.support.SimpleHttpServerFactoryBean"
<property name="contexts">
<util:map>
<entry key="/remoting/AccountService" value-ref="accountExporter"
</util:map>
</property>
<property name="port" value="8080" />
</bean>
As mentioned before, you can choose what HTTP client you want to use. By default, the
HttpInvokerProxy uses the JDKs HTTP functionality, but you can also use the Apache
HttpComponents client by setting the httpInvokerRequestExecutor property:
<property name="httpInvokerRequestExecutor">
<bean class="org.springframework.remoting.httpinvoker.HttpComponentsHttpInvokerReq
</property>
914 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Spring provides a convenient base class for JAX-WS servlet endpoint implementations SpringBeanAutowiringSupport . To expose our AccountService we extend Springs
SpringBeanAutowiringSupport class and implement our business logic here, usually
delegating the call to the business layer. Well simply use Springs @Autowired
annotation for expressing such dependencies on Spring-managed beans.
/**
* 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 AccountServiceEndpoint needs to run in the same web application as the Spring
context to allow for access to Springs facilities. This is the case by default in Java EE 5
environments, using the standard contract for JAX-WS servlet endpoint deployment. See
25/08/2016 12:10
915 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
916 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
917 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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:
<bean id="client" class="example.AccountClientImpl">
...
<property name="service" ref="accountWebService"/>
</bean>
From the client code we can access the web service just as if it was a normal class:
public class AccountClientImpl {
private AccountService service;
public void setService(AccountService service) {
this.service = service;
}
public void foo() {
service.insertAccount(...);
}
}
28.6 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
25/08/2016 12:10
918 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
remoting support. See Chapter 30, JMS (Java Message Service) for information on
Springs rich support for JMS-based messaging.
The following interface is used on both the server and the client side.
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.
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.
<?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">
25/08/2016 12:10
919 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
On the server, you just need to expose the service object using the
JmsInvokerServiceExporter .
<?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="checkingAccountService"
class="org.springframework.jms.remoting.JmsInvokerServiceExporter"
<property name="serviceInterface" value="com.foo.CheckingAccountService"
<property name="service">
<bean class="com.foo.SimpleCheckingAccountService"/>
</property>
</bean>
<bean class="org.springframework.jms.listener.SimpleMessageListenerContainer"
<property name="connectionFactory" ref="connectionFactory"/>
<property name="destination" ref="queue"/>
<property name="concurrentConsumers" value="3"/>
<property name="messageListener" ref="checkingAccountService"/>
</bean>
</beans>
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"
}
}
25/08/2016 12:10
920 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
28.7 AMQP
Refer to the Spring AMQP Reference Document 'Spring Remoting with AMQP' section for
more information.
25/08/2016 12:10
921 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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.
25/08/2016 12:10
922 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
28.10.1 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.
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
25/08/2016 12:10
923 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
HTTP methods that make invoking many RESTful services a one-liner and enforce REST
best practices.
RestTemplate Method
Method
DELETE
delete
GET
getForObject getForEntity
HEAD
OPTIONS
POST
PUT
PATCH and
exchange execute
others
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
25/08/2016 12:10
924 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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<Account> ), 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<String,String> . For example,
String result = restTemplate.getForObject(
"http://example.com/hotels/{hotel}/bookings/{booking}", String.class
using a Map<String,String> .
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.
Note that the java.net implementation for HTTP requests may raise an
exception when accessing the status of a response that represents an error
25/08/2016 12:10
925 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
The general callback interface is RequestCallback and is called when the execute
method is invoked.
public <T> T execute(String url, HttpMethod method, RequestCallback requestCallback,
ResponseExtractor<T> responseExtractor, String... urlVariables)
// also has an overload with urlVariables as a Map<String, String>.
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
25/08/2016 12:10
926 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
documentation for more information on using the execute method and the meaning of its
other method arguments.
25/08/2016 12:10
927 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
HttpEntity class.
Perhaps most importantly, the exchange() method can be used to add request headers
and read response headers. For example:
HttpHeaders requestHeaders = new HttpHeaders();
requestHeaders.set("MyRequestHeader", "MyValue");
HttpEntity<?> requestEntity = new HttpEntity(requestHeaders);
HttpEntity<String> 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.
// Indicate whether the given class and media type can be written by this converte
boolean canWrite(Class<?> clazz, MediaType mediaType);
25/08/2016 12:10
928 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
// Read an object of the given type from the given input message, and returns it.
T read(Class<T> clazz, HttpInputMessage inputMessage) throws IOException, HttpMess
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
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 .
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<String, String> .
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[]) .
MarshallingHttpMessageConverter
25/08/2016 12:10
929 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
An HttpMessageConverter implementation that can read and write XML using Springs
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 ).
MappingJackson2HttpMessageConverter
An HttpMessageConverter implementation that can read and write JSON using
Jacksons ObjectMapper . JSON mapping can be customized as needed through the
use of Jacksons 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 ).
MappingJackson2XmlHttpMessageConverter
An HttpMessageConverter implementation that can read and write XML using Jackson
XML extensions XmlMapper . XML mapping can be customized as needed through the
use of JAXB or Jacksons 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 ).
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 ).
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.
25/08/2016 12:10
930 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
applications for those needs: multiple threads may be blocked, waiting for remote HTTP
responses.
AsyncRestTemplate and Section 28.10.1, RestTemplate's APIs are very similar; see
Table 28.1, Overview of RestTemplate methods. The main difference between those
APIs is that AsyncRestTemplate returns ListenableFuture wrappers as opposed to
concrete results.
The previous RestTemplate example translates to:
// async call
Future<ResponseEntity<String>> futureEntity = template.getForEntity(
"http://example.com/hotels/{hotel}/bookings/{booking}", String.class, "42"
// get the concrete result - synchronous call
ResponseEntity<String> entity = futureEntity.get();
25/08/2016 12:10
931 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
932 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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 well 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 well 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:
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:
25/08/2016 12:10
933 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
<bean id="myComponent"
class="org.springframework.ejb.access.LocalStatelessSessionProxyFactoryBean"
<property name="jndiName" value="ejb/myBean"/>
<property name="businessInterface" value="com.mycom.MyComponent"/>
</bean>
<bean id="myController" class="com.mycom.myController">
<property name="myComponent" ref="myComponent"/>
</bean>
Theres a lot of work happening behind the scenes, courtesy of the Spring AOP
framework, although you arent 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 theres 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
<jee:local-slsb> configuration element in Springs "jee" namespace:
<jee:local-slsb id="myComponent" jndi-name="ejb/myBean"
business-interface="com.mycom.MyComponent"/>
<bean id="myController" class="com.mycom.myController">
<property name="myComponent" ref="myComponent"/>
</bean>
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 havent 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 dont want to make fine-grained
calls to EJBs anyway, as theres 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
25/08/2016 12:10
934 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
935 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
business interface.
25/08/2016 12:10
936 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
...
}
25/08/2016 12:10
937 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
938 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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
MessageProducers 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.
30.2.2 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.
25/08/2016 12:10
939 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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 .
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.
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.
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 acknowledgment mode.
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,
25/08/2016 12:10
940 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
941 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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 EEs JMS restrictions.
25/08/2016 12:10
942 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
DefaultMessageListenerContainer
This message listener container is the one used in most cases. In contrast to
SimpleMessageListenerContainer , this container variant allows for dynamic
adaptation 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 the participation in
externally managed transactions, 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.
25/08/2016 12:10
943 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
944 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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.
import
import
import
import
import
javax.jms.ConnectionFactory;
javax.jms.JMSException;
javax.jms.Message;
javax.jms.Queue;
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 Springs 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
25/08/2016 12:10
945 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
946 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Header={
... standard headers ...
CorrelationID={123-00001}
}
Properties={
AccountID={Integer:1234}
}
Fields={
Name={String:Mark}
Age={Integer:47}
}
}
In a fashion similar to a Message-Driven Bean (MDB) in the EJB world, the MessageDriven POJO (MDP) acts as a receiver for JMS messages. The one restriction (but see
25/08/2016 12:10
947 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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:
import
import
import
import
javax.jms.JMSException;
javax.jms.Message;
javax.jms.MessageListener;
javax.jms.TextMessage;
Once youve implemented your MessageListener , its 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 ).
<!-- this is the Message Driven POJO (MDP) -->
<bean id="messageListener" class="jmsexample.ExampleListener" />
25/08/2016 12:10
948 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Please refer to the Spring javadocs of the various message listener containers for a full
description of the features supported by each implementation.
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.
25/08/2016 12:10
949 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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.
public interface MessageDelegate {
void handleMessage(String message);
void handleMessage(Map message);
void handleMessage(byte[] message);
void handleMessage(Serializable message);
}
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.
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.
25/08/2016 12:10
950 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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:
public interface ResponsiveTextMessageDelegate {
// notice the return type...
String receive(TextMessage message);
}
25/08/2016 12:10
951 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Then you just need to add it to our earlier container configuration. The container will take
care of the rest.
25/08/2016 12:10
952 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
<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>
25/08/2016 12:10
953 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
<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 SimpleTaskWorkManagers "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 servers 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 providers
documentation to find out about the actual capabilities of your connector, and consult
`GenericMessageEndpointManagers JavaDoc for the Spring-specific configuration
details.
25/08/2016 12:10
954 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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.
@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
MessageListenerAdapter provides).
The annotated endpoint infrastructure creates a message listener container behind the
scenes for each annotated method, using a JmsListenerContainerFactory . Such
container is not registered against the application context but can be easily located for
management purposes using the JmsListenerEndpointRegistry bean.
25/08/2016 12:10
955 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
return factory;
}
}
25/08/2016 12:10
956 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
registrar.registerEndpoint(endpoint);
}
}
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
@Valid .
25/08/2016 12:10
957 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
The ability to inject Springs Message abstraction is particularly useful to benefit from all
the information stored in the transport-specific message without relying on transportspecific API.
@JmsListener(destination = "myDestination")
public void processOrder(Message<Order> order) { ... }
@Bean
public DefaultMessageHandlerMethodFactory myHandlerMethodFactory() {
DefaultMessageHandlerMethodFactory factory = new DefaultMessageHandlerMethodFa
factory.setValidator(myValidator());
return factory;
}
}
25/08/2016 12:10
958 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
@SendTo("status")
public OrderStatus processOrder(Order order) {
// order processing
return status;
}
If you have several @JmsListener -annotated methods, you can also place
the @SendTo annotation at class-level to share a default reply destination.
If you need to set additional headers in a transport-independent manner, you could return
a Message instead, something like:
@JmsListener(destination = "myDestination")
@SendTo("status")
public Message<OrderStatus> processOrder(Order order) {
// order processing
return MessageBuilder
.withPayload(status)
.setHeader("code", 1234)
.build();
}
If you need to compute the response destination at runtime, you can encapsulate your
response in a JmsResponse instance that also provides the destination to use at runtime.
The previous example can be rewritten as follows:
@JmsListener(destination = "myDestination")
public JmsResponse<Message<OrderStatus>> processOrder(Order order) {
// order processing
Message<OrderStatus> response = MessageBuilder
.withPayload(status)
.setHeader("code", 1234)
.build();
return JmsResponse.forQueue(response, "status");
}
25/08/2016 12:10
959 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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
http://www.springframework.org/schema/jms http://www.springframework.org/s
<!-- bean definitions here -->
</beans>
The example above is equivalent to creating two distinct listener container bean
definitions and two distinct MessageListenerAdapter bean definitions as demonstrated
in Section 30.4.4, the MessageListenerAdapter. In addition to the attributes shown
above, the listener element may contain several optional ones. The following table
describes all available attributes:
Description
A bean name for the hosting listener container. If not specified, a
bean name will be automatically generated.
destination
(required)
DestinationResolver strategy.
ref
(required)
25/08/2016 12:10
960 de 1194
Attribute
method
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Description
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
subscription
selector
concurrency
25/08/2016 12:10
961 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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.
Description
The type of this listener container. Available options are:
default , simple , default102 , or simple102 (the default
value is 'default' ).
container-class
factory-id
connection-
factory
task-executor
destination-
resolver
message-
converter
error-handler
25/08/2016 12:10
962 de 1194
Attribute
destination-type
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Description
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).
response-
destination-type
client-id
cache
acknowledge
transaction-
manager
concurrency
25/08/2016 12:10
963 de 1194
Attribute
prefetch
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Description
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
back-off
recovery-
interval
phase
Configuring a JCA-based listener container with the "jms" schema support is very similar.
<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:
25/08/2016 12:10
964 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Description
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
activation-
spec-factory
destination-
resolver
message-
converter
destination-type
response-
destination-type
client-id
acknowledge
transaction-
manager
25/08/2016 12:10
965 de 1194
Attribute
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Description
specified, native acknowledging will be used (see the
"acknowledge" attribute).
concurrency
prefetch
31. JMX
31.1 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 doesnt 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 Section 31.8, Further Resources at the end
of this chapter.
Specifically, Springs 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
25/08/2016 12:10
966 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
classes need not be aware of either Spring or JMX in order to take advantage of the
Spring JMX features.
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:
25/08/2016 12:10
967 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
<beans>
<!-- this bean must not be lazily initialized if the exporting is to happen -->
<bean id="exporter" class="org.springframework.jmx.export.MBeanExporter"
<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 Section 31.4,
Controlling the ObjectNames for your beans.
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.
25/08/2016 12:10
968 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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 MBeanExporters `server property to the MBeanServer value returned
by an MBeanServerFactoryBean ; for example:
<beans>
<!-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>
25/08/2016 12:10
969 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
<beans>
<bean id="mbeanServer" class="org.springframework.jmx.support.MBeanServerFactoryBe
<!-- 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 factory-method:
<beans>
<bean id="exporter" class="org.springframework.jmx.export.MBeanExporter"
<property name="server">
<!-- Custom MBeanServerLocator -->
<bean class="platform.package.MBeanServerLocator" factory-method
</property>
</bean>
<!-- other beans here -->
</beans>
25/08/2016 12:10
970 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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 Section 31.4, Controlling the ObjectNames for your beans.
Explanation
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
25/08/2016 12:10
971 de 1194
Registration behavior
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Explanation
thrown. This is useful in settings where
multiple applications want to share a
common MBean in a shared
MBeanServer .
REGISTRATION_REPLACE_EXISTING
25/08/2016 12:10
972 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
973 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
The example below shows the annotated version of the JmxTestBean class that you saw
earlier:
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)
25/08/2016 12:10
974 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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 Section 31.3.3, Source-Level 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 :
<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.AnnotationJmxAttributeSou
25/08/2016 12:10
975 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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.
Annotation
Annotation
Type
@ManagedResource
Class
@ManagedOperation
Method
@ManagedAttribute
Method (only
of a Class as
JMX managed
resources
Mark a method as
a JMX operation
Mark a getter or
setter as one half
getters and
of a JMX attribute
setters)
25/08/2016 12:10
976 de 1194
Purpose
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Annotation
Annotation
Type
Define descriptions
@ManagedOperationParameter and
for operation
@ManagedOperationParameters
Method
parameters
The following configuration parameters are available for use on these source-level
metadata types:
Description
Used by
Applies to
ManagedResource
MetadataNamingStrategy
to determine the
ObjectName of a
managed resource
description
ManagedResource ,
ManagedAttribute ,
operation
ManagedOperation ,
ManagedOperationParameter
currencyTimeLimit
ManagedResource ,
currencyTimeLimit
ManagedAttribute
descriptor field
defaultValue
ManagedAttribute
defaultValue descriptor
field
log
ManagedResource
descriptor field
logFile
ManagedResource
ManagedResource
persistPolicy descriptor
25/08/2016 12:10
977 de 1194
Parameter
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Description
Applies to
field
persistPeriod
ManagedResource
persistPeriod descriptor
field
persistLocation
ManagedResource
persistLocation
descriptor field
persistName
ManagedResource
persistName descriptor
field
name
ManagedOperationParameter
an operation parameter
index
ManagedOperationParameter
operation parameter
25/08/2016 12:10
978 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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 Section 31.4, Controlling the ObjectNames for your
beans.
25/08/2016 12:10
979 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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:
<beans>
25/08/2016 12:10
980 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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.
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.
25/08/2016 12:10
981 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
982 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
</bean>
</beans>
<bean id="attributeSource"
class="org.springframework.jmx.export.annotation.AnnotationJmxAttributeSou
</beans>
25/08/2016 12:10
983 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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
MetadataNamingStrategy.
@EnableMBeanExport(server="myMBeanServer", defaultDomain="myDomain")
@Configuration
ContextConfiguration {
}
<context:mbean-export server="myMBeanServer" default-domain="myDomain"/>
25/08/2016 12:10
984 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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
25/08/2016 12:10
985 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
JMXConnector:
<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:
<bean id="registry" class="org.springframework.remoting.rmi.RmiRegistryFactoryBean"
<property name="port" value="1099"/>
</bean>
25/08/2016 12:10
986 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
In the case of the above example, MX4J 3.0.0 was used; see the official MX4J
documentation for more information.
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:
<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>
25/08/2016 12:10
987 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
31.7 Notifications
Springs JMX offering includes comprehensive support for JMX notifications.
javax.management.AttributeChangeNotification;
javax.management.Notification;
javax.management.NotificationFilter;
javax.management.NotificationListener;
25/08/2016 12:10
988 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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:
<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">
25/08/2016 12:10
989 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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:
<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:
<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>
25/08/2016 12:10
990 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
<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'.)
<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">
25/08/2016 12:10
991 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
</bean>
</property>
<property name="notificationFilter" ref="customerNotificationListe
</bean>
</list>
</property>
</bean>
<!-- implements both the NotificationListener and NotificationFilter interfaces -<bean id="customerNotificationListener" class="com.example.ConsoleLoggingNotificat
<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>
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.
25/08/2016 12:10
992 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
are publishing events via the NotificationPublisher mechanism are not responsible
for the state management of any notification listeners and the like Springs 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.
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
private
private
private
String name;
int age;
boolean isSuperman;
NotificationPublisher publisher;
25/08/2016 12:10
993 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
}
}
The NotificationPublisher interface and the machinery to get it all working is one of
the nicer features of Springs 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.
25/08/2016 12:10
994 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
typical Spring style, leveraging the Spring Frameworks general resource and transaction
management facilities.
The client side of connectors doesnt 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.
25/08/2016 12:10
995 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
When you use a connector in non-managed mode, you cant 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.
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 .
25/08/2016 12:10
996 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
<bean id="connectionFactory"
class="org.springframework.jca.cci.connection.ConnectionSpecConnectionFactoryA
<property name="targetConnectionFactory" ref="targetConnectionFactory"/>
<property name="connectionSpec">
<bean class="com.sun.connector.cciblackbox.CciConnectionSpec">
<property name="user" value="sa"/>
<property name="password" value=""/>
</bean>
</property>
</bean>
25/08/2016 12:10
997 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
998 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
In order to create an input Record , the developer can use a dedicated implementation of
the RecordCreator interface.
public interface RecordCreator {
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 Springs
CciTemplate for extracting data from the output Record .
public interface RecordExtractor {
25/08/2016 12:10
999 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
}
}
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.
public class CciTemplate implements CciOperations {
25/08/2016 12:10
1000 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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:
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.
public class CciTemplate implements CciOperations {
25/08/2016 12:10
1001 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
1002 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
32.3.5 Summary
The following table summarizes the mechanisms of the CciTemplate class and the
corresponding methods called on the CCI Interaction interface:
CciTemplate
execute method
signature
outputRecordCreator
property
Interaction
Record
not set
Record
execute(InteractionSpec,
execute(InteractionSpec,
Record)
Record)
Record
set
boolean
execute(InteractionSpec,
execute(InteractionSpec,
Record)
Record, Record)
void
execute(InteractionSpec,
not set
void
execute(InteractionSpec,
25/08/2016 12:10
1003 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
CciTemplate method
CciTemplate
execute method
signature
outputRecordCreator
property
Interaction
Record, Record)
void
Record, Record)
set
void
execute(InteractionSpec,
execute(InteractionSpec,
Record, Record)
Record, Record)
Record
not set
Record
execute(InteractionSpec,
execute(InteractionSpec,
RecordCreator)
Record)
Record
set
void
execute(InteractionSpec,
execute(InteractionSpec,
RecordCreator)
Record, Record)
Record
not set
Record
execute(InteractionSpec,
execute(InteractionSpec,
Record, RecordExtractor)
Record)
Record
set
void
execute(InteractionSpec,
execute(InteractionSpec,
Record, RecordExtractor)
Record, Record)
Record
not set
Record
execute(InteractionSpec,
execute(InteractionSpec,
RecordCreator,
Record)
RecordExtractor)
Record
set
void
execute(InteractionSpec,
execute(InteractionSpec,
RecordCreator,
Record, Record)
RecordExtractor)
25/08/2016 12:10
1004 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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.
public interface ConnectionCallback {
Object doInConnection(Connection connection, ConnectionFactory connectionFactory)
throws ResourceException, SQLException, DataAccessException;
}
Then the program can use CCI via Springs template and specify mappings between
custom objects and CCI Records .
25/08/2016 12:10
1005 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
1006 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
For the examples above, the corresponding configuration of the involved Spring beans
could look like this in non-managed mode:
In managed mode (that is, in a Java EE environment), the configuration could look as
25/08/2016 12:10
1007 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
follows:
<jee:jndi-lookup id="connectionFactory" jndi-name="eis/cicseci"/>
<bean id="component" class="MyDaoImpl">
<property name="connectionFactory" ref="connectionFactory"/>
</bean>
32.4.1 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:
public abstract class MappingRecordOperation extends EisOperation {
...
protected abstract Record createInputRecord(RecordFactory recordFactory,
25/08/2016 12:10
1008 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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:
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 :
32.4.2 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
25/08/2016 12:10
1009 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
into an input COMMAREA and the output COMMAREA into an output object.
public abstract class MappingCommAreaOperation extends MappingRecordOperation {
...
protected abstract byte[] objectToBytes(Object inObject)
throws IOException, DataAccessException;
protected abstract Object bytesToObject(byte[] bytes)
throws IOException, DataAccessException;
...
}
32.4.4 Summary
The operation object approach uses records in the same manner as the CciTemplate
class.
25/08/2016 12:10
1010 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
MappingRecordOperation
execute method
method signature
outputRecordCreator
property
Interaction
Object execute(Object)
not set
Record
execute(InteractionSpec,
Record)
Object execute(Object)
set
boolean
execute(InteractionSpec,
Record, Record)
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.
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;
25/08/2016 12:10
1011 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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.
public class MyDaoImpl extends CciDaoSupport implements MyDao {
25/08/2016 12:10
1012 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
class="org.springframework.jca.cci.connection.ConnectionSpecConnectionFactoryA
<property name="targetConnectionFactory" ref="targetConnectionFactory"/>
<property name="connectionSpec">
<bean class="com.sun.connector.cciblackbox.CciConnectionSpec">
<property name="user" value="sa"/>
<property name="password" value=""/>
</bean>
</property>
</bean>
<bean id="component" class="MyDaoImpl">
<property name="connectionFactory" ref="connectionFactory"/>
</bean>
In managed mode (that is, in a Java EE environment), the configuration could look as
follows:
<jee:jndi-lookup id="targetConnectionFactory" jndi-name="eis/blackbox"/>
<bean id="connectionFactory"
class="org.springframework.jca.cci.connection.ConnectionSpecConnectionFactoryA
<property name="targetConnectionFactory" ref="targetConnectionFactory"/>
<property name="connectionSpec">
<bean class="com.sun.connector.cciblackbox.CciConnectionSpec">
<property name="user" value="sa"/>
<property name="password" value=""/>
</bean>
</property>
</bean>
<bean id="component" class="MyDaoImpl">
<property name="connectionFactory" ref="connectionFactory"/>
</bean>
25/08/2016 12:10
1013 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
1014 de 1194
<property
<property
<property
<property
</bean>
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
name="serverName" value="TXSERIES"/>
name="connectionURL" value="local:"/>
name="userName" value="CICSUSER"/>
name="password" value="CICS"/>
In managed mode (that is, in a Java EE environment), the configuration could look as
follows:
<jee:jndi-lookup id="connectionFactory" jndi-name="eis/cicseci"/>
<bean id="component" class="MyDaoImpl">
<property name="connectionFactory" ref="connectionFactory"/>
</bean>
32.5 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).
<connector>
<resourceadapter>
<!-- <transaction-support>NoTransaction</transaction-support> -->
<!-- <transaction-support>LocalTransaction</transaction-support> -->
<transaction-support>XATransaction</transaction-support>
<resourceadapter>
<connector>
For global transactions, you can use Springs generic transaction infrastructure to
demarcate transactions, with JtaTransactionManager as backend (delegating to the
Java EE servers distributed transaction coordinator underneath).
For local transactions on a single CCI ConnectionFactory , Spring provides a specific
25/08/2016 12:10
1015 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Both transaction strategies can be used with any of Springs transaction demarcation
facilities, be it declarative or programmatic. This is a consequence of Springs 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 Springs transaction facilities, see the chapter entitled
Chapter 17, Transaction Management.
33. Email
33.1 Introduction
Library dependencies
The following JAR needs to be on the classpath of your application in order to use
the Spring Frameworks email library.
The JavaMail library
This library is freely available on the webfor example, in Maven Central as
com.sun.mail:javax.mail .
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.
25/08/2016 12:10
1016 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
The org.springframework.mail package is the root level package for the Spring
Frameworks 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
33.2 Usage
Lets assume there is a business interface called OrderManager :
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.
25/08/2016 12:10
1017 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
1018 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
javax.mail.Message;
javax.mail.MessagingException;
javax.mail.internet.InternetAddress;
javax.mail.internet.MimeMessage;
import
import
import
import
javax.mail.internet.MimeMessage;
org.springframework.mail.MailException;
org.springframework.mail.javamail.JavaMailSender;
org.springframework.mail.javamail.MimeMessagePreparator;
25/08/2016 12:10
1019 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
}
catch (MailException ex) {
// simply log it and go on...
System.err.println(ex.getMessage());
}
}
}
The mail code is a crosscutting concern and could well be a candidate for
refactoring into a custom Spring AOP aspect, which then could be executed
at appropriate joinpoints on the OrderManager target.
The Spring Frameworks mail support ships with the standard JavaMail implementation.
Please refer to the relevant javadocs for more information.
25/08/2016 12:10
1020 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
The following example shows you how to use the MimeMessageHelper to send an email
along with a single JPEG image attachment.
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("[email protected]");
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);
Inline resources
The following example shows you how to use the MimeMessageHelper to send an email
along with an inline image.
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("[email protected]");
// 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);
Inline resources are added to the mime message using the specified
Content-ID ( identifier1234 in the above example). The order in
25/08/2016 12:10
1021 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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 wont work!
A Velocity-based example
To use 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.
# in the com/foo/package
<html>
<body>
<h3>Hi ${user.userName}, welcome to the Chipping Sodbury On-the-Hill message b
<div>
25/08/2016 12:10
1022 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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).
package com.foo;
import
import
import
import
import
org.apache.velocity.app.VelocityEngine;
org.springframework.mail.javamail.JavaMailSender;
org.springframework.mail.javamail.MimeMessageHelper;
org.springframework.mail.javamail.MimeMessagePreparator;
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);
}
25/08/2016 12:10
1023 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
1024 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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).
25/08/2016 12:10
1025 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
1026 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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.
25/08/2016 12:10
1027 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
with a variety of methods for scheduling tasks to run at some point in the future.
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
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.
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.
25/08/2016 12:10
1028 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
1029 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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 <task:annotation-driven> element.
<task:annotation-driven executor="myExecutor" scheduler="myScheduler"/>
<task:executor id="myExecutor" pool-size="5"/>
<task:scheduler id="myScheduler" pool-size="10"/>
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 .
25/08/2016 12:10
1030 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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.
@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.
@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.
@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.
@Scheduled(cron="*/5 * * * * MON-FRI")
public void doSomething() {
// something that should execute on weekdays only
}
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.
25/08/2016 12:10
1031 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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.
@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.
@Async
25/08/2016 12:10
1032 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Future<String> returnSomething(int i) {
// this will be executed asynchronously
}
There is no direct XML equivalent for @Async since such methods should
be designed for asynchronous execution in the first place, not externally
re-declared to be async. However, you may manually set up Springs
AsyncExecutionInterceptor with Spring AOP, in combination with a
custom pointcut.
25/08/2016 12:10
1033 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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.
@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 <qualifier> element or Springs @Qualifier annotation.
@Override
public void handleUncaughtException(Throwable ex, Method method, Object... params)
// handle exception
}
}
25/08/2016 12:10
1034 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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.
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 executors 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' elements 'pool-size'
attribute also accepts a range in the form of "min-max".
<task:executor
id="executorWithPoolSizeRange"
pool-size="5-25"
queue-capacity="100"/>
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 executors
queue capacity. For the full description of the relationship between pool size and queue
capacity, consult the documentation for 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 queues 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
25/08/2016 12:10
1035 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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, lets 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.
<task:executor
id="executorWithCallerRunsPolicy"
pool-size="5-25"
queue-capacity="100"
rejection-policy="CALLER_RUNS"/>
Finally, the keep-alive setting determines the time limit (in seconds) for which threads
may remain idle before being terminated. If there are more than the core number of
threads currently in the pool, after waiting this amount of time without processing a task,
excess threads will get terminated. A time value of zero will cause excess threads to
terminate immediately after executing a task without remaining follow-up work in the task
queue.
<task:executor
id="executorWithKeepAlive"
pool-size="5-25"
keep-alive="120"/>
25/08/2016 12:10
1036 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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 'fixedrate', 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 'initialdelay' 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.
<task:scheduled-tasks scheduler="myScheduler">
<task:scheduled ref="beanA" method="methodA" fixed-delay="5000" initial-delay
<task:scheduled ref="beanB" method="methodB" fixed-rate="5000"/>
<task:scheduled ref="beanC" method="methodC" cron="*/5 * * * * MON-FRI"/>
</task:scheduled-tasks>
<task:scheduler id="myScheduler" pool-size="10"/>
25/08/2016 12:10
1037 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Quartz JobDetail objects contain all information needed to run a job. Spring provides a
JobDetailFactoryBean which provides bean-style properties for XML configuration
purposes. Lets have a look at an example:
The job detail configuration 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 JobDetail also gets
its properties from the job data mapped to properties of the job instance. So in this case,
if the ExampleJob contains a bean property named timeout , the JobDetail will have
it applied automatically:
package example;
public class ExampleJob extends QuartzJobBean {
private int timeout;
/**
* Setter called after the ExampleJob is instantiated
* with the value from the JobDetailFactoryBean (5)
*/
public void setTimeout(int timeout) {
this.timeout = timeout;
}
All additional properties from the job data map are of course available to you as well.
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
25/08/2016 12:10
1038 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
The above example will result in the doIt method being called on the
exampleBusinessObject method (see below):
public class ExampleBusinessObject {
// properties and collaborators
public void doIt() {
// do the actual work
}
}
<bean id="exampleBusinessObject" class="examples.ExampleBusinessObject"/>
25/08/2016 12:10
1039 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Now weve 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 :
<bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="triggers">
25/08/2016 12:10
1040 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
<list>
<ref bean="cronTrigger"/>
<ref bean="simpleTrigger"/>
</list>
</property>
</bean>
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 SchedulerFactoryBean javadocs for more information.
25/08/2016 12:10
1041 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
detail. Before diving into all of the ins and outs of the dynamic language support, lets 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 wont know that the underlying implementation is a
Groovy script.
package org.springframework.scripting;
public interface Messenger {
String getMessage();
}
Here is the definition of a class that has a dependency on the Messenger interface.
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...
}
}
25/08/2016 12:10
1042 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Finally, here are the bean definitions that will effect the injection of the Groovy-defined
Messenger implementation into an instance of the DefaultBookingService class.
To use the custom dynamic language tags to define dynamic-languagebacked 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 Chapter 41, XML
Schema-based configuration.
<!-- this is the bean definition for the Groovy-backed Messenger implementation -<lang:groovy id="messenger" script-source="classpath:Messenger.groovy">
<lang:property name="message" value="I Can Do The Frug" />
</lang:groovy>
<!-- an otherwise normal bean that will be injected by the Groovy-backed Messenger
<bean id="bookingService" class="x.y.DefaultBookingService">
<property name="messenger" ref="messenger" />
</bean>
</beans>
25/08/2016 12:10
1043 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Hopefully the above XML snippet is self-explanatory, but dont worry unduly if it isnt.
Keep reading for the in-depth detail on the whys and wherefores of the above
configuration.
25/08/2016 12:10
1044 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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 <lang:language/> element to
define the dynamic language-backed bean.
Each of the supported languages has a corresponding <lang:language/> element:
<lang:jruby/> (JRuby)
<lang:groovy/> (Groovy)
<lang:bsh/> (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).
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.
Lets 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
25/08/2016 12:10
1045 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
<!-- this bean is now 'refreshable' due to the presence of the 'refresh-check-dela
<lang:groovy id="messenger"
refresh-check-delay="5000" <!-- switches refreshing on with 5 seconds
script-source="classpath:Messenger.groovy">
<lang:property name="message" value="I Can Do The Frug" />
</lang:groovy>
<bean id="bookingService" class="x.y.DefaultBookingService">
<property name="messenger" ref="messenger" />
</bean>
</beans>
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 dont want the refresh behavior, then simply dont 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.
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();
25/08/2016 12:10
1046 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
System.out.println(messenger.getMessage());
}
}
Lets 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.
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-languagebacked 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 <lang:inline-script/> element notation (see the
section called Inline dynamic language source files). Additionally, it only applies to
beans where changes to the underlying source file can actually be detected; for example,
25/08/2016 12:10
1047 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
by code that checks the last modified date of a dynamic language source file that exists
on the filesystem.
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 <lang:inline-script/>
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
moments work using inline source. (See Section 35.4.2, Scripted Validators 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
<![CDATA[]]> region might be better.)
25/08/2016 12:10
1048 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
1049 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
<lang:groovy id="badMessenger"
script-source="classpath:Messenger.groovy">
<!-- this next constructor argument will not be injected into the GroovyMessenger
<!-- in fact, this isn't even allowed according to the schema -->
<constructor-arg value="This will not work" />
<!-- only property values are injected into the dynamic-language-backed object -->
<lang:property name="anotherMessage" value="Passed straight through to the dynamic
</lang>
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 (lets leave the
discussion as to whether that is a good thing to another day).
25/08/2016 12:10
1050 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
package org.springframework.scripting;
public interface Messenger {
String getMessage();
}
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.
<lang:jruby id="messageService"
script-interfaces="org.springframework.scripting.Messenger"
script-source="classpath:RubyMessenger.rb">
<lang:property name="message" value="Hello World!" />
</lang:jruby>
Take note of the last line of that JRuby source ( 'RubyMessenger.new' ). When using
JRuby in the context of Springs 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:
require 'java'
include_class 'org.springframework.scripting.Messenger'
25/08/2016 12:10
1051 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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 youll 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 dont 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):
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 Section 35.4, Scenarios for some scenarios where you might want to use
JRuby-based beans.
25/08/2016 12:10
1052 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
1053 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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
Section 35.4, Scenarios 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.
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.
public final class SimpleMethodTracingCustomizer implements GroovyObjectCustomizer {
public void customize(GroovyObject goo) {
DelegatingMetaClass metaClass = new DelegatingMetaClass(goo.getMetaClass()) {
25/08/2016 12:10
1054 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
<!-- ... and plug it into the desired Groovy bean via the 'customizer-ref' attribu
<lang:groovy id="calculator"
script-source="classpath:org/springframework/scripting/groovy/Calculator.groov
customizer-ref="tracingCustomizer" />
If you are not using the Spring namespace support, you can still use the
GroovyObjectCustomizer functionality.
25/08/2016 12:10
1055 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Here is the BeanShell 'implementation' (the term is used loosely here) of the Messenger
interface.
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).
<lang:bsh id="messageService" script-source="classpath:BshMessenger.bsh"
script-interfaces="org.springframework.scripting.Messenger">
<lang:property name="message" value="Hello World!" />
</lang:bsh>
See Section 35.4, Scenarios for some scenarios where you might want to use
25/08/2016 12:10
1056 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
35.4 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.
In order to effect this automatic 'pickup' of any changes to dynamiclanguage-backed beans, you will have had to enable the 'refreshable beans'
functionality. See the section called Refreshable beans for a full treatment
of this feature.
org.springframework.showcase.fortune.service.FortuneService
org.springframework.showcase.fortune.domain.Fortune
org.springframework.web.servlet.ModelAndView
org.springframework.web.servlet.mvc.Controller
25/08/2016 12:10
1057 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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())
}
}
<lang:groovy id="fortune"
refresh-check-delay="3000"
script-source="/WEB-INF/groovy/FortuneController.groovy">
<lang:property name="fortuneService" ref="fortuneService"/>
</lang:groovy>
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 the section called Refreshable beans for
a full and detailed treatment of this feature.
25/08/2016 12:10
1058 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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."
}
}
35.5.2 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 <lang:language/> elements
allows you to control the scope of the underlying scripted bean, just as it does with a
25/08/2016 12:10
1059 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Find below an example of using the scope attribute to define a Groovy bean scoped as a
prototype.
See Section 7.5, Bean scopes in Chapter 7, The IoC container for a fuller discussion of
the scoping support in the Spring Framework.
25/08/2016 12:10
1060 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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.
25/08/2016 12:10
1061 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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 a few implementations of that abstraction available out of the box: JDK
java.util.concurrent.ConcurrentMap based caches, EhCache, Gemfire cache,
Caffeine, Guava caches and JSR-107 compliant caches. See Section 36.7, Plugging-in
different back-end caches 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. .
25/08/2016 12:10
1062 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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:
All the other caches that do not contain the value will be updated as well
even though the cached method was not actually executed.
@Cacheable({"books", "isbns"})
public Book findBook(ISBN isbn) {...}
25/08/2016 12:10
1063 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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 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.
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 SpEL 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 default generator since methods tend to be quite
25/08/2016 12:10
1064 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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:
@Cacheable(cacheNames="books", keyGenerator="myKeyGenerator")
public Book findBook(ISBN isbn, boolean checkWarehouse, boolean includeUsed)
25/08/2016 12:10
1065 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
@Cacheable(cacheNames="books", cacheManager="anotherCacheManager")
public Book findBook(ISBN isbn) {...}
It is also possible to replace the CacheResolver entirely in a similar fashion as for key
generation. 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:
@Cacheable(cacheResolver="runtimeCacheResolver")
public Book findBook(ISBN isbn) {...}
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.
Synchronized caching
In a multi-threaded environment, certain operations might be concurrently invoked for the
same argument (typically on startup). By default, the cache abstraction does not lock
anything and the same value may be computed several times, defeating the purpose of
caching.
For those particular cases, the sync attribute can be used to instruct the underlying
cache provider to lock the cache entry while the value is being computed. As a result,
only one thread will be busy computing the value while the others are blocked until the
entry is updated in the cache.
@Cacheable(cacheNames="foos", sync="true")
public Foo executeExpensiveOperation(String id) {...}
This is an optional feature and your favorite cache library may not support it.
All CacheManager implementations provided by the core framework
support it. Check the documentation of your cache provider for more details.
25/08/2016 12:10
1066 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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 condition 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 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:
@Cacheable(cacheNames="book", condition="#name.length < 32")
public Book findBook(String name)
In addition the condition parameter, the unless parameter can be used to veto the
adding of a value to the cache. Unlike condition , unless expressions are evaluated
after the method has been called. Expanding on the previous example - perhaps we only
want to cache paperback books:
Location
Description
The name of the
Example
#root.methodName
root object
#root.method.name
invoked
target
root object
#root.target
invoked
targetClass
root object
#root.targetClass
being invoked
25/08/2016 12:10
1067 de 1194
Name
args
Location
root object
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Description
The arguments (as
Example
#root.args[0]
root object
Collection of caches
#root.caches[0].name
evaluation
name
context
method arguments. If
#p<#arg> notation as an
alias).
available (e.g. no
debug information), the
argument names are
also available under
the #a<#arg> where
#arg stands for the
argument index
(starting from 0).
result
evaluation
context
#result
to be cached). Only
available in unless
expressions,
cache put
expressions (to
compute the key ), or
cache evict
expressions (when
beforeInvocation is
false ).
25/08/2016 12:10
1068 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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:
@CachePut(cacheNames="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.
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
25/08/2016 12:10
1069 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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 dont interact with the
cache) - this is not the case with @Cacheable which adds/updates data into the cache
and thus requires a result.
@CacheConfig is a class-level annotation that allows to share the cache names, the
custom KeyGenerator , the custom CacheManager and finally the custom
25/08/2016 12:10
1070 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:cache="http://www.springframework.org/schema/cache"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/sch
http://www.springframework.org/schema/cache http://www.springframework.org/sch
<cache:annotation-driven />
</beans>
25/08/2016 12:10
1071 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Annotation
Default
Descripti
Attribute
cache-manager
N/A (See
cacheManager
Name of c
CachingConfigurer
manager t
javadocs)
default
CacheRes
be initialize
the scenes
cache man
`cacheMan
set). For m
fine-graine
manageme
cache reso
consider s
'cache-res
attribute.
cache-resolver
N/A (See
A SimpleCacheResolver using
The bean
CacheRes
javadocs)
to be used
the backin
This attribu
required, a
needs to b
as an alter
'cache-ma
attribute.
key-generator
N/A (See
CachingConfigurer
SimpleKeyGenerator
Name of th
key genera
javadocs)
25/08/2016 12:10
1072 de 1194
XML Attribute
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Annotation
Default
Descripti
Attribute
error-handler
N/A (See
SimpleCacheErrorHandler
Name of th
CachingConfigurer
cache erro
javadocs)
use. By de
exception
a cache re
operations
back at the
mode
mode
proxy
The defau
"proxy" pro
annotated
proxied us
AOP frame
(following
semantics
discussed
applying to
calls comin
through th
only). The
mode "asp
instead we
affected cl
Springs A
caching as
modifying
class byte
apply to an
method ca
weaving re
spring-asp
the classp
as load-tim
(or compile
weaving) e
(See
Spring co
25/08/2016 12:10
1073 de 1194
XML Attribute
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Annotation
Default
Descripti
Attribute
for details
set up load
weaving.)
proxy-target-class
proxyTargetClass
false
Applies to
only. Contr
type of cac
proxies are
classes an
the
@CacheEv
annotation
proxy-ta
attribute is
true
class-base
are create
proxy-ta
is false
attribute is
then stand
interface-b
proxies are
(See
Proxying
mechanism
detailed ex
of the diffe
types.)
order
order
Ordered.LOWEST_PRECEDENCE Defines th
the cache
is applied
annotated
@Cacheab
@CacheEv
more infor
about the r
25/08/2016 12:10
1074 de 1194
XML Attribute
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Annotation
Default
Descripti
Attribute
to ordering
advice, se
section ca
ordering
specified o
means tha
subsystem
the order o
advice.
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
25/08/2016 12:10
1075 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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. Also, the proxy must be fully initialized to provide the expected
behaviour so you should not rely on this feature in your initialization code,
i.e. @PostConstruct .
25/08/2016 12:10
1076 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Above, we have defined our own SlowService annotation which itself is annotated with
@Cacheable - now we can replace the following code:
@Cacheable(cacheNames="books", key="#isbn")
public Book findBook(ISBN isbn, boolean checkWarehouse, boolean includeUsed)
with:
@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 above,
the annotation-driven behavior needs to be enabled.
JSR-107
@Cacheable
@CacheResult
Remark
Fairly similar.
@CacheResult can
cache specific
25/08/2016 12:10
1077 de 1194
Spring
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
JSR-107
Remark
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.
25/08/2016 12:10
1078 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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:
@CacheResult(cacheNames="books", cacheResolverFactory=MyCacheResolverFactory.class
public Book findBook(ISBN isbn)
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.
@CacheResult(cacheName="books")
public Book findBook(@CacheKey ISBN isbn, boolean checkWarehouse, boolean includeUsed)
25/08/2016 12:10
1079 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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 Springs
own annotations. Be aware however that if these services are impacting the
same caches, a consistent and identical key generation implementation
should be used.
In the configuration above, the bookService is made cacheable. The caching semantics
25/08/2016 12:10
1080 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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
Chapter 11, Aspect Oriented Programming with Spring). 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).
25/08/2016 12:10
1081 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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.
<bean id="cacheManager"
class="org.springframework.cache.ehcache.EhCacheCacheManager" p:cache-manager-re
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 .
It is also possible to provide the caches to use explicitly. In that case, only those will be
made available by the manager:
25/08/2016 12:10
1082 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
</set>
</property>
</bean>
The Caffeine CacheManager also supports customs Caffeine and CacheLoader . See
the Caffeine documentation for more information about those.
It is also possible to provide the caches to use explicitly. In that case, only those will be
made available by the manager:
<bean id="cacheManager" class="org.springframework.cache.guava.GuavaCacheManager"
<property name="caches">
<set>
<value>default</value>
<value>books</value>
</set>
</property>
</bean>
25/08/2016 12:10
1083 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
JSR-107 compliant caches can also be used by Springs 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 :
<bean id="cacheManager"
class="org.springframework.cache.jcache.JCacheCacheManager"
p:cache-manager-ref="jCacheManager"/>
<!-- JSR-107 cache manager setup
<bean id="jCacheManager" .../>
-->
25/08/2016 12:10
1084 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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
adapters 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.
25/08/2016 12:10
1085 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
39.1.1 Hibernate
For the currently recommended usage patterns for Hibernate see Section 20.3,
Hibernate.
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.
<beans>
<bean id="myProductDao" class="product.ProductDaoImpl">
<property name="sessionFactory" ref="mySessionFactory"/>
</bean>
</beans>
public class ProductDaoImpl implements ProductDao {
private HibernateTemplate hibernateTemplate;
public void setSessionFactory(SessionFactory sessionFactory) {
this.hibernateTemplate = new HibernateTemplate(sessionFactory);
}
25/08/2016 12:10
1086 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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.
public class ProductDaoImpl implements ProductDao {
private HibernateTemplate hibernateTemplate;
public void setSessionFactory(SessionFactory sessionFactory) {
this.hibernateTemplate = new HibernateTemplate(sessionFactory);
}
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:
public class ProductDaoImpl extends HibernateDaoSupport implements ProductDao {
25/08/2016 12:10
1087 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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
25/08/2016 12:10
1088 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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.
39.2.1 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
25/08/2016 12:10
1089 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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.
39.2.3 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 .
25/08/2016 12:10
1090 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
40.1.1 Concepts
Springs pointcut model enables pointcut reuse independent of advice types. Its 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:
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:
public interface ClassFilter {
boolean matches(Class clazz);
}
25/08/2016 12:10
1091 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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.
25/08/2016 12:10
1092 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Static pointcuts
Static pointcuts are based on method and target class, and cannot take into account the
methods arguments. Static pointcuts are sufficient - and best - for most usages. Its
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.
Lets consider some static pointcut implementations included with Spring.
25/08/2016 12:10
1093 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
as the one bean encapsulates both pointcut and advice, as shown below:
<bean id="settersAndAbsquatulateAdvisor"
class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
<property name="advice">
<ref bean="beanNameOfAopAllianceInterceptor"/>
</property>
<property name="patterns">
<list>
<value>.set.</value>
<value>.*absquatulate</value>
</list>
</property>
</bean>
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.
Dynamic pointcuts
Dynamic pointcuts are costlier to evaluate than static pointcuts. They take into account
methodarguments, 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.
25/08/2016 12:10
1094 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
1095 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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 invocations result: the return value of the join point.
A simple MethodInterceptor implementation looks as follows:
public class DebugInterceptor implements MethodInterceptor {
public Object invoke(MethodInvocation invocation) throws Throwable {
System.out.println("Before: invocation=[" + invocation + "]");
25/08/2016 12:10
1096 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Note the call to the MethodInvocations 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 dont want to do this without good reason!
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. (Springs API design would allow
for field before advice, although the usual objects apply to field interception and its
unlikely that Spring will ever implement it).
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
25/08/2016 12:10
1097 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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:
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;
}
}
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:
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):
public class RemoteThrowsAdvice implements ThrowsAdvice {
public void afterThrowing(RemoteException ex) throws Throwable {
// Do something with remote exception
25/08/2016 12:10
1098 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
}
}
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.
public static class CombinedThrowsAdvice implements ThrowsAdvice {
public void afterThrowing(RemoteException ex) throws Throwable {
// Do something with remote exception
}
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 methods signature!
25/08/2016 12:10
1099 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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:
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 doesnt change the execution path. If it throws an exception, this will be
thrown up the interceptor chain instead of the return value.
Introduction advice
Spring treats introduction advice as a special kind of interception advice.
Introduction requires an IntroductionAdvisor , and an IntroductionInterceptor ,
implementing the following interface:
public interface IntroductionInterceptor extends MethodInterceptor {
25/08/2016 12:10
1100 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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:
public interface IntroductionAdvisor extends Advisor, IntroductionInfo {
ClassFilter getClassFilter();
void validateInterfaces() throws IllegalArgumentException;
}
public interface IntroductionInfo {
Class[] getInterfaces();
}
25/08/2016 12:10
1101 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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, well 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. Its 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 dont 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.
25/08/2016 12:10
1102 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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);
}
}
25/08/2016 12:10
1103 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
The Spring 2.0 AOP support also uses factory beans under the covers.
40.4.1 Basics
The ProxyFactoryBean , like other Spring FactoryBean implementations, introduces a
level of indirection. If you define a ProxyFactoryBean with name foo , what objects
25/08/2016 12:10
1104 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
referencing foo see is not the ProxyFactoryBean instance itself, but an object created
by the ProxyFactoryBeans 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.
25/08/2016 12:10
1105 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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 isnt supplied, a CGLIB
proxy for the target class will be used (but see also below Section 12.5.3, JDK- and
CGLIB-based proxies).
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 cant 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 Section 12.5.6, Using 'global'
advisors.
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 .
25/08/2016 12:10
1106 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
If the class of a target object that is to be proxied (hereafter simply referred to as the
target class) doesnt 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 isnt 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.
25/08/2016 12:10
1107 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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.
<bean id="personTarget" class="com.mycompany.PersonImpl">
<property name="name"><value>Tony</value></property>
<property name="age"><value>51</value></property>
</bean>
<bean id="myAdvisor" class="com.mycompany.MyAdvisor">
<property name="someProperty"><value>Custom string property value</value>
</bean>
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.
You might be wondering why the list doesnt hold bean references. The
reason for this is that if the ProxyFactoryBeans 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 its necessary to be able to obtain an instance of the prototype
from the factory; holding a reference isnt sufficient.
The "person" bean definition above can be used in place of a Person implementation, as
follows:
Person person = (Person) factory.getBean("person");
25/08/2016 12:10
1108 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Other beans in the same IoC context can express a strongly typed dependency on it, as
with an ordinary Java object:
<bean id="personUser" class="com.mycompany.PersonUser">
<property name="person"><ref bean="person" /></property>
</bean>
The PersonUser class in this example would expose a property of type Person. As far
as its 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).
Its 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:
<bean id="myAdvisor" class="com.mycompany.MyAdvisor">
<property name="someProperty"><value>Custom string property value</value>
</bean>
This has the advantage that theres 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. Theres 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.
25/08/2016 12:10
1109 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
1110 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
<list>
<value>global*</value>
</list>
</property>
</bean>
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.
<bean id="myService" parent="txProxyTemplate">
<property name="target">
<bean class="org.springframework.samples.MyServiceImpl">
</bean>
</property>
</bean>
It is of course possible to override properties from the parent template, such as in this
case, the transaction propagation settings:
<bean id="mySpecialService" parent="txProxyTemplate">
<property name="target">
<bean class="org.springframework.samples.MySpecialServiceImpl">
25/08/2016 12:10
1111 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
</property>
<property name="transactionAttributes">
<props>
<prop key="get*">PROPAGATION_REQUIRED,readOnly</prop>
<prop key="find*">PROPAGATION_REQUIRED,readOnly</prop>
<prop key="load*">PROPAGATION_REQUIRED,readOnly</prop>
<prop key="store*">PROPAGATION_REQUIRED</prop>
</props>
</property>
</bean>
Note that in the example above, we have explicitly marked the parent bean definition as
abstract by using the abstract attribute, as described previously, 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 theabstract attribute to true,
otherwise the application context will actually try to pre-instantiate it.
25/08/2016 12:10
1112 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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.
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
25/08/2016 12:10
1113 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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, its possible to add or remove advisors or interceptors even once a proxy has
been created. The only restriction is that its 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:
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));
Its questionable whether its 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
25/08/2016 12:10
1114 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
BeanNameAutoProxyCreator
The BeanNameAutoProxyCreator class is a BeanPostProcessor that automatically
creates AOP proxies for beans with names matching literal values or wildcards.
<bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator"
<property name="beanNames"><value>jdk*,onlyJdk</value></property>
<property name="interceptorNames">
<list>
<value>myInterceptor</value>
</list>
</property>
</bean>
25/08/2016 12:10
1115 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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
advisors 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.)
<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreato
25/08/2016 12:10
1116 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
<bean class="org.springframework.transaction.interceptor.TransactionAttributeSourceAdv
<property name="transactionInterceptor" ref="transactionInterceptor"/>
</bean>
<bean id="customAdvisor" class="com.mycompany.MyAdvisor"/>
<bean id="businessObject1" class="com.mycompany.BusinessObject1">
<!-- Properties omitted -->
</bean>
<bean id="businessObject2" class="com.mycompany.BusinessObject2"/>
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 .
25/08/2016 12:10
1117 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreato
<bean class="org.springframework.transaction.interceptor.TransactionAttributeSourceAdv
<property name="transactionInterceptor" ref="transactionInterceptor"/>
</bean>
<bean id="transactionInterceptor"
class="org.springframework.transaction.interceptor.TransactionInterceptor"
<property name="transactionManager" ref="transactionManager"/>
<property name="transactionAttributeSource">
<bean class="org.springframework.transaction.interceptor.AttributesTransaction
<property name="attributes" ref="attributes"/>
</bean>
</property>
</bean>
<bean id="attributes" class="org.springframework.metadata.commons.CommonsAttributes"
25/08/2016 12:10
1118 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreato
<bean class="org.springframework.transaction.interceptor.TransactionAttributeSourceAdv
<property name="transactionInterceptor" ref="transactionInterceptor"/>
</bean>
<bean id="transactionInterceptor"
class="org.springframework.transaction.interceptor.TransactionInterceptor"
<property name="transactionManager" ref="transactionManager"/>
<property name="transactionAttributeSource">
<bean class="org.springframework.transaction.annotation.AnnotationTransactionA
</property>
</bean>
25/08/2016 12:10
1119 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
If the attribute aware pointcut matches any methods in the anyBean or other bean
definitions, the mixin will be applied. Note that both lockMixin and lockableAdvisor
definitions are prototypes. The myAttributeAwarePointcut pointcut can be a singleton
definition, as it doesnt hold state for individual advised objects.
25/08/2016 12:10
1120 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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.
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 doesnt add any advice - and its not necessary to add advice to
use a TargetSource - of course any TargetSource can be used in conjunction with
arbitrary advice.
25/08/2016 12:10
1121 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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 Commons Pool 2.2, which provides a fairly
efficient pooling implementation. Youll need the commons-pool Jar on your applications
classpath to use this feature. Its also possible to subclass
org.springframework.aop.target.AbstractPoolingTargetSource to support any
other pooling API.
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 isnt necessary to specify interceptors to use pooling.
If you want only pooling, and no other advice, dont set the interceptorNames property at
25/08/2016 12:10
1122 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Its 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.
Youll need to define an advisor like this:
Simpler pooling is available using autoproxying. Its possible to set the TargetSources
used by any autoproxy creator.
25/08/2016 12:10
1123 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Theres 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.
25/08/2016 12:10
1124 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
1125 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
element is still present, and if you wanted to, you could continue to write the exact same
style of Spring XML configuration using only <bean/> 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 applicationspecific 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 applications domain; the process
involved in doing so is covered in the appendix entitled Chapter 42, Extensible XML
authoring.
25/08/2016 12:10
1126 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
http://www.springframework.org/schema/beans http://www.springframework.org/sch
<!-- bean definitions here -->
</beans>
The above Spring XML configuration fragment is boilerplate that you can copy and paste
(!) and then plug <bean/> 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 Section 41.2.2, the util schema
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.
25/08/2016 12:10
1127 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
<util:constant/>
Before
There is also a convenience usage form where the static field is specified as the bean
name:
<bean id="java.sql.Connection.TRANSACTION_SERIALIZABLE"
25/08/2016 12:10
1128 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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 doesnt have to be
specified for the bean reference:
25/08/2016 12:10
1129 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
<bean class="example.Client">
<property name="persistenceContextType" value="TRANSACTION" />
</bean>
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.
<util:property-path/>
Before
<!-- target bean to be referenced by name -->
<bean id="testBean" class="org.springframework.beans.TestBean" scope="prototype"
<property name="age" value="10"/>
<property name="spouse">
<bean class="org.springframework.beans.TestBean">
<property name="age" value="11"/>
</bean>
</property>
</bean>
<!-- will result in 10, which is the value of property 'age' of bean 'testBean' -->
<bean id="testBean.age" class="org.springframework.beans.factory.config.PropertyPathFa
The value of the path attribute of the <property-path/> tag follows the form
25/08/2016 12:10
1130 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
There is also a shortcut form, where the bean name is the property path.
<!-- will result in 10, which is the value of property 'age' of bean 'person' -->
<bean id="person.age"
class="org.springframework.beans.factory.config.PropertyPathFactoryBean"
25/08/2016 12:10
1131 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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:
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.
<util:properties/>
Before
<!-- creates a java.util.Properties instance with values loaded from the supplied loca
<bean id="jdbcConfiguration" class="org.springframework.beans.factory.config.Propertie
<property name="location" value="classpath:com/foo/jdbc-production.properties"
</bean>
<!-- creates a java.util.Properties instance with values loaded from the supplied loca
<util:properties id="jdbcConfiguration" location="classpath:com/foo/jdbc-production.pr
<util:list/>
Before
<!-- creates a java.util.List instance with values loaded from the supplied 'sourceLis
<bean id="emails" class="org.springframework.beans.factory.config.ListFactoryBean"
<property name="sourceList">
<list>
<value>[email protected]</value>
<value>[email protected]</value>
<value>[email protected]</value>
25/08/2016 12:10
1132 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
</list>
</property>
</bean>
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 <util:list/> element. For
example, if we really need a java.util.LinkedList to be instantiated, we could use
the following configuration:
<util:list id="emails" list-class="java.util.LinkedList">
<value>[email protected]</value>
<value>[email protected]</value>
<value>[email protected]</value>
<value>d'[email protected]</value>
</util:list>
<util:map/>
Before
<!-- creates a java.util.Map instance with values loaded from the supplied 'sourceMap'
<bean id="emails" class="org.springframework.beans.factory.config.MapFactoryBean"
<property name="sourceMap">
<map>
<entry key="pechorin" value="[email protected]"/>
<entry key="raskolnikov" value="[email protected]"/>
<entry key="stavrogin" value="[email protected]"/>
<entry key="porfiry" value="[email protected]"/>
25/08/2016 12:10
1133 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
</map>
</property>
</bean>
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 <util:map/> element. For
example, if we really need a java.util.TreeMap to be instantiated, we could use the
following configuration:
<util:map id="emails" map-class="java.util.TreeMap">
<entry key="pechorin" value="[email protected]"/>
<entry key="raskolnikov" value="[email protected]"/>
<entry key="stavrogin" value="[email protected]"/>
<entry key="porfiry" value="[email protected]"/>
</util:map>
<util:set/>
Before
<!-- creates a java.util.Set instance with values loaded from the supplied 'sourceSet'
<bean id="emails" class="org.springframework.beans.factory.config.SetFactoryBean"
<property name="sourceSet">
<set>
<value>[email protected]</value>
<value>[email protected]</value>
<value>[email protected]</value>
<value>[email protected]</value>
25/08/2016 12:10
1134 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
</set>
</property>
</bean>
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 <util:set/> element. For
example, if we really need a java.util.TreeSet to be instantiated, we could use the
following configuration:
<util:set id="emails" set-class="java.util.TreeSet">
<value>[email protected]</value>
<value>[email protected]</value>
<value>[email protected]</value>
<value>[email protected]</value>
</util:set>
25/08/2016 12:10
1135 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jee="http://www.springframework.org/schema/jee" xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/sch
http://www.springframework.org/schema/jee http://www.springframework.org/schem
</beans>
<jee:jndi-lookup/> (simple)
Before
<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="jdbc/MyDataSource"/>
</bean>
<bean id="userDao" class="com.foo.JdbcUserDao">
<!-- Spring will do the cast automatically (as usual) -->
<property name="dataSource" ref="dataSource"/>
</bean>
After
<jee:jndi-lookup id="dataSource" jndi-name="jdbc/MyDataSource"/>
<bean id="userDao" class="com.foo.JdbcUserDao">
<!-- Spring will do the cast automatically (as usual) -->
<property name="dataSource" ref="dataSource"/>
</bean>
After
<jee:jndi-lookup id="simple" jndi-name="jdbc/MyDataSource">
<jee:environment>foo=bar</jee:environment>
</jee:jndi-lookup>
25/08/2016 12:10
1136 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
After
<jee:jndi-lookup/> (complex)
Before
<bean id="simple" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="jdbc/MyDataSource"/>
<property name="cache" value="true"/>
<property name="resourceRef" value="true"/>
<property name="lookupOnStartup" value="false"/>
<property name="expectedType" value="com.myapp.DefaultFoo"/>
<property name="proxyInterface" value="com.myapp.Foo"/>
</bean>
After
<jee:jndi-lookup id="simple"
jndi-name="jdbc/MyDataSource"
cache="true"
resource-ref="true"
lookup-on-startup="false"
expected-type="com.myapp.DefaultFoo"
proxy-interface="com.myapp.Foo"/>
25/08/2016 12:10
1137 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
<jee:local-slsb/> (simple)
The <jee:local-slsb/> tag configures a reference to an EJB Stateless SessionBean.
Before
<bean id="simple"
class="org.springframework.ejb.access.LocalStatelessSessionProxyFactoryBean"
<property name="jndiName" value="ejb/RentalServiceBean"/>
<property name="businessInterface" value="com.foo.service.RentalService"
</bean>
After
<jee:local-slsb id="simpleSlsb" jndi-name="ejb/RentalServiceBean"
business-interface="com.foo.service.RentalService"/>
<jee:local-slsb/> (complex)
<bean id="complexLocalEjb"
class="org.springframework.ejb.access.LocalStatelessSessionProxyFactoryBean"
<property name="jndiName" value="ejb/RentalServiceBean"/>
<property name="businessInterface" value="com.foo.service.RentalService"
<property name="cacheHome" value="true"/>
<property name="lookupHomeOnStartup" value="true"/>
<property name="resourceRef" value="true"/>
</bean>
After
<jee:local-slsb id="complexLocalEjb"
jndi-name="ejb/RentalServiceBean"
business-interface="com.foo.service.RentalService"
cache-home="true"
lookup-home-on-startup="true"
resource-ref="true">
<jee:remote-slsb/>
The <jee:remote-slsb/> tag configures a reference to a remote EJB Stateless
SessionBean.
Before
<bean id="complexRemoteEjb"
25/08/2016 12:10
1138 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
class="org.springframework.ejb.access.SimpleRemoteStatelessSessionProxyFactory
<property name="jndiName" value="ejb/MyRemoteBean"/>
<property name="businessInterface" value="com.foo.service.RentalService"
<property name="cacheHome" value="true"/>
<property name="lookupHomeOnStartup" value="true"/>
<property name="resourceRef" value="true"/>
<property name="homeInterface" value="com.foo.service.RentalService"/>
<property name="refreshHomeOnConnectFailure" value="true"/>
</bean>
After
<jee:remote-slsb id="complexRemoteEjb"
jndi-name="ejb/MyRemoteBean"
business-interface="com.foo.service.RentalService"
cache-home="true"
lookup-home-on-startup="true"
resource-ref="true"
home-interface="com.foo.service.RentalService"
refresh-home-on-connect-failure="true">
25/08/2016 12:10
1139 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
25/08/2016 12:10
1140 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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/sch
http://www.springframework.org/schema/tx http://www.springframework.org/schema
http://www.springframework.org/schema/aop http://www.springframework.org/schem
</beans>
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.
25/08/2016 12:10
1141 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
following snippet references the correct schema so that the tags in the context
namespace are available to you.
<property-placeholder/>
This element activates the replacement of ${} placeholders, resolved against the
specified properties file (as a Spring resource location). This element is a convenience
mechanism that sets up a PropertyPlaceholderConfigurer for you; if you need more
control over the PropertyPlaceholderConfigurer , just define one yourself explicitly.
<annotation-config/>
Activates the Spring infrastructure for various annotations to be detected in bean classes:
Springs @Required and @Autowired , as well as JSR 250s @PostConstruct ,
@PreDestroy and @Resource (if available), and JPAs @PersistenceContext and
@PersistenceUnit (if available). Alternatively, you can choose to activate the individual
BeanPostProcessors for those annotations explicitly.
<component-scan/>
This element is detailed in Section 7.9, Annotation-based container configuration.
<load-time-weaver/>
This element is detailed in Section 11.8.4, Load-time weaving with AspectJ in the Spring
Framework.
25/08/2016 12:10
1142 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
<spring-configured/>
This element is detailed in Section 11.8.1, Using AspectJ to dependency inject domain
objects with Spring.
<mbean-export/>
This element is detailed in Section 31.4.3, Configuring annotation based MBean export.
25/08/2016 12:10
1143 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
25/08/2016 12:10
1144 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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.
25/08/2016 12:10
1145 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
pattern="yyyy-MM-dd HH:mm"
lenient="true"/>
(Dont 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.)
(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 <myns:dateformat/> element.
25/08/2016 12:10
1146 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
<myns:dateformat id="dateFormat"
pattern="yyyy-MM-dd HH:mm"
lenient="true"/>
Note that after weve created the infrastructure classes, the above snippet of XML will
essentially be exactly the same as the following XML snippet. In other words, were just
creating a bean in the container, identified by the name 'dateFormat' of type
SimpleDateFormat , with a couple of properties set.
<bean id="dateFormat" class="java.text.SimpleDateFormat">
<constructor-arg value="yyyy-HH-dd HH:mm"/>
<property name="lenient" value="true"/>
</bean>
25/08/2016 12:10
1147 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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
<myns:dateformat/> element results in a single SimpleDateFormat bean definition).
Spring features a number of convenience classes that support this scenario. In this
example, well make use the NamespaceHandlerSupport class:
package org.springframework.samples.xml;
import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
public class MyNamespaceHandler extends NamespaceHandlerSupport {
The observant reader will notice that there isnt 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
42.4 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, well
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:
package org.springframework.samples.xml;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
25/08/2016 12:10
1148 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
import org.springframework.util.StringUtils;
import org.w3c.dom.Element;
import java.text.SimpleDateFormat;
25/08/2016 12:10
1149 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
42.5.1 '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:
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.
42.5.2 '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):
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.
25/08/2016 12:10
1150 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
http://www.mycompany.com/schema/myns http://www.mycompany.com/schema/myns/myns
<!-- as a top-level bean -->
<myns:dateformat id="defaultDateFormat" pattern="yyyy-MM-dd HH:mm" lenient
<bean id="jobDetailTemplate" abstract="true">
<property name="dateFormat">
<!-- as an inner bean -->
<myns:dateformat pattern="HH:mm MM-dd-yyyy"/>
</property>
</bean>
</beans>
The above configuration actually nests custom extensions within each other. The class
that is actually configured by the above <foo:component/> element is the Component
class (shown directly below). Notice how the Component class does not expose a setter
25/08/2016 12:10
1151 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
method for the 'components' property; this makes it hard (or rather impossible) to
configure a bean definition for the Component class using setter injection.
package com.foo;
import java.util.ArrayList;
import java.util.List;
public class Component {
private String name;
private List<Component> components = new ArrayList<Component> ();
// mmm, there is no setter method for the 'components'
public void addComponent(Component component) {
this.components.add(component);
}
public List<Component> 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.
package com.foo;
import org.springframework.beans.factory.FactoryBean;
import java.util.List;
public class ComponentFactoryBean implements FactoryBean<Component> {
private Component parent;
private List<Component> children;
public void setParent(Component parent) {
25/08/2016 12:10
1152 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
this.parent = parent;
}
public void setChildren(List<Component> 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<Component> 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 the steps described previously, well start off by creating
the XSD schema to define the structure of our custom tag.
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<xsd:schema xmlns="http://www.foo.com/schema/component"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.foo.com/schema/component"
elementFormDefault="qualified"
attributeFormDefault="unqualified">
<xsd:element name="component">
<xsd:complexType>
<xsd:choice minOccurs="0" maxOccurs="unbounded">
<xsd:element ref="component"/>
</xsd:choice>
<xsd:attribute name="id" type="xsd:ID"/>
<xsd:attribute name="name" use="required" type="xsd:string"/>
</xsd:complexType>
25/08/2016 12:10
1153 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
</xsd:element>
</xsd:schema>
org.springframework.beans.factory.config.BeanDefinition;
org.springframework.beans.factory.support.AbstractBeanDefinition;
org.springframework.beans.factory.support.BeanDefinitionBuilder;
org.springframework.beans.factory.support.ManagedList;
org.springframework.beans.factory.xml.AbstractBeanDefinitionParser;
org.springframework.beans.factory.xml.ParserContext;
org.springframework.util.xml.DomUtils;
org.w3c.dom.Element;
import java.util.List;
public class ComponentBeanDefinitionParser extends AbstractBeanDefinitionParser {
25/08/2016 12:10
1154 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
}
return factory.getBeanDefinition();
}
Lastly, the various artifacts need to be registered with the Spring XML infrastructure.
# in 'META-INF/spring.handlers'
http\://www.foo.com/schema/component=com.foo.ComponentNamespaceHandler
# in 'META-INF/spring.schemas'
http\://www.foo.com/schema/component/component.xsd=com/foo/component.xsd
25/08/2016 12:10
1155 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Now onto the custom extension. Firstly, the authoring of the XSD schema describing the
custom attribute (quite easy in this case).
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<xsd:schema xmlns="http://www.foo.com/schema/jcache"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.foo.com/schema/jcache"
elementFormDefault="qualified">
<xsd:attribute name="cache-name" type="xsd:string"/>
</xsd:schema>
25/08/2016 12:10
1156 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
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 .
package com.foo;
import
import
import
import
import
import
import
org.springframework.beans.factory.config.BeanDefinitionHolder;
org.springframework.beans.factory.support.AbstractBeanDefinition;
org.springframework.beans.factory.support.BeanDefinitionBuilder;
org.springframework.beans.factory.xml.BeanDefinitionDecorator;
org.springframework.beans.factory.xml.ParserContext;
org.w3c.dom.Attr;
org.w3c.dom.Node;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
25/08/2016 12:10
1157 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Lastly, the various artifacts need to be registered with the Spring XML infrastructure.
# in 'META-INF/spring.handlers'
http\://www.foo.com/schema/jcache=com.foo.JCacheNamespaceHandler
# in 'META-INF/spring.schemas'
http\://www.foo.com/schema/jcache/jcache.xsd=com/foo/jcache.xsd
25/08/2016 12:10
1158 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Required?
Runtime
Description
Expression?
value
false
true
Required?
Runtime
Description
Expression?
25/08/2016 12:10
1159 de 1194
Attribute
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Required?
Runtime
Description
Expression?
tag, as boolean value.
Overrides the default HTML
escaping setting for the
current page.
ignoreNestedPath false
true
path
true
true
Required?
Runtime
Description
Expression?
htmlEscape
false
true
25/08/2016 12:10
1160 de 1194
Attribute
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Required?
Runtime
Description
Expression?
javaScriptEscape false
true
Required?
Runtime
Description
Expression?
expression
true
true
htmlEscape
false
true
javaScriptEscape false
true
scope
false
true
var
false
true
25/08/2016 12:10
1161 de 1194
Attribute
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Required?
Runtime
Description
Expression?
to. If not specified the
evaluation result is
converted to a String and
written as output.
Required?
Runtime
Description
Expression?
htmlEscape false
true
name
true
true
25/08/2016 12:10
1162 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Required?
Runtime
Description
Expression?
defaultHtmlEscape true
true
Required?
Runtime
Description
Expression?
arguments
false
true
argumentSeparator false
true
code
false
true
25/08/2016 12:10
1163 de 1194
Attribute
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Required?
Runtime
Description
Expression?
provided, the text attribute
will be used.
htmlEscape
false
true
javaScriptEscape
false
true
message
false
true
A
MessageSourceResolvable
argument (direct or through
JSP EL). Fits nicely when
used in conjunction with
Springs 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
25/08/2016 12:10
1164 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Attribute
Required?
Runtime
Description
Expression?
text
false
true
var
false
true
Required?
Runtime
Description
Expression?
path
true
true
25/08/2016 12:10
1165 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Required?
Runtime
Description
Expression?
name
true
true
value
false
true
Required?
Runtime
Description
Expression?
arguments
false
true
argumentSeparator false
true
25/08/2016 12:10
1166 de 1194
Attribute
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Required?
Runtime
Description
Expression?
code
false
true
htmlEscape
false
true
javaScriptEscape
false
true
message
false
true
A
MessageSourceResolvable
argument (direct or through
JSP EL).
scope
false
true
text
false
true
var
false
true
25/08/2016 12:10
1167 de 1194
Attribute
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Required?
Runtime
Description
Expression?
outputted to the writer (i.e.
typically directly to the
JSP).
Required?
Runtime
Description
Expression?
htmlEscape false
true
scope
false
true
value
true
true
25/08/2016 12:10
1168 de 1194
Attribute
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Required?
Runtime
Description
Expression?
var
false
true
Required?
Runtime
Description
Expression?
value
true
true
context
false
true
Specifies a remote
application context path.
The default is the current
application context path.
var
false
true
25/08/2016 12:10
1169 de 1194
Attribute
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Required?
Runtime
Description
Expression?
not specified the URL is
written as output.
scope
false
true
htmlEscape
false
true
javaScriptEscape false
true
25/08/2016 12:10
1170 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Required?
Runtime
Description
Expression?
disabled
false
true
id
false
true
name
false
true
value
false
true
25/08/2016 12:10
1171 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Required?
Runtime
Description
Expression?
accesskey
false
true
cssClass
false
true
cssErrorClass
false
true
cssStyle
false
true
dir
false
true
disabled
false
true
htmlEscape
false
true
Enable/disable HTML
escaping of rendered values.
id
false
true
label
false
true
lang
false
true
onblur
false
true
onchange
false
true
onclick
false
true
ondblclick
false
true
onfocus
false
true
onkeydown
false
true
25/08/2016 12:10
1172 de 1194
Attribute
Required?
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Runtime
Description
Expression?
onkeypress
false
true
onkeyup
false
true
onmousedown false
true
onmousemove false
true
onmouseout
false
true
onmouseover
false
true
onmouseup
false
true
path
true
true
tabindex
false
true
title
false
true
value
false
true
Required?
Runtime
Description
Expression?
accesskey
false
true
cssClass
false
true
cssErrorClass
false
true
25/08/2016 12:10
1173 de 1194
Attribute
Required?
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Runtime
Description
Expression?
cssStyle
false
true
delimiter
false
true
dir
false
true
disabled
false
true
element
false
true
htmlEscape
false
true
Enable/disable HTML
escaping of rendered values.
id
false
true
itemLabel
false
true
items
true
true
itemValue
false
true
lang
false
true
onblur
false
true
onchange
false
true
25/08/2016 12:10
1174 de 1194
Attribute
Required?
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Runtime
Description
Expression?
onclick
false
true
ondblclick
false
true
onfocus
false
true
onkeydown
false
true
onkeypress
false
true
onkeyup
false
true
onmousedown false
true
onmousemove false
true
onmouseout
false
true
onmouseover
false
true
onmouseup
false
true
path
true
true
tabindex
false
true
title
false
true
Required?
Runtime
Description
Expression?
cssClass
false
true
25/08/2016 12:10
1175 de 1194
Attribute
Required?
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Runtime
Description
Expression?
cssStyle
false
true
delimiter
false
true
dir
false
true
element
false
true
htmlEscape
false
true
Enable/disable HTML
escaping of rendered values.
id
false
true
lang
false
true
onclick
false
true
ondblclick
false
true
onkeydown
false
true
onkeypress
false
true
onkeyup
false
true
onmousedown false
true
onmousemove false
true
onmouseout
false
true
onmouseover
false
true
onmouseup
false
true
path
false
true
tabindex
false
true
title
false
true
25/08/2016 12:10
1176 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Required?
Runtime
Description
Expression?
acceptCharset
false
true
action
false
true
cssClass
false
true
cssStyle
false
true
dir
false
true
enctype
false
true
htmlEscape
false
true
Enable/disable HTML
escaping of rendered
values.
id
false
true
25/08/2016 12:10
1177 de 1194
Attribute
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Required?
Runtime
Description
Expression?
lang
false
true
method
false
true
methodParam
false
true
modelAttribute
false
true
name
false
true
onclick
false
true
ondblclick
false
true
onkeydown
false
true
onkeypress
false
true
onkeyup
false
true
onmousedown
false
true
onmousemove
false
true
onmouseout
false
true
onmouseover
false
true
onmouseup
false
true
onreset
false
true
onsubmit
false
true
servletRelativeAction false
true
Action reference to be
appended to the current
25/08/2016 12:10
1178 de 1194
Attribute
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Required?
Runtime
Description
Expression?
target
false
true
title
false
true
Required?
Runtime
Description
Expression?
htmlEscape false
true
Enable/disable HTML
escaping of rendered values.
id
false
true
path
true
true
Required?
Runtime
Description
Expression?
accesskey
false
true
alt
false
true
25/08/2016 12:10
1179 de 1194
Attribute
Required?
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Runtime
Description
Expression?
autocomplete
false
true
cssClass
false
true
cssErrorClass
false
true
cssStyle
false
true
dir
false
true
disabled
false
true
htmlEscape
false
true
Enable/disable HTML
escaping of rendered values.
id
false
true
lang
false
true
maxlength
false
true
onblur
false
true
onchange
false
true
onclick
false
true
ondblclick
false
true
onfocus
false
true
onkeydown
false
true
onkeypress
false
true
onkeyup
false
true
onmousedown false
true
onmousemove false
true
25/08/2016 12:10
1180 de 1194
Attribute
Required?
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Runtime
Description
Expression?
onmouseout
false
true
onmouseover
false
true
onmouseup
false
true
onselect
false
true
path
true
true
readonly
false
true
size
false
true
tabindex
false
true
title
false
true
Required?
Runtime
Description
Expression?
cssClass
false
true
cssErrorClass
false
true
cssStyle
false
true
25/08/2016 12:10
1181 de 1194
Attribute
Required?
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Runtime
Description
Expression?
Optional Attribute
dir
false
true
for
false
true
htmlEscape
false
true
Enable/disable HTML
escaping of rendered values.
id
false
true
lang
false
true
onclick
false
true
ondblclick
false
true
onkeydown
false
true
onkeypress
false
true
onkeyup
false
true
onmousedown false
true
onmousemove false
true
onmouseout
false
true
onmouseover
false
true
onmouseup
false
true
path
true
true
tabindex
false
true
title
false
true
25/08/2016 12:10
1182 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Required?
Runtime
Description
Expression?
cssClass
false
true
cssErrorClass
false
true
cssStyle
false
true
dir
false
true
disabled
false
true
htmlEscape
false
true
Enable/disable HTML
escaping of rendered values.
id
false
true
label
false
true
lang
false
true
onclick
false
true
ondblclick
false
true
onkeydown
false
true
onkeypress
false
true
onkeyup
false
true
onmousedown false
true
onmousemove false
true
onmouseout
false
true
onmouseover
false
true
25/08/2016 12:10
1183 de 1194
Attribute
Required?
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Runtime
Description
Expression?
tabindex
false
true
title
false
true
value
true
true
Required?
Runtime
Description
Expression?
cssClass
false
true
cssErrorClass
false
true
cssStyle
false
true
dir
false
true
disabled
false
true
htmlEscape
false
true
Enable/disable HTML
escaping of rendered values.
id
false
true
25/08/2016 12:10
1184 de 1194
Attribute
Required?
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Runtime
Description
Expression?
itemLabel
false
true
items
true
true
itemValue
false
true
lang
false
true
onclick
false
true
ondblclick
false
true
onkeydown
false
true
onkeypress
false
true
onkeyup
false
true
onmousedown false
true
onmousemove false
true
onmouseout
false
true
onmouseover
false
true
onmouseup
false
true
tabindex
false
true
title
false
true
25/08/2016 12:10
1185 de 1194
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Required?
Runtime
Description
Expression?
accesskey
false
true
alt
false
true
autocomplete
false
true
cssClass
false
true
cssErrorClass
false
true
cssStyle
false
true
dir
false
true
disabled
false
true
htmlEscape
false
true
Enable/disable HTML
escaping of rendered values.
id
false
true
lang
false
true
maxlength
false
true
onblur
false
true
onchange
false
true
onclick
false
true
ondblclick
false
true
onfocus
false
true
25/08/2016 12:10
1186 de 1194
Attribute
Required?
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Runtime
Description
Expression?
onkeydown
false
true
onkeypress
false
true
onkeyup
false
true
onmousedown
false
true
onmousemove
false
true
onmouseout
false
true
onmouseover
false
true
onmouseup
false
true
onselect
false
true
path
true
true
readonly
false
true
showPassword false
true
size
false
true
tabindex
false
true
title
false
true
25/08/2016 12:10
1187 de 1194
Attribute
Required?
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Runtime
Description
Expression?
accesskey
false
true
cssClass
false
true
cssErrorClass
false
true
cssStyle
false
true
dir
false
true
disabled
false
true
htmlEscape
false
true
Enable/disable HTML
escaping of rendered values.
id
false
true
label
false
true
lang
false
true
onblur
false
true
onchange
false
true
onclick
false
true
ondblclick
false
true
onfocus
false
true
onkeydown
false
true
onkeypress
false
true
onkeyup
false
true
onmousedown false
true
25/08/2016 12:10
1188 de 1194
Attribute
Required?
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Runtime
Description
Expression?
onmousemove false
true
onmouseout
false
true
onmouseover
false
true
onmouseup
false
true
path
true
true
tabindex
false
true
title
false
true
value
false
true
Required?
Runtime
Description
Expression?
accesskey
false
true
cssClass
false
true
cssErrorClass
false
true
cssStyle
false
true
delimiter
false
true
25/08/2016 12:10
1189 de 1194
Attribute
Required?
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Runtime
Description
Expression?
'radio'. There is no delimiter
by default.
dir
false
true
disabled
false
true
element
false
true
htmlEscape
false
true
Enable/disable HTML
escaping of rendered values.
id
false
true
itemLabel
false
true
items
true
true
itemValue
false
true
lang
false
true
onblur
false
true
onchange
false
true
onclick
false
true
ondblclick
false
true
onfocus
false
true
25/08/2016 12:10
1190 de 1194
Attribute
Required?
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Runtime
Description
Expression?
onkeydown
false
true
onkeypress
false
true
onkeyup
false
true
onmousedown false
true
onmousemove false
true
onmouseout
false
true
onmouseover
false
true
onmouseup
false
true
path
true
true
tabindex
false
true
title
false
true
Required?
Runtime
Description
Expression?
accesskey
false
true
cssClass
false
true
cssErrorClass
false
true
25/08/2016 12:10
1191 de 1194
Attribute
Required?
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Runtime
Description
Expression?
cssStyle
false
true
dir
false
true
disabled
false
true
htmlEscape
false
true
Enable/disable HTML
escaping of rendered values.
id
false
true
itemLabel
false
true
items
false
true
itemValue
false
true
lang
false
true
multiple
false
true
onblur
false
true
onchange
false
true
onclick
false
true
ondblclick
false
true
onfocus
false
true
onkeydown
false
true
onkeypress
false
true
25/08/2016 12:10
1192 de 1194
Attribute
Required?
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Runtime
Description
Expression?
onmousedown false
true
onmousemove false
true
onmouseout
false
true
onmouseover
false
true
onmouseup
false
true
path
true
true
size
false
true
tabindex
false
true
title
false
true
Required?
Runtime
Description
Expression?
accesskey
false
true
cols
false
true
cssClass
false
true
cssErrorClass
false
true
cssStyle
false
true
25/08/2016 12:10
1193 de 1194
Attribute
Required?
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Runtime
Description
Expression?
Optional Attribute
dir
false
true
disabled
false
true
htmlEscape
false
true
Enable/disable HTML
escaping of rendered values.
id
false
true
lang
false
true
onblur
false
true
onchange
false
true
onclick
false
true
ondblclick
false
true
onfocus
false
true
onkeydown
false
true
onkeypress
false
true
onkeyup
false
true
onmousedown false
true
onmousemove false
true
onmouseout
false
true
onmouseover
false
true
onmouseup
false
true
onselect
false
true
path
true
true
25/08/2016 12:10
1194 de 1194
Attribute
Required?
http://docs.spring.io/spring/docs/current/spring-framework-reference/h...
Runtime
Description
Expression?
readonly
false
true
rows
false
true
tabindex
false
true
title
false
true
25/08/2016 12:10