Skip to content

Commit 8dd1332

Browse files
authored
Fix NPEs in DSL Specs (#8597)
* Fix NPEs in DSL Specs The `BaseWsInboundGatewaySpec` and `TailAdapterSpec` don't override super methods and when we call them we fail with NPE since `target` was not populated. * Fix `BaseWsInboundGatewaySpec` and its inheritors to populate the `target` from their ctors. * Remove redundant methods from `BaseWsInboundGatewaySpec` hierarchy * Propagate `AbstractWebServiceInboundGateway` properties directly to the target from the `BaseWsInboundGatewaySpec` inheritors * Override `MessageProducerSpec` methods in the `TailAdapterSpec` to populate respective option into the `FileTailInboundChannelAdapterFactoryBean` * Expose more missed options for producer endpoint in the `FileTailInboundChannelAdapterFactoryBean` **Cherry-pick to `6.0.x` & `5.5.x`** * * `acceptIfNotNull()` for `errorMessageStrategy` in the `FileTailInboundChannelAdapterFactoryBean` * * Fix `Unmarshaller` population logic in the `MarshallingWsInboundGatewaySpec`
1 parent feb4705 commit 8dd1332

File tree

8 files changed

+100
-62
lines changed

8 files changed

+100
-62
lines changed

spring-integration-core/src/main/java/org/springframework/integration/dsl/MessagingGatewaySpec.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
public abstract class MessagingGatewaySpec<S extends MessagingGatewaySpec<S, G>, G extends MessagingGatewaySupport>
3636
extends IntegrationComponentSpec<S, G> {
3737

38-
public MessagingGatewaySpec(@Nullable G gateway) {
38+
public MessagingGatewaySpec(G gateway) {
3939
this.target = gateway;
4040
}
4141

spring-integration-file/src/main/java/org/springframework/integration/file/config/FileTailInboundChannelAdapterFactoryBean.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import org.springframework.integration.file.tail.ApacheCommonsFileTailingMessageProducer;
3030
import org.springframework.integration.file.tail.FileTailingMessageProducerSupport;
3131
import org.springframework.integration.file.tail.OSDelegatingFileTailingMessageProducer;
32+
import org.springframework.integration.support.ErrorMessageStrategy;
3233
import org.springframework.lang.Nullable;
3334
import org.springframework.messaging.MessageChannel;
3435
import org.springframework.scheduling.TaskScheduler;
@@ -84,6 +85,12 @@ public class FileTailInboundChannelAdapterFactoryBean extends AbstractFactoryBea
8485

8586
private ApplicationEventPublisher applicationEventPublisher;
8687

88+
private long sendTimeout;
89+
90+
private boolean shouldTrack;
91+
92+
private ErrorMessageStrategy errorMessageStrategy;
93+
8794
public void setNativeOptions(String nativeOptions) {
8895
if (StringUtils.hasText(nativeOptions)) {
8996
this.nativeOptions = nativeOptions;
@@ -166,6 +173,18 @@ public void setPhase(int phase) {
166173
this.phase = phase;
167174
}
168175

176+
public void setSendTimeout(long sendTimeout) {
177+
this.sendTimeout = sendTimeout;
178+
}
179+
180+
public void setShouldTrack(boolean shouldTrack) {
181+
this.shouldTrack = shouldTrack;
182+
}
183+
184+
public void setErrorMessageStrategy(ErrorMessageStrategy errorMessageStrategy) {
185+
this.errorMessageStrategy = errorMessageStrategy;
186+
}
187+
169188
@Override
170189
public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
171190
this.applicationEventPublisher = applicationEventPublisher;
@@ -242,6 +261,8 @@ protected FileTailingMessageProducerSupport createInstance() {
242261
adapter.setOutputChannel(this.outputChannel);
243262
adapter.setErrorChannel(this.errorChannel);
244263
adapter.setBeanName(this.beanName);
264+
adapter.setSendTimeout(this.sendTimeout);
265+
adapter.setShouldTrack(this.shouldTrack);
245266
BeanFactory beanFactory = getBeanFactory();
246267
JavaUtils.INSTANCE
247268
.acceptIfNotNull(this.taskExecutor, adapter::setTaskExecutor)
@@ -253,6 +274,7 @@ protected FileTailingMessageProducerSupport createInstance() {
253274
.acceptIfNotNull(this.applicationEventPublisher, adapter::setApplicationEventPublisher)
254275
.acceptIfNotNull(this.outputChannelName, adapter::setOutputChannelName)
255276
.acceptIfNotNull(this.errorChannelName, adapter::setErrorChannelName)
277+
.acceptIfNotNull(this.errorMessageStrategy, adapter::setErrorMessageStrategy)
256278
.acceptIfNotNull(beanFactory, adapter::setBeanFactory);
257279
adapter.afterPropertiesSet();
258280
this.tailAdapter = adapter;

spring-integration-file/src/main/java/org/springframework/integration/file/dsl/TailAdapterSpec.java

Lines changed: 34 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import org.springframework.integration.dsl.MessageProducerSpec;
2424
import org.springframework.integration.file.config.FileTailInboundChannelAdapterFactoryBean;
2525
import org.springframework.integration.file.tail.FileTailingMessageProducerSupport;
26+
import org.springframework.integration.support.ErrorMessageStrategy;
2627
import org.springframework.lang.Nullable;
2728
import org.springframework.messaging.MessageChannel;
2829
import org.springframework.scheduling.TaskScheduler;
@@ -40,12 +41,6 @@ public class TailAdapterSpec extends MessageProducerSpec<TailAdapterSpec, FileTa
4041

4142
private final FileTailInboundChannelAdapterFactoryBean factoryBean = new FileTailInboundChannelAdapterFactoryBean();
4243

43-
@Nullable
44-
private MessageChannel outputChannel;
45-
46-
@Nullable
47-
private MessageChannel errorChannel;
48-
4944
protected TailAdapterSpec() {
5045
super(null);
5146
this.factoryBean.setBeanFactory(new DefaultListableBeanFactory());
@@ -148,7 +143,7 @@ public TailAdapterSpec end(boolean end) {
148143
/**
149144
* If {@code true}, close and reopen the file between reading chunks.
150145
* Default {@code false}.
151-
* @param reopen the reopen.
146+
* @param reopen the 'reopen' option.
152147
* @return the spec.
153148
* @see org.springframework.integration.file.tail.ApacheCommonsFileTailingMessageProducer#setReopen(boolean)
154149
*/
@@ -177,13 +172,43 @@ public TailAdapterSpec autoStartup(boolean autoStartup) {
177172

178173
@Override
179174
public TailAdapterSpec outputChannel(MessageChannel outputChannel) {
180-
this.outputChannel = outputChannel;
175+
this.factoryBean.setOutputChannel(outputChannel);
181176
return _this();
182177
}
183178

184179
@Override
185180
public TailAdapterSpec errorChannel(MessageChannel errorChannel) {
186-
this.errorChannel = errorChannel;
181+
this.factoryBean.setErrorChannel(errorChannel);
182+
return _this();
183+
}
184+
185+
@Override
186+
public TailAdapterSpec outputChannel(String outputChannel) {
187+
this.factoryBean.setOutputChannelName(outputChannel);
188+
return _this();
189+
}
190+
191+
@Override
192+
public TailAdapterSpec errorChannel(String errorChannel) {
193+
this.factoryBean.setErrorChannelName(errorChannel);
194+
return _this();
195+
}
196+
197+
@Override
198+
public TailAdapterSpec sendTimeout(long sendTimeout) {
199+
this.factoryBean.setSendTimeout(sendTimeout);
200+
return _this();
201+
}
202+
203+
@Override
204+
public TailAdapterSpec shouldTrack(boolean shouldTrack) {
205+
this.factoryBean.setShouldTrack(shouldTrack);
206+
return _this();
207+
}
208+
209+
@Override
210+
public TailAdapterSpec errorMessageStrategy(ErrorMessageStrategy errorMessageStrategy) {
211+
this.factoryBean.setErrorMessageStrategy(errorMessageStrategy);
187212
return _this();
188213
}
189214

@@ -199,10 +224,6 @@ protected FileTailingMessageProducerSupport doGet() {
199224
}
200225
Assert.notNull(tailingMessageProducerSupport,
201226
"The 'FileTailInboundChannelAdapterFactoryBean' must not produce null");
202-
if (this.errorChannel != null) {
203-
tailingMessageProducerSupport.setErrorChannel(this.errorChannel);
204-
}
205-
tailingMessageProducerSupport.setOutputChannel(this.outputChannel);
206227
return tailingMessageProducerSupport;
207228
}
208229

spring-integration-file/src/test/java/org/springframework/integration/file/dsl/FileTests.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2016-2022 the original author or authors.
2+
* Copyright 2016-2023 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.
@@ -65,6 +65,7 @@
6565
import org.springframework.integration.file.support.FileExistsMode;
6666
import org.springframework.integration.file.support.FileUtils;
6767
import org.springframework.integration.file.tail.ApacheCommonsFileTailingMessageProducer;
68+
import org.springframework.integration.support.DefaultErrorMessageStrategy;
6869
import org.springframework.integration.support.MessageBuilder;
6970
import org.springframework.integration.test.util.TestUtils;
7071
import org.springframework.messaging.Message;
@@ -355,9 +356,12 @@ public IntegrationFlow tailFlow() {
355356
return IntegrationFlow
356357
.from(Files.tailAdapter(new File(tmpDir, "TailTest"))
357358
.delay(500)
359+
.errorMessageStrategy(new DefaultErrorMessageStrategy())
358360
.end(false)
359361
.id("tailer")
360-
.autoStartup(false))
362+
.autoStartup(false)
363+
.shouldTrack(true)
364+
.sendTimeout(30_000))
361365
.transform("hello "::concat)
362366
.channel(MessageChannels.queue("tailChannel"))
363367
.get();

spring-integration-ws/src/main/java/org/springframework/integration/ws/dsl/BaseWsInboundGatewaySpec.java

Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@
2727
* @param <E> the target {@link AbstractWebServiceInboundGateway} implementation type.
2828
*
2929
* @author Gary Russell
30+
* @author Artem Bilan
31+
*
3032
* @since 5.3
3133
*
3234
*/
@@ -35,10 +37,10 @@ public abstract class BaseWsInboundGatewaySpec<
3537
extends MessagingGatewaySpec<S, E> {
3638

3739
/**
38-
* Construct an instance.
40+
* Construct an instance based on the provided {@link AbstractWebServiceInboundGateway}.
3941
*/
40-
protected BaseWsInboundGatewaySpec() {
41-
super(null);
42+
protected BaseWsInboundGatewaySpec(E gateway) {
43+
super(gateway);
4244
}
4345

4446
/**
@@ -51,15 +53,4 @@ public S headerMapper(SoapHeaderMapper headerMapper) {
5153
return _this();
5254
}
5355

54-
@Override
55-
protected E doGet() {
56-
return assemble(create());
57-
}
58-
59-
protected abstract E create();
60-
61-
protected E assemble(E gateway) {
62-
return gateway;
63-
}
64-
6556
}

spring-integration-ws/src/main/java/org/springframework/integration/ws/dsl/MarshallingWsInboundGatewaySpec.java

Lines changed: 13 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -24,45 +24,41 @@
2424
* The spec for a {@link MarshallingWebServiceInboundGateway}.
2525
*
2626
* @author Gary Russell
27+
* @author Artem Bilan
28+
*
2729
* @since 5.3
2830
*
2931
*/
30-
public class MarshallingWsInboundGatewaySpec extends BaseWsInboundGatewaySpec<MarshallingWsInboundGatewaySpec,
31-
MarshallingWebServiceInboundGateway> {
32+
public class MarshallingWsInboundGatewaySpec
33+
extends BaseWsInboundGatewaySpec<MarshallingWsInboundGatewaySpec, MarshallingWebServiceInboundGateway> {
3234

33-
protected Marshaller gatewayMarshaller; // NOSONAR
3435

35-
protected Unmarshaller gatewayUnmarshaller; // NOSONAR
36+
protected MarshallingWsInboundGatewaySpec() {
37+
super(new MarshallingWebServiceInboundGateway());
38+
}
3639

3740
/**
3841
* Specify a marshaller to use.
3942
* @param marshaller the marshaller.
4043
* @return the spec.
4144
*/
4245
public MarshallingWsInboundGatewaySpec marshaller(Marshaller marshaller) {
43-
this.gatewayMarshaller = marshaller;
46+
this.target.setMarshaller(marshaller);
47+
if (marshaller instanceof Unmarshaller unmarshaller) {
48+
return unmarshaller(unmarshaller);
49+
}
4450
return this;
4551
}
4652

4753
/**
48-
* Specify an unmarshaller to use. Required if the {@link #gatewayMarshaller} is not also
54+
* Specify an unmarshaller to use. Required if the {@link #marshaller} is not also
4955
* an {@link Unmarshaller}.
5056
* @param unmarshaller the unmarshaller.
5157
* @return the spec.
5258
*/
5359
public MarshallingWsInboundGatewaySpec unmarshaller(Unmarshaller unmarshaller) {
54-
this.gatewayUnmarshaller = unmarshaller;
60+
this.target.setUnmarshaller(unmarshaller);
5561
return this;
5662
}
5763

58-
@Override
59-
protected MarshallingWebServiceInboundGateway create() {
60-
if (this.gatewayUnmarshaller != null) {
61-
return new MarshallingWebServiceInboundGateway(this.gatewayMarshaller, this.gatewayUnmarshaller);
62-
}
63-
else {
64-
return new MarshallingWebServiceInboundGateway(this.gatewayMarshaller);
65-
}
66-
}
67-
6864
}

spring-integration-ws/src/main/java/org/springframework/integration/ws/dsl/SimpleWsInboundGatewaySpec.java

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -22,30 +22,27 @@
2222
* The spec for a {@link SimpleWebServiceInboundGateway}.
2323
*
2424
* @author Gary Russell
25-
* @since 5.3
25+
* @author Artem Bilan
2626
*
27+
* @since 5.3
2728
*/
28-
public class SimpleWsInboundGatewaySpec extends BaseWsInboundGatewaySpec<SimpleWsInboundGatewaySpec,
29-
SimpleWebServiceInboundGateway> {
29+
public class SimpleWsInboundGatewaySpec
30+
extends BaseWsInboundGatewaySpec<SimpleWsInboundGatewaySpec, SimpleWebServiceInboundGateway> {
3031

31-
protected boolean extractPayload = true; // NOSONAR
32+
protected SimpleWsInboundGatewaySpec() {
33+
super(new SimpleWebServiceInboundGateway());
34+
}
3235

3336
/**
3437
* Specify true to extract the payloadSource from the request or use
3538
* the entire request as the payload; default true.
39+
*
3640
* @param extract true to extract.
3741
* @return the spec.
3842
*/
3943
public SimpleWsInboundGatewaySpec extractPayload(boolean extract) {
40-
this.extractPayload = extract;
44+
this.target.setExtractPayload(extract);
4145
return this;
4246
}
4347

44-
@Override
45-
protected SimpleWebServiceInboundGateway create() {
46-
SimpleWebServiceInboundGateway gateway = new SimpleWebServiceInboundGateway();
47-
gateway.setExtractPayload(this.extractPayload);
48-
return gateway;
49-
}
50-
5148
}

spring-integration-ws/src/test/java/org/springframework/integration/ws/dsl/WsDslTests.java

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import org.springframework.expression.Expression;
2525
import org.springframework.expression.common.LiteralExpression;
2626
import org.springframework.integration.test.util.TestUtils;
27+
import org.springframework.integration.ws.DefaultSoapHeaderMapper;
2728
import org.springframework.integration.ws.MarshallingWebServiceInboundGateway;
2829
import org.springframework.integration.ws.MarshallingWebServiceOutboundGateway;
2930
import org.springframework.integration.ws.SimpleWebServiceInboundGateway;
@@ -71,10 +72,16 @@ void marshallingInbound() {
7172

7273
@Test
7374
void simpleInbound() {
74-
SimpleWebServiceInboundGateway gateway = Ws.simpleInboundGateway()
75-
.extractPayload(false)
76-
.getObject();
75+
DefaultSoapHeaderMapper testHeaderMapper = new DefaultSoapHeaderMapper();
76+
SimpleWebServiceInboundGateway gateway =
77+
Ws.simpleInboundGateway()
78+
.extractPayload(false)
79+
.headerMapper(testHeaderMapper)
80+
.errorChannel("myErrorChannel")
81+
.getObject();
7782
assertThat(TestUtils.getPropertyValue(gateway, "extractPayload", Boolean.class)).isFalse();
83+
assertThat(TestUtils.getPropertyValue(gateway, "headerMapper")).isSameAs(testHeaderMapper);
84+
assertThat(TestUtils.getPropertyValue(gateway, "errorChannelName")).isEqualTo("myErrorChannel");
7885
}
7986

8087
@Test

0 commit comments

Comments
 (0)