INT-2549: Ignore MBean call reply in op-invoc-c-a
JIRA: https://jira.spring.io/browse/INT-2549 * Add `expectReply` property into the `OperationInvokingMessageHandler` to align the one-way and request-reply behavior with all other similar components in Spring Integration * Ignore an operation invocation result in case of `expectReply == false` and log warning * Provide some refactoring into the `OperationInvokingMessageHandler` to fix Sonar complains about complexity **Cherry-pick to 5.0.x, 4.3.x**
This commit is contained in:
committed by
Gary Russell
parent
f43fa9772e
commit
800227558b
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
* Copyright 2002-2019 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.
|
||||
@@ -88,8 +88,7 @@ public class OperationInvokingMessageHandlerTests {
|
||||
@Test
|
||||
public void invocationWithMapPayload() {
|
||||
QueueChannel outputChannel = new QueueChannel();
|
||||
OperationInvokingMessageHandler handler = new OperationInvokingMessageHandler();
|
||||
handler.setServer(server);
|
||||
OperationInvokingMessageHandler handler = new OperationInvokingMessageHandler(server);
|
||||
handler.setObjectName(this.objectName);
|
||||
handler.setOutputChannel(outputChannel);
|
||||
handler.setOperationName("x");
|
||||
@@ -108,8 +107,7 @@ public class OperationInvokingMessageHandlerTests {
|
||||
@Test
|
||||
public void invocationWithPayloadNoReturnValue() {
|
||||
QueueChannel outputChannel = new QueueChannel();
|
||||
OperationInvokingMessageHandler handler = new OperationInvokingMessageHandler();
|
||||
handler.setServer(server);
|
||||
OperationInvokingMessageHandler handler = new OperationInvokingMessageHandler(server);
|
||||
handler.setObjectName(this.objectName);
|
||||
handler.setOutputChannel(outputChannel);
|
||||
handler.setOperationName("y");
|
||||
@@ -122,8 +120,7 @@ public class OperationInvokingMessageHandlerTests {
|
||||
@Test(expected = MessagingException.class)
|
||||
public void invocationWithMapPayloadNotEnoughParameters() {
|
||||
QueueChannel outputChannel = new QueueChannel();
|
||||
OperationInvokingMessageHandler handler = new OperationInvokingMessageHandler();
|
||||
handler.setServer(server);
|
||||
OperationInvokingMessageHandler handler = new OperationInvokingMessageHandler(server);
|
||||
handler.setObjectName(this.objectName);
|
||||
handler.setOutputChannel(outputChannel);
|
||||
handler.setOperationName("x");
|
||||
@@ -141,8 +138,7 @@ public class OperationInvokingMessageHandlerTests {
|
||||
@Test
|
||||
public void invocationWithListPayload() {
|
||||
QueueChannel outputChannel = new QueueChannel();
|
||||
OperationInvokingMessageHandler handler = new OperationInvokingMessageHandler();
|
||||
handler.setServer(server);
|
||||
OperationInvokingMessageHandler handler = new OperationInvokingMessageHandler(server);
|
||||
handler.setObjectName(this.objectName);
|
||||
handler.setOutputChannel(outputChannel);
|
||||
handler.setOperationName("x");
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
object-name="org.springframework.integration.jmx.config:type=TestBean,name=testBeanAdapter"
|
||||
operation-name="test">
|
||||
<jmx:request-handler-advice-chain>
|
||||
<bean class="org.springframework.integration.jmx.config.OperationInvokingChannelAdapterParserTests$FooADvice" />
|
||||
<bean class="org.springframework.integration.jmx.config.OperationInvokingChannelAdapterParserTests.FooAdvice" />
|
||||
</jmx:request-handler-advice-chain>
|
||||
</jmx:operation-invoking-channel-adapter>
|
||||
|
||||
@@ -37,8 +37,8 @@
|
||||
operation-name="test"/>
|
||||
</si:chain>
|
||||
|
||||
<si:chain input-channel="operationWithinChainWithNonNullReturn">
|
||||
<jmx:operation-invoking-channel-adapter
|
||||
<si:chain id="chainWithOperation" input-channel="operationWithinChainWithNonNullReturn">
|
||||
<jmx:operation-invoking-channel-adapter id="operationWithinChainWithNonNullReturnHandler"
|
||||
object-name="org.springframework.integration.jmx.config:type=TestBean,name=testBeanAdapter"
|
||||
operation-name="testWithReturn"/>
|
||||
</si:chain>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2019 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,34 +17,39 @@
|
||||
package org.springframework.integration.jmx.config;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
import static org.mockito.BDDMockito.willReturn;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.junit.After;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.springframework.beans.DirectFieldAccessor;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.integration.handler.advice.AbstractRequestHandlerAdvice;
|
||||
import org.springframework.integration.jmx.JmxHeaders;
|
||||
import org.springframework.integration.jmx.OperationInvokingMessageHandler;
|
||||
import org.springframework.integration.support.MessageBuilder;
|
||||
import org.springframework.integration.test.util.TestUtils;
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.messaging.MessageChannel;
|
||||
import org.springframework.messaging.MessagingException;
|
||||
import org.springframework.messaging.support.GenericMessage;
|
||||
import org.springframework.test.annotation.DirtiesContext;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
/**
|
||||
* @author Mark Fisher
|
||||
* @author Oleg Zhurakousky
|
||||
* @author Artem Bilan
|
||||
* @author Gary Russell
|
||||
*
|
||||
* @since 2.0
|
||||
*/
|
||||
@ContextConfiguration
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@RunWith(SpringRunner.class)
|
||||
@DirtiesContext
|
||||
public class OperationInvokingChannelAdapterParserTests {
|
||||
|
||||
@@ -63,6 +68,17 @@ public class OperationInvokingChannelAdapterParserTests {
|
||||
@Autowired
|
||||
private TestBean testBean;
|
||||
|
||||
@Autowired
|
||||
private BeanFactory beanFactory;
|
||||
|
||||
@Autowired
|
||||
@Qualifier("operationWithNonNullReturn.handler")
|
||||
private OperationInvokingMessageHandler operationWithNonNullReturnHandler;
|
||||
|
||||
@Autowired
|
||||
@Qualifier("chainWithOperation$child.operationWithinChainWithNonNullReturnHandler.handler")
|
||||
private OperationInvokingMessageHandler operationWithinChainWithNonNullReturnHandler;
|
||||
|
||||
private static volatile int adviceCalled;
|
||||
|
||||
@After
|
||||
@@ -72,30 +88,36 @@ public class OperationInvokingChannelAdapterParserTests {
|
||||
|
||||
|
||||
@Test
|
||||
public void adapterWithDefaults() throws Exception {
|
||||
public void adapterWithDefaults() {
|
||||
assertEquals(0, testBean.messages.size());
|
||||
input.send(new GenericMessage<String>("test1"));
|
||||
input.send(new GenericMessage<String>("test2"));
|
||||
input.send(new GenericMessage<String>("test3"));
|
||||
input.send(new GenericMessage<>("test1"));
|
||||
input.send(new GenericMessage<>("test2"));
|
||||
input.send(new GenericMessage<>("test3"));
|
||||
assertEquals(3, testBean.messages.size());
|
||||
assertEquals(3, adviceCalled);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOutboundAdapterWithNonNullReturn() throws Exception {
|
||||
try {
|
||||
operationWithNonNullReturn.send(new GenericMessage<String>("test1"));
|
||||
fail("Expect MessagingException about non-null return");
|
||||
}
|
||||
catch (Exception e) {
|
||||
assertTrue(e instanceof MessagingException);
|
||||
// TODO Add check exception's message about 'must have a void return' after <jmx:operation-invoking-channel-adapter/> refactoring
|
||||
}
|
||||
public void testOutboundAdapterWithNonNullReturn() {
|
||||
Log logger = spy(TestUtils.getPropertyValue(this.operationWithNonNullReturnHandler, "logger", Log.class));
|
||||
|
||||
willReturn(true)
|
||||
.given(logger)
|
||||
.isWarnEnabled();
|
||||
|
||||
new DirectFieldAccessor(this.operationWithNonNullReturnHandler)
|
||||
.setPropertyValue("logger", logger);
|
||||
|
||||
this.operationWithNonNullReturn.send(new GenericMessage<>("test1"));
|
||||
|
||||
verify(logger).warn("This component doesn't expect a reply. " +
|
||||
"The MBean operation 'testWithReturn' result '[test1]' for " +
|
||||
"'org.springframework.integration.jmx.config:type=TestBean,name=testBeanAdapter' is ignored.");
|
||||
}
|
||||
|
||||
@Test
|
||||
// Headers should be ignored
|
||||
public void adapterWitJmxHeaders() throws Exception {
|
||||
public void adapterWitJmxHeaders() {
|
||||
assertEquals(0, testBean.messages.size());
|
||||
input.send(this.createMessage("1"));
|
||||
input.send(this.createMessage("2"));
|
||||
@@ -104,21 +126,26 @@ public class OperationInvokingChannelAdapterParserTests {
|
||||
}
|
||||
|
||||
@Test //INT-2275
|
||||
public void testInvokeOperationWithinChain() throws Exception {
|
||||
operationInvokingWithinChain.send(new GenericMessage<String>("test1"));
|
||||
public void testInvokeOperationWithinChain() {
|
||||
operationInvokingWithinChain.send(new GenericMessage<>("test1"));
|
||||
assertEquals(1, testBean.messages.size());
|
||||
}
|
||||
|
||||
@Test //INT-2275
|
||||
public void testOperationWithinChainWithNonNullReturn() throws Exception {
|
||||
try {
|
||||
operationWithinChainWithNonNullReturn.send(new GenericMessage<String>("test1"));
|
||||
fail("Expect MessagingException about non-null return");
|
||||
}
|
||||
catch (Exception e) {
|
||||
assertTrue(e instanceof MessagingException);
|
||||
// TODO Add check exception's message about 'must have a void return' after <jmx:operation-invoking-channel-adapter/> refactoring
|
||||
}
|
||||
@Test
|
||||
public void testOperationWithinChainWithNonNullReturn() {
|
||||
Log logger =
|
||||
spy(TestUtils.getPropertyValue(this.operationWithinChainWithNonNullReturnHandler, "logger", Log.class));
|
||||
|
||||
willReturn(true)
|
||||
.given(logger)
|
||||
.isWarnEnabled();
|
||||
|
||||
new DirectFieldAccessor(this.operationWithinChainWithNonNullReturnHandler)
|
||||
.setPropertyValue("logger", logger);
|
||||
this.operationWithinChainWithNonNullReturn.send(new GenericMessage<>("test1"));
|
||||
verify(logger).warn("This component doesn't expect a reply. " +
|
||||
"The MBean operation 'testWithReturn' result '[test1]' for " +
|
||||
"'org.springframework.integration.jmx.config:type=TestBean,name=testBeanAdapter' is ignored.");
|
||||
}
|
||||
|
||||
private Message<?> createMessage(String payload) {
|
||||
@@ -127,7 +154,7 @@ public class OperationInvokingChannelAdapterParserTests {
|
||||
.setHeader(JmxHeaders.OPERATION_NAME, "blah").build();
|
||||
}
|
||||
|
||||
public static class FooADvice extends AbstractRequestHandlerAdvice {
|
||||
public static class FooAdvice extends AbstractRequestHandlerAdvice {
|
||||
|
||||
@Override
|
||||
protected Object doInvoke(ExecutionCallback callback, Object target, Message<?> message) throws Exception {
|
||||
|
||||
Reference in New Issue
Block a user