Modernize the integration section of the refdoc

This commit adds Java and Kotlin tabs to XML code snippets where
relevant, and leverages code includes.

Closes gh-32600
This commit is contained in:
Sébastien Deleuze
2024-05-06 16:05:15 +02:00
parent bdc4ecd599
commit c6459b40e4
95 changed files with 2880 additions and 522 deletions

View File

@@ -518,41 +518,9 @@ disable it by removing only one configuration line rather than all the annotatio
your code).
To enable caching annotations add the annotation `@EnableCaching` to one of your
`@Configuration` classes:
`@Configuration` classes or use the `cache:annotation-driven` element with XML:
[source,java,indent=0,subs="verbatim,quotes"]
----
@Configuration
@EnableCaching
public class AppConfig {
@Bean
CacheManager cacheManager() {
CaffeineCacheManager cacheManager = new CaffeineCacheManager();
cacheManager.setCacheSpecification(...);
return cacheManager;
}
}
----
Alternatively, for XML configuration you can use the `cache:annotation-driven` element:
[source,xml,indent=0,subs="verbatim,quotes"]
----
<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 https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/cache https://www.springframework.org/schema/cache/spring-cache.xsd">
<cache:annotation-driven/>
<bean id="cacheManager" class="org.springframework.cache.caffeine.CaffeineCacheManager">
<property name="cacheSpecification" value="..."/>
</bean>
</beans>
----
include-code::./CacheConfiguration[tag=snippet,indent=0]
Both the `cache:annotation-driven` element and the `@EnableCaching` annotation let you
specify various options that influence the way the caching behavior is added to the

View File

@@ -13,18 +13,7 @@ The JDK-based `Cache` implementation resides under
`org.springframework.cache.concurrent` package. It lets you use `ConcurrentHashMap`
as a backing `Cache` store. The following example shows how to configure two caches:
[source,xml,indent=0,subs="verbatim,quotes"]
----
<!-- simple cache manager -->
<bean id="cacheManager" class="org.springframework.cache.support.SimpleCacheManager">
<property name="caches">
<set>
<bean class="org.springframework.cache.concurrent.ConcurrentMapCacheFactoryBean" p:name="default"/>
<bean class="org.springframework.cache.concurrent.ConcurrentMapCacheFactoryBean" p:name="books"/>
</set>
</property>
</bean>
----
include-code::./CacheConfiguration[tag=snippet,indent=0]
The preceding snippet uses the `SimpleCacheManager` to create a `CacheManager` for the
two nested `ConcurrentMapCache` instances named `default` and `books`. Note that the
@@ -52,26 +41,12 @@ of Caffeine.
The following example configures a `CacheManager` that creates the cache on demand:
[source,xml,indent=0,subs="verbatim,quotes"]
----
<bean id="cacheManager"
class="org.springframework.cache.caffeine.CaffeineCacheManager"/>
----
include-code::./CacheConfiguration[tag=snippet,indent=0]
You can also provide the caches to use explicitly. In that case, only those
are made available by the manager. The following example shows how to do so:
[source,xml,indent=0,subs="verbatim,quotes"]
----
<bean id="cacheManager" class="org.springframework.cache.caffeine.CaffeineCacheManager">
<property name="cacheNames">
<set>
<value>default</value>
<value>books</value>
</set>
</property>
</bean>
----
include-code::./CustomCacheConfiguration[tag=snippet,indent=0]
The Caffeine `CacheManager` also supports custom `Caffeine` and `CacheLoader`.
See the https://github.com/ben-manes/caffeine/wiki[Caffeine documentation]
@@ -97,15 +72,7 @@ implementation is located in the `org.springframework.cache.jcache` package.
Again, to use it, you need to declare the appropriate `CacheManager`.
The following example shows how to do so:
[source,xml,indent=0,subs="verbatim,quotes"]
----
<bean id="cacheManager"
class="org.springframework.cache.jcache.JCacheCacheManager"
p:cache-manager-ref="jCacheManager"/>
<!-- JSR-107 cache manager setup -->
<bean id="jCacheManager" .../>
----
include-code::./CacheConfiguration[tag=snippet,indent=0]
[[cache-store-configuration-noop]]
@@ -119,18 +86,7 @@ cache declarations (which can prove tedious), you can wire in a simple dummy cac
performs no caching -- that is, it forces the cached methods to be invoked every time.
The following example shows how to do so:
[source,xml,indent=0,subs="verbatim,quotes"]
----
<bean id="cacheManager" class="org.springframework.cache.support.CompositeCacheManager">
<property name="cacheManagers">
<list>
<ref bean="jdkCache"/>
<ref bean="gemfireCache"/>
</list>
</property>
<property name="fallbackToNoOpCache" value="true"/>
</bean>
----
include-code::./CacheConfiguration[tag=snippet,indent=0]
The `CompositeCacheManager` in the preceding chains multiple `CacheManager` instances and,
through the `fallbackToNoOpCache` flag, adds a no-op cache for all the definitions not

View File

@@ -41,14 +41,7 @@ JavaMail features, such as MIME message support to the `MailSender` interface
Assume that we have a business interface called `OrderManager`, as the following example shows:
[source,java,indent=0,subs="verbatim,quotes"]
----
public interface OrderManager {
void placeOrder(Order order);
}
----
include-code::./OrderManager[tag=snippet,indent=0]
Further assume that we have a requirement stating that an email message with an
order number needs to be generated and sent to a customer who placed the relevant order.
@@ -60,70 +53,11 @@ order number needs to be generated and sent to a customer who placed the relevan
The following example shows how to use `MailSender` and `SimpleMailMessage` to send an
email when someone places an order:
[source,java,indent=0,subs="verbatim,quotes"]
----
import org.springframework.mail.MailException;
import org.springframework.mail.MailSender;
import org.springframework.mail.SimpleMailMessage;
public class SimpleOrderManager implements OrderManager {
private MailSender mailSender;
private SimpleMailMessage templateMessage;
public void setMailSender(MailSender mailSender) {
this.mailSender = mailSender;
}
public void setTemplateMessage(SimpleMailMessage templateMessage) {
this.templateMessage = templateMessage;
}
public void placeOrder(Order order) {
// Do the business calculations...
// Call the collaborators to persist the order...
// Create a thread-safe "copy" of the template message and customize it
SimpleMailMessage msg = new SimpleMailMessage(this.templateMessage);
msg.setTo(order.getCustomer().getEmailAddress());
msg.setText(
"Dear " + order.getCustomer().getFirstName()
+ order.getCustomer().getLastName()
+ ", thank you for placing order. Your order number is "
+ order.getOrderNumber());
try {
this.mailSender.send(msg);
}
catch (MailException ex) {
// simply log it and go on...
System.err.println(ex.getMessage());
}
}
}
----
include-code::./SimpleOrderManager[tag=snippet,indent=0]
The following example shows the bean definitions for the preceding code:
[source,xml,indent=0,subs="verbatim,quotes"]
----
<bean id="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl">
<property name="host" value="mail.mycompany.example"/>
</bean>
<!-- this is a template message that we can pre-load with default state -->
<bean id="templateMessage" class="org.springframework.mail.SimpleMailMessage">
<property name="from" value="customerservice@mycompany.example"/>
<property name="subject" value="Your order"/>
</bean>
<bean id="orderManager" class="com.mycompany.businessapp.support.SimpleOrderManager">
<property name="mailSender" ref="mailSender"/>
<property name="templateMessage" ref="templateMessage"/>
</bean>
----
include-code::./MailConfiguration[tag=snippet,indent=0]
[[mail-usage-mime]]

View File

@@ -37,23 +37,7 @@ declarations to it.
To enable support for `@JmsListener` annotations, you can add `@EnableJms` to one of
your `@Configuration` classes, as the following example shows:
[source,java,indent=0,subs="verbatim,quotes"]
----
@Configuration
@EnableJms
public class AppConfig {
@Bean
public DefaultJmsListenerContainerFactory jmsListenerContainerFactory() {
DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
factory.setConnectionFactory(connectionFactory());
factory.setDestinationResolver(destinationResolver());
factory.setSessionTransacted(true);
factory.setConcurrency("3-10");
return factory;
}
}
----
include-code::./JmsConfiguration[tag=snippet,indent=0]
By default, the infrastructure looks for a bean named `jmsListenerContainerFactory`
as the source for the factory to use to create message listener containers. In this
@@ -67,22 +51,6 @@ container factory. See the javadoc of classes that implement
{spring-framework-api}/jms/annotation/JmsListenerConfigurer.html[`JmsListenerConfigurer`]
for details and examples.
If you prefer xref:integration/jms/namespace.adoc[XML configuration], you can use the `<jms:annotation-driven>`
element, as the following example shows:
[source,xml,indent=0,subs="verbatim,quotes"]
----
<jms:annotation-driven/>
<bean id="jmsListenerContainerFactory"
class="org.springframework.jms.config.DefaultJmsListenerContainerFactory">
<property name="connectionFactory" ref="connectionFactory"/>
<property name="destinationResolver" ref="destinationResolver"/>
<property name="sessionTransacted" value="true"/>
<property name="concurrency" value="3-10"/>
</bean>
----
[[jms-annotated-programmatic-registration]]
== Programmatic Endpoint Registration

View File

@@ -7,62 +7,13 @@ automatically determine the `ActivationSpec` class name from the provider's
`ResourceAdapter` class name. Therefore, it is typically possible to provide
Spring's generic `JmsActivationSpecConfig`, as the following example shows:
[source,xml,indent=0,subs="verbatim,quotes"]
----
<bean class="org.springframework.jms.listener.endpoint.JmsMessageEndpointManager">
<property name="resourceAdapter" ref="resourceAdapter"/>
<property name="activationSpecConfig">
<bean class="org.springframework.jms.listener.endpoint.JmsActivationSpecConfig">
<property name="destinationName" value="myQueue"/>
</bean>
</property>
<property name="messageListener" ref="myMessageListener"/>
</bean>
----
include-code::./JmsConfiguration[tag=snippet,indent=0]
Alternatively, you can set up a `JmsMessageEndpointManager` with a given
`ActivationSpec` object. The `ActivationSpec` object may also come from a JNDI lookup
(using `<jee:jndi-lookup>`). The following example shows how to do so:
[source,xml,indent=0,subs="verbatim,quotes"]
----
<bean class="org.springframework.jms.listener.endpoint.JmsMessageEndpointManager">
<property name="resourceAdapter" ref="resourceAdapter"/>
<property name="activationSpec">
<bean class="org.apache.activemq.ra.ActiveMQActivationSpec">
<property name="destination" value="myQueue"/>
<property name="destinationType" value="jakarta.jms.Queue"/>
</bean>
</property>
<property name="messageListener" ref="myMessageListener"/>
</bean>
----
Using Spring's `ResourceAdapterFactoryBean`, you can configure the target `ResourceAdapter`
locally, as the following example shows:
[source,xml,indent=0,subs="verbatim,quotes"]
----
<bean id="resourceAdapter" class="org.springframework.jca.support.ResourceAdapterFactoryBean">
<property name="resourceAdapter">
<bean class="org.apache.activemq.ra.ActiveMQResourceAdapter">
<property name="serverUrl" value="tcp://localhost:61616"/>
</bean>
</property>
<property name="workManager">
<bean class="org.springframework.jca.work.SimpleTaskWorkManager"/>
</property>
</bean>
----
The specified `WorkManager` can also point to an environment-specific thread pool --
typically through a `SimpleTaskWorkManager` instance's `asyncTaskExecutor` property.
Consider defining a shared thread pool for all your `ResourceAdapter` instances
if you happen to use multiple adapters.
In some environments, you can instead obtain the entire `ResourceAdapter` object from JNDI
(by using `<jee:jndi-lookup>`). The Spring-based message listeners can then interact with
the server-hosted `ResourceAdapter`, which also use the server's built-in `WorkManager`.
include-code::./AlternativeJmsConfiguration[tag=snippet,indent=0]
See the javadoc for {spring-framework-api}/jms/listener/endpoint/JmsMessageEndpointManager.html[`JmsMessageEndpointManager`],
{spring-framework-api}/jms/listener/endpoint/JmsActivationSpecConfig.html[`JmsActivationSpecConfig`],

View File

@@ -31,30 +31,7 @@ on multiple threads, it is important to ensure that your implementation is threa
The following example shows a simple implementation of an MDP:
[source,java,indent=0,subs="verbatim,quotes"]
----
import jakarta.jms.JMSException;
import jakarta.jms.Message;
import jakarta.jms.MessageListener;
import jakarta.jms.TextMessage;
public class ExampleListener implements MessageListener {
public void onMessage(Message message) {
if (message instanceof TextMessage textMessage) {
try {
System.out.println(textMessage.getText());
}
catch (JMSException ex) {
throw new RuntimeException(ex);
}
}
else {
throw new IllegalArgumentException("Message must be of type TextMessage");
}
}
}
----
include-code::./ExampleListener[tag=snippet,indent=0]
Once you have implemented your `MessageListener`, it is time to create a message listener
container.
@@ -62,18 +39,7 @@ container.
The following example shows how to define and configure one of the message listener
containers that ships with Spring (in this case, `DefaultMessageListenerContainer`):
[source,xml,indent=0,subs="verbatim,quotes"]
----
<!-- this is the Message Driven POJO (MDP) -->
<bean id="messageListener" class="jmsexample.ExampleListener"/>
<!-- and this is the message listener container -->
<bean id="jmsContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="connectionFactory"/>
<property name="destination" ref="destination"/>
<property name="messageListener" ref="messageListener"/>
</bean>
----
include-code::./JmsConfiguration[tag=snippet,indent=0]
See the Spring javadoc of the various message listener containers (all of which implement
{spring-framework-api}/jms/listener/MessageListenerContainer.html[MessageListenerContainer])
@@ -123,19 +89,7 @@ messaging support. In a nutshell, it lets you expose almost any class as an MDP
Consider the following interface definition:
[source,java,indent=0,subs="verbatim,quotes"]
----
public interface MessageDelegate {
void handleMessage(String message);
void handleMessage(Map message);
void handleMessage(byte[] message);
void handleMessage(Serializable message);
}
----
include-code::./MessageDelegate[tag=snippet,indent=0]
Notice that, although the interface extends neither the `MessageListener` nor the
`SessionAwareMessageListener` interface, you can still use it as an MDP by using the
@@ -145,33 +99,13 @@ receive and handle.
Now consider the following implementation of the `MessageDelegate` interface:
[source,java,indent=0,subs="verbatim,quotes"]
----
public class DefaultMessageDelegate implements MessageDelegate {
// implementation elided for clarity...
}
----
include-code::./DefaultMessageDelegate[tag=snippet,indent=0]
In particular, note how the preceding implementation of the `MessageDelegate` interface (the
`DefaultMessageDelegate` class) has no JMS dependencies at all. It truly is a
POJO that we can make into an MDP through the following configuration:
[source,xml,indent=0,subs="verbatim,quotes"]
----
<!-- this is the Message Driven POJO (MDP) -->
<bean id="messageListener" class="org.springframework.jms.listener.adapter.MessageListenerAdapter">
<constructor-arg>
<bean class="jmsexample.DefaultMessageDelegate"/>
</constructor-arg>
</bean>
<!-- and this is the message listener container... -->
<bean id="jmsContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="connectionFactory"/>
<property name="destination" ref="destination"/>
<property name="messageListener" ref="messageListener"/>
</bean>
----
include-code::./JmsConfiguration[tag=snippet,indent=0]
The next example shows another MDP that can handle only receiving JMS
`TextMessage` messages. Notice how the message handling method is actually called
@@ -181,38 +115,15 @@ also how the `receive(..)` method is strongly typed to receive and respond only
`TextMessage` messages.
The following listing shows the definition of the `TextMessageDelegate` interface:
[source,java,indent=0,subs="verbatim,quotes"]
----
public interface TextMessageDelegate {
void receive(TextMessage message);
}
----
include-code::./TextMessageDelegate[tag=snippet,indent=0]
The following listing shows a class that implements the `TextMessageDelegate` interface:
[source,java,indent=0,subs="verbatim,quotes"]
----
public class DefaultTextMessageDelegate implements TextMessageDelegate {
// implementation elided for clarity...
}
----
include-code::./DefaultTextMessageDelegate[tag=snippet,indent=0]
The configuration of the attendant `MessageListenerAdapter` would then be as follows:
[source,xml,indent=0,subs="verbatim,quotes"]
----
<bean id="messageListener" class="org.springframework.jms.listener.adapter.MessageListenerAdapter">
<constructor-arg>
<bean class="jmsexample.DefaultTextMessageDelegate"/>
</constructor-arg>
<property name="defaultListenerMethod" value="receive"/>
<!-- we don't want automatic message context extraction -->
<property name="messageConverter">
<null/>
</property>
</bean>
----
include-code::./MessageListenerConfiguration[tag=snippet,indent=0]
Note that, if the `messageListener` receives a JMS `Message` of a type
other than `TextMessage`, an `IllegalStateException` is thrown (and subsequently
@@ -220,21 +131,9 @@ swallowed). Another of the capabilities of the `MessageListenerAdapter` class is
ability to automatically send back a response `Message` if a handler method returns a
non-void value. Consider the following interface and class:
[source,java,indent=0,subs="verbatim,quotes"]
----
public interface ResponsiveTextMessageDelegate {
include-code::./ResponsiveTextMessageDelegate[tag=snippet,indent=0]
// notice the return type...
String receive(TextMessage message);
}
----
[source,java,indent=0,subs="verbatim,quotes"]
----
public class DefaultResponsiveTextMessageDelegate implements ResponsiveTextMessageDelegate {
// implementation elided for clarity...
}
----
include-code::./DefaultResponsiveTextMessageDelegate[tag=snippet,indent=0]
If you use the `DefaultResponsiveTextMessageDelegate` in conjunction with a
`MessageListenerAdapter`, any non-null value that is returned from the execution of
@@ -264,15 +163,7 @@ has committed but message processing failed to commit.
Consider the following bean definition:
[source,xml,indent=0,subs="verbatim,quotes"]
----
<bean id="jmsContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="connectionFactory"/>
<property name="destination" ref="destination"/>
<property name="messageListener" ref="messageListener"/>
<property name="sessionTransacted" value="true"/>
</bean>
----
include-code::./JmsConfiguration[tag=snippet,indent=0]
To participate in an externally managed transaction, you need to configure a
transaction manager and use a listener container that supports externally managed
@@ -288,24 +179,9 @@ semantics, at the expense of XA transaction log overhead).
The following bean definition creates a transaction manager:
[source,xml,indent=0,subs="verbatim,quotes"]
----
<bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager"/>
----
include-code::./ExternalTxJmsConfiguration[tag=transactionManagerSnippet,indent=0]
Then we need to add it to our earlier container configuration. The container
takes care of the rest. The following example shows how to do so:
[source,xml,indent=0,subs="verbatim,quotes"]
----
<bean id="jmsContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="connectionFactory"/>
<property name="destination" ref="destination"/>
<property name="messageListener" ref="messageListener"/>
<property name="transactionManager" ref="transactionManager"/> <1>
</bean>
----
<1> Our transaction manager.
include-code::./ExternalTxJmsConfiguration[tag=jmsContainerSnippet,indent=0]

View File

@@ -5,63 +5,13 @@ The core class in Spring's JMX framework is the `MBeanExporter`. This class is
responsible for taking your Spring beans and registering them with a JMX `MBeanServer`.
For example, consider the following class:
[source,java,indent=0,subs="verbatim,quotes",chomp="-packages",chomp="-packages"]
----
package org.springframework.jmx;
public class JmxTestBean implements IJmxTestBean {
private String name;
private int age;
private boolean isSuperman;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public int add(int x, int y) {
return x + y;
}
public void dontExposeMe() {
throw new RuntimeException();
}
}
----
include-code::./JmxTestBean[tag=snippet,indent=0]
To expose the properties and methods of this bean as attributes and operations of an
MBean, you can configure an instance of the `MBeanExporter` class in your
configuration file and pass in the bean, as the following example shows:
[source,xml,indent=0,subs="verbatim,quotes"]
----
<beans>
<!-- this bean must not be lazily initialized if the exporting is to happen -->
<bean id="exporter" class="org.springframework.jmx.export.MBeanExporter" lazy-init="false">
<property name="beans">
<map>
<entry key="bean:name=testBean1" value-ref="testBean"/>
</map>
</property>
</bean>
<bean id="testBean" class="org.springframework.jmx.JmxTestBean">
<property name="name" value="TEST"/>
<property name="age" value="100"/>
</bean>
</beans>
----
include-code::./JmxConfiguration[tag=snippet,indent=0]
The pertinent bean definition from the preceding configuration snippet is the `exporter`
bean. The `beans` property tells the `MBeanExporter` exactly which of your beans must be

View File

@@ -122,25 +122,10 @@ your management interfaces, a convenience subclass of `MBeanExporter` is availab
`namingStrategy`, `assembler`, and `attributeSource` configuration,
since it always uses standard Java annotation-based metadata (autodetection is
always enabled as well). In fact, rather than defining an `MBeanExporter` bean, an even
simpler syntax is supported by the `@EnableMBeanExport` `@Configuration` annotation,
as the following example shows:
simpler syntax is supported by the `@EnableMBeanExport` `@Configuration` annotation or the `<context:mbean-export/>`
element as the following example shows:
[source,java,indent=0,subs="verbatim,quotes"]
----
@Configuration
@EnableMBeanExport
public class AppConfig {
}
----
If you prefer XML-based configuration, the `<context:mbean-export/>` element serves the
same purpose and is shown in the following listing:
[source,xml,indent=0,subs="verbatim,quotes"]
----
<context:mbean-export/>
----
include-code::./JmxConfiguration[tag=snippet,indent=0]
If necessary, you can provide a reference to a particular MBean `server`, and the
`defaultDomain` attribute (a property of `AnnotationMBeanExporter`) accepts an alternate
@@ -148,21 +133,7 @@ value for the generated MBean `ObjectName` domains. This is used in place of the
fully qualified package name as described in the previous section on
xref:integration/jmx/naming.adoc#jmx-naming-metadata[MetadataNamingStrategy], as the following example shows:
[source,java,indent=0,subs="verbatim,quotes"]
----
@EnableMBeanExport(server="myMBeanServer", defaultDomain="myDomain")
@Configuration
ContextConfiguration {
}
----
The following example shows the XML equivalent of the preceding annotation-based example:
[source,xml,indent=0,subs="verbatim,quotes"]
----
<context:mbean-export server="myMBeanServer" default-domain="myDomain"/>
----
include-code::./CustomJmxConfiguration[tag=snippet,indent=0]
CAUTION: Do not use interface-based AOP proxies in combination with autodetection of JMX
annotations in your bean classes. Interface-based proxies "`hide`" the target class, which

View File

@@ -79,38 +79,7 @@ Spring's `TaskExecutor` implementations are commonly used with dependency inject
In the following example, we define a bean that uses the `ThreadPoolTaskExecutor`
to asynchronously print out a set of messages:
[source,java,indent=0,subs="verbatim,quotes"]
----
import org.springframework.core.task.TaskExecutor;
public class TaskExecutorExample {
private class MessagePrinterTask implements Runnable {
private String message;
public MessagePrinterTask(String message) {
this.message = message;
}
public void run() {
System.out.println(message);
}
}
private TaskExecutor taskExecutor;
public TaskExecutorExample(TaskExecutor taskExecutor) {
this.taskExecutor = taskExecutor;
}
public void printMessages() {
for(int i = 0; i < 25; i++) {
taskExecutor.execute(new MessagePrinterTask("Message" + i));
}
}
}
----
include-code::./TaskExecutorExample[tag=snippet,indent=0]
As you can see, rather than retrieving a thread from the pool and executing it yourself,
you add your `Runnable` to the queue. Then the `TaskExecutor` uses its internal rules to
@@ -118,19 +87,7 @@ decide when the task gets run.
To configure the rules that the `TaskExecutor` uses, we expose simple bean properties:
[source,xml,indent=0,subs="verbatim,quotes"]
----
<bean id="taskExecutor" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
<property name="corePoolSize" value="5"/>
<property name="maxPoolSize" value="10"/>
<property name="queueCapacity" value="25"/>
</bean>
<bean id="taskExecutorExample" class="TaskExecutorExample">
<constructor-arg ref="taskExecutor"/>
</bean>
----
include-code::./TaskExecutorConfiguration[tag=snippet,indent=0]
[[scheduling-task-scheduler]]
@@ -269,16 +226,10 @@ execution.
=== Enable Scheduling Annotations
To enable support for `@Scheduled` and `@Async` annotations, you can add `@EnableScheduling`
and `@EnableAsync` to one of your `@Configuration` classes, as the following example shows:
and `@EnableAsync` to one of your `@Configuration` classes, or `<task:annotation-driven>` element,
as the following example shows:
[source,java,indent=0,subs="verbatim,quotes"]
----
@Configuration
@EnableAsync
@EnableScheduling
public class AppConfig {
}
----
include-code::./SchedulingConfiguration[tag=snippet,indent=0]
You can pick and choose the relevant annotations for your application. For example,
if you need only support for `@Scheduled`, you can omit `@EnableAsync`. For more
@@ -288,16 +239,6 @@ interface, the `AsyncConfigurer` interface, or both. See the
and {spring-framework-api}/scheduling/annotation/AsyncConfigurer.html[`AsyncConfigurer`]
javadoc for full details.
If you prefer XML configuration, you can use the `<task:annotation-driven>` element,
as the following example shows:
[source,xml,indent=0,subs="verbatim,quotes"]
----
<task:annotation-driven executor="myExecutor" scheduler="myScheduler"/>
<task:executor id="myExecutor" pool-size="5"/>
<task:scheduler id="myScheduler" pool-size="10"/>
----
Note that, with the preceding XML, 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`.