From 7e9b12571a354320704dbcd31dfd97236b84cea7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jiri=20Dan=C4=9Bk?= Date: Wed, 22 Feb 2023 20:59:18 +0100 Subject: [PATCH] Fixes #558: NullPointerException in cli-activemq-jmx when NumberOfPages address property changed type --- .../redhat/amqx/management/ObjectReader.java | 44 ++++++++++++++++++- .../com/redhat/amqx/management/Resolver.java | 4 ++ .../management/activemq/ActiveMQResolver.java | 6 +++ .../artemis/AbstractArtemisManager.java | 6 +-- .../management/artemis/ArtemisResolver.java | 21 ++++++--- 5 files changed, 70 insertions(+), 11 deletions(-) diff --git a/cli-activemq-jmx/src/main/java/com/redhat/amqx/management/ObjectReader.java b/cli-activemq-jmx/src/main/java/com/redhat/amqx/management/ObjectReader.java index b97cfc8b..4e8a4953 100644 --- a/cli-activemq-jmx/src/main/java/com/redhat/amqx/management/ObjectReader.java +++ b/cli-activemq-jmx/src/main/java/com/redhat/amqx/management/ObjectReader.java @@ -6,6 +6,14 @@ import org.slf4j.LoggerFactory; import javax.management.AttributeNotFoundException; +import javax.management.InstanceNotFoundException; +import javax.management.MBeanAttributeInfo; +import javax.management.MBeanException; +import javax.management.MBeanInfo; +import javax.management.MBeanServerConnection; +import javax.management.ObjectName; +import javax.management.ReflectionException; +import java.io.IOException; import java.lang.reflect.InvocationHandler; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; @@ -100,7 +108,10 @@ private Map extractMethodProperty(Method method, Object object, throw new DestinationException( String.format("Unable to access '%s' of '%s' object!", object.getClass(), method.getName())); } catch (Throwable e) { - logger.debug(e.getCause().toString()); + logger.debug(e.toString()); + if (e.getCause() != null) { + logger.debug(e.getCause().toString()); + } } return methodPropertyMap; } @@ -169,6 +180,37 @@ public Map getObjectProperties(Object object, List exclu } return propertiesMap; } + + public Map getRawObjectProperties(MBeanServerConnection mBeanServerConnection, ObjectName objectName, List excludeMethodList) throws DestinationException { + Map propertiesMap = new HashMap<>(); + + MBeanInfo info; + try { + info = mBeanServerConnection.getMBeanInfo(objectName); + } catch (Throwable e) { + throw new RuntimeException(e); + } + for (MBeanAttributeInfo attributeInfo : info.getAttributes()) { + String attributeName = attributeInfo.getName(); + + // get rid of get/is+lowercase first letter + String propertyName = getPropertyNameByMethod(attributeName, 0); + + Object value = null; + try { + value = mBeanServerConnection.getAttribute(objectName, attributeName); + propertiesMap.put(propertyName, value); + } catch (MBeanException | AttributeNotFoundException | InstanceNotFoundException | ReflectionException | + IOException e) { + + e.printStackTrace(); + } catch (Throwable e) { + logger.debug(e.toString()); + } + } + + return propertiesMap; + } } class ProxyHandler implements InvocationHandler { diff --git a/cli-activemq-jmx/src/main/java/com/redhat/amqx/management/Resolver.java b/cli-activemq-jmx/src/main/java/com/redhat/amqx/management/Resolver.java index 07b60c21..25433d30 100644 --- a/cli-activemq-jmx/src/main/java/com/redhat/amqx/management/Resolver.java +++ b/cli-activemq-jmx/src/main/java/com/redhat/amqx/management/Resolver.java @@ -1,5 +1,7 @@ package com.redhat.amqx.management; +import javax.management.ObjectName; + /** * Interface for resolving view management * objects like queues, topics, broker information. @@ -18,6 +20,8 @@ public interface Resolver { U getAddressView(String addressName) throws Exception; + public ObjectName getAddressObjectName(String addressName) throws Exception; + V getDivertView(String addressName, String divertName) throws Exception; } diff --git a/cli-activemq-jmx/src/main/java/com/redhat/amqx/management/activemq/ActiveMQResolver.java b/cli-activemq-jmx/src/main/java/com/redhat/amqx/management/activemq/ActiveMQResolver.java index 900870f8..f5a3db7f 100644 --- a/cli-activemq-jmx/src/main/java/com/redhat/amqx/management/activemq/ActiveMQResolver.java +++ b/cli-activemq-jmx/src/main/java/com/redhat/amqx/management/activemq/ActiveMQResolver.java @@ -57,6 +57,12 @@ public QueueViewMBean getAddressView(String queueName) throws Exception { return null; } + @Override + public ObjectName getAddressObjectName(String addressName) throws Exception { + System.err.println("Does not exist for AMQ!"); + return null; + } + @Override public QueueViewMBean getDivertView(String addressName, String divertName) throws Exception { System.err.println("Does not exist for AMQ!"); diff --git a/cli-activemq-jmx/src/main/java/com/redhat/amqx/management/artemis/AbstractArtemisManager.java b/cli-activemq-jmx/src/main/java/com/redhat/amqx/management/artemis/AbstractArtemisManager.java index 12dfe71a..b9050d7a 100644 --- a/cli-activemq-jmx/src/main/java/com/redhat/amqx/management/artemis/AbstractArtemisManager.java +++ b/cli-activemq-jmx/src/main/java/com/redhat/amqx/management/artemis/AbstractArtemisManager.java @@ -8,7 +8,6 @@ import com.redhat.amqx.management.AbstractConnectionManager; import com.redhat.amqx.management.Credentials; import com.redhat.amqx.management.Resolver; -import org.apache.activemq.artemis.api.core.ActiveMQAddressDoesNotExistException; import org.apache.activemq.artemis.api.core.management.ActiveMQServerControl; import org.apache.activemq.artemis.api.core.management.AddressControl; import org.apache.activemq.artemis.api.core.management.DivertControl; @@ -20,6 +19,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import javax.management.ObjectName; import java.io.IOException; import java.util.*; @@ -176,8 +176,8 @@ public Map getDestinationProperties(String addressName, String d } } - AddressControl addressControl = (AddressControl) getResolver().getAddressView(addressName); - propertiesMap.putAll(objectReader.getObjectProperties(addressControl, excludeMethods)); + ObjectName addressObjectName = getResolver().getAddressObjectName(addressName); + propertiesMap.putAll(objectReader.getRawObjectProperties(mBeanServerConnection, addressObjectName, excludeMethods)); propertiesMap.put("address-settings", new JSONObject(getServerControlMBean().getAddressSettingsAsJSON(addressName))); return propertiesMap; } diff --git a/cli-activemq-jmx/src/main/java/com/redhat/amqx/management/artemis/ArtemisResolver.java b/cli-activemq-jmx/src/main/java/com/redhat/amqx/management/artemis/ArtemisResolver.java index c359c091..ce385b7d 100644 --- a/cli-activemq-jmx/src/main/java/com/redhat/amqx/management/artemis/ArtemisResolver.java +++ b/cli-activemq-jmx/src/main/java/com/redhat/amqx/management/artemis/ArtemisResolver.java @@ -4,6 +4,7 @@ import org.apache.activemq.artemis.api.core.SimpleString; import org.apache.activemq.artemis.api.core.management.*; import org.apache.activemq.artemis.api.core.RoutingType; +import org.jetbrains.annotations.NotNull; import javax.management.MBeanServerConnection; import javax.management.MBeanServerInvocationHandler; @@ -16,10 +17,12 @@ public class ArtemisResolver implements Resolver",module=Core,ServerType=Server"; // 1.5.1 org.apache.activemq.artemis:type=Broker,brokerName="amq",serviceType=Address,name="queue-anycast2" // 2.0 org.apache.activemq.artemis:broker="",component=addresses,address="",subcomponent=queues,routing-type="",queue="" - objectName = ObjectNameBuilder.create(DEFAULT_DOMAIN, brokerName, true).getActiveMQServerObjectName(); + ObjectName objectName = objectNameBuilder.getActiveMQServerObjectName(); return MBeanServerInvocationHandler.newProxyInstance(mBeanServerConnection, objectName, ActiveMQServerControl.class, false); } @Override public QueueControl getQueueView(String addressName, String queueName) throws Exception { - ObjectName objectName = ObjectNameBuilder.create(DEFAULT_DOMAIN, brokerName, true).getQueueObjectName(new SimpleString(addressName), new SimpleString(queueName), RoutingType.ANYCAST); + ObjectName objectName = objectNameBuilder.getQueueObjectName(new SimpleString(addressName), new SimpleString(queueName), RoutingType.ANYCAST); return MBeanServerInvocationHandler.newProxyInstance(mBeanServerConnection, objectName, QueueControl.class, false); } @Override public QueueControl getTopicView(String addressName, String topicName) throws Exception { // if address doesn't add RoutingType.MULTICAST, it does not have any type - ObjectName objectName = ObjectNameBuilder.create(DEFAULT_DOMAIN, brokerName, true).getQueueObjectName(new SimpleString(addressName), new SimpleString(topicName), RoutingType.MULTICAST); + ObjectName objectName = objectNameBuilder.getQueueObjectName(new SimpleString(addressName), new SimpleString(topicName), RoutingType.MULTICAST); return MBeanServerInvocationHandler.newProxyInstance(mBeanServerConnection, objectName, QueueControl.class, false); } public AcceptorControl getAcceptorView(String acceptorName) throws Exception { - ObjectName objectname = ObjectNameBuilder.create(DEFAULT_DOMAIN, brokerName, true).getAcceptorObjectName(acceptorName); + ObjectName objectname = objectNameBuilder.getAcceptorObjectName(acceptorName); return MBeanServerInvocationHandler.newProxyInstance(mBeanServerConnection, objectname, AcceptorControl.class, false); } public AddressControl getAddressView(String addressName) throws Exception { - ObjectName objectname = ObjectNameBuilder.create(DEFAULT_DOMAIN, brokerName, true).getAddressObjectName(new SimpleString(addressName)); + ObjectName objectname = getAddressObjectName(addressName); return MBeanServerInvocationHandler.newProxyInstance(mBeanServerConnection, objectname, AddressControl.class, false); } + @NotNull + public ObjectName getAddressObjectName(String addressName) throws Exception { + return objectNameBuilder.getAddressObjectName(new SimpleString(addressName)); + } + public DivertControl getDivertView(String addressName, String divertName) throws Exception { - ObjectName objectname = ObjectNameBuilder.create(DEFAULT_DOMAIN, brokerName, true).getDivertObjectName(divertName, addressName); + ObjectName objectname = objectNameBuilder.getDivertObjectName(divertName, addressName); return MBeanServerInvocationHandler.newProxyInstance(mBeanServerConnection, objectname, DivertControl.class, false); }