Skip to content

Commit 4f34d92

Browse files
artembilangaryrussell
authored andcommitted
INT-4573: Fix logic in the OperationInvokingMH
JIRA: https://jira.spring.io/browse/INT-4573 * Fix check order for headers first in the `resolveObjectName()` and `resolveOperationName()`. Then fallback to defaults configured on the `OperationInvokingMessageHandler` * Remove also a deprecated API in the `OperationInvokingMessageHandler` * Remove requirements for `object-name` and `operation-name` XML attributes since those options can be provided in the request message headers * Fix `OperationInvokingChannelAdapterParserTests` for proper headers resolution * Mention `JmxHeaders.OBJECT_NAME` and `JmxHeaders.OPERATION_NAME` headers in the `jmx.adoc`
1 parent 0ce6d1c commit 4f34d92

File tree

5 files changed

+41
-62
lines changed

5 files changed

+41
-62
lines changed

spring-integration-jmx/src/main/java/org/springframework/integration/jmx/OperationInvokingMessageHandler.java

+19-45
Original file line numberDiff line numberDiff line change
@@ -65,25 +65,14 @@
6565
*/
6666
public class OperationInvokingMessageHandler extends AbstractReplyProducingMessageHandler implements InitializingBean {
6767

68-
private MBeanServerConnection server;
68+
private final MBeanServerConnection server;
6969

7070
private ObjectName defaultObjectName;
7171

7272
private String operationName;
7373

7474
private boolean expectReply = true;
7575

76-
/**
77-
* Construct an instance with no arguments; for backward compatibility.
78-
* The {@link #setServer(MBeanServerConnection)} must be used as well.
79-
* The {@link #OperationInvokingMessageHandler(MBeanServerConnection)}
80-
* is a preferred way for instantiation.
81-
* @since 4.3.20
82-
* @deprecated since 4.3.20
83-
*/
84-
@Deprecated
85-
public OperationInvokingMessageHandler() {
86-
}
8776

8877
/**
8978
* Construct an instance based on the provided {@link MBeanServerConnection}.
@@ -95,17 +84,6 @@ public OperationInvokingMessageHandler(MBeanServerConnection server) {
9584
this.server = server;
9685
}
9786

98-
/**
99-
* Provide a reference to the MBeanServer within which the MBean
100-
* target for operation invocation has been registered.
101-
* @param server The MBean server connection.
102-
* @deprecated since 4.3.20 in favor of {@link #OperationInvokingMessageHandler(MBeanServerConnection)}
103-
*/
104-
@Deprecated
105-
public void setServer(MBeanServerConnection server) {
106-
this.server = server;
107-
}
108-
10987
/**
11088
* Specify a default ObjectName to use when no such header is
11189
* available on the Message being handled.
@@ -146,11 +124,6 @@ public String getComponentType() {
146124
return this.expectReply ? "jmx:operation-invoking-outbound-gateway" : "jmx:operation-invoking-channel-adapter";
147125
}
148126

149-
@Override
150-
protected void doInit() {
151-
Assert.notNull(this.server, "MBeanServer is required.");
152-
}
153-
154127
@Override
155128
protected Object handleRequestMessage(Message<?> requestMessage) {
156129
ObjectName objectName = resolveObjectName(requestMessage);
@@ -245,35 +218,36 @@ private boolean valueTypeMatchesParameterType(Object value, MBeanParameterInfo p
245218
}
246219

247220
/**
248-
* First checks if defaultObjectName is set, otherwise falls back on {@link JmxHeaders#OBJECT_NAME} header.
221+
* First checks {@link JmxHeaders#OBJECT_NAME} header in the request message,
222+
* otherwise falls back to {@link #defaultObjectName}.
249223
*/
250224
private ObjectName resolveObjectName(Message<?> message) {
251-
ObjectName objectName = this.defaultObjectName;
252-
if (objectName == null) {
253-
Object objectNameHeader = message.getHeaders().get(JmxHeaders.OBJECT_NAME);
254-
if (objectNameHeader instanceof ObjectName) {
255-
objectName = (ObjectName) objectNameHeader;
225+
ObjectName objectName;
226+
Object objectNameHeader = message.getHeaders().get(JmxHeaders.OBJECT_NAME);
227+
if (objectNameHeader != null) {
228+
try {
229+
objectName = ObjectNameManager.getInstance(objectNameHeader);
256230
}
257-
else if (objectNameHeader instanceof String) {
258-
try {
259-
objectName = ObjectNameManager.getInstance(objectNameHeader);
260-
}
261-
catch (MalformedObjectNameException e) {
262-
throw new IllegalArgumentException(e);
263-
}
231+
catch (MalformedObjectNameException e) {
232+
throw new IllegalArgumentException(e);
264233
}
265234
}
266-
Assert.notNull(objectName, "Failed to resolve ObjectName.");
235+
else {
236+
objectName = this.defaultObjectName;
237+
238+
}
239+
Assert.notNull(objectName, "Failed to resolve ObjectName: either from headers or 'defaultObjectName'.");
267240
return objectName;
268241
}
269242

270243
/**
271-
* First checks if defaultOperationName is set, otherwise falls back on {@link JmxHeaders#OPERATION_NAME} header.
244+
* First checks if {@link JmxHeaders#OPERATION_NAME} header,
245+
* otherwise falls back to {@link #operationName}.
272246
*/
273247
private String resolveOperationName(Message<?> message) {
274-
String operation = this.operationName;
248+
String operation = message.getHeaders().get(JmxHeaders.OPERATION_NAME, String.class);
275249
if (operation == null) {
276-
operation = message.getHeaders().get(JmxHeaders.OPERATION_NAME, String.class);
250+
operation = this.operationName;
277251
}
278252
Assert.notNull(operation, "Failed to resolve operation name.");
279253
return operation;

spring-integration-jmx/src/main/resources/org/springframework/integration/jmx/config/spring-integration-jmx-5.2.xsd

+2-2
Original file line numberDiff line numberDiff line change
@@ -318,8 +318,8 @@
318318
</xsd:annotation>
319319
<xsd:complexContent>
320320
<xsd:extension base="mbeanServerIdentifierType">
321-
<xsd:attribute name="object-name" type="xsd:string" use="required" />
322-
<xsd:attribute name="operation-name" type="xsd:string" use="required" />
321+
<xsd:attribute name="object-name" type="xsd:string" />
322+
<xsd:attribute name="operation-name" type="xsd:string" />
323323
</xsd:extension>
324324
</xsd:complexContent>
325325
</xsd:complexType>

spring-integration-jmx/src/test/java/org/springframework/integration/jmx/config/OperationInvokingChannelAdapterParserTests-context.xml

+2
Original file line numberDiff line numberDiff line change
@@ -43,4 +43,6 @@
4343
operation-name="testWithReturn"/>
4444
</si:chain>
4545

46+
<jmx:operation-invoking-channel-adapter id="input2"/>
47+
4648
</beans>

spring-integration-jmx/src/test/java/org/springframework/integration/jmx/config/OperationInvokingChannelAdapterParserTests.java

+17-14
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@
2727
import org.junit.runner.RunWith;
2828

2929
import org.springframework.beans.DirectFieldAccessor;
30-
import org.springframework.beans.factory.BeanFactory;
3130
import org.springframework.beans.factory.annotation.Autowired;
3231
import org.springframework.beans.factory.annotation.Qualifier;
3332
import org.springframework.integration.handler.advice.AbstractRequestHandlerAdvice;
@@ -57,19 +56,19 @@ public class OperationInvokingChannelAdapterParserTests {
5756
private MessageChannel input;
5857

5958
@Autowired
60-
private MessageChannel operationWithNonNullReturn;
59+
private MessageChannel input2;
6160

6261
@Autowired
63-
private MessageChannel operationInvokingWithinChain;
62+
private MessageChannel operationWithNonNullReturn;
6463

6564
@Autowired
66-
private MessageChannel operationWithinChainWithNonNullReturn;
65+
private MessageChannel operationInvokingWithinChain;
6766

6867
@Autowired
69-
private TestBean testBean;
68+
private MessageChannel operationWithinChainWithNonNullReturn;
7069

7170
@Autowired
72-
private BeanFactory beanFactory;
71+
private TestBean testBean;
7372

7473
@Autowired
7574
@Qualifier("operationWithNonNullReturn.handler")
@@ -79,7 +78,7 @@ public class OperationInvokingChannelAdapterParserTests {
7978
@Qualifier("chainWithOperation$child.operationWithinChainWithNonNullReturnHandler.handler")
8079
private OperationInvokingMessageHandler operationWithinChainWithNonNullReturnHandler;
8180

82-
private static volatile int adviceCalled;
81+
private static int adviceCalled;
8382

8483
@After
8584
public void resetLists() {
@@ -119,9 +118,9 @@ public void testOutboundAdapterWithNonNullReturn() {
119118
// Headers should be ignored
120119
public void adapterWitJmxHeaders() {
121120
assertThat(testBean.messages.size()).isEqualTo(0);
122-
input.send(this.createMessage("1"));
123-
input.send(this.createMessage("2"));
124-
input.send(this.createMessage("3"));
121+
this.input2.send(createMessage("1"));
122+
this.input2.send(createMessage("2"));
123+
this.input2.send(createMessage("3"));
125124
assertThat(testBean.messages.size()).isEqualTo(3);
126125
}
127126

@@ -134,24 +133,27 @@ public void testInvokeOperationWithinChain() {
134133
@Test
135134
public void testOperationWithinChainWithNonNullReturn() {
136135
Log logger =
137-
spy(TestUtils.getPropertyValue(this.operationWithinChainWithNonNullReturnHandler, "logger", Log.class));
136+
spy(TestUtils.getPropertyValue(this.operationWithinChainWithNonNullReturnHandler, "logger",
137+
Log.class));
138138

139139
willReturn(true)
140140
.given(logger)
141141
.isWarnEnabled();
142142

143143
new DirectFieldAccessor(this.operationWithinChainWithNonNullReturnHandler)
144144
.setPropertyValue("logger", logger);
145-
this.operationWithinChainWithNonNullReturn.send(new GenericMessage<>("test1"));
145+
this.operationWithinChainWithNonNullReturn.send(new GenericMessage<>("test1"));
146146
verify(logger).warn("This component doesn't expect a reply. " +
147147
"The MBean operation 'testWithReturn' result '[test1]' for " +
148148
"'org.springframework.integration.jmx.config:type=TestBean,name=testBeanAdapter' is ignored.");
149149
}
150150

151151
private Message<?> createMessage(String payload) {
152152
return MessageBuilder.withPayload(payload)
153-
.setHeader(JmxHeaders.OBJECT_NAME, "org.springframework.integration.jmx.config:type=TestBean,name=foo")
154-
.setHeader(JmxHeaders.OPERATION_NAME, "blah").build();
153+
.setHeader(JmxHeaders.OBJECT_NAME,
154+
"org.springframework.integration.jmx.config:type=TestBean,name=testBeanAdapter")
155+
.setHeader(JmxHeaders.OPERATION_NAME, "test")
156+
.build();
155157
}
156158

157159
public static class FooAdvice extends AbstractRequestHandlerAdvice {
@@ -163,4 +165,5 @@ protected Object doInvoke(ExecutionCallback callback, Object target, Message<?>
163165
}
164166

165167
}
168+
166169
}

src/reference/asciidoc/jmx.adoc

+1-1
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,7 @@ You can also implement your own filter.
184184

185185
The operation-invoking channel adapter enables message-driven invocation of any managed operation exposed by an MBean.
186186
Each invocation requires the operation name to be invoked and the object name of the target MBean.
187-
Both of these must be explicitly provided by adapter configuration, as the following example shows:
187+
Both of these must be explicitly provided by adapter configuration or via `JmxHeaders.OBJECT_NAME` and `JmxHeaders.OPERATION_NAME` message headers, respectively:
188188

189189
====
190190
[source,xml]

0 commit comments

Comments
 (0)