Skip to content

Commit a62832c

Browse files
artembilangaryrussell
authored andcommitted
INT-4458: Do not expose recursive generics API (#2432)
* INT-4458: Do not expose recursive generics API JIRA: https://jira.spring.io/browse/INT-4458 According Kotlin generics system restrictions we can't expose API based on the recursive generics, like we have with Java DSL for JMS * Replace explicit recursive generics on factory method with the wildcard (`?`). This way both Kotlin and Java are able to instantiate target object and perform the proper chain API auto-completion * Fix `JmsInboundChannelAdapterSpec` to deal with provided `S` type for the `configureListenerContainer()` - the way we can configure a `JmsDefaultListenerContainerSpec` * Add `kotlin-spring` Gradle plugin to avoid extra `open` modificator on `@Bean` methods * Add `JmsDslKotlinTests.kt` **Cherry-pick to 5.0.x excluding Kotlin support** * Fix `Amqp` DSL factory for recursive generics * Polishing for Kotlin tests
1 parent f970bf0 commit a62832c

File tree

7 files changed

+185
-82
lines changed

7 files changed

+185
-82
lines changed

build.gradle

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
buildscript {
2-
ext.kotlinVersion = '1.2.40'
2+
ext.kotlinVersion = '1.2.41'
33
repositories {
44
maven { url 'https://repo.spring.io/plugins-release' }
55
}
66
dependencies {
77
classpath 'io.spring.gradle:docbook-reference-plugin:0.3.1'
88
classpath 'org.asciidoctor:asciidoctor-gradle-plugin:1.5.3'
99
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion"
10+
classpath "org.jetbrains.kotlin:kotlin-allopen:$kotlinVersion"
1011
}
1112
}
1213

@@ -61,6 +62,7 @@ subprojects { subproject ->
6162
apply plugin: 'jacoco'
6263
apply plugin: 'checkstyle'
6364
apply plugin: 'kotlin'
65+
apply plugin: 'kotlin-spring'
6466

6567
sourceSets {
6668
test {
@@ -77,6 +79,7 @@ subprojects { subproject ->
7779

7880
compileTestKotlin {
7981
kotlinOptions {
82+
freeCompilerArgs = ['-Xjsr305=strict']
8083
jvmTarget = '1.8'
8184
}
8285
}
@@ -176,7 +179,7 @@ subprojects { subproject ->
176179
exclude group: 'org.jetbrains.kotlin', module: 'kotlin-reflect'
177180
}
178181

179-
testCompile "org.jetbrains.kotlin:kotlin-stdlib:$kotlinVersion"
182+
testCompile "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlinVersion"
180183
testRuntime "org.jetbrains.kotlin:kotlin-reflect:$kotlinVersion"
181184

182185
}

spring-integration-amqp/src/main/java/org/springframework/integration/amqp/dsl/Amqp.java

Lines changed: 12 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,8 @@ public static AmqpInboundGatewaySMLCSpec inboundGateway(ConnectionFactory connec
5353
* @param queueNames the queueNames.
5454
* @return the AmqpInboundGatewaySpec.
5555
*/
56-
public static AmqpInboundGatewaySMLCSpec inboundGateway(ConnectionFactory connectionFactory, AmqpTemplate amqpTemplate,
57-
String... queueNames) {
56+
public static AmqpInboundGatewaySMLCSpec inboundGateway(ConnectionFactory connectionFactory,
57+
AmqpTemplate amqpTemplate, String... queueNames) {
5858

5959
SimpleMessageListenerContainer listenerContainer = new SimpleMessageListenerContainer(connectionFactory);
6060
listenerContainer.setQueueNames(queueNames);
@@ -81,8 +81,8 @@ public static AmqpInboundGatewaySMLCSpec inboundGateway(ConnectionFactory connec
8181
* @param queues the queues.
8282
* @return the AmqpInboundGatewaySpec.
8383
*/
84-
public static AmqpInboundGatewaySMLCSpec inboundGateway(ConnectionFactory connectionFactory, AmqpTemplate amqpTemplate,
85-
Queue... queues) {
84+
public static AmqpInboundGatewaySMLCSpec inboundGateway(ConnectionFactory connectionFactory,
85+
AmqpTemplate amqpTemplate, Queue... queues) {
8686

8787
SimpleMessageListenerContainer listenerContainer = new SimpleMessageListenerContainer(connectionFactory);
8888
listenerContainer.setQueues(queues);
@@ -266,51 +266,41 @@ public static AmqpAsyncOutboundGatewaySpec asyncOutboundGateway(AsyncRabbitTempl
266266
/**
267267
* Create an initial AmqpPollableMessageChannelSpec.
268268
* @param connectionFactory the connectionFactory.
269-
* @param <S> the spec type.
270269
* @return the AmqpPollableMessageChannelSpec.
271270
*/
272-
public static <S extends AmqpPollableMessageChannelSpec<S>> AmqpPollableMessageChannelSpec<S> pollableChannel(
273-
ConnectionFactory connectionFactory) {
274-
271+
public static AmqpPollableMessageChannelSpec<?> pollableChannel(ConnectionFactory connectionFactory) {
275272
return pollableChannel(null, connectionFactory);
276273
}
277274

278275
/**
279276
* Create an initial AmqpPollableMessageChannelSpec.
280277
* @param id the id.
281278
* @param connectionFactory the connectionFactory.
282-
* @param <S> the spec type.
283279
* @return the AmqpPollableMessageChannelSpec.
284280
*/
285-
public static <S extends AmqpPollableMessageChannelSpec<S>> AmqpPollableMessageChannelSpec<S> pollableChannel(
286-
String id, ConnectionFactory connectionFactory) {
287-
288-
return new AmqpPollableMessageChannelSpec<S>(connectionFactory).id(id);
281+
public static AmqpPollableMessageChannelSpec<?> pollableChannel(String id, ConnectionFactory connectionFactory) {
282+
return new AmqpPollableMessageChannelSpec<>(connectionFactory)
283+
.id(id);
289284
}
290285

291286
/**
292287
* Create an initial AmqpMessageChannelSpec.
293288
* @param connectionFactory the connectionFactory.
294-
* @param <S> the spec type.
295289
* @return the AmqpMessageChannelSpec.
296290
*/
297-
public static <S extends AmqpMessageChannelSpec<S>> AmqpMessageChannelSpec<S> channel(
298-
ConnectionFactory connectionFactory) {
299-
291+
public static AmqpMessageChannelSpec<?> channel(ConnectionFactory connectionFactory) {
300292
return channel(null, connectionFactory);
301293
}
302294

303295
/**
304296
* Create an initial AmqpMessageChannelSpec.
305297
* @param id the id.
306298
* @param connectionFactory the connectionFactory.
307-
* @param <S> the spec type.
308299
* @return the AmqpMessageChannelSpec.
309300
*/
310-
public static <S extends AmqpMessageChannelSpec<S>> AmqpMessageChannelSpec<S> channel(String id,
311-
ConnectionFactory connectionFactory) {
312-
313-
return new AmqpMessageChannelSpec<S>(connectionFactory).id(id);
301+
public static AmqpMessageChannelSpec<?> channel(String id, ConnectionFactory connectionFactory) {
302+
return new AmqpMessageChannelSpec<>(connectionFactory)
303+
.id(id);
314304
}
315305

316306
/**

spring-integration-core/src/test/kotlin/org/springframework/integration/dsl/routers/RouterDslTests.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,10 +68,10 @@ class RouterDslTests {
6868

6969
@Configuration
7070
@EnableIntegration
71-
open class Config {
71+
class Config {
7272

7373
@Bean
74-
open fun routerTwoSubFlows() =
74+
fun routerTwoSubFlows() =
7575
IntegrationFlow { f ->
7676
f.split()
7777
.route<Int, Boolean>({ p -> p % 2 == 0 },

spring-integration-jms/src/main/java/org/springframework/integration/jms/dsl/Jms.java

Lines changed: 44 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2014-2017 the original author or authors.
2+
* Copyright 2014-2018 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.
@@ -36,47 +36,40 @@ public final class Jms {
3636
/**
3737
* The factory to produce a {@link JmsPollableMessageChannelSpec}.
3838
* @param connectionFactory the JMS ConnectionFactory to build on
39-
* @param <S> the {@link JmsPollableMessageChannelSpec} inheritor type
4039
* @return the {@link JmsPollableMessageChannelSpec} instance
4140
*/
42-
public static <S extends JmsPollableMessageChannelSpec<S>> JmsPollableMessageChannelSpec<S> pollableChannel(
43-
ConnectionFactory connectionFactory) {
41+
public static JmsPollableMessageChannelSpec<?> pollableChannel(ConnectionFactory connectionFactory) {
4442
return pollableChannel(null, connectionFactory);
4543
}
4644

4745
/**
4846
* The factory to produce a {@link JmsPollableMessageChannelSpec}.
4947
* @param id the bean name for the target {@code PollableChannel} component
5048
* @param connectionFactory the JMS ConnectionFactory to build on
51-
* @param <S> the {@link JmsPollableMessageChannelSpec} inheritor type
5249
* @return the {@link JmsPollableMessageChannelSpec} instance
5350
*/
54-
public static <S extends JmsPollableMessageChannelSpec<S>> JmsPollableMessageChannelSpec<S> pollableChannel(
55-
String id, ConnectionFactory connectionFactory) {
56-
return new JmsPollableMessageChannelSpec<S>(connectionFactory).id(id);
51+
public static JmsPollableMessageChannelSpec<?> pollableChannel(String id, ConnectionFactory connectionFactory) {
52+
return new JmsPollableMessageChannelSpec<>(connectionFactory).id(id);
5753
}
5854

5955
/**
6056
* The factory to produce a {@link JmsMessageChannelSpec}.
6157
* @param connectionFactory the JMS ConnectionFactory to build on
62-
* @param <S> the {@link JmsMessageChannelSpec} inheritor type
6358
* @return the {@link JmsMessageChannelSpec} instance
6459
*/
65-
public static <S extends JmsMessageChannelSpec<S>> JmsMessageChannelSpec<S> channel(
66-
ConnectionFactory connectionFactory) {
60+
public static JmsMessageChannelSpec<?> channel(ConnectionFactory connectionFactory) {
6761
return channel(null, connectionFactory);
6862
}
6963

7064
/**
7165
* The factory to produce a {@link JmsMessageChannelSpec}.
7266
* @param id the bean name for the target {@code MessageChannel} component
7367
* @param connectionFactory the JMS ConnectionFactory to build on
74-
* @param <S> the {@link JmsMessageChannelSpec} inheritor type
7568
* @return the {@link JmsMessageChannelSpec} instance
7669
*/
77-
public static <S extends JmsMessageChannelSpec<S>> JmsMessageChannelSpec<S> channel(String id,
78-
ConnectionFactory connectionFactory) {
79-
return new JmsMessageChannelSpec<S>(connectionFactory).id(id);
70+
public static JmsMessageChannelSpec<?> channel(String id, ConnectionFactory connectionFactory) {
71+
return new JmsMessageChannelSpec<>(connectionFactory)
72+
.id(id);
8073
}
8174

8275
/**
@@ -96,18 +89,17 @@ public static JmsPublishSubscribeMessageChannelSpec publishSubscribeChannel(Conn
9689
*/
9790
public static JmsPublishSubscribeMessageChannelSpec publishSubscribeChannel(String id,
9891
ConnectionFactory connectionFactory) {
92+
9993
return new JmsPublishSubscribeMessageChannelSpec(connectionFactory).id(id);
10094
}
10195

10296
/**
10397
* The factory to produce a {@link JmsOutboundChannelAdapterSpec}.
10498
* @param jmsTemplate the JmsTemplate to build on
105-
* @param <S> the {@link JmsOutboundChannelAdapterSpec} inheritor type
10699
* @return the {@link JmsOutboundChannelAdapterSpec} instance
107100
*/
108-
public static <S extends JmsOutboundChannelAdapterSpec<S>> JmsOutboundChannelAdapterSpec<S> outboundAdapter(
109-
JmsTemplate jmsTemplate) {
110-
return new JmsOutboundChannelAdapterSpec<S>(jmsTemplate);
101+
public static JmsOutboundChannelAdapterSpec<?> outboundAdapter(JmsTemplate jmsTemplate) {
102+
return new JmsOutboundChannelAdapterSpec<>(jmsTemplate);
111103
}
112104

113105
/**
@@ -117,18 +109,17 @@ public static <S extends JmsOutboundChannelAdapterSpec<S>> JmsOutboundChannelAda
117109
*/
118110
public static JmsOutboundChannelAdapterSpec.JmsOutboundChannelSpecTemplateAware outboundAdapter(
119111
ConnectionFactory connectionFactory) {
112+
120113
return new JmsOutboundChannelAdapterSpec.JmsOutboundChannelSpecTemplateAware(connectionFactory);
121114
}
122115

123116
/**
124117
* The factory to produce a {@link JmsInboundChannelAdapterSpec}.
125118
* @param jmsTemplate the JmsTemplate to build on
126-
* @param <S> the {@link JmsInboundChannelAdapterSpec} inheritor type
127119
* @return the {@link JmsInboundChannelAdapterSpec} instance
128120
*/
129-
public static <S extends JmsInboundChannelAdapterSpec<S>> JmsInboundChannelAdapterSpec<S> inboundAdapter(
130-
JmsTemplate jmsTemplate) {
131-
return new JmsInboundChannelAdapterSpec<S>(jmsTemplate);
121+
public static JmsInboundChannelAdapterSpec<?> inboundAdapter(JmsTemplate jmsTemplate) {
122+
return new JmsInboundChannelAdapterSpec<>(jmsTemplate);
132123
}
133124

134125
/**
@@ -138,6 +129,7 @@ public static <S extends JmsInboundChannelAdapterSpec<S>> JmsInboundChannelAdapt
138129
*/
139130
public static JmsInboundChannelAdapterSpec.JmsInboundChannelSpecTemplateAware inboundAdapter(
140131
ConnectionFactory connectionFactory) {
132+
141133
return new JmsInboundChannelAdapterSpec.JmsInboundChannelSpecTemplateAware(connectionFactory);
142134
}
143135

@@ -153,12 +145,10 @@ public static JmsOutboundGatewaySpec outboundGateway(ConnectionFactory connectio
153145
/**
154146
* The factory to produce a {@link JmsOutboundGatewaySpec}.
155147
* @param listenerContainer the JMS {@link AbstractMessageListenerContainer} to build on
156-
* @param <S> the {@link JmsInboundGatewaySpec} inheritor type
157148
* @return the {@link JmsOutboundGatewaySpec} instance
158149
*/
159-
public static <S extends JmsInboundGatewaySpec<S>> JmsInboundGatewaySpec<S> inboundGateway(
160-
AbstractMessageListenerContainer listenerContainer) {
161-
return new JmsInboundGatewaySpec<S>(listenerContainer);
150+
public static JmsInboundGatewaySpec<?> inboundGateway(AbstractMessageListenerContainer listenerContainer) {
151+
return new JmsInboundGatewaySpec<>(listenerContainer);
162152
}
163153

164154
/**
@@ -168,26 +158,35 @@ public static <S extends JmsInboundGatewaySpec<S>> JmsInboundGatewaySpec<S> inbo
168158
*/
169159
public static JmsInboundGatewaySpec.JmsInboundGatewayListenerContainerSpec<JmsDefaultListenerContainerSpec, DefaultMessageListenerContainer>
170160
inboundGateway(ConnectionFactory connectionFactory) {
171-
return inboundGateway(connectionFactory, DefaultMessageListenerContainer.class);
161+
162+
try {
163+
return new JmsInboundGatewaySpec.JmsInboundGatewayListenerContainerSpec<>(
164+
new JmsDefaultListenerContainerSpec()
165+
.connectionFactory(connectionFactory));
166+
}
167+
catch (Exception e) {
168+
throw new IllegalStateException(e);
169+
}
172170
}
173171

174172
/**
175173
* The factory to produce a {@link JmsOutboundGatewaySpec}.
176174
* @param connectionFactory the JMS ConnectionFactory to build on
177175
* @param containerClass the {@link AbstractMessageListenerContainer} implementation class
178176
* to instantiate listener container
179-
* @param <S> the {@link JmsListenerContainerSpec} inheritor type
180177
* @param <C> the {@link AbstractMessageListenerContainer} inheritor type
181178
* @return the {@link JmsOutboundGatewaySpec} instance
182179
*/
183-
public static <S extends JmsListenerContainerSpec<S, C>, C extends AbstractMessageListenerContainer>
184-
JmsInboundGatewaySpec.JmsInboundGatewayListenerContainerSpec<S, C> inboundGateway(ConnectionFactory connectionFactory,
185-
Class<C> containerClass) {
180+
@SuppressWarnings({ "rawtypes", "unchecked" })
181+
public static <C extends AbstractMessageListenerContainer>
182+
JmsInboundGatewaySpec.JmsInboundGatewayListenerContainerSpec<?, C> inboundGateway(
183+
ConnectionFactory connectionFactory, Class<C> containerClass) {
184+
186185
try {
187-
JmsListenerContainerSpec<S, C> spec =
188-
new JmsListenerContainerSpec<S, C>(containerClass)
186+
JmsListenerContainerSpec<?, C> spec =
187+
new JmsListenerContainerSpec<>(containerClass)
189188
.connectionFactory(connectionFactory);
190-
return new JmsInboundGatewaySpec.JmsInboundGatewayListenerContainerSpec<S, C>(spec);
189+
return new JmsInboundGatewaySpec.JmsInboundGatewayListenerContainerSpec(spec);
191190
}
192191
catch (Exception e) {
193192
throw new IllegalStateException(e);
@@ -197,13 +196,10 @@ JmsInboundGatewaySpec.JmsInboundGatewayListenerContainerSpec<S, C> inboundGatewa
197196
/**
198197
* The factory to produce a {@link JmsMessageDrivenChannelAdapterSpec}.
199198
* @param listenerContainer the {@link AbstractMessageListenerContainer} to build on
200-
* @param <S> the {@link JmsMessageDrivenChannelAdapterSpec} inheritor type
201199
* @return the {@link JmsMessageDrivenChannelAdapterSpec} instance
202200
*/
203-
public static <S extends JmsMessageDrivenChannelAdapterSpec<S>>
204-
JmsMessageDrivenChannelAdapterSpec<S> messageDrivenChannelAdapter(
205-
AbstractMessageListenerContainer listenerContainer) {
206-
return new JmsMessageDrivenChannelAdapterSpec<S>(listenerContainer);
201+
public static JmsMessageDrivenChannelAdapterSpec<?> messageDrivenChannelAdapter(AbstractMessageListenerContainer listenerContainer) {
202+
return new JmsMessageDrivenChannelAdapterSpec<>(listenerContainer);
207203
}
208204

209205
/**
@@ -215,7 +211,8 @@ JmsMessageDrivenChannelAdapterSpec<S> messageDrivenChannelAdapter(
215211
messageDrivenChannelAdapter(ConnectionFactory connectionFactory) {
216212
try {
217213
return new JmsMessageDrivenChannelAdapterSpec.JmsMessageDrivenChannelAdapterListenerContainerSpec<>(
218-
new JmsDefaultListenerContainerSpec().connectionFactory(connectionFactory));
214+
new JmsDefaultListenerContainerSpec()
215+
.connectionFactory(connectionFactory));
219216
}
220217
catch (Exception e) {
221218
throw new IllegalStateException(e);
@@ -227,18 +224,18 @@ JmsMessageDrivenChannelAdapterSpec<S> messageDrivenChannelAdapter(
227224
* @param connectionFactory the JMS ConnectionFactory to build on
228225
* @param containerClass the {@link AbstractMessageListenerContainer} implementation class
229226
* to instantiate listener container
230-
* @param <S> the {@link JmsListenerContainerSpec} inheritor type
231227
* @param <C> the {@link AbstractMessageListenerContainer} inheritor type
232228
* @return the {@link JmsMessageDrivenChannelAdapterSpec} instance
233229
*/
234-
public static <S extends JmsListenerContainerSpec<S, C>, C extends AbstractMessageListenerContainer>
235-
JmsMessageDrivenChannelAdapterSpec.JmsMessageDrivenChannelAdapterListenerContainerSpec<S, C>
230+
@SuppressWarnings({ "rawtypes", "unchecked" })
231+
public static <C extends AbstractMessageListenerContainer>
232+
JmsMessageDrivenChannelAdapterSpec.JmsMessageDrivenChannelAdapterListenerContainerSpec<?, C>
236233
messageDrivenChannelAdapter(ConnectionFactory connectionFactory, Class<C> containerClass) {
237234
try {
238-
S spec =
239-
new JmsListenerContainerSpec<S, C>(containerClass)
235+
JmsListenerContainerSpec<?, C> spec =
236+
new JmsListenerContainerSpec<>(containerClass)
240237
.connectionFactory(connectionFactory);
241-
return new JmsMessageDrivenChannelAdapterSpec.JmsMessageDrivenChannelAdapterListenerContainerSpec<>(spec);
238+
return new JmsMessageDrivenChannelAdapterSpec.JmsMessageDrivenChannelAdapterListenerContainerSpec(spec);
242239
}
243240
catch (Exception e) {
244241
throw new IllegalStateException(e);

spring-integration-jms/src/main/java/org/springframework/integration/jms/dsl/JmsInboundGatewaySpec.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2016-2017 the original author or authors.
2+
* Copyright 2016-2018 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.
@@ -35,6 +35,7 @@
3535
* @param <S> the target {@link JmsInboundGatewaySpec} implementation type.
3636
*
3737
* @author Artem Bilan
38+
*
3839
* @since 5.0
3940
*/
4041
public class JmsInboundGatewaySpec<S extends JmsInboundGatewaySpec<S>>
@@ -184,9 +185,9 @@ public S extractReplyPayload(boolean extractReplyPayload) {
184185
public static class JmsInboundGatewayListenerContainerSpec<S extends JmsListenerContainerSpec<S, C>, C extends AbstractMessageListenerContainer>
185186
extends JmsInboundGatewaySpec<JmsInboundGatewayListenerContainerSpec<S, C>> {
186187

187-
private final JmsListenerContainerSpec<S, C> spec;
188+
private final S spec;
188189

189-
JmsInboundGatewayListenerContainerSpec(JmsListenerContainerSpec<S, C> spec) {
190+
JmsInboundGatewayListenerContainerSpec(S spec) {
190191
super(spec.get());
191192
this.spec = spec;
192193
this.spec.get().setAutoStartup(false);
@@ -213,7 +214,7 @@ public JmsInboundGatewayListenerContainerSpec<S, C> destination(String destinati
213214
}
214215

215216
public JmsInboundGatewayListenerContainerSpec<S, C> configureListenerContainer(
216-
Consumer<JmsListenerContainerSpec<S, C>> configurer) {
217+
Consumer<S> configurer) {
217218
Assert.notNull(configurer, "'configurer' must not be null");
218219
configurer.accept(this.spec);
219220
return _this();

0 commit comments

Comments
 (0)