Skip to content

Commit 29186e2

Browse files
mrpiggiartembilan
authored andcommitted
GH-8757: Add nullabilty to .support.converter
Fixes #8757 * Add ctor `ObjectStringMessageConverter(Charset)` * create tests for `ObjectStringMessageConverter` * fix codestyle issues * revise JavaDoc * `@NonNullApi` for `org.springframework.integration.support.converter` * revise `SimpleMessageConverter` * `inboundMessageMapper` and `outboundMessageMapper` are initialized to their default implementations Bboth are set in non-default ctors with final setters * remove `@Nullable` from `private BeanFactory beanFactory` * Handle empty `String... headerNames` * Some code clean up
1 parent 6909fbe commit 29186e2

File tree

8 files changed

+160
-58
lines changed

8 files changed

+160
-58
lines changed

spring-integration-core/src/main/java/org/springframework/integration/support/converter/AllowListDeserializingConverter.java

Lines changed: 3 additions & 1 deletion
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-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.
@@ -30,6 +30,7 @@
3030
import org.springframework.core.serializer.DefaultDeserializer;
3131
import org.springframework.core.serializer.Deserializer;
3232
import org.springframework.core.serializer.support.SerializationFailedException;
33+
import org.springframework.lang.Nullable;
3334
import org.springframework.util.Assert;
3435
import org.springframework.util.PatternMatchUtils;
3536

@@ -55,6 +56,7 @@ public class AllowListDeserializingConverter implements Converter<byte[], Object
5556

5657
private final Deserializer<Object> deserializer;
5758

59+
@Nullable
5860
private final ClassLoader defaultDeserializerClassLoader;
5961

6062
private final boolean usingDefaultDeserializer;

spring-integration-core/src/main/java/org/springframework/integration/support/converter/DefaultDatatypeChannelMessageConverter.java

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2014-2019 the original author or authors.
2+
* Copyright 2014-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.
@@ -22,6 +22,7 @@
2222
import org.springframework.core.convert.ConversionService;
2323
import org.springframework.core.convert.support.DefaultConversionService;
2424
import org.springframework.integration.support.utils.IntegrationUtils;
25+
import org.springframework.lang.Nullable;
2526
import org.springframework.messaging.Message;
2627
import org.springframework.messaging.MessageHeaders;
2728
import org.springframework.messaging.converter.MessageConverter;
@@ -33,22 +34,21 @@
3334
* if present.
3435
*
3536
* @author Gary Russell
37+
*
3638
* @since 4.0
3739
*
3840
*/
39-
public class DefaultDatatypeChannelMessageConverter implements MessageConverter,
40-
BeanFactoryAware {
41+
public class DefaultDatatypeChannelMessageConverter implements MessageConverter, BeanFactoryAware {
4142

42-
private volatile ConversionService conversionService = DefaultConversionService.getSharedInstance();
43+
private ConversionService conversionService = DefaultConversionService.getSharedInstance();
4344

44-
private volatile boolean conversionServiceSet;
45+
private boolean conversionServiceSet;
4546

4647
/**
4748
* Specify the {@link ConversionService} to use when trying to convert to
4849
* requested type. If this property is not set explicitly but
4950
* the converter is managed within a context, it will attempt to locate a
5051
* bean named "integrationConversionService" defined within that context.
51-
*
5252
* @param conversionService The conversion service.
5353
*/
5454
public void setConversionService(ConversionService conversionService) {
@@ -59,7 +59,7 @@ public void setConversionService(ConversionService conversionService) {
5959

6060
@Override
6161
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
62-
if (!this.conversionServiceSet && beanFactory != null) {
62+
if (!this.conversionServiceSet) {
6363
ConversionService integrationConversionService = IntegrationUtils.getConversionService(beanFactory);
6464
if (integrationConversionService != null) {
6565
this.conversionService = integrationConversionService;
@@ -81,7 +81,7 @@ public Object fromMessage(Message<?> message, Class<?> targetClass) {
8181
}
8282

8383
@Override
84-
public Message<?> toMessage(Object payload, MessageHeaders header) {
84+
public Message<?> toMessage(Object payload, @Nullable MessageHeaders header) {
8585
throw new UnsupportedOperationException("This converter does not support this method");
8686
}
8787

spring-integration-core/src/main/java/org/springframework/integration/support/converter/MapMessageConverter.java

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2019 the original author or authors.
2+
* Copyright 2002-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.
@@ -31,6 +31,7 @@
3131
import org.springframework.messaging.MessageHeaders;
3232
import org.springframework.messaging.converter.MessageConverter;
3333
import org.springframework.util.Assert;
34+
import org.springframework.util.ObjectUtils;
3435

3536
/**
3637
* Converts to/from a Map with 2 keys ('headers' and 'payload').
@@ -43,15 +44,15 @@
4344
*/
4445
public class MapMessageConverter implements MessageConverter, BeanFactoryAware {
4546

46-
private volatile String[] headerNames;
47+
private String[] headerNames = {};
4748

48-
private volatile boolean filterHeadersInToMessage;
49+
private boolean filterHeadersInToMessage;
4950

50-
private volatile BeanFactory beanFactory;
51+
private BeanFactory beanFactory;
5152

52-
private volatile MessageBuilderFactory messageBuilderFactory = new DefaultMessageBuilderFactory();
53+
private MessageBuilderFactory messageBuilderFactory = new DefaultMessageBuilderFactory();
5354

54-
private volatile boolean messageBuilderFactorySet;
55+
private boolean messageBuilderFactorySet;
5556

5657

5758
@Override
@@ -77,16 +78,19 @@ protected MessageBuilderFactory getMessageBuilderFactory() {
7778
* @param headerNames The header names.
7879
*/
7980
public void setHeaderNames(String... headerNames) {
80-
Assert.notEmpty(headerNames, "at least one header name is required");
81-
this.headerNames = Arrays.copyOf(headerNames, headerNames.length);
81+
if (ObjectUtils.isEmpty(headerNames)) {
82+
this.headerNames = new String[] {};
83+
}
84+
else {
85+
this.headerNames = Arrays.copyOf(headerNames, headerNames.length);
86+
}
8287
}
8388

8489
/**
85-
* By default all headers on Map passed to {@link #toMessage(Object, MessageHeaders)}
90+
* By default, all headers on Map passed to {@link #toMessage(Object, MessageHeaders)}
8691
* will be mapped. Set this property
87-
* to 'true' if you wish to limit the inbound headers to those in
88-
* the #headerNames.
89-
*
92+
* to 'true' if you wish to limit the inbound headers to those
93+
* in the {@link #headerNames}.
9094
* @param filterHeadersInToMessage true if the headers should be filtered.
9195
*/
9296
public void setFilterHeadersInToMessage(boolean filterHeadersInToMessage) {

spring-integration-core/src/main/java/org/springframework/integration/support/converter/ObjectStringMessageConverter.java

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2017-2019 the original author or authors.
2+
* Copyright 2017-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.
@@ -16,6 +16,9 @@
1616

1717
package org.springframework.integration.support.converter;
1818

19+
import java.nio.charset.Charset;
20+
21+
import org.springframework.lang.Nullable;
1922
import org.springframework.messaging.Message;
2023
import org.springframework.messaging.converter.StringMessageConverter;
2124

@@ -24,16 +27,31 @@
2427
* <p>
2528
* Delegates to super when payload is {@code byte[]} or {@code String}.
2629
* Performs {@link Object#toString()} in other cases.
30+
* <p>
31+
* This class is intended to serve as a fallback converter for internal message deserialization purposes. Therefore, it
32+
* is recommended to exclusively use the
33+
* {@link org.springframework.messaging.converter.AbstractMessageConverter#fromMessage(Message, Class) fromMessage}
34+
* method with {@code String.class} as the {@code targetClass}.
2735
*
2836
* @author Marius Bogoevici
2937
* @author Artem Bilan
38+
* @author Falk Hanisch
3039
*
3140
* @since 5.0
3241
*/
3342
public class ObjectStringMessageConverter extends StringMessageConverter {
3443

44+
public ObjectStringMessageConverter(Charset defaultCharset) {
45+
super(defaultCharset);
46+
}
47+
48+
public ObjectStringMessageConverter() {
49+
super();
50+
}
51+
52+
3553
@Override
36-
protected Object convertFromInternal(Message<?> message, Class<?> targetClass, Object conversionHint) {
54+
protected Object convertFromInternal(Message<?> message, Class<?> targetClass, @Nullable Object conversionHint) {
3755
Object payload = message.getPayload();
3856
if (payload instanceof String || payload instanceof byte[]) {
3957
return super.convertFromInternal(message, targetClass, conversionHint);

spring-integration-core/src/main/java/org/springframework/integration/support/converter/PassThruMessageConverter.java

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2015-2019 the original author or authors.
2+
* Copyright 2015-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.
@@ -16,11 +16,11 @@
1616

1717
package org.springframework.integration.support.converter;
1818

19+
import org.springframework.lang.Nullable;
1920
import org.springframework.messaging.Message;
2021
import org.springframework.messaging.MessageHeaders;
2122
import org.springframework.messaging.converter.MessageConverter;
2223
import org.springframework.messaging.support.MessageBuilder;
23-
import org.springframework.util.Assert;
2424

2525
/**
2626
* The simple {@link MessageConverter} implementation which contract is to return
@@ -31,6 +31,7 @@
3131
* operates only with {@link Message}s, e.g. Spring Integration Adapters.
3232
*
3333
* @author Artem Bilan
34+
*
3435
* @since 4.2
3536
*/
3637
public class PassThruMessageConverter implements MessageConverter {
@@ -41,9 +42,13 @@ public Object fromMessage(Message<?> message, Class<?> targetClass) {
4142
}
4243

4344
@Override
44-
public Message<?> toMessage(Object payload, MessageHeaders headers) {
45-
Assert.isInstanceOf(byte[].class, payload, "'payload' must be of 'byte[]' type.");
46-
return MessageBuilder.createMessage(payload, headers);
45+
public Message<?> toMessage(Object payload, @Nullable MessageHeaders headers) {
46+
if (payload instanceof byte[]) {
47+
return MessageBuilder.withPayload(payload).copyHeaders(headers).build();
48+
}
49+
else {
50+
return null;
51+
}
4752
}
4853

4954
}

spring-integration-core/src/main/java/org/springframework/integration/support/converter/SimpleMessageConverter.java

Lines changed: 29 additions & 30 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-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.
@@ -42,51 +42,50 @@
4242
@SuppressWarnings({"unchecked", "rawtypes"})
4343
public class SimpleMessageConverter implements MessageConverter, BeanFactoryAware {
4444

45-
private volatile InboundMessageMapper inboundMessageMapper;
45+
private InboundMessageMapper inboundMessageMapper = new DefaultInboundMessageMapper();
4646

47-
private volatile OutboundMessageMapper outboundMessageMapper;
47+
private OutboundMessageMapper outboundMessageMapper = new DefaultOutboundMessageMapper();
4848

49-
private volatile MessageBuilderFactory messageBuilderFactory = new DefaultMessageBuilderFactory();
49+
private MessageBuilderFactory messageBuilderFactory = new DefaultMessageBuilderFactory();
5050

51-
private volatile boolean messageBuilderFactorySet;
51+
private boolean messageBuilderFactorySet;
5252

5353
private BeanFactory beanFactory;
5454

55-
public SimpleMessageConverter() {
56-
this(null, null);
57-
}
55+
public SimpleMessageConverter() { }
5856

5957
public SimpleMessageConverter(InboundMessageMapper<?> inboundMessageMapper) {
60-
this(inboundMessageMapper,
61-
(inboundMessageMapper instanceof OutboundMessageMapper
62-
? (OutboundMessageMapper<?>) inboundMessageMapper
63-
: null));
58+
setInboundMessageMapper(inboundMessageMapper);
59+
if (inboundMessageMapper instanceof OutboundMessageMapper<?> messageMapper) {
60+
setOutboundMessageMapper(messageMapper);
61+
}
6462
}
6563

6664
public SimpleMessageConverter(OutboundMessageMapper<?> outboundMessageMapper) {
67-
this(outboundMessageMapper instanceof InboundMessageMapper
68-
? (InboundMessageMapper<?>) outboundMessageMapper
69-
: null,
70-
outboundMessageMapper);
65+
if (outboundMessageMapper instanceof InboundMessageMapper<?> messageMapper) {
66+
setInboundMessageMapper(messageMapper);
67+
}
68+
setOutboundMessageMapper(outboundMessageMapper);
7169
}
7270

7371
public SimpleMessageConverter(InboundMessageMapper<?> inboundMessageMapper,
7472
OutboundMessageMapper<?> outboundMessageMapper) {
75-
this.setInboundMessageMapper(inboundMessageMapper);
76-
this.setOutboundMessageMapper(outboundMessageMapper);
73+
74+
setInboundMessageMapper(inboundMessageMapper);
75+
setOutboundMessageMapper(outboundMessageMapper);
7776
}
7877

7978

80-
public final void setInboundMessageMapper(InboundMessageMapper<?> inboundMessageMapper) {
81-
this.inboundMessageMapper = (inboundMessageMapper != null)
82-
? inboundMessageMapper
83-
: new DefaultInboundMessageMapper();
79+
public final void setInboundMessageMapper(@Nullable InboundMessageMapper<?> inboundMessageMapper) {
80+
if (inboundMessageMapper != null) {
81+
this.inboundMessageMapper = inboundMessageMapper;
82+
}
8483
}
8584

86-
public final void setOutboundMessageMapper(OutboundMessageMapper<?> outboundMessageMapper) {
87-
this.outboundMessageMapper = (outboundMessageMapper != null
88-
? outboundMessageMapper
89-
: new DefaultOutboundMessageMapper());
85+
public final void setOutboundMessageMapper(@Nullable OutboundMessageMapper<?> outboundMessageMapper) {
86+
if (outboundMessageMapper != null) {
87+
this.outboundMessageMapper = outboundMessageMapper;
88+
}
9089
}
9190

9291
@Override
@@ -110,8 +109,8 @@ public Message<?> toMessage(Object object, @Nullable MessageHeaders headers) {
110109
try {
111110
return this.inboundMessageMapper.toMessage(object, headers);
112111
}
113-
catch (Exception e) {
114-
throw new MessageConversionException("failed to convert object to Message", e);
112+
catch (Exception ex) {
113+
throw new MessageConversionException("failed to convert object to Message", ex);
115114
}
116115
}
117116

@@ -121,8 +120,8 @@ public Object fromMessage(Message<?> message, Class<?> targetClass) {
121120
try {
122121
return this.outboundMessageMapper.fromMessage(message);
123122
}
124-
catch (Exception e) {
125-
throw new MessageConversionException(message, "failed to convert Message to object", e);
123+
catch (Exception ex) {
124+
throw new MessageConversionException(message, "failed to convert Message to object", ex);
126125
}
127126
}
128127

Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
/**
22
* Provides classes supporting message conversion.
33
*/
4+
@org.springframework.lang.NonNullApi
5+
@org.springframework.lang.NonNullFields
46
package org.springframework.integration.support.converter;

0 commit comments

Comments
 (0)