Skip to content

Commit

Permalink
Clarify SchedulerFactoryBean's LocalDataSourceJobStore overriding
Browse files Browse the repository at this point in the history
Includes clarification of interface-level cache annotations for target-class proxies.

Closes gh-27709
See gh-27726
  • Loading branch information
jhoeller committed Dec 14, 2021
1 parent c44447f commit d7b9270
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 16 deletions.
Expand Up @@ -39,6 +39,7 @@
* Subclass of Quartz's {@link JobStoreCMT} class that delegates to a Spring-managed
* {@link DataSource} instead of using a Quartz-managed JDBC connection pool.
* This JobStore will be used if SchedulerFactoryBean's "dataSource" property is set.
* You may also configure it explicitly, possibly as a custom subclass of this class.
*
* <p>Supports both transactional and non-transactional DataSource access.
* With a non-XA DataSource and local Spring transactions, a single DataSource
Expand All @@ -58,6 +59,8 @@
* @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
*/
Expand Down
Expand Up @@ -310,9 +310,11 @@ public void setTaskExecutor(Executor taskExecutor) {

/**
* Set the default {@link DataSource} to be used by the Scheduler.
* 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.
* (You may explicitly define Spring's {@link LocalDataSourceJobStore}
* but that's the default when using this method anyway.)
* <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.
Expand Down
Expand Up @@ -83,6 +83,19 @@ private void fooGetSimple(FooService service) {
assertCacheHit(key, value, cache);
}

@Test
public void barServiceWithCacheableInterfaceCglib() {
this.context = new AnnotationConfigApplicationContext(BarConfigCglib.class);
BarService service = this.context.getBean(BarService.class);
Cache cache = getCache();

Object key = new Object();
assertCacheMiss(key, cache);

Object value = service.getSimple(key);
assertCacheHit(key, value, cache);
}

@Test
public void beanConditionOff() {
this.context = new AnnotationConfigApplicationContext(BeanConditionConfig.class);
Expand Down Expand Up @@ -185,6 +198,36 @@ public Object getWithCondition(Object key) {
}


@Configuration
@Import(SharedConfig.class)
@EnableCaching(proxyTargetClass = true)
static class BarConfigCglib {

@Bean
public BarService barService() {
return new BarServiceImpl();
}
}


interface BarService {

@Cacheable(cacheNames = "testCache")
Object getSimple(Object key);
}


static class BarServiceImpl implements BarService {

private final AtomicLong counter = new AtomicLong();

@Override
public Object getSimple(Object key) {
return this.counter.getAndIncrement();
}
}


@Configuration
@Import(FooConfig.class)
@EnableCaching
Expand Down
32 changes: 17 additions & 15 deletions src/docs/asciidoc/integration.adoc
Expand Up @@ -5396,6 +5396,7 @@ You can use these macros instead of the six-digit value, thus: `@Scheduled(cron
|===



[[scheduling-quartz]]
=== Using the Quartz Scheduler

Expand Down Expand Up @@ -5451,7 +5452,6 @@ has it applied automatically:
protected void executeInternal(JobExecutionContext ctx) throws JobExecutionException {
// do the actual work
}
}
----

Expand Down Expand Up @@ -5571,11 +5571,19 @@ 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,
or specify an `org.springframework.scheduling.quartz.LocalDataSourceJobStore` variant which
is a full-fledged replacement for the standard `org.quartz.impl.jdbcjobstore.JobStoreTX`.




Expand Down Expand Up @@ -5877,7 +5885,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.
Expand Down Expand Up @@ -6035,7 +6042,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.
Expand Down Expand Up @@ -6094,7 +6100,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.
Expand Down Expand Up @@ -6235,13 +6240,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
Expand Down Expand Up @@ -6378,7 +6381,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.
Expand Down

0 comments on commit d7b9270

Please sign in to comment.