BAEL 5842 - Calling JMX MBean Method from a Shell Script (#13028)

* bael 5842

* bael-5842 - editor review 1
This commit is contained in:
Ulisses Lima 2022-12-19 11:29:17 -03:00 committed by GitHub
parent 0fd77aa664
commit 88f2eca118
10 changed files with 387 additions and 0 deletions

View File

@ -0,0 +1,25 @@
package com.baeldung.jmxshell;
import java.lang.management.ManagementFactory;
import java.util.Scanner;
import javax.management.MBeanServer;
import javax.management.ObjectName;
import com.baeldung.jmxshell.bean.Calculator;
public class JmxCalculatorMain {
public static void main(String[] args) throws Exception {
MBeanServer server = ManagementFactory.getPlatformMBeanServer();
server.registerMBean(new Calculator(), new ObjectName("com.baeldung.jxmshell:type=basic,name=calculator"));
System.out.printf("mbean registered. pid: %s\n", ManagementFactory.getRuntimeMXBean()
.getName());
try (Scanner scanner = new Scanner(System.in)) {
System.out.println("<press enter to terminate>");
scanner.nextLine();
}
}
}

View File

@ -0,0 +1,32 @@
package com.baeldung.jmxshell.bean;
public class Calculator implements CalculatorMBean {
private Integer a = 0;
private Integer b = 0;
@Override
public Integer sum() {
return a + b;
}
@Override
public Integer getA() {
return a;
}
@Override
public void setA(Integer a) {
this.a = a;
}
@Override
public Integer getB() {
return b;
}
@Override
public void setB(Integer b) {
this.b = b;
}
}

View File

@ -0,0 +1,14 @@
package com.baeldung.jmxshell.bean;
public interface CalculatorMBean {
Integer sum();
Integer getA();
void setA(Integer a);
Integer getB();
void setB(Integer b);
}

View File

@ -0,0 +1,68 @@
package com.baeldung.jmxshell.custom;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import javax.management.Attribute;
import javax.management.MBeanAttributeInfo;
import javax.management.MBeanInfo;
import javax.management.MBeanServerConnection;
import javax.management.ObjectName;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;
public class JmxConnectionWrapper {
private final Map<String, MBeanAttributeInfo> attributeMap;
private final MBeanServerConnection connection;
private final ObjectName objectName;
public JmxConnectionWrapper(String url, String beanName) throws Exception {
objectName = new ObjectName(beanName);
connection = JMXConnectorFactory.connect(new JMXServiceURL(url))
.getMBeanServerConnection();
MBeanInfo bean = connection.getMBeanInfo(objectName);
MBeanAttributeInfo[] attributes = bean.getAttributes();
this.attributeMap = Stream.of(attributes)
.peek(System.out::println)
.collect(Collectors.toMap(MBeanAttributeInfo::getName, Function.identity()));
}
public boolean hasAttribute(String attributeName) {
return attributeMap.containsKey(attributeName);
}
public Object attributeValue(String name, String value) throws Exception {
if (value != null) {
connection.setAttribute(objectName, new Attribute(name, parse(value)));
}
return connection.getAttribute(objectName, name);
}
public Object invoke(String operation) throws Exception {
String[] signature = new String[] {};
Object[] params = new Object[] {};
return connection.invoke(objectName, operation, params, signature);
}
private static Object parse(String value) {
if (value == null)
return null;
if (value.matches("\\d+")) {
return Integer.valueOf(value);
} else if (value.trim()
.toLowerCase()
.matches("true|false")) {
return Boolean.valueOf(value);
}
return value.equals("null") ? null : value;
}
}

View File

@ -0,0 +1,34 @@
package com.baeldung.jmxshell.custom;
public class JmxInvoker {
public static void main(String... args) throws Exception {
String serviceURL = args[0];
String name = args[1];
String operation = args[2];
String attributeValue = null;
if (args.length > 3) {
attributeValue = args[3];
}
String result = execute(serviceURL, name, operation, attributeValue);
System.out.println(result);
}
public static String execute(String url, String mBeanName, String operation, String attributeValue) {
try {
JmxConnectionWrapper connection = new JmxConnectionWrapper(url, mBeanName);
if (connection.hasAttribute(operation)) {
Object value = connection.attributeValue(operation, attributeValue);
return operation + "=" + value;
} else {
Object result = connection.invoke(operation);
return operation + "(): " + result;
}
} catch (Exception e) {
e.printStackTrace();
return e.getClass() + ": " + e.getMessage();
}
}
}

View File

@ -0,0 +1,45 @@
#!/bin/sh
jar='/tmp/core-java-perf.jar'
address='localhost:11234'
mbean='com.baeldung.jxmshell:name=calculator,type=basic'
operation='sum'
while test $# -gt 0
do
case "$1" in
--jar)
shift
jar="$1"
;;
--address)
shift
address="$1"
;;
--mbean)
shift
mbean="$1"
;;
--run|-x)
shift
operation="$1"
;;
--get)
shift
operation="$1"
;;
--set)
shift
operation="$1 $2"
;;
-*)
echo "bad option '$1'"
exit 1
;;
esac
shift
done
java -cp "$jar" com.baeldung.jmxshell.custom.JmxInvoker \
"service:jmx:rmi:///jndi/rmi://$address/jmxrmi" \
"$mbean" \
"$operation"

View File

@ -0,0 +1,54 @@
#!/bin/bash
jar='/tmp/cmdline-jmxclient-0.10.3.jar'
address='localhost:11234'
mbean='com.baeldung.jxmshell:name=calculator,type=basic'
operation='sum'
command="$mbean"
while test $# -gt 0
do
case "$1" in
--jar)
shift
jar="$1"
;;
--address)
shift
address="$1"
;;
--mbean)
shift
mbean="$1"
;;
--run|-x)
shift
operation="$1"
command="${mbean} ${operation}"
;;
--set)
shift
operation="$1"
shift
attribute_value="$1"
command="${mbean} ${operation}=${attribute_value}"
;;
--get)
shift
operation="$1"
command="${mbean} ${operation}"
;;
-*)
echo "bad option '$1'"
exit 1
;;
esac
shift
done
java -jar "$jar" - "$address" "$command"

View File

@ -0,0 +1,22 @@
#!/usr/bin/perl
$jar = "/tmp/jmxterm-1.0.4-uber.jar";
$host = "localhost";
$port = 11234;
$mbean = $ARGV[0] || "com.baeldung.jxmshell:name=calculator,type=basic";
$operation = $ARGV[1] || "sum";
open JMX, "| java -jar $jar -n";
print JMX "open $host:$port\n";
$attribute_value = $ARGV[2];
if (defined $attribute_value) {
print JMX "set -b ${mbean} ${operation} ${attribute_value}\n";
} else {
print JMX "run -b ${mbean} ${operation}\n";
}
print JMX "close\n";
close JMX;

View File

@ -0,0 +1,46 @@
#!/bin/sh
jar='/tmp/jmxterm-1.0.4-uber.jar'
address='localhost:11234'
mbean='com.baeldung.jxmshell:name=calculator,type=basic'
operation='sum'
command="info -b $mbean"
while test $# -gt 0
do
case "$1" in
--jar|-j)
shift; jar="$1"
;;
--address|-l)
shift; address="$1"
;;
--mbean|-b)
shift; mbean="$1"
;;
--run|-x)
shift; operation="$1"
command="run -b ${mbean} ${operation}"
;;
--set)
shift; operation="$1"
shift; attribute_value="$1"
command="set -b ${mbean} ${operation} ${attribute_value}"
;;
--get)
shift; operation="$1"
command="get -b ${mbean} ${operation}"
;;
-*)
echo "bad option '$1'"
exit 1
;;
esac
shift
done
echo "$command" | java -jar "$jar" -l "$address" -n -v silent

View File

@ -0,0 +1,47 @@
package com.baeldung.jmxshell.custom;
import static org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.api.MethodOrderer.OrderAnnotation;
import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestMethodOrder;
@TestMethodOrder(OrderAnnotation.class)
class JmxInvokerLiveTest {
private static final String JMX_URL = "service:jmx:rmi:///jndi/rmi://localhost:11234/jmxrmi";
private static final String JMX_MBEAN_NAME = "com.baeldung.jxmshell:name=calculator,type=basic";
private static final String ATTRIBUTE_A = "A";
private static final String ATTRIBUTE_B = "B";
private static final String SUM_OPERATION = "sum";
private static final Integer ATTRIBUTE_VALUE = 1;
@Test
@Order(1)
void givenAttributeValue_whenSetAttributeA_thenResultMatches() {
String attributeValue = ATTRIBUTE_VALUE.toString();
String result = JmxInvoker.execute(JMX_URL, JMX_MBEAN_NAME, ATTRIBUTE_A, attributeValue);
assertEquals(ATTRIBUTE_A + "=" + attributeValue, result);
}
@Test
@Order(2)
void givenAttributeValue_whenSetAttributeB_thenResultMatches() {
String attributeValue = ATTRIBUTE_VALUE.toString();
String result = JmxInvoker.execute(JMX_URL, JMX_MBEAN_NAME, ATTRIBUTE_B, attributeValue);
assertEquals(ATTRIBUTE_B + "=" + attributeValue, result);
}
@Test
@Order(3)
void whenSumOperation_thenSumIsCorrect() {
String result = JmxInvoker.execute(JMX_URL, JMX_MBEAN_NAME, SUM_OPERATION, null);
assertEquals(SUM_OPERATION + "(): " + (ATTRIBUTE_VALUE + ATTRIBUTE_VALUE), result);
}
}