28
28
import org .springframework .context .annotation .Configuration ;
29
29
import org .springframework .integration .annotation .ServiceActivator ;
30
30
import org .springframework .integration .aws .support .AwsHeaders ;
31
- import org .springframework .integration .aws .support .KPLBackpressureException ;
31
+ import org .springframework .integration .aws .support .KplBackpressureException ;
32
32
import org .springframework .integration .config .EnableIntegration ;
33
+ import org .springframework .integration .handler .advice .RequestHandlerRetryAdvice ;
33
34
import org .springframework .messaging .Message ;
34
35
import org .springframework .messaging .MessageChannel ;
35
36
import org .springframework .messaging .MessageHandler ;
37
+ import org .springframework .messaging .MessageHandlingException ;
36
38
import org .springframework .messaging .support .MessageBuilder ;
39
+ import org .springframework .retry .support .RetryTemplate ;
37
40
import org .springframework .test .annotation .DirtiesContext ;
38
41
import org .springframework .test .context .junit .jupiter .SpringJUnitConfig ;
39
42
40
43
import static org .assertj .core .api .Assertions .assertThat ;
44
+ import static org .assertj .core .api .Assertions .assertThatExceptionOfType ;
41
45
import static org .mockito .ArgumentMatchers .any ;
42
46
import static org .mockito .BDDMockito .given ;
43
47
import static org .mockito .Mockito .clearInvocations ;
44
48
import static org .mockito .Mockito .mock ;
45
49
import static org .mockito .Mockito .verify ;
46
50
47
- /**
51
+ /** The class contains test cases for KplMessageHandler.
52
+ *
48
53
* @author Siddharth Jain
54
+ *
49
55
* @since 3.0.9
50
56
*/
51
57
@ SpringJUnitConfig
@@ -63,42 +69,42 @@ public class KplMessageHandlerTests {
63
69
64
70
@ Test
65
71
@ SuppressWarnings ("unchecked" )
66
- void testKPLMessageHandler_raw_payload_success () {
72
+ void kplMessageHandlerWithRawPayloadBackpressureDisabledSuccess () {
67
73
given (this .kinesisProducer .addUserRecord (any (UserRecord .class )))
68
74
.willReturn (mock ());
69
75
final Message <?> message = MessageBuilder
70
- .withPayload ("message1 " )
71
- .setHeader (AwsHeaders .PARTITION_KEY , "fooKey " )
76
+ .withPayload ("someMessage " )
77
+ .setHeader (AwsHeaders .PARTITION_KEY , "somePartitionKey " )
72
78
.setHeader (AwsHeaders .SEQUENCE_NUMBER , "10" )
73
- .setHeader ("foo " , "bar " )
79
+ .setHeader ("someHeaderKey " , "someHeaderValue " )
74
80
.build ();
75
81
76
82
77
83
ArgumentCaptor <UserRecord > userRecordRequestArgumentCaptor = ArgumentCaptor
78
84
.forClass (UserRecord .class );
79
-
85
+ this . kplMessageHandler . setBackPressureThreshold ( 0 );
80
86
this .kinesisSendChannel .send (message );
81
87
verify (this .kinesisProducer ).addUserRecord (userRecordRequestArgumentCaptor .capture ());
82
- verify (this .kinesisProducer , Mockito .times ( 0 )).getOutstandingRecordsCount ();
88
+ verify (this .kinesisProducer , Mockito .never ( )).getOutstandingRecordsCount ();
83
89
UserRecord userRecord = userRecordRequestArgumentCaptor .getValue ();
84
- assertThat (userRecord .getStreamName ()).isEqualTo ("foo " );
85
- assertThat (userRecord .getPartitionKey ()).isEqualTo ("fooKey " );
90
+ assertThat (userRecord .getStreamName ()).isEqualTo ("someStream " );
91
+ assertThat (userRecord .getPartitionKey ()).isEqualTo ("somePartitionKey " );
86
92
assertThat (userRecord .getExplicitHashKey ()).isNull ();
87
93
}
88
94
89
95
@ Test
90
96
@ SuppressWarnings ("unchecked" )
91
- void testKPLMessageHandler_raw_payload_backpressure_capacity_available_test () {
97
+ void kplMessageHandlerWithRawPayloadBackpressureEnabledCapacityAvailable () {
92
98
given (this .kinesisProducer .addUserRecord (any (UserRecord .class )))
93
99
.willReturn (mock ());
94
100
this .kplMessageHandler .setBackPressureThreshold (2 );
95
101
given (this .kinesisProducer .getOutstandingRecordsCount ())
96
102
.willReturn (1 );
97
103
final Message <?> message = MessageBuilder
98
- .withPayload ("message1 " )
99
- .setHeader (AwsHeaders .PARTITION_KEY , "fooKey " )
104
+ .withPayload ("someMessage " )
105
+ .setHeader (AwsHeaders .PARTITION_KEY , "somePartitionKey " )
100
106
.setHeader (AwsHeaders .SEQUENCE_NUMBER , "10" )
101
- .setHeader ("foo " , "bar " )
107
+ .setHeader ("someHeaderKey " , "someHeaderValue " )
102
108
.build ();
103
109
104
110
@@ -107,40 +113,36 @@ void testKPLMessageHandler_raw_payload_backpressure_capacity_available_test() {
107
113
108
114
this .kinesisSendChannel .send (message );
109
115
verify (this .kinesisProducer ).addUserRecord (userRecordRequestArgumentCaptor .capture ());
110
- verify (this .kinesisProducer , Mockito . times ( 1 ) ).getOutstandingRecordsCount ();
116
+ verify (this .kinesisProducer ).getOutstandingRecordsCount ();
111
117
UserRecord userRecord = userRecordRequestArgumentCaptor .getValue ();
112
- assertThat (userRecord .getStreamName ()).isEqualTo ("foo " );
113
- assertThat (userRecord .getPartitionKey ()).isEqualTo ("fooKey " );
118
+ assertThat (userRecord .getStreamName ()).isEqualTo ("someStream " );
119
+ assertThat (userRecord .getPartitionKey ()).isEqualTo ("somePartitionKey " );
114
120
assertThat (userRecord .getExplicitHashKey ()).isNull ();
115
121
}
116
122
117
123
@ Test
118
124
@ SuppressWarnings ("unchecked" )
119
- void testKPLMessageHandler_raw_payload_backpressure_insufficient_capacity_test () {
125
+ void kplMessageHandlerWithRawPayloadBackpressureEnabledCapacityInsufficient () {
120
126
given (this .kinesisProducer .addUserRecord (any (UserRecord .class )))
121
127
.willReturn (mock ());
122
128
this .kplMessageHandler .setBackPressureThreshold (2 );
123
129
given (this .kinesisProducer .getOutstandingRecordsCount ())
124
130
.willReturn (5 );
125
131
final Message <?> message = MessageBuilder
126
- .withPayload ("message1 " )
127
- .setHeader (AwsHeaders .PARTITION_KEY , "fooKey " )
132
+ .withPayload ("someMessage " )
133
+ .setHeader (AwsHeaders .PARTITION_KEY , "somePartitionKey " )
128
134
.setHeader (AwsHeaders .SEQUENCE_NUMBER , "10" )
129
- .setHeader ("foo " , "bar " )
135
+ .setHeader ("someHeaderKey " , "someHeaderValue " )
130
136
.build ();
131
137
132
- try {
133
- this .kinesisSendChannel .send (message );
134
- }
135
- catch (Exception ex ) {
136
- assertThat (ex ).isNotNull ();
137
- assertThat (ex .getCause ()).isNotNull ();
138
- assertThat (ex .getCause ().getClass ()).isEqualTo (KPLBackpressureException .class );
139
- assertThat (ex .getCause ().getMessage ()).isEqualTo ("Buffer already at max capacity." );
140
- }
138
+ assertThatExceptionOfType (RuntimeException .class )
139
+ .isThrownBy (() -> this .kinesisSendChannel .send (message ))
140
+ .withCauseInstanceOf (MessageHandlingException .class )
141
+ .withRootCauseExactlyInstanceOf (KplBackpressureException .class )
142
+ .withStackTraceContaining ("Cannot send record to kinesis since buffer is at max capacity." );
141
143
142
- verify (this .kinesisProducer , Mockito .times ( 0 )).addUserRecord (any (UserRecord .class ));
143
- verify (this .kinesisProducer , Mockito . times ( 1 ) ).getOutstandingRecordsCount ();
144
+ verify (this .kinesisProducer , Mockito .never ( )).addUserRecord (any (UserRecord .class ));
145
+ verify (this .kinesisProducer ).getOutstandingRecordsCount ();
144
146
}
145
147
146
148
@ AfterEach
@@ -158,13 +160,25 @@ public KinesisProducer kinesisProducer() {
158
160
}
159
161
160
162
@ Bean
161
- @ ServiceActivator (inputChannel = "kinesisSendChannel" )
163
+ public RequestHandlerRetryAdvice retryAdvice () {
164
+ RequestHandlerRetryAdvice requestHandlerRetryAdvice = new RequestHandlerRetryAdvice ();
165
+ requestHandlerRetryAdvice .setRetryTemplate (RetryTemplate .builder ()
166
+ .retryOn (KplBackpressureException .class )
167
+ .exponentialBackoff (100 , 2.0 , 1000 )
168
+ .maxAttempts (3 )
169
+ .build ());
170
+ return requestHandlerRetryAdvice ;
171
+ }
172
+
173
+ @ Bean
174
+ @ ServiceActivator (inputChannel = "kinesisSendChannel" , adviceChain = {"retryAdvice" })
162
175
public MessageHandler kplMessageHandler (KinesisProducer kinesisProducer ) {
163
176
KplMessageHandler kplMessageHandler = new KplMessageHandler (kinesisProducer );
164
177
kplMessageHandler .setAsync (true );
165
- kplMessageHandler .setStream ("foo " );
178
+ kplMessageHandler .setStream ("someStream " );
166
179
return kplMessageHandler ;
167
180
}
181
+
168
182
}
169
183
170
184
}
0 commit comments