1
1
/*
2
- * Copyright 2002-2019 the original author or authors.
2
+ * Copyright 2002-2022 the original author or authors.
3
3
*
4
4
* Licensed under the Apache License, Version 2.0 (the "License");
5
5
* you may not use this file except in compliance with the License.
20
20
21
21
import java .io .BufferedReader ;
22
22
import java .io .InputStreamReader ;
23
+ import java .lang .reflect .Method ;
23
24
import java .sql .Timestamp ;
24
25
import java .util .ArrayList ;
26
+ import java .util .Collection ;
25
27
import java .util .List ;
26
28
import java .util .Properties ;
27
29
import java .util .UUID ;
30
32
31
33
import javax .sql .DataSource ;
32
34
35
+ import org .apache .commons .dbcp2 .DataSourceConnectionFactory ;
36
+ import org .apache .commons .dbcp2 .PoolableConnection ;
37
+ import org .apache .commons .dbcp2 .PoolableConnectionFactory ;
38
+ import org .apache .commons .dbcp2 .PoolingDataSource ;
39
+ import org .apache .commons .pool2 .ObjectPool ;
40
+ import org .apache .commons .pool2 .impl .GenericObjectPool ;
41
+ import org .apache .commons .pool2 .impl .GenericObjectPoolConfig ;
33
42
import org .junit .jupiter .api .BeforeEach ;
34
43
import org .junit .jupiter .api .Test ;
35
44
36
45
import org .springframework .beans .factory .annotation .Autowired ;
46
+ import org .springframework .beans .factory .support .DefaultListableBeanFactory ;
47
+ import org .springframework .core .MethodParameter ;
48
+ import org .springframework .core .annotation .SynthesizingMethodParameter ;
37
49
import org .springframework .integration .IntegrationMessageHeaderAccessor ;
38
50
import org .springframework .integration .channel .DirectChannel ;
51
+ import org .springframework .integration .handler .support .CollectionArgumentResolver ;
39
52
import org .springframework .integration .history .MessageHistory ;
40
53
import org .springframework .integration .store .MessageGroup ;
41
54
import org .springframework .integration .support .MessageBuilder ;
47
60
import org .springframework .messaging .support .GenericMessage ;
48
61
import org .springframework .test .annotation .DirtiesContext ;
49
62
import org .springframework .test .context .junit .jupiter .SpringJUnitConfig ;
63
+ import org .springframework .transaction .annotation .Propagation ;
50
64
import org .springframework .transaction .annotation .Transactional ;
51
65
52
66
/**
@@ -90,7 +104,6 @@ public void testAddAndGet() {
90
104
91
105
@ Test
92
106
public void testWithMessageHistory () {
93
-
94
107
Message <?> message = new GenericMessage <>("Hello" );
95
108
DirectChannel fooChannel = new DirectChannel ();
96
109
fooChannel .setBeanName ("fooChannel" );
@@ -185,14 +198,14 @@ public void testAddAndUpdateWithChange() {
185
198
}
186
199
187
200
@ Test
188
- public void testAddAndRemoveMessageGroup () throws Exception {
201
+ public void testAddAndRemoveMessageGroup () {
189
202
Message <String > message = MessageBuilder .withPayload ("foo" ).build ();
190
203
message = messageStore .addMessage (message );
191
204
assertThat (messageStore .removeMessage (message .getHeaders ().getId ())).isNotNull ();
192
205
}
193
206
194
207
@ Test
195
- public void testAddAndGetMessageGroup () throws Exception {
208
+ public void testAddAndGetMessageGroup () {
196
209
String groupId = "X" ;
197
210
Message <String > message = MessageBuilder .withPayload ("foo" ).setCorrelationId (groupId ).build ();
198
211
long now = System .currentTimeMillis ();
@@ -203,7 +216,7 @@ public void testAddAndGetMessageGroup() throws Exception {
203
216
}
204
217
205
218
@ Test
206
- public void testAddAndRemoveMessageFromMessageGroup () throws Exception {
219
+ public void testAddAndRemoveMessageFromMessageGroup () {
207
220
String groupId = "X" ;
208
221
Message <String > message = MessageBuilder .withPayload ("foo" ).setCorrelationId (groupId ).build ();
209
222
messageStore .addMessagesToGroup (groupId , message );
@@ -213,7 +226,7 @@ public void testAddAndRemoveMessageFromMessageGroup() throws Exception {
213
226
}
214
227
215
228
@ Test
216
- public void testAddAndRemoveMessagesFromMessageGroup () throws Exception {
229
+ public void testAddAndRemoveMessagesFromMessageGroup () {
217
230
String groupId = "X" ;
218
231
this .messageStore .setRemoveBatchSize (10 );
219
232
List <Message <?>> messages = new ArrayList <>();
@@ -230,7 +243,7 @@ public void testAddAndRemoveMessagesFromMessageGroup() throws Exception {
230
243
}
231
244
232
245
@ Test
233
- public void testRemoveMessageGroup () throws Exception {
246
+ public void testRemoveMessageGroup () {
234
247
JdbcTemplate template = new JdbcTemplate (this .dataSource );
235
248
template .afterPropertiesSet ();
236
249
String groupId = "X" ;
@@ -247,7 +260,7 @@ public void testRemoveMessageGroup() throws Exception {
247
260
}
248
261
249
262
@ Test
250
- public void testCompleteMessageGroup () throws Exception {
263
+ public void testCompleteMessageGroup () {
251
264
String groupId = "X" ;
252
265
Message <String > message = MessageBuilder .withPayload ("foo" ).setCorrelationId (groupId ).build ();
253
266
messageStore .addMessagesToGroup (groupId , message );
@@ -319,7 +332,7 @@ public void testExpireMessageGroupOnCreateOnly() throws Exception {
319
332
template .afterPropertiesSet ();
320
333
321
334
template .update ("UPDATE INT_MESSAGE_GROUP set CREATED_DATE=? where GROUP_KEY=? and REGION=?" ,
322
- ( PreparedStatementSetter ) ps -> {
335
+ ps -> {
323
336
ps .setTimestamp (1 , new Timestamp (System .currentTimeMillis () - 10000 ));
324
337
ps .setString (2 , UUIDConverter .getUUID (groupId ).toString ());
325
338
ps .setString (3 , "DEFAULT" );
@@ -333,7 +346,7 @@ public void testExpireMessageGroupOnCreateOnly() throws Exception {
333
346
}
334
347
335
348
@ Test
336
- public void testExpireMessageGroupOnIdleOnly () throws Exception {
349
+ public void testExpireMessageGroupOnIdleOnly () {
337
350
String groupId = "X" ;
338
351
Message <String > message = MessageBuilder .withPayload ("foo" ).setCorrelationId (groupId ).build ();
339
352
messageStore .setTimeoutOnIdle (true );
@@ -406,7 +419,6 @@ public void testMessagePollingFromTheGroup() throws Exception {
406
419
407
420
@ Test
408
421
public void testSameMessageToMultipleGroups () {
409
-
410
422
final String group1Id = "group1" ;
411
423
final String group2Id = "group2" ;
412
424
@@ -436,7 +448,7 @@ public void testSameMessageToMultipleGroups() {
436
448
}
437
449
438
450
@ Test
439
- public void testSameMessageAndGroupToMultipleRegions () throws Exception {
451
+ public void testSameMessageAndGroupToMultipleRegions () {
440
452
441
453
final String groupId = "myGroup" ;
442
454
final String region1 = "region1" ;
@@ -474,7 +486,7 @@ public void testSameMessageAndGroupToMultipleRegions() throws Exception {
474
486
}
475
487
476
488
@ Test
477
- public void testCompletedNotExpiredGroupINT3037 () throws Exception {
489
+ public void testCompletedNotExpiredGroupINT3037 () {
478
490
/*
479
491
* based on the aggregator scenario as follows;
480
492
*
@@ -528,4 +540,44 @@ public void testMessageGroupCondition() {
528
540
assertThat (this .messageStore .getMessageGroup (groupId ).getCondition ()).isEqualTo ("testCondition" );
529
541
}
530
542
543
+
544
+ @ Test
545
+ @ Transactional (propagation = Propagation .NEVER )
546
+ public void testMessageGroupStreamNoConnectionPoolLeak () throws NoSuchMethodException {
547
+ DataSourceConnectionFactory connFactory = new DataSourceConnectionFactory (this .dataSource );
548
+ PoolableConnectionFactory poolFactory = new PoolableConnectionFactory (connFactory , null );
549
+ GenericObjectPoolConfig <PoolableConnection > config = new GenericObjectPoolConfig <>();
550
+ config .setMaxTotal (2 );
551
+ config .setMaxWaitMillis (500 );
552
+ ObjectPool <PoolableConnection > connPool = new GenericObjectPool <>(poolFactory , config );
553
+ poolFactory .setPool (connPool );
554
+ PoolingDataSource <PoolableConnection > poolingDataSource = new PoolingDataSource <>(connPool );
555
+
556
+ JdbcMessageStore pooledMessageStore = new JdbcMessageStore (poolingDataSource );
557
+
558
+ CollectionArgumentResolver collectionArgumentResolver = new CollectionArgumentResolver (true );
559
+ collectionArgumentResolver .setBeanFactory (new DefaultListableBeanFactory ());
560
+ Method methodForCollectionOfPayloads = getClass ().getMethod ("methodForCollectionOfPayloads" , Collection .class );
561
+ MethodParameter methodParameter = SynthesizingMethodParameter .forExecutable (methodForCollectionOfPayloads , 0 );
562
+
563
+ String groupId = "X" ;
564
+ Message <String > message = MessageBuilder .withPayload ("test data" ).build ();
565
+ pooledMessageStore .addMessagesToGroup (groupId , message );
566
+
567
+ // Before the stream close fix in the 'CollectionArgumentResolver'
568
+ // it failed with "Cannot get a connection, pool error Timeout waiting for idle object"
569
+ for (int i = 0 ; i < 3 ; i ++) {
570
+ Object result =
571
+ collectionArgumentResolver .resolveArgument (methodParameter ,
572
+ new GenericMessage <>(pooledMessageStore .getMessageGroup (groupId ).getMessages ()));
573
+
574
+ assertThat (result ).isInstanceOf (Collection .class ).asList ().hasSize (1 ).contains ("test data" );
575
+ }
576
+
577
+ pooledMessageStore .removeMessageGroup (groupId );
578
+ }
579
+
580
+ public void methodForCollectionOfPayloads (Collection <String > payloads ) {
581
+ }
582
+
531
583
}
0 commit comments