@ -19,8 +19,8 @@ a number of Java EE (and related) technologies.
@@ -19,8 +19,8 @@ a number of Java EE (and related) technologies.
== Remoting and Web Services with Spring
Spring features integration classes for remoting support with various technologies.
The remoting support eases the development of remote-enabled services, implemented by
your usual POJOs. Currently, Spring supports the following remoting technologies:
The remoting support eases the development of remote-enabled services, implemented
by your usual POJOs. Currently, Spring supports the following remoting technologies:
* *Remote Method Invocation (RMI)*: Through the use of `RmiProxyFactoryBean` and
`RmiServiceExporter`, Spring supports both traditional RMI (with `java.rmi.Remote`
@ -34,10 +34,11 @@ your usual POJOs. Currently, Spring supports the following remoting technologies
@@ -34,10 +34,11 @@ your usual POJOs. Currently, Spring supports the following remoting technologies
`HessianServiceExporter`, you can transparently expose your services through the
lightweight binary HTTP-based protocol provided by Caucho.
* *JAX-WS*: Spring provides remoting support for web services through JAX-WS.
* *JMS*: Remoting by using JMS as the underlying protocol is supported through the
`JmsInvokerServiceExporter` and `JmsInvokerProxyFactoryBean` classes.
* *AMQP*: Remoting by using AMQP as the underlying protocol is supported by the Spring
AMQP project.
* *JMS*: Remoting via JMS as the underlying protocol is supported through the
`JmsInvokerServiceExporter` and `JmsInvokerProxyFactoryBean` classes in the
`spring-jms` module.
* *AMQP*: Remoting via AMQP as the underlying protocol is supported by the
separate Spring AMQP project.
While discussing the remoting capabilities of Spring, we use the following domain
model and corresponding services:
@ -88,9 +89,9 @@ model and corresponding services:
@@ -88,9 +89,9 @@ model and corresponding services:
----
====
This section starts by exposing the service to a remote client by using RMI and talk a bit about
the drawbacks of using RMI. It then continues with an example that uses Hessian as the
protocol.
This section starts by exposing the service to a remote client by using RMI and talk a bit
about the drawbacks of using RMI. It then continues with an example that uses Hessian as
the protocol.
@ -147,8 +148,8 @@ The following example shows how to do so:
@@ -147,8 +148,8 @@ The following example shows how to do so:
In the preceding example, we override 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. So, in the preceding example, the
service is bound at `'rmi://HOST:1199/AccountService'`. We use this URL later on
to link in the service at the client side.
service is bound at `'rmi://HOST:1199/AccountService'`. We use this URL later on to link in
the service at the client side.
NOTE: The `servicePort` property has been omitted (it defaults to 0). This means that an
anonymous port is used to communicate with the service.
@ -6541,7 +6542,7 @@ number of milliseconds to wait before the first execution of the method, as the
@@ -6541,7 +6542,7 @@ number of milliseconds to wait before the first execution of the method, as the
----
====
If simple periodic scheduling is not expressive enough, you ca provide a cron expression.
If simple periodic scheduling is not expressive enough, you can provide a cron expression.
For example, the following executes only on weekdays:
====
@ -7136,9 +7137,9 @@ support of <<cache-jsr-107,JSR-107 annotations>> and more customization options.
@@ -7136,9 +7137,9 @@ support of <<cache-jsr-107,JSR-107 annotations>> and more customization options.
The terms, "`buffer`" and "`cache,`" tend to be used interchangeably. Note, however,
that they represent different things. Traditionally, a buffer is used as an intermediate
temporary store for data between a fast and a slow entity. As one party would has to wait
temporary store for data between a fast and a slow entity. As one party would have to wait
for the other (which affects performance), the buffer alleviates this by allowing entire
blocks of data to move at once rather then in small chunks. The data is written and read
blocks of data to move at once rather than in small chunks. The data is written and read
only once from the buffer. Furthermore, the buffers are visible to at least one party
that is aware of it.
@ -7150,16 +7151,17 @@ You can find a further explanation of the differences between a buffer and a cac
@@ -7150,16 +7151,17 @@ You can find a further explanation of the differences between a buffer and a cac
At its core, the cache abstraction applies caching to Java methods, thus reducing the number
of executions based on the information available in the cache. That is, each time a
targeted method is invoked, the abstraction applies a caching behavior that checks
whether the method has been already executed for the given arguments. If it has been executed,
the cached result is returned without having to execute the actual method. If the method has
not been executed, then it is executed, and the result is cached and returned to the user so that, the
next time the method is invoked, the cached result is returned. This way, expensive
methods (whether CPU- or IO-bound) can be executed only once for a given set of
parameters and the result reused without having to actually execute the method again.
The caching logic is applied transparently without any interference to the invoker.
At its core, the cache abstraction applies caching to Java methods, thus reducing the
number of executions based on the information available in the cache. That is, each time
a targeted method is invoked, the abstraction applies a caching behavior that checks
whether the method has been already executed for the given arguments. If it has been
executed, the cached result is returned without having to execute the actual method.
If the method has not been executed, then it is executed, and the result is cached and
returned to the user so that, the next time the method is invoked, the cached result is
returned. This way, expensive methods (whether CPU- or IO-bound) can be executed only
once for a given set of parameters and the result reused without having to actually
execute the method again. The caching logic is applied transparently without any
interference to the invoker.
IMPORTANT: 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 executed.
@ -7168,12 +7170,11 @@ The caching abstraction provides other cache-related operations, such as the abi
@@ -7168,12 +7170,11 @@ The caching abstraction provides other cache-related operations, such as the abi
to update the content of the cache or to remove one or all entries. These are useful if
the cache deals with data that can change during the course of the application.
As with other services in the Spring Framework, the caching service is an
abstraction (not a cache implementation) and requires the use of actual storage to
store the cache data -- that is, the abstraction frees you from having to write
the caching logic but does not provide the actual data store. This abstraction is
materialized by the `org.springframework.cache.Cache` and
As with other services in the Spring Framework, the caching service is an abstraction
(not a cache implementation) and requires the use of actual storage to store the cache data --
that is, the abstraction frees you from having to write the caching logic but does not
provide the actual data store. This abstraction is materialized by the
`org.springframework.cache.Cache` and `org.springframework.cache.CacheManager` interfaces.
Spring provides <<cache-store-configuration, a few implementations>> of that abstraction:
JDK `java.util.concurrent.ConcurrentMap` based caches, https://www.ehcache.org/[Ehcache 2.x],
@ -7218,11 +7219,12 @@ For caching declaration, Spring's caching abstraction provides a set of Java ann
@@ -7218,11 +7219,12 @@ For caching declaration, Spring's caching abstraction provides a set of Java ann
[[cache-annotations-cacheable]]
==== The `@Cacheable` Annotation
As the name implies, you can use `@Cacheable` to demarcate methods that are cacheable -- that
is, methods for which the result is stored in the cache so that, on subsequent invocations
(with the same arguments), the value in the cache is returned without having to actually
execute the method. In its simplest form, the annotation declaration requires the name
of the cache associated with the annotated method, as the following example shows:
As the name implies, you can use `@Cacheable` to demarcate methods that are cacheable --
that is, methods for which the result is stored in the cache so that, on subsequent
invocations (with the same arguments), the value in the cache is returned without
having to actually execute the method. In its simplest form, the annotation declaration
requires the name of the cache associated with the annotated method, as the following
example shows:
====
[source,java,indent=0]
@ -7236,10 +7238,9 @@ of the cache associated with the annotated method, as the following example show
@@ -7236,10 +7238,9 @@ of the cache associated with the annotated method, as the following example show
In the preceding snippet, the `findBook` method is associated with the cache named `books`.
Each time the method is called, the cache is checked to see whether the invocation has
already been executed and does not have to be repeated. While in most cases, only one
cache is declared, the annotation lets multiple names be specified so that more
than one cache is being used. In this case, each of the caches is checked before
executing the method -- if at least one cache is hit, the associated value is
returned.
cache is declared, the annotation lets multiple names be specified so that more than one
cache is being used. In this case, each of the caches is checked before executing the
method -- if at least one cache is hit, the associated value is returned.
NOTE: All the other caches that do not contain the value are also updated, even though
the cached method was not actually executed.
@ -7258,17 +7259,17 @@ The following example uses `@Cacheable` on the `findBook` method:
@@ -7258,17 +7259,17 @@ The following example uses `@Cacheable` on the `findBook` method:
[[cache-annotations-cacheable-default-key]]
===== Default Key Generation
Since caches are essentially key-value stores, each invocation of a cached method needs
to be translated into a suitable key for cache access. The caching
abstraction uses a simple `KeyGenerator` based on the following algorithm:
Since caches are essentially key-value stores, each invocation of a cached method
needs to be translated into a suitable key for cache access. The caching abstraction
uses a simple `KeyGenerator` based on the following algorithm:
* If no params are given, return `SimpleKey.EMPTY`.
* If only one param is given, return that instance.
* If more the one param is given, return a `SimpleKey` that contains all parameters.
This approach works well for most use-cases, as long as parameters have natural keys
and implement valid `hashCode()` and `equals()` methods. If that is not the case, you need to change the
strategy.
and implement valid `hashCode()` and `equals()` methods. If that is not the case,
you need to change the strategy.
To provide a different default key generator, you need to implement the
@ -7338,8 +7339,9 @@ The preceding snippets show how easy it is to select a certain argument, one of
@@ -7338,8 +7339,9 @@ The preceding snippets show how easy it is to select a certain argument, one of
properties, or even an arbitrary (static) method.
If the algorithm responsible for generating the key is too specific or if it needs
to be shared, you can define a custom `keyGenerator` on the operation. To do
so, specify the name of the `KeyGenerator` bean implementation to use, as the following example shows:
to be shared, you can define a custom `keyGenerator` on the operation. To do so,
specify the name of the `KeyGenerator` bean implementation to use, as the following
example shows:
====
[source,java,indent=0]
@ -7369,8 +7371,8 @@ To provide a different default cache resolver, you need to implement the
@@ -7369,8 +7371,8 @@ To provide a different default cache resolver, you need to implement the
The default cache resolution fits well for applications that work with a
single `CacheManager` and have no complex cache resolution requirements.
For applications that work with several cache managers, you can
set the `cacheManager` to use for each operation, as the following example shows:
For applications that work with several cache managers, you can set the
`cacheManager` to use for each operation, as the following example shows:
====
[source,java,indent=0]
@ -7420,8 +7422,8 @@ of caching.
@@ -7420,8 +7422,8 @@ of caching.
For those particular cases, you can use the `sync` attribute to instruct the underlying
cache provider to lock the cache entry while the value is being computed. As a result,
only one thread is busy computing the value, while the others are blocked until the
entry is updated in the cache. The following example shows how to use the `sync` attribute:
only one thread is busy computing the value, while the others are blocked until the entry
is updated in the cache. The following example shows how to use the `sync` attribute:
====
[source,java,indent=0]
@ -7433,8 +7435,8 @@ entry is updated in the cache. The following example shows how to use the `sync`
@@ -7433,8 +7435,8 @@ entry is updated in the cache. The following example shows how to use the `sync`
<1> Using the `sync` attribute.
====
NOTE: This is an optional feature, and your favorite cache library may not support it. All
`CacheManager` implementations provided by the core framework support it. See the
NOTE: This is an optional feature, and your favorite cache library may not support it.
All `CacheManager` implementations provided by the core framework support it. See the
documentation of your cache provider for more details.
[[cache-annotations-cacheable-condition]]
@ -7552,11 +7554,11 @@ available to the context so that you can use them for key and conditional comput
@@ -7552,11 +7554,11 @@ available to the context so that you can use them for key and conditional comput
[[cache-annotations-put]]
==== The `@CachePut` Annotation
When the cache needs to be updated without interfering with the method
execution, you can use the `@CachePut` annotation. That is, the method is always
executed and its result is 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. The following example uses the `@CachePut` annotation:
When the cache needs to be updated without interfering with the method execution,
you can use the `@CachePut` annotation. That is, the method is always executed and its
result is 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. The following example uses the `@CachePut` annotation:
[source,java,indent=0]
[subs="verbatim,quotes"]
@ -7568,11 +7570,11 @@ than method flow optimization. The following example uses the `@CachePut` annota
@@ -7568,11 +7570,11 @@ than method flow optimization. The following example uses the `@CachePut` annota
IMPORTANT: 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
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 declarations should be avoided. Note also that such conditions should not rely
on the result object (that is, the `#result` variable), as these are validated up-front to confirm
the exclusion.
on the result object (that is, the `#result` variable), as these are validated up-front to
confirm the exclusion.
[[cache-annotations-evict]]
@ -7586,7 +7588,7 @@ Similarly to its sibling, `@CacheEvict` requires specifying one or more caches
@@ -7586,7 +7588,7 @@ Similarly to its sibling, `@CacheEvict` requires specifying one or more caches
that are affected by the action, allows a custom cache and key resolution or a
condition to be specified, and features an extra parameter
(`allEntries`) that indicates whether a cache-wide eviction needs to be performed
rather then just an entry eviction (based on the key). The following example evicts
rather than just an entry eviction (based on the key). The following example evicts
all entries from the `books` cache:
====
@ -7599,11 +7601,11 @@ all entries from the `books` cache:
@@ -7599,11 +7601,11 @@ all entries from the `books` cache:
<1> Using the `allEntries` attribute to evict all entries from the cache.
====
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 the preceding example shows. Note that the framework ignores
any key specified in this scenario as it does not apply (the entire cache is evicted, not
only one entry).
This option comes in handy when an entire cache region needs to be cleared out.
Rather than evicting each entry (which would take a long time, since it is inefficient),
all the entries are removed in one operation, as the preceding example shows.
Note that the framework ignores any key specified in this scenario as it does not apply
(the entire cache is evicted, not only one entry).
You can also indicate whether the eviction should occur after (the default) or before
the method executes by using the `beforeInvocation` attribute. The former provides the
@ -7614,10 +7616,9 @@ The latter (`beforeInvocation=true`) causes the eviction to always occur before
@@ -7614,10 +7616,9 @@ The latter (`beforeInvocation=true`) causes the eviction to always occur before
method is invoked. This is useful in cases where the eviction does not need to be tied
to the method outcome.
Note that `void` methods can be used with `@CacheEvict` - as the
methods act as a trigger, the return values are ignored (as they do nt interact with the
cache). This is not the case with `@Cacheable` which adds or updates data into the cache
and, thus, requires a result.
Note that `void` methods can be used with `@CacheEvict` - as the methods act as a trigger,
the return values are ignored (as they do not interact with the cache). This is not the case
with `@Cacheable` which adds or updates data into the cache and, thus, requires a result.
[[cache-annotations-caching]]
@ -8124,9 +8125,9 @@ or eviction contracts.
@@ -8124,9 +8125,9 @@ or eviction contracts.
NOTE: Ehcache 3.x is fully JSR-107 compliant and no dedicated support is required for it.
The Ehcache 2.x implementation is located in the `org.springframework.cache.ehcache` package.
Again, to use it, you need to declare the appropriate `CacheManager`. The following
example shows how to do so:
The Ehcache 2.x implementation is located in the `org.springframework.cache.ehcache`
package. Again, to use it, you need to declare the appropriate `CacheManager`.
The following example shows how to do so:
====
[source,xml,indent=0]
@ -8226,7 +8227,7 @@ The following example shows how to do so:
@@ -8226,7 +8227,7 @@ The following example shows how to do so:
Sometimes, when switching environments or doing testing, you might have cache
declarations without having an actual backing cache configured. As this is an invalid
configuration, an exception is thrown at runtime, since the caching infrastructure
is unable to find a suitable store. In situations like this, rather then removing the
is unable to find a suitable store. In situations like this, rather than removing the
cache declarations (which can prove tedious), you can wire in a simple dummy cache that
performs no caching -- that is, it forces the cached methods to be executed every time.