Skip to content

Commit 1a55eeb

Browse files
committed
Migration JMS to SF Core Retry; Nullability for gateway
Related to: #10345 Related to: #10083 * Replace Spring Retry functionality in the JMS module to Spring Framework Core `retry` API * Apply Nullability to the Core `gateway` package * Apply Nullability to the Core `support.util` package * Also, mitigate Nullability in the `IntegrationManagement`
1 parent b4ca71d commit 1a55eeb

File tree

22 files changed

+394
-401
lines changed

22 files changed

+394
-401
lines changed

spring-integration-core/src/main/java/org/springframework/integration/context/IntegrationObjectSupport.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import org.springframework.context.ApplicationContext;
3131
import org.springframework.context.ApplicationContextAware;
3232
import org.springframework.core.convert.ConversionService;
33+
import org.springframework.core.convert.support.DefaultConversionService;
3334
import org.springframework.core.log.LogAccessor;
3435
import org.springframework.expression.Expression;
3536
import org.springframework.expression.ExpressionParser;
@@ -290,6 +291,9 @@ public ConversionService getConversionService() {
290291
ConversionService conversionServiceToUse = this.conversionService;
291292
if (conversionServiceToUse == null) {
292293
conversionServiceToUse = IntegrationUtils.getConversionService(this.beanFactory);
294+
if (conversionServiceToUse == null) {
295+
conversionServiceToUse = DefaultConversionService.getSharedInstance();
296+
}
293297
this.conversionService = conversionServiceToUse;
294298
}
295299
return conversionServiceToUse;

spring-integration-core/src/main/java/org/springframework/integration/gateway/AnnotationGatewayProxyFactoryBean.java

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ public class AnnotationGatewayProxyFactoryBean<T> extends GatewayProxyFactoryBea
6363

6464
private BeanExpressionResolver resolver = new StandardBeanExpressionResolver();
6565

66+
@SuppressWarnings("NullAway.Init")
6667
private BeanExpressionContext expressionContext;
6768

6869
public AnnotationGatewayProxyFactoryBean(Class<T> serviceInterface) {
@@ -100,7 +101,10 @@ private static AnnotationAttributes mergeAnnotationAttributes(Class<?> serviceIn
100101
@Override
101102
protected void onInit() {
102103
if (getBeanFactory() instanceof ConfigurableBeanFactory beanFactory) {
103-
this.resolver = beanFactory.getBeanExpressionResolver();
104+
BeanExpressionResolver beanExpressionResolverToUse = beanFactory.getBeanExpressionResolver();
105+
if (beanExpressionResolverToUse != null) {
106+
this.resolver = beanExpressionResolverToUse;
107+
}
104108
this.expressionContext = new BeanExpressionContext(beanFactory, null);
105109
}
106110

@@ -131,12 +135,13 @@ protected void onInit() {
131135
setErrorOnTimeout(this.gatewayAttributes.getBoolean("errorOnTimeout"));
132136

133137
boolean proxyDefaultMethods = this.gatewayAttributes.getBoolean("proxyDefaultMethods");
134-
if (proxyDefaultMethods) { // Override only if annotation attribute is different
138+
if (proxyDefaultMethods) { // Override only if the annotation attribute is different
135139
setProxyDefaultMethods(true);
136140
}
137141
super.onInit();
138142
}
139143

144+
@SuppressWarnings("NullAway") // Dataflow analysis limitation
140145
private void populateGatewayMethodMetadataIfAny() {
141146
if (getGlobalMethodMetadata() != null) {
142147
return;
@@ -210,14 +215,12 @@ else if (StringUtils.hasText(asyncExecutor)) {
210215
}
211216
}
212217

213-
@Nullable
214-
private String resolveAttribute(String attributeName) {
218+
private @Nullable String resolveAttribute(String attributeName) {
215219
ConfigurableBeanFactory beanFactory = (ConfigurableBeanFactory) getBeanFactory();
216220
return beanFactory.resolveEmbeddedValue(this.gatewayAttributes.getString(attributeName));
217221
}
218222

219-
@Nullable
220-
private <V> V evaluateExpression(@Nullable String value, Class<V> targetClass) {
223+
private <V> @Nullable V evaluateExpression(@Nullable String value, Class<V> targetClass) {
221224
if (StringUtils.hasText(value)) {
222225
Object result = this.resolver.evaluate(value, this.expressionContext);
223226
return getConversionService().convert(result, targetClass);

spring-integration-core/src/main/java/org/springframework/integration/gateway/DefaultMethodInvokingMethodInterceptor.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,12 +54,12 @@ class DefaultMethodInvokingMethodInterceptor implements MethodInterceptor {
5454
new ConcurrentReferenceHashMap<>(10, ReferenceType.WEAK);
5555

5656
@Override
57-
public Object invoke(MethodInvocation invocation) throws Throwable { // NOSONAR
57+
public @Nullable Object invoke(MethodInvocation invocation) throws Throwable { // NOSONAR
5858
Method method = invocation.getMethod();
5959
if (!method.isDefault()) {
6060
return invocation.proceed();
6161
}
62-
Object[] arguments = invocation.getArguments();
62+
@Nullable Object[] arguments = invocation.getArguments();
6363
Object proxy = ((ProxyMethodInvocation) invocation).getProxy();
6464
return getMethodHandle(method)
6565
.bindTo(proxy)
@@ -122,9 +122,9 @@ private Lookup getLookup(Class<?> declaringClass, Method privateLookupIn) {
122122

123123
private volatile boolean constructorResolved;
124124

125-
private transient Constructor<Lookup> constructor;
125+
private transient @Nullable Constructor<Lookup> constructor;
126126

127-
private final Supplier<Constructor<Lookup>> constructorSupplier =
127+
private final Supplier<@Nullable Constructor<Lookup>> constructorSupplier =
128128
() -> {
129129
if (!this.constructorResolved) {
130130
Constructor<Lookup> ctor = null;

spring-integration-core/src/main/java/org/springframework/integration/gateway/GatewayMessageHandler.java

Lines changed: 37 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626

2727
import org.springframework.beans.factory.BeanCreationException;
2828
import org.springframework.core.task.SimpleAsyncTaskExecutor;
29+
import org.springframework.integration.JavaUtils;
2930
import org.springframework.integration.handler.AbstractReplyProducingMessageHandler;
3031
import org.springframework.integration.support.management.ManageableLifecycle;
3132
import org.springframework.messaging.Message;
@@ -43,31 +44,33 @@ public class GatewayMessageHandler extends AbstractReplyProducingMessageHandler
4344

4445
private final Lock lock = new ReentrantLock();
4546

47+
@SuppressWarnings("NullAway.Init")
4648
private volatile GatewayProxyFactoryBean<?> gatewayProxyFactoryBean;
4749

50+
@SuppressWarnings("NullAway.Init")
4851
private volatile Object exchanger;
4952

5053
private volatile boolean running;
5154

52-
private MessageChannel requestChannel;
55+
private @Nullable MessageChannel requestChannel;
5356

54-
private String requestChannelName;
57+
private @Nullable String requestChannelName;
5558

56-
private MessageChannel replyChannel;
59+
private @Nullable MessageChannel replyChannel;
5760

58-
private String replyChannelName;
61+
private @Nullable String replyChannelName;
5962

60-
private MessageChannel errorChannel;
63+
private @Nullable MessageChannel errorChannel;
6164

62-
private String errorChannelName;
65+
private @Nullable String errorChannelName;
6366

64-
private Long requestTimeout;
67+
private @Nullable Long requestTimeout;
6568

66-
private Long replyTimeout;
69+
private @Nullable Long replyTimeout;
6770

6871
private boolean errorOnTimeout;
6972

70-
private Executor executor = new SimpleAsyncTaskExecutor();
73+
private @Nullable Executor executor = new SimpleAsyncTaskExecutor();
7174

7275
public void setRequestChannel(MessageChannel requestChannel) {
7376
this.requestChannel = requestChannel;
@@ -135,45 +138,45 @@ protected Object handleRequestMessage(Message<?> requestMessage) {
135138
}
136139

137140
private void initialize() {
141+
GatewayProxyFactoryBean<?> newGatewayProxyFactoryBean;
138142
if (isAsync()) {
139-
this.gatewayProxyFactoryBean = new GatewayProxyFactoryBean<>(AsyncRequestReplyExchanger.class);
143+
newGatewayProxyFactoryBean = new GatewayProxyFactoryBean<>(AsyncRequestReplyExchanger.class);
140144
}
141145
else {
142-
this.gatewayProxyFactoryBean = new GatewayProxyFactoryBean<>(RequestReplyExchanger.class);
146+
newGatewayProxyFactoryBean = new GatewayProxyFactoryBean<>(RequestReplyExchanger.class);
143147
}
144148

145-
this.gatewayProxyFactoryBean.setDefaultRequestChannel(this.requestChannel);
146-
this.gatewayProxyFactoryBean.setDefaultRequestChannelName(this.requestChannelName);
147-
this.gatewayProxyFactoryBean.setDefaultReplyChannel(this.replyChannel);
148-
this.gatewayProxyFactoryBean.setDefaultReplyChannelName(this.replyChannelName);
149-
this.gatewayProxyFactoryBean.setErrorChannel(this.errorChannel);
150-
this.gatewayProxyFactoryBean.setErrorChannelName(this.errorChannelName);
151-
this.gatewayProxyFactoryBean.setErrorOnTimeout(this.errorOnTimeout);
152-
this.gatewayProxyFactoryBean.setAsyncExecutor(this.executor);
153-
if (this.requestTimeout != null) {
154-
this.gatewayProxyFactoryBean.setDefaultRequestTimeout(this.requestTimeout);
155-
}
156-
if (this.replyTimeout != null) {
157-
this.gatewayProxyFactoryBean.setDefaultReplyTimeout(this.replyTimeout);
158-
}
159-
160-
this.gatewayProxyFactoryBean.setBeanName(getComponentName() + "#gpfb");
161-
this.gatewayProxyFactoryBean.setBeanFactory(getBeanFactory());
162-
this.gatewayProxyFactoryBean.setApplicationContext(getApplicationContext());
163-
this.gatewayProxyFactoryBean.setBeanClassLoader(getBeanClassLoader());
164-
this.gatewayProxyFactoryBean.afterPropertiesSet();
149+
JavaUtils.INSTANCE
150+
.acceptIfNotNull(this.requestChannel, newGatewayProxyFactoryBean::setDefaultRequestChannel)
151+
.acceptIfHasText(this.requestChannelName, newGatewayProxyFactoryBean::setDefaultRequestChannelName)
152+
.acceptIfNotNull(this.replyChannel, newGatewayProxyFactoryBean::setDefaultReplyChannel)
153+
.acceptIfHasText(this.replyChannelName, newGatewayProxyFactoryBean::setDefaultReplyChannelName)
154+
.acceptIfNotNull(this.errorChannel, newGatewayProxyFactoryBean::setErrorChannel)
155+
.acceptIfHasText(this.errorChannelName, newGatewayProxyFactoryBean::setErrorChannelName)
156+
.acceptIfNotNull(this.requestTimeout, newGatewayProxyFactoryBean::setDefaultRequestTimeout)
157+
.acceptIfNotNull(this.replyTimeout, newGatewayProxyFactoryBean::setDefaultReplyTimeout);
158+
159+
newGatewayProxyFactoryBean.setAsyncExecutor(this.executor);
160+
newGatewayProxyFactoryBean.setErrorOnTimeout(this.errorOnTimeout);
161+
newGatewayProxyFactoryBean.setBeanName(getComponentName() + "#gpfb");
162+
newGatewayProxyFactoryBean.setBeanFactory(getBeanFactory());
163+
newGatewayProxyFactoryBean.setApplicationContext(getApplicationContext());
164+
newGatewayProxyFactoryBean.setBeanClassLoader(getBeanClassLoader());
165+
newGatewayProxyFactoryBean.afterPropertiesSet();
165166

166167
try {
167-
this.exchanger = this.gatewayProxyFactoryBean.getObject();
168+
this.exchanger = newGatewayProxyFactoryBean.getObject();
168169
}
169170
catch (Exception e) {
170171
throw new BeanCreationException("Can't instantiate the GatewayProxyFactoryBean: " + this, e);
171172
}
172173
if (this.running) {
173174
// We must stop gatewayProxyFactoryBean because after the normal start its "gatewayMap" is still empty
174-
this.gatewayProxyFactoryBean.stop();
175-
this.gatewayProxyFactoryBean.start();
175+
newGatewayProxyFactoryBean.stop();
176+
newGatewayProxyFactoryBean.start();
176177
}
178+
179+
this.gatewayProxyFactoryBean = newGatewayProxyFactoryBean;
177180
}
178181

179182
@Override

0 commit comments

Comments
 (0)