Skip to content

Commit f56f5cf

Browse files
artembilanspring-builds
authored andcommitted
GH-9695: Replace AMQP tx-size with batch-size
Fixes: #9695 Issue link: #9695 The `txSize` in the `SimpleMessageListenerContainer` has been replaced with more reasonable `batchSize`. Spring Integration XML support for AMQP module has missed to fix this change: we didn't have a respective test. * Deprecate `tx-size` (will be removed in `6.5`) XML attribute for the `<amqp:inbound-channel-adapter>` and introduce `batch-size` * Cover with the tests * Fix docs from `tx-size` to `batch-size` (cherry picked from commit 2cf83b5)
1 parent 857f703 commit f56f5cf

File tree

7 files changed

+66
-45
lines changed

7 files changed

+66
-45
lines changed

spring-integration-amqp/src/main/java/org/springframework/integration/amqp/config/AbstractAmqpInboundAdapterParser.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ abstract class AbstractAmqpInboundAdapterParser extends AbstractSingleBeanDefini
5959
"receive-timeout",
6060
"shutdown-timeout",
6161
"tx-size",
62+
"batch-size",
6263
"missing-queues-fatal"
6364
};
6465

@@ -154,7 +155,13 @@ private BeanDefinition buildListenerContainer(Element element, ParserContext par
154155
}
155156
builder.addConstructorArgReference(connectionFactoryRef);
156157
for (String attributeName : CONTAINER_VALUE_ATTRIBUTES) {
157-
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, attributeName);
158+
// TODO remove 'tx-size' in 6.5
159+
if ("tx-size".equals(attributeName)) {
160+
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, attributeName, "batchSize");
161+
}
162+
else {
163+
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, attributeName);
164+
}
158165
}
159166
for (String attributeName : CONTAINER_REFERENCE_ATTRIBUTES) {
160167
IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, attributeName);

spring-integration-amqp/src/main/resources/org/springframework/integration/amqp/config/spring-integration-amqp.xsd

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -969,7 +969,7 @@ standard headers to also be mapped. To map all non-standard headers the 'NON_STA
969969
<xsd:documentation>
970970
Acknowledge Mode for the MessageListenerContainer; default 'AUTO'
971971
meaning the adapter automatically acknowledges the message(s)
972-
according to the tx-size.
972+
according to the batch-size.
973973
</xsd:documentation>
974974
</xsd:annotation>
975975
<xsd:simpleType>
@@ -1039,7 +1039,7 @@ standard headers to also be mapped. To map all non-standard headers the 'NON_STA
10391039
<xsd:documentation>
10401040
Specifies how many messages to send to each consumer in a single request. Often this can be set
10411041
quite high
1042-
to improve throughput. It should be greater than or equal to the tx-size value.
1042+
to improve throughput. It should be greater than or equal to the batch-size value.
10431043
</xsd:documentation>
10441044
</xsd:appinfo>
10451045
</xsd:annotation>
@@ -1117,10 +1117,23 @@ standard headers to also be mapped. To map all non-standard headers the 'NON_STA
11171117
<xsd:annotation>
11181118
<xsd:appinfo>
11191119
<xsd:documentation>
1120+
[DEPRECATED]
11201121
How many messages to process in a single transaction (if the channel is transactional). For best
11211122
results it should be
11221123
less than or equal to the prefetch count.
11231124
Not allowed when 'consumers-per-queue' is set.
1125+
Deprecated in favor of 'batch-size'.
1126+
</xsd:documentation>
1127+
</xsd:appinfo>
1128+
</xsd:annotation>
1129+
</xsd:attribute>
1130+
<xsd:attribute name="batch-size" type="xsd:string">
1131+
<xsd:annotation>
1132+
<xsd:appinfo>
1133+
<xsd:documentation>
1134+
How many messages to process in a single request.
1135+
For best results it should be less than or equal to the prefetch count.
1136+
Not allowed when 'consumers-per-queue' is set.
11241137
</xsd:documentation>
11251138
</xsd:appinfo>
11261139
</xsd:annotation>

spring-integration-amqp/src/test/java/org/springframework/integration/amqp/config/AmqpInboundChannelAdapterParserTests-context.xml

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,12 @@
11
<?xml version="1.0" encoding="UTF-8"?>
22
<beans xmlns="http://www.springframework.org/schema/beans"
3-
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4-
xmlns:amqp="http://www.springframework.org/schema/integration/amqp"
5-
xmlns:int="http://www.springframework.org/schema/integration"
6-
xmlns:rabbit="http://www.springframework.org/schema/rabbit"
7-
xmlns:context="http://www.springframework.org/schema/context"
8-
xmlns:util="http://www.springframework.org/schema/util"
9-
xsi:schemaLocation="http://www.springframework.org/schema/integration/amqp https://www.springframework.org/schema/integration/amqp/spring-integration-amqp.xsd
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xmlns:amqp="http://www.springframework.org/schema/integration/amqp"
5+
xmlns:int="http://www.springframework.org/schema/integration"
6+
xmlns:context="http://www.springframework.org/schema/context"
7+
xmlns:util="http://www.springframework.org/schema/util"
8+
xsi:schemaLocation="http://www.springframework.org/schema/integration/amqp https://www.springframework.org/schema/integration/amqp/spring-integration-amqp.xsd
109
http://www.springframework.org/schema/integration https://www.springframework.org/schema/integration/spring-integration.xsd
11-
http://www.springframework.org/schema/rabbit https://www.springframework.org/schema/rabbit/spring-rabbit.xsd
1210
http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
1311
http://www.springframework.org/schema/util https://www.springframework.org/schema/util/spring-util.xsd
1412
http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
@@ -20,32 +18,34 @@
2018
</util:properties>
2119

2220
<amqp:inbound-channel-adapter id="rabbitInbound" queue-names="inboundchanneladapter.test.1"
23-
batch-mode="EXTRACT_PAYLOADS"/>
21+
batch-mode="EXTRACT_PAYLOADS" tx-size="2"/>
2422

2523
<amqp:inbound-channel-adapter id="autoStartFalse" queue-names="inboundchanneladapter.test.2"
26-
auto-startup="false" phase="123" acknowledge-mode="${ackMode}" missing-queues-fatal="false" />
24+
auto-startup="false" phase="123" acknowledge-mode="${ackMode}"
25+
missing-queues-fatal="false"
26+
batch-size="3"/>
2727

2828
<amqp:inbound-channel-adapter id="withHeaderMapperStandardAndCustomHeaders"
29-
channel="requestChannel" queue-names="inboundchanneladapter.test.2"
30-
auto-startup="false" phase="123"
31-
mapped-request-headers="foo*, STANDARD_REQUEST_HEADERS"/>
29+
channel="requestChannel" queue-names="inboundchanneladapter.test.2"
30+
auto-startup="false" phase="123"
31+
mapped-request-headers="foo*, STANDARD_REQUEST_HEADERS"/>
3232

3333
<amqp:inbound-channel-adapter id="withHeaderMapperOnlyCustomHeaders"
34-
channel="requestChannel" queue-names="inboundchanneladapter.test.2"
35-
auto-startup="false" phase="123"
36-
mapped-request-headers="foo*"/>
34+
channel="requestChannel" queue-names="inboundchanneladapter.test.2"
35+
auto-startup="false" phase="123"
36+
mapped-request-headers="foo*"/>
3737

3838
<amqp:inbound-channel-adapter id="withHeaderMapperNothingToMap"
39-
channel="requestChannel" queue-names="inboundchanneladapter.test.2"
40-
auto-startup="false" phase="123"
41-
mapped-request-headers=""/>
39+
channel="requestChannel" queue-names="inboundchanneladapter.test.2"
40+
auto-startup="false" phase="123"
41+
mapped-request-headers=""/>
4242

4343
<amqp:inbound-channel-adapter id="withHeaderMapperDefaultMapping"
44-
channel="requestChannel" queue-names="inboundchanneladapter.test.2"
45-
auto-startup="false" phase="123"/>
44+
channel="requestChannel" queue-names="inboundchanneladapter.test.2"
45+
auto-startup="false" phase="123"/>
4646

4747
<amqp:inbound-channel-adapter id="dmlc" queue-names="inboundchanneladapter.test.2" consumers-per-queue="2"
48-
auto-startup="false" />
48+
auto-startup="false"/>
4949

5050
<int:channel id="requestChannel">
5151
<int:queue/>

spring-integration-amqp/src/test/java/org/springframework/integration/amqp/config/AmqpInboundChannelAdapterParserTests.java

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2022 the original author or authors.
2+
* Copyright 2002-2024 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -16,8 +16,7 @@
1616

1717
package org.springframework.integration.amqp.config;
1818

19-
import org.junit.Test;
20-
import org.junit.runner.RunWith;
19+
import org.junit.jupiter.api.Test;
2120

2221
import org.springframework.amqp.core.AcknowledgeMode;
2322
import org.springframework.amqp.core.Message;
@@ -37,10 +36,10 @@
3736
import org.springframework.integration.channel.QueueChannel;
3837
import org.springframework.integration.test.util.TestUtils;
3938
import org.springframework.test.annotation.DirtiesContext;
40-
import org.springframework.test.context.ContextConfiguration;
41-
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
39+
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
4240

4341
import static org.assertj.core.api.Assertions.assertThat;
42+
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
4443

4544
/**
4645
* @author Mark Fisher
@@ -49,8 +48,7 @@
4948
*
5049
* @since 2.1
5150
*/
52-
@ContextConfiguration
53-
@RunWith(SpringJUnit4ClassRunner.class)
51+
@SpringJUnitConfig
5452
@DirtiesContext
5553
public class AmqpInboundChannelAdapterParserTests {
5654

@@ -71,6 +69,8 @@ public void verifyIdAsChannel() {
7169
.isInstanceOf(SimpleMessageListenerContainer.class);
7270
assertThat(TestUtils.getPropertyValue(adapter, "batchMode", BatchMode.class))
7371
.isEqualTo(BatchMode.EXTRACT_PAYLOADS);
72+
assertThat(TestUtils.getPropertyValue(adapter, "messageListenerContainer.batchSize", Integer.class))
73+
.isEqualTo(2);
7474
}
7575

7676
@Test
@@ -95,6 +95,8 @@ public void verifyLifeCycle() {
9595
.isEqualTo(AcknowledgeMode.NONE);
9696
assertThat(TestUtils.getPropertyValue(adapter, "messageListenerContainer.missingQueuesFatal", Boolean.class))
9797
.isFalse();
98+
assertThat(TestUtils.getPropertyValue(adapter, "messageListenerContainer.batchSize", Integer.class))
99+
.isEqualTo(3);
98100
}
99101

100102
@Test
@@ -216,14 +218,13 @@ public void withHeaderMapperDefaultMapping() throws Exception {
216218

217219
@Test
218220
public void testInt2971HeaderMapperAndMappedHeadersExclusivity() {
219-
try {
220-
new ClassPathXmlApplicationContext("AmqpInboundChannelAdapterParserTests-headerMapper-fail-context.xml",
221-
this.getClass()).close();
222-
}
223-
catch (BeanDefinitionParsingException e) {
224-
assertThat(e.getMessage().startsWith("Configuration problem: The 'header-mapper' attribute " +
225-
"is mutually exclusive with 'mapped-request-headers' or 'mapped-reply-headers'")).isTrue();
226-
}
221+
assertThatExceptionOfType(BeanDefinitionParsingException.class)
222+
.isThrownBy(() ->
223+
new ClassPathXmlApplicationContext(
224+
"AmqpInboundChannelAdapterParserTests-headerMapper-fail-context.xml",
225+
getClass()))
226+
.withMessageStartingWith("Configuration problem: The 'header-mapper' attribute " +
227+
"is mutually exclusive with 'mapped-request-headers' or 'mapped-reply-headers'");
227228
}
228229

229230
}

src/reference/antora/modules/ROOT/pages/amqp.adoc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ The following adapters are available:
3232
* xref:amqp/inbound-gateway.adoc[Inbound Gateway]
3333
* xref:amqp/outbound-channel-adapter.adoc[Outbound Channel Adapter]
3434
* xref:amqp/outbound-gateway.adoc[Outbound Gateway]
35-
* xref:amqp-async-outbound-gateway[Async Outbound Gateway]
35+
* xref:amqp/async-outbound-gateway.adoc[Async Outbound Gateway]
3636
* xref:amqp/rmq-streams.adoc#rmq-stream-inbound-channel-adapter[RabbitMQ Stream Queue Inbound Channel Adapter]
3737
* xref:amqp/rmq-streams.adoc#rmq-stream-outbound-channel-adapter[RabbitMQ Stream Queue Outbound Channel Adapter]
3838

src/reference/antora/modules/ROOT/pages/amqp/inbound-channel-adapter.adoc

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ XML::
8787
task-executor="" <22>
8888
transaction-attribute="" <23>
8989
transaction-manager="" <24>
90-
tx-size="" <25>
90+
batch-size="" <25>
9191
consumers-per-queue <26>
9292
batch-mode="MESSAGES"/> <27>
9393
@@ -146,7 +146,7 @@ By default, this value is `Integer.MAX_VALUE`, meaning that this container start
146146
Optional.
147147
<17> Tells the AMQP broker how many messages to send to each consumer in a single request.
148148
Often, you can set this value high to improve throughput.
149-
It should be greater than or equal to the transaction size (see the `tx-size` attribute, later in this list).
149+
It should be greater than or equal to the transaction size (see the `batch-size` attribute, later in this list).
150150
Optional (defaults to `1`).
151151
<18> Receive timeout in milliseconds.
152152
Optional (defaults to `1000`).
@@ -173,7 +173,7 @@ If the `channelTransacted` flag is `false`, no transaction semantics apply to th
173173
For further information, see
174174
https://docs.spring.io/spring-amqp/reference/html/%255Freference.html#%5Ftransactions[Transactions with Spring AMQP].
175175
Optional.
176-
<25> Tells the `SimpleMessageListenerContainer` how many messages to process in a single transaction (if the channel is transactional).
176+
<25> Tells the `SimpleMessageListenerContainer` how many messages to process in a single request.
177177
For best results, it should be less than or equal to the value set in `prefetch-count`.
178178
Not allowed when 'consumers-per-queue' is set.
179179
Optional (defaults to `1`).

src/reference/antora/modules/ROOT/pages/amqp/inbound-gateway.adoc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ Java DSL::
1010
+
1111
[source, java, role="primary"]
1212
----
13-
@Bean // return the upper cased payload
13+
@Bean // return the upper-cased payload
1414
public IntegrationFlow amqpInboundGateway(ConnectionFactory connectionFactory) {
1515
return IntegrationFlow.from(Amqp.inboundGateway(connectionFactory, "foo"))
1616
.transform(String.class, String::toUpperCase)

0 commit comments

Comments
 (0)