Browse Source

Backported clarifications for SchedulerFactoryBean and cache annotations

See gh-27709
See gh-27726
pull/28694/head
Juergen Hoeller 3 years ago
parent
commit
ec13a3f1ba
  1. 4
      spring-context-support/src/main/java/org/springframework/scheduling/quartz/LocalDataSourceJobStore.java
  2. 3
      spring-context-support/src/main/java/org/springframework/scheduling/quartz/SchedulerFactoryBean.java
  3. 95
      src/docs/asciidoc/integration.adoc

4
spring-context-support/src/main/java/org/springframework/scheduling/quartz/LocalDataSourceJobStore.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2020 the original author or authors.
* Copyright 2002-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -58,6 +58,8 @@ import org.springframework.lang.Nullable; @@ -58,6 +58,8 @@ import org.springframework.lang.Nullable;
* @since 1.1
* @see SchedulerFactoryBean#setDataSource
* @see SchedulerFactoryBean#setNonTransactionalDataSource
* @see SchedulerFactoryBean#getConfigTimeDataSource()
* @see SchedulerFactoryBean#getConfigTimeNonTransactionalDataSource()
* @see org.springframework.jdbc.datasource.DataSourceUtils#doGetConnection
* @see org.springframework.jdbc.datasource.DataSourceUtils#releaseConnection
*/

3
spring-context-support/src/main/java/org/springframework/scheduling/quartz/SchedulerFactoryBean.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2018 the original author or authors.
* Copyright 2002-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -313,6 +313,7 @@ public class SchedulerFactoryBean extends SchedulerAccessor implements FactoryBe @@ -313,6 +313,7 @@ public class SchedulerFactoryBean extends SchedulerAccessor implements FactoryBe
* If set, this will override corresponding settings in Quartz properties.
* <p>Note: If this is set, the Quartz settings should not define
* a job store "dataSource" to avoid meaningless double configuration.
* Also, do not define a "org.quartz.jobStore.class" property at all.
* <p>A Spring-specific subclass of Quartz' JobStoreCMT will be used.
* It is therefore strongly recommended to perform all operations on
* the Scheduler within Spring-managed (or plain JTA) transactions.

95
src/docs/asciidoc/integration.adoc

@ -6615,7 +6615,6 @@ has it applied automatically: @@ -6615,7 +6615,6 @@ has it applied automatically:
protected void executeInternal(JobExecutionContext ctx) throws JobExecutionException {
// do the actual work
}
}
----
@ -6740,11 +6739,17 @@ seconds and one running every morning at 6 AM. To finalize everything, we need t @@ -6740,11 +6739,17 @@ seconds and one running every morning at 6 AM. To finalize everything, we need t
</bean>
----
More properties are available for the `SchedulerFactoryBean`, such as the calendars
used by the job details, properties to customize Quartz with, and others. See the
{api-spring-framework}/scheduling/quartz/SchedulerFactoryBean.html[`SchedulerFactoryBean`]
More properties are available for the `SchedulerFactoryBean`, such as the calendars used by the
job details, properties to customize Quartz with, and a Spring-provided JDBC DataSource. See
the {api-spring-framework}/scheduling/quartz/SchedulerFactoryBean.html[`SchedulerFactoryBean`]
javadoc for more information.
NOTE: `SchedulerFactoryBean` also recognizes a `quartz.properties` file in the classpath,
based on Quartz property keys, as with regular Quartz configuration. Please note that many
`SchedulerFactoryBean` settings interact with common Quartz settings in the properties file;
it is therefore not recommended to specify values at both levels. For example, do not set
an "org.quartz.jobStore.class" property if you mean to rely on a Spring-provided DataSource.
@ -6756,8 +6761,8 @@ an existing Spring application. Similar to the <<data-access.adoc#transaction, t @@ -6756,8 +6761,8 @@ an existing Spring application. Similar to the <<data-access.adoc#transaction, t
support, the caching abstraction allows consistent use of various caching solutions with
minimal impact on the code.
As from Spring 4.1, the cache abstraction has been significantly extended with the
support of <<cache-jsr-107,JSR-107 annotations>> and more customization options.
In Spring Framework 4.1, the cache abstraction was significantly extended with support
for <<cache-jsr-107,JSR-107 annotations>> and more customization options.
@ -6815,15 +6820,16 @@ compliant caches (such as Ehcache 3.x). See <<cache-plug>> for more information @@ -6815,15 +6820,16 @@ compliant caches (such as Ehcache 3.x). See <<cache-plug>> for more information
plugging in other cache stores and providers.
IMPORTANT: The caching abstraction has no special handling for multi-threaded and
multi-process environments, as such features are handled by the cache implementation. .
multi-process environments, as such features are handled by the cache implementation.
If you have a multi-process environment (that is, an application deployed on several nodes),
you need to configure your cache provider accordingly. Depending on your use cases, a copy
of the same data on several nodes can be enough. However, if you change the data during
the course of the application, you may need to enable other propagation mechanisms.
Caching a particular item is a direct equivalent of the typical get-if-not-found-then-
proceed-and-put-eventually code blocks found with programmatic cache interaction.
Caching a particular item is a direct equivalent of the typical
get-if-not-found-then-proceed-and-put-eventually code blocks
found with programmatic cache interaction.
No locks are applied, and several threads may try to load the same item concurrently.
The same applies to eviction. If several threads are trying to update or evict data
concurrently, you may use stale data. Certain cache providers offer advanced features
@ -6875,7 +6881,7 @@ method -- if at least one cache is hit, the associated value is returned. @@ -6875,7 +6881,7 @@ 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 invoked.
The following example uses `@Cacheable` on the `findBook` method:
The following example uses `@Cacheable` on the `findBook` method with multiple caches:
[source,java,indent=0]
[subs="verbatim,quotes"]
@ -7028,7 +7034,7 @@ regardless of the content of the annotation. @@ -7028,7 +7034,7 @@ 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
results in an exception. as a custom `CacheManager` is ignored by the
results in an exception, as a custom `CacheManager` is ignored by the
`CacheResolver` implementation. This is probably not what you expect.
====
@ -7053,7 +7059,6 @@ is updated in the cache. The following example shows how to use the `sync` attri @@ -7053,7 +7059,6 @@ is updated in the cache. The following example shows how to use the `sync` attri
----
<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
documentation of your cache provider for more details.
@ -7092,9 +7097,11 @@ want to cache paperback books, as the following example does: @@ -7092,9 +7097,11 @@ want to cache paperback books, as the following example does:
<1> Using the `unless` attribute to block hardbacks.
The cache abstraction supports `java.util.Optional`, using its content as the cached value
only if it is present. `#result` always refers to the business entity and never a
supported wrapper, so the previous example can be rewritten as follows:
The cache abstraction supports `java.util.Optional` return types. If an `Optional` value
is _present_, it will be stored in the associated cache. If an `Optional` value is not
present, `null` will be stored in the associated cache. `#result` always refers to the
business entity and never a supported wrapper, so the previous example can be rewritten
as follows:
[source,java,indent=0]
[subs="verbatim,quotes"]
@ -7103,8 +7110,8 @@ supported wrapper, so the previous example can be rewritten as follows: @@ -7103,8 +7110,8 @@ supported wrapper, so the previous example can be rewritten as follows:
public Optional<Book> findBook(String name)
----
Note that `result` still refers to `Book` and not `Optional`. As it might be `null`, we
should use the safe navigation operator.
Note that `#result` still refers to `Book` and not `Optional<Book>`. Since it might be
`null`, we use SpEL's <<core.adoc#expressions-operator-safe-navigation, safe navigation operator>>.
[[cache-spel-context]]
===== Available Caching SpEL Evaluation Context
@ -7214,7 +7221,6 @@ all entries from the `books` cache: @@ -7214,7 +7221,6 @@ 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 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.
@ -7275,7 +7281,6 @@ comes into play. The following examples uses `@CacheConfig` to set the name of t @@ -7275,7 +7281,6 @@ comes into play. The following examples uses `@CacheConfig` to set the name of t
----
<1> Using `@CacheConfig` to set the name of the cache.
`@CacheConfig` is a class-level annotation that allows sharing the cache names,
the custom `KeyGenerator`, the custom `CacheManager`, and the custom `CacheResolver`.
Placing this annotation on the class does not turn on any caching operation.
@ -7418,13 +7423,11 @@ if you need to annotate non-public methods, as it changes the bytecode itself. @@ -7418,13 +7423,11 @@ if you need to annotate non-public methods, as it changes the bytecode itself.
****
TIP: Spring recommends that you only annotate concrete classes (and methods of concrete
classes) with the `@Cache{asterisk}` annotation, as opposed to annotating interfaces.
You certainly can place the `@Cache{asterisk}` annotation on an interface (or an interface
method), but this works only as you would expect it to if you use interface-based proxies.
The fact that Java annotations are not inherited from interfaces means that, if you use
class-based proxies (`proxy-target-class="true"`) or the weaving-based aspect
(`mode="aspectj"`), the caching settings are not recognized by the proxying and weaving
infrastructure, and the object is not wrapped in a caching proxy.
classes) with the `@Cache{asterisk}` annotations, as opposed to annotating interfaces.
You certainly can place an `@Cache{asterisk}` annotation on an interface (or an interface
method), but this works only if you use the proxy mode (`mode="proxy"`). If you use the
weaving-based aspect (`mode="aspectj"`), the caching settings are not recognized on
interface-level declarations by the weaving infrastructure.
NOTE: In proxy mode (the default), only external method calls coming in through the
proxy are intercepted. This means that self-invocation (in effect, a method within the
@ -7499,7 +7502,7 @@ up its declaration at runtime and understands its meaning. Note that, as mention @@ -7499,7 +7502,7 @@ up its declaration at runtime and understands its meaning. Note that, as mention
=== JCache (JSR-107) Annotations
Since version 4.1, Spring's caching abstraction fully supports the JCache standard
annotations: `@CacheResult`, `@CachePut`, `@CacheRemove`, and `@CacheRemoveAll`
(JSR-107) annotations: `@CacheResult`, `@CachePut`, `@CacheRemove`, and `@CacheRemoveAll`
as well as the `@CacheDefaults`, `@CacheKey`, and `@CacheValue` companions.
You can use these annotations even without migrating your cache store to JSR-107.
The internal implementation uses Spring's caching abstraction and provides default
@ -7513,8 +7516,8 @@ you can switch to these standard annotations without changing your cache storage @@ -7513,8 +7516,8 @@ you can switch to these standard annotations without changing your cache storage
==== Feature Summary
For those who are familiar with Spring's caching annotations, the following table
describes the main differences between the Spring annotations and the JSR-107
counterpart:
describes the main differences between the Spring annotations and their JSR-107
counterparts:
.Spring vs. JSR-107 caching annotations
[cols="1,1,3"]
@ -7565,7 +7568,6 @@ to customize the factory for each cache operation, as the following example show @@ -7565,7 +7568,6 @@ to customize the factory for each cache operation, as the following example show
----
<1> Customizing the factory for this operation.
NOTE: For all referenced classes, Spring tries to locate a bean with the given type.
If more than one match exists, a new instance is created and can use the regular
bean lifecycle callbacks, such as dependency injection.
@ -7609,16 +7611,15 @@ invoking the method again: @@ -7609,16 +7611,15 @@ invoking the method again:
==== Enabling JSR-107 Support
You need do nothing specific to enable the JSR-107 support alongside Spring's
declarative annotation support. Both `@EnableCaching` and the
`cache:annotation-driven` element automatically enable the JCache support
if both the JSR-107 API and the `spring-context-support` module are present
in the classpath.
You do not need to do anything specific to enable the JSR-107 support alongside Spring's
declarative annotation support. Both `@EnableCaching` and the `cache:annotation-driven`
XML element automatically enable the JCache support if both the JSR-107 API and the
`spring-context-support` module are present in the classpath.
NOTE: Depending on your use case, the choice is basically yours. You can even
mix and match services by using the JSR-107 API on some and using Spring's own
annotations on others. However, if these services impact the same caches,
you should use a consistent and identical key generation implementation.
NOTE: Depending on your use case, the choice is basically yours. You can even mix and
match services by using the JSR-107 API on some and using Spring's own annotations on
others. However, if these services impact the same caches, you should use a consistent
and identical key generation implementation.
@ -7848,15 +7849,13 @@ invoked every time. @@ -7848,15 +7849,13 @@ invoked every time.
=== Plugging-in Different Back-end Caches
Clearly, there are plenty of caching products out there that you can use as a backing
store. To plug them in, you need to provide a `CacheManager` and a `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
https://en.wikipedia.org/wiki/Adapter_pattern[adapters] that map the caching abstraction
framework on top of the storage API, as the `ehcache` classes do. Most `CacheManager`
classes can use the classes in the `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.
store. For those that do not support JSR-107 you need to provide a `CacheManager` and a
`Cache` implementation. This may sound harder than it is, since, in practice, the classes
tend to be simple https://en.wikipedia.org/wiki/Adapter_pattern[adapters] that map the
caching abstraction framework on top of the storage API, as the `ehcache` classes do.
Most `CacheManager` classes can use the classes in the
`org.springframework.cache.support` package (such as `AbstractCacheManager` which takes
care of the boiler-plate code, leaving only the actual mapping to be completed).

Loading…
Cancel
Save