From a30dc10447e8076d7cd65c55342e6955fb3cfd52 Mon Sep 17 00:00:00 2001 From: Artem Bilan Date: Thu, 6 Oct 2022 14:26:38 -0400 Subject: [PATCH] Improve messaging gateway mapping The `#args` and `#gatewayMethod` SpEL variables have been deprecated for a while * Remove their population and usage in favor of `MethodArgsHolder` `root` of the evaluation context This change optimize a gateway mapping logic the way that there is no need in evaluation context for every call: we can just reuse a global one * Some other `GatewayMethodInboundMessageMapper` code style refactoring * Fix effected test classes and their configs --- .../GatewayMethodInboundMessageMapper.java | 98 ++++++++----------- .../BarrierMessageHandlerTests.java | 2 +- .../configuration/EnableIntegrationTests.java | 4 +- .../gateway/AsyncGatewayTests.java | 4 +- .../gateway/GatewayInterfaceTests-context.xml | 6 +- .../gateway/GatewayInterfaceTests.java | 6 +- .../GatewayInterfaceTests2-context.xml | 6 +- ...hodInboundMessageMapperToMessageTests.java | 60 +++++++----- .../GatewayProxyMessageMappingTests.java | 6 +- ...ewayWithPayloadExpressionTests-context.xml | 8 +- .../GatewayWithPayloadExpressionTests.java | 13 +-- .../integration/gateway/TestService.java | 6 +- src/reference/asciidoc/gateway.adoc | 8 +- 13 files changed, 105 insertions(+), 122 deletions(-) diff --git a/spring-integration-core/src/main/java/org/springframework/integration/gateway/GatewayMethodInboundMessageMapper.java b/spring-integration-core/src/main/java/org/springframework/integration/gateway/GatewayMethodInboundMessageMapper.java index 7d1b864fa9..8937181220 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/gateway/GatewayMethodInboundMessageMapper.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/gateway/GatewayMethodInboundMessageMapper.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2021 the original author or authors. + * Copyright 2002-2022 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -38,7 +38,6 @@ import org.springframework.core.annotation.SynthesizingMethodParameter; import org.springframework.expression.EvaluationContext; import org.springframework.expression.Expression; import org.springframework.expression.spel.standard.SpelExpressionParser; -import org.springframework.expression.spel.support.StandardEvaluationContext; import org.springframework.integration.expression.ExpressionUtils; import org.springframework.integration.mapping.InboundMessageMapper; import org.springframework.integration.mapping.MessageMappingException; @@ -107,9 +106,7 @@ class GatewayMethodInboundMessageMapper implements InboundMessageMapper evaluateHeaders(EvaluationContext methodInvocationEvaluationContext, - MethodArgsHolder methodArgsHolder, Map headerExpressions) { + private Map evaluateHeaders(MethodArgsHolder methodArgsHolder, + Map headerExpressions) { Map evaluatedHeaders = new HashMap<>(); for (Map.Entry entry : headerExpressions.entrySet()) { - Object value = entry.getValue().getValue(methodInvocationEvaluationContext, methodArgsHolder); + Object value = entry.getValue() + .getValue(GatewayMethodInboundMessageMapper.this.evaluationContext, methodArgsHolder); evaluatedHeaders.put(entry.getKey(), value); } return evaluatedHeaders; } - // TODO Remove in the future release. The MethodArgsHolder as a root object covers this use-case. - private StandardEvaluationContext createMethodInvocationEvaluationContext(Object[] arguments) { - StandardEvaluationContext context = ExpressionUtils.createStandardEvaluationContext(this.beanFactory); - context.setVariable("args", arguments); - context.setVariable("gatewayMethod", this.method); - return context; - } - @Nullable private Object evaluatePayloadExpression(String expressionString, Object argumentValue) { Expression expression = this.parameterPayloadExpressions.computeIfAbsent(expressionString, PARSER::parseExpression); - return expression.getValue(this.payloadExpressionEvaluationContext, argumentValue); + return expression.getValue(this.evaluationContext, argumentValue); } @@ -287,15 +272,11 @@ class GatewayMethodInboundMessageMapper implements InboundMessageMapper toMessage(MethodArgsHolder holder, @Nullable Map headersToMap) { Object messageOrPayload = null; boolean foundPayloadAnnotation = false; Object[] arguments = holder.getArgs(); - EvaluationContext methodInvocationEvaluationContext = createMethodInvocationEvaluationContext(arguments); Map headersToPopulate = headersToMap != null ? new HashMap<>(headersToMap) @@ -303,7 +284,7 @@ class GatewayMethodInboundMessageMapper implements InboundMessageMapper "The 'payload' (or 'Message') for gateway [" + GatewayMethodInboundMessageMapper.this.method + "] method call cannot be determined (must not be 'null') from the provided arguments: " + Arrays.toString(arguments)); - populateSendAndReplyTimeoutHeaders(methodInvocationEvaluationContext, holder, headersToPopulate); - return buildMessage(holder, headersToPopulate, messageOrPayload, methodInvocationEvaluationContext); + populateSendAndReplyTimeoutHeaders(holder, headersToPopulate); + return buildMessage(holder, headersToPopulate, messageOrPayload); } private void headerOrHeaders(Map headersToPopulate, Object argumentValue, @@ -406,45 +387,46 @@ class GatewayMethodInboundMessageMapper implements InboundMessageMapper headersToPopulate) { + private void populateSendAndReplyTimeoutHeaders(MethodArgsHolder methodArgsHolder, + Map headersToPopulate) { if (GatewayMethodInboundMessageMapper.this.sendTimeoutExpression != null) { headersToPopulate.computeIfAbsent(GenericMessagingTemplate.DEFAULT_SEND_TIMEOUT_HEADER, v -> GatewayMethodInboundMessageMapper.this.sendTimeoutExpression - .getValue(methodInvocationEvaluationContext, methodArgsHolder, Long.class)); + .getValue(GatewayMethodInboundMessageMapper.this.evaluationContext, + methodArgsHolder, Long.class)); } if (GatewayMethodInboundMessageMapper.this.replyTimeoutExpression != null) { headersToPopulate.computeIfAbsent(GenericMessagingTemplate.DEFAULT_RECEIVE_TIMEOUT_HEADER, v -> GatewayMethodInboundMessageMapper.this.replyTimeoutExpression - .getValue(methodInvocationEvaluationContext, methodArgsHolder, Long.class)); + .getValue(GatewayMethodInboundMessageMapper.this.evaluationContext, + methodArgsHolder, Long.class)); } } private Message buildMessage(MethodArgsHolder methodArgsHolder, Map headers, - Object messageOrPayload, EvaluationContext methodInvocationEvaluationContext) { + Object messageOrPayload) { + MessageBuilderFactory msgBuilderFactory = GatewayMethodInboundMessageMapper.this.messageBuilderFactory; AbstractIntegrationMessageBuilder builder = - (messageOrPayload instanceof Message) - ? this.msgBuilderFactory.fromMessage((Message) messageOrPayload) - : this.msgBuilderFactory.withPayload(messageOrPayload); + (messageOrPayload instanceof Message msg) + ? msgBuilderFactory.fromMessage(msg) + : msgBuilderFactory.withPayload(messageOrPayload); builder.copyHeadersIfAbsent(headers); // Explicit headers in XML override any @Header annotations... if (!CollectionUtils.isEmpty(GatewayMethodInboundMessageMapper.this.headerExpressions)) { - Map evaluatedHeaders = evaluateHeaders(methodInvocationEvaluationContext, - methodArgsHolder, GatewayMethodInboundMessageMapper.this.headerExpressions); + Map evaluatedHeaders = + evaluateHeaders(methodArgsHolder, GatewayMethodInboundMessageMapper.this.headerExpressions); builder.copyHeaders(evaluatedHeaders); } // ...whereas global (default) headers do not... if (!CollectionUtils.isEmpty(GatewayMethodInboundMessageMapper.this.globalHeaderExpressions)) { - Map evaluatedHeaders = evaluateHeaders(methodInvocationEvaluationContext, - methodArgsHolder, GatewayMethodInboundMessageMapper.this.globalHeaderExpressions); + Map evaluatedHeaders = + evaluateHeaders(methodArgsHolder, + GatewayMethodInboundMessageMapper.this.globalHeaderExpressions); builder.copyHeadersIfAbsent(evaluatedHeaders); } - if (GatewayMethodInboundMessageMapper.this.headers != null) { - builder.copyHeadersIfAbsent(GatewayMethodInboundMessageMapper.this.headers); - } - return builder.build(); + return builder.copyHeadersIfAbsent(GatewayMethodInboundMessageMapper.this.headers).build(); } } diff --git a/spring-integration-core/src/test/java/org/springframework/integration/aggregator/BarrierMessageHandlerTests.java b/spring-integration-core/src/test/java/org/springframework/integration/aggregator/BarrierMessageHandlerTests.java index b92001d3e0..c001617b22 100644 --- a/spring-integration-core/src/test/java/org/springframework/integration/aggregator/BarrierMessageHandlerTests.java +++ b/spring-integration-core/src/test/java/org/springframework/integration/aggregator/BarrierMessageHandlerTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2020 the original author or authors. + * Copyright 2015-2022 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/spring-integration-core/src/test/java/org/springframework/integration/configuration/EnableIntegrationTests.java b/spring-integration-core/src/test/java/org/springframework/integration/configuration/EnableIntegrationTests.java index 32f76fe43f..ec83487da6 100644 --- a/spring-integration-core/src/test/java/org/springframework/integration/configuration/EnableIntegrationTests.java +++ b/spring-integration-core/src/test/java/org/springframework/integration/configuration/EnableIntegrationTests.java @@ -1467,7 +1467,7 @@ public class EnableIntegrationTests { @TestMessagingGateway public interface TestGateway { - @Gateway(headers = @GatewayHeader(name = "calledMethod", expression = "#gatewayMethod.name")) + @Gateway(headers = @GatewayHeader(name = "calledMethod", expression = "method.name")) String echo(String payload); @Gateway(requestChannel = "sendAsyncChannel") @@ -1482,7 +1482,7 @@ public class EnableIntegrationTests { @TestMessagingGateway2 public interface TestGateway2 { - @Gateway(headers = @GatewayHeader(name = "calledMethod", expression = "#gatewayMethod.name")) + @Gateway(headers = @GatewayHeader(name = "calledMethod", expression = "method.name")) String echo2(String payload); } diff --git a/spring-integration-core/src/test/java/org/springframework/integration/gateway/AsyncGatewayTests.java b/spring-integration-core/src/test/java/org/springframework/integration/gateway/AsyncGatewayTests.java index 64b11acf67..6b2a5afb95 100644 --- a/spring-integration-core/src/test/java/org/springframework/integration/gateway/AsyncGatewayTests.java +++ b/spring-integration-core/src/test/java/org/springframework/integration/gateway/AsyncGatewayTests.java @@ -393,10 +393,10 @@ public class AsyncGatewayTests { CompletableFuture> returnMessageListenable(String s); - @Gateway(headers = @GatewayHeader(name = "method", expression = "#gatewayMethod.name")) + @Gateway(headers = @GatewayHeader(name = "method", expression = "method.name")) CustomFuture returnCustomFuture(String s); - @Gateway(headers = @GatewayHeader(name = "method", expression = "#gatewayMethod.name")) + @Gateway(headers = @GatewayHeader(name = "method", expression = "method.name")) Future returnCustomFutureWithTypeFuture(String s); Mono returnStringPromise(String s); diff --git a/spring-integration-core/src/test/java/org/springframework/integration/gateway/GatewayInterfaceTests-context.xml b/spring-integration-core/src/test/java/org/springframework/integration/gateway/GatewayInterfaceTests-context.xml index c2bdeae0f7..913528efc6 100644 --- a/spring-integration-core/src/test/java/org/springframework/integration/gateway/GatewayInterfaceTests-context.xml +++ b/spring-integration-core/src/test/java/org/springframework/integration/gateway/GatewayInterfaceTests-context.xml @@ -13,9 +13,9 @@ service-interface="org.springframework.integration.gateway.GatewayInterfaceTests$Bar" default-request-channel="requestChannelBaz" error-channel="errorChannel"> - - - + + + diff --git a/spring-integration-core/src/test/java/org/springframework/integration/gateway/GatewayInterfaceTests.java b/spring-integration-core/src/test/java/org/springframework/integration/gateway/GatewayInterfaceTests.java index 7f32068594..d6b3015345 100644 --- a/spring-integration-core/src/test/java/org/springframework/integration/gateway/GatewayInterfaceTests.java +++ b/spring-integration-core/src/test/java/org/springframework/integration/gateway/GatewayInterfaceTests.java @@ -522,8 +522,8 @@ public class GatewayInterfaceTests { void baz(String payload); - @Gateway(payloadExpression = "#args[0]", requestChannel = "lateReplyChannel", - requestTimeoutExpression = "#args[1]", replyTimeoutExpression = "#args[2]") + @Gateway(payloadExpression = "args[0]", requestChannel = "lateReplyChannel", + requestTimeoutExpression = "args[1]", replyTimeoutExpression = "args[2]") String lateReply(String payload, long requestTimeout, long replyTimeout); } @@ -651,7 +651,7 @@ public class GatewayInterfaceTests { @Profile("gatewayTest") public interface Int2634Gateway { - @Gateway(requestChannel = "gatewayChannel", payloadExpression = "#args[0]") + @Gateway(requestChannel = "gatewayChannel", payloadExpression = "args[0]") Object test1(Map map); @Gateway(requestChannel = "gatewayChannel") diff --git a/spring-integration-core/src/test/java/org/springframework/integration/gateway/GatewayInterfaceTests2-context.xml b/spring-integration-core/src/test/java/org/springframework/integration/gateway/GatewayInterfaceTests2-context.xml index b4bfeca232..668aeab0b4 100644 --- a/spring-integration-core/src/test/java/org/springframework/integration/gateway/GatewayInterfaceTests2-context.xml +++ b/spring-integration-core/src/test/java/org/springframework/integration/gateway/GatewayInterfaceTests2-context.xml @@ -8,9 +8,9 @@ - - - + + + diff --git a/spring-integration-core/src/test/java/org/springframework/integration/gateway/GatewayMethodInboundMessageMapperToMessageTests.java b/spring-integration-core/src/test/java/org/springframework/integration/gateway/GatewayMethodInboundMessageMapperToMessageTests.java index 4969e33f97..e7bea7d7c9 100644 --- a/spring-integration-core/src/test/java/org/springframework/integration/gateway/GatewayMethodInboundMessageMapperToMessageTests.java +++ b/spring-integration-core/src/test/java/org/springframework/integration/gateway/GatewayMethodInboundMessageMapperToMessageTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2022 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,13 +17,15 @@ package org.springframework.integration.gateway; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; +import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; import static org.mockito.Mockito.mock; import java.lang.reflect.Method; import java.util.HashMap; import java.util.Map; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.springframework.beans.factory.BeanFactory; import org.springframework.expression.Expression; @@ -40,6 +42,7 @@ import org.springframework.messaging.handler.annotation.Payload; /** * @author Mark Fisher * @author Gary Russell + * @author Artem Bilan */ public class GatewayMethodInboundMessageMapperToMessageTests { @@ -52,20 +55,22 @@ public class GatewayMethodInboundMessageMapperToMessageTests { assertThat(message.getPayload()).isEqualTo("test"); } - @Test(expected = IllegalArgumentException.class) + @Test public void toMessageWithTooManyParameters() throws Exception { Method method = TestService.class.getMethod("sendPayload", String.class); GatewayMethodInboundMessageMapper mapper = new GatewayMethodInboundMessageMapper(method); mapper.setBeanFactory(mock(BeanFactory.class)); - mapper.toMessage(new Object[] { "test", "oops" }); + assertThatIllegalArgumentException() + .isThrownBy(() -> mapper.toMessage(new Object[] { "test", "oops" })); } - @Test(expected = IllegalArgumentException.class) + @Test public void toMessageWithEmptyParameterArray() throws Exception { Method method = TestService.class.getMethod("sendPayload", String.class); GatewayMethodInboundMessageMapper mapper = new GatewayMethodInboundMessageMapper(method); mapper.setBeanFactory(mock(BeanFactory.class)); - mapper.toMessage(new Object[] {}); + assertThatIllegalArgumentException() + .isThrownBy(() -> mapper.toMessage(new Object[] {})); } @Test @@ -79,13 +84,14 @@ public class GatewayMethodInboundMessageMapperToMessageTests { assertThat(message.getHeaders().get("foo")).isEqualTo("bar"); } - @Test(expected = MessageMappingException.class) + @Test public void toMessageWithPayloadAndRequiredHeaderButNullValue() throws Exception { Method method = TestService.class.getMethod( "sendPayloadAndHeader", String.class, String.class); GatewayMethodInboundMessageMapper mapper = new GatewayMethodInboundMessageMapper(method); mapper.setBeanFactory(mock(BeanFactory.class)); - mapper.toMessage(new Object[] { "test", null }); + assertThatExceptionOfType(MessageMappingException.class) + .isThrownBy(() -> mapper.toMessage(new Object[] { "test", null })); } @Test @@ -116,7 +122,7 @@ public class GatewayMethodInboundMessageMapperToMessageTests { "sendPayloadAndHeadersMap", String.class, Map.class); GatewayMethodInboundMessageMapper mapper = new GatewayMethodInboundMessageMapper(method); mapper.setBeanFactory(mock(BeanFactory.class)); - Map headers = new HashMap(); + Map headers = new HashMap<>(); headers.put("abc", 123); headers.put("def", 456); Message message = mapper.toMessage(new Object[] { "test", headers }); @@ -135,15 +141,16 @@ public class GatewayMethodInboundMessageMapperToMessageTests { assertThat(message.getPayload()).isEqualTo("test"); } - @Test(expected = MessageMappingException.class) + @Test public void toMessageWithPayloadAndHeadersMapWithNonStringKey() throws Exception { Method method = TestService.class.getMethod( "sendPayloadAndHeadersMap", String.class, Map.class); GatewayMethodInboundMessageMapper mapper = new GatewayMethodInboundMessageMapper(method); mapper.setBeanFactory(mock(BeanFactory.class)); - Map headers = new HashMap(); + Map headers = new HashMap<>(); headers.put(123, "abc"); - mapper.toMessage(new Object[] { "test", headers }); + assertThatExceptionOfType(MessageMappingException.class) + .isThrownBy(() -> mapper.toMessage(new Object[] { "test", headers })); } @Test @@ -167,13 +174,14 @@ public class GatewayMethodInboundMessageMapperToMessageTests { assertThat(message.getHeaders().get("foo")).isEqualTo("bar"); } - @Test(expected = MessageMappingException.class) + @Test public void toMessageWithMessageParameterAndRequiredHeaderButNullValue() throws Exception { Method method = TestService.class.getMethod("sendMessageAndHeader", Message.class, String.class); GatewayMethodInboundMessageMapper mapper = new GatewayMethodInboundMessageMapper(method); mapper.setBeanFactory(mock(BeanFactory.class)); Message inputMessage = MessageBuilder.withPayload("test message").build(); - mapper.toMessage(new Object[] { inputMessage, null }); + assertThatExceptionOfType(MessageMappingException.class) + .isThrownBy(() -> mapper.toMessage(new Object[] { inputMessage, null })); } @Test @@ -198,26 +206,28 @@ public class GatewayMethodInboundMessageMapperToMessageTests { assertThat(message.getHeaders().get("foo")).isNull(); } - @Test(expected = MessageMappingException.class) + @Test public void noArgs() throws Exception { - Method method = TestService.class.getMethod("noArgs", new Class[] {}); + Method method = TestService.class.getMethod("noArgs"); GatewayMethodInboundMessageMapper mapper = new GatewayMethodInboundMessageMapper(method); mapper.setBeanFactory(mock(BeanFactory.class)); - mapper.toMessage(new Object[] {}); + assertThatExceptionOfType(MessageMappingException.class) + .isThrownBy(() -> mapper.toMessage(new Object[] {})); } - @Test(expected = MessageMappingException.class) + @Test public void onlyHeaders() throws Exception { Method method = TestService.class.getMethod("onlyHeaders", String.class, String.class); GatewayMethodInboundMessageMapper mapper = new GatewayMethodInboundMessageMapper(method); mapper.setBeanFactory(mock(BeanFactory.class)); - mapper.toMessage(new Object[] { "abc", "def" }); + assertThatExceptionOfType(MessageMappingException.class) + .isThrownBy(() -> mapper.toMessage(new Object[] { "abc", "def" })); } @Test public void toMessageWithPayloadAndHeaders() throws Exception { Method method = TestService.class.getMethod("sendPayload", String.class); - Map headers = new HashMap(); + Map headers = new HashMap<>(); headers.put("foo", new LiteralExpression("foo")); headers.put("bar", new SpelExpressionParser().parseExpression("6 * 7")); headers.put("baz", new LiteralExpression("hello")); @@ -232,7 +242,7 @@ public class GatewayMethodInboundMessageMapperToMessageTests { @Test public void toMessageWithNonHeaderMapPayloadExpressionA() throws Exception { Method method = TestService.class.getMethod("sendNonHeadersMap", Map.class); - Map map = new HashMap(); + Map map = new HashMap<>(); map.put(1, "One"); map.put(2, "Two"); GatewayMethodInboundMessageMapper mapper = new GatewayMethodInboundMessageMapper(method); @@ -258,7 +268,7 @@ public class GatewayMethodInboundMessageMapperToMessageTests { @Test public void toMessageWithNonHeaderMapPayloadAnnotation() throws Exception { Method method = TestService.class.getMethod("sendNonHeadersMapWithPayloadAnnotation", Map.class); - Map map = new HashMap(); + Map map = new HashMap<>(); map.put(1, "One"); map.put(2, "Two"); GatewayMethodInboundMessageMapper mapper = new GatewayMethodInboundMessageMapper(method); @@ -270,10 +280,10 @@ public class GatewayMethodInboundMessageMapperToMessageTests { @Test public void toMessageWithTwoMapsOneNonHeaderPayloadExpression() throws Exception { Method method = TestService.class.getMethod("sendNonHeadersMapFirstArgument", Map.class, Map.class); - Map mapA = new HashMap(); + Map mapA = new HashMap<>(); mapA.put(1, "One"); mapA.put(2, "Two"); - Map mapB = new HashMap(); + Map mapB = new HashMap<>(); mapB.put("1", "ONE"); mapB.put("2", "TWO"); GatewayMethodInboundMessageMapper mapper = new GatewayMethodInboundMessageMapper(method); @@ -310,7 +320,7 @@ public class GatewayMethodInboundMessageMapperToMessageTests { void sendNonHeadersMap(Map map); - @Payload("#args[0]") + @Payload("args[0]") void sendNonHeadersMapWithPayloadAnnotation(Map map); void sendNonHeadersMapFirstArgument(Map mapA, Map mapB); diff --git a/spring-integration-core/src/test/java/org/springframework/integration/gateway/GatewayProxyMessageMappingTests.java b/spring-integration-core/src/test/java/org/springframework/integration/gateway/GatewayProxyMessageMappingTests.java index 0044bdb5d2..ab2a02d5ad 100644 --- a/spring-integration-core/src/test/java/org/springframework/integration/gateway/GatewayProxyMessageMappingTests.java +++ b/spring-integration-core/src/test/java/org/springframework/integration/gateway/GatewayProxyMessageMappingTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2022 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -226,10 +226,10 @@ public class GatewayProxyMessageMappingTests { void twoMapsAndOneAnnotatedWithPayload(@Payload Map payload, Map headers); - @Payload("#args[0] + #args[1] + '!'") + @Payload("args[0] + args[1] + '!'") void payloadAnnotationAtMethodLevel(String a, String b); - @Payload("@testBean.exclaim(#args[0])") + @Payload("@testBean.exclaim(args[0])") void payloadAnnotationAtMethodLevelUsingBeanResolver(String s); void payloadAnnotationWithExpression(@Payload("toUpperCase()") String s); diff --git a/spring-integration-core/src/test/java/org/springframework/integration/gateway/GatewayWithPayloadExpressionTests-context.xml b/spring-integration-core/src/test/java/org/springframework/integration/gateway/GatewayWithPayloadExpressionTests-context.xml index 3e32bb5b24..7c6d3494a3 100644 --- a/spring-integration-core/src/test/java/org/springframework/integration/gateway/GatewayWithPayloadExpressionTests-context.xml +++ b/spring-integration-core/src/test/java/org/springframework/integration/gateway/GatewayWithPayloadExpressionTests-context.xml @@ -8,13 +8,13 @@ https://www.springframework.org/schema/integration/spring-integration.xsd"> - - - + + + diff --git a/spring-integration-core/src/test/java/org/springframework/integration/gateway/GatewayWithPayloadExpressionTests.java b/spring-integration-core/src/test/java/org/springframework/integration/gateway/GatewayWithPayloadExpressionTests.java index 679d297f18..1ae2275a42 100644 --- a/spring-integration-core/src/test/java/org/springframework/integration/gateway/GatewayWithPayloadExpressionTests.java +++ b/spring-integration-core/src/test/java/org/springframework/integration/gateway/GatewayWithPayloadExpressionTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2022 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,15 +18,13 @@ package org.springframework.integration.gateway; import static org.assertj.core.api.Assertions.assertThat; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.messaging.Message; import org.springframework.messaging.PollableChannel; import org.springframework.messaging.handler.annotation.Payload; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; /** * @author Mark Fisher @@ -35,8 +33,7 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; * * @since 2.0 */ -@RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration +@SpringJUnitConfig public class GatewayWithPayloadExpressionTests { @Autowired @@ -91,7 +88,7 @@ public class GatewayWithPayloadExpressionTests { public interface SampleAnnotatedGateway { - @Payload("#args[0] + #args[1]") + @Payload("args[0] + args[1]") void send(String value1, String value2); } diff --git a/spring-integration-core/src/test/java/org/springframework/integration/gateway/TestService.java b/spring-integration-core/src/test/java/org/springframework/integration/gateway/TestService.java index 1f788ce6d1..4052e275f0 100644 --- a/spring-integration-core/src/test/java/org/springframework/integration/gateway/TestService.java +++ b/spring-integration-core/src/test/java/org/springframework/integration/gateway/TestService.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2021 the original author or authors. + * Copyright 2002-2022 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -38,7 +38,7 @@ public interface TestService { void oneWay(String input); - @Payload("#args[0]") + @Payload("args[0]") void oneWayWithTimeouts(String input, Long sendTimeout, Long receiveTimeout); String solicitResponse(); @@ -51,7 +51,7 @@ public interface TestService { Message requestReplyWithMessageReturnValue(String input); - @Payload("#gatewayMethod.name + #args.length") + @Payload("method.name + args.length") String requestReplyWithPayloadAnnotation(); Future> async(String s); diff --git a/src/reference/asciidoc/gateway.adoc b/src/reference/asciidoc/gateway.adoc index 10d4c9ecf7..b172b49660 100644 --- a/src/reference/asciidoc/gateway.adoc +++ b/src/reference/asciidoc/gateway.adoc @@ -163,13 +163,7 @@ NOTE: If a no-argument gateway is specified in XML, and the interface method has The `
` element supports `expression` as an alternative to `value`. The SpEL expression is evaluated to determine the value of the header. Starting with version 5.2, the `#root` object of the evaluation context is a `MethodArgsHolder` with `getMethod()` and `getArgs()` accessors. - -These two expression evaluation context variables are deprecated since version 5.2: - -* #args: An `Object[]` containing the method arguments -* #gatewayMethod: The object (derived from `java.reflect.Method`) that represents the method in the `service-interface` that was invoked. -A header containing this variable can be used later in the flow (for example, for routing). -For example, if you wish to route on the simple method name, you might add a header with the following expression: `#gatewayMethod.name`. +For example, if you wish to route on the simple method name, you might add a header with the following expression: `method.name`. NOTE: The `java.reflect.Method` is not serializable. A header with an expression of `method` is lost if you later serialize the message.