From ace3f3b8ea9e1e9c9d257ef4168a1f64956aebdb Mon Sep 17 00:00:00 2001 From: Tadayoshi Sato Date: Fri, 17 Nov 2023 16:56:59 +0900 Subject: [PATCH] fix(jmx,camel): make Operations more robust on potential Jolokia max depth shortage error --- .../src/plugins/shared/jolokia-service.ts | 9 ++-- .../plugins/shared/operations/Operations.tsx | 6 +-- .../plugins/shared/operations/operation.ts | 51 ++++++++++++------- 3 files changed, 41 insertions(+), 25 deletions(-) diff --git a/packages/hawtio/src/plugins/shared/jolokia-service.ts b/packages/hawtio/src/plugins/shared/jolokia-service.ts index b5e1710d..b3ab59ea 100644 --- a/packages/hawtio/src/plugins/shared/jolokia-service.ts +++ b/packages/hawtio/src/plugins/shared/jolokia-service.ts @@ -463,7 +463,10 @@ class JolokiaService implements IJolokiaService { } // Overwrite max depth as listing MBeans requires some constant depth to work // See: https://github.com/hawtio/hawtio-next/issues/670 - options.maxDepth = JOLOKIA_LIST_MAX_DEPTH + const { maxDepth } = this.loadJolokiaStoredOptions() + if (maxDepth < JOLOKIA_LIST_MAX_DEPTH) { + options.maxDepth = JOLOKIA_LIST_MAX_DEPTH + } switch (method) { case JolokiaListMethod.OPTIMISED: { log.debug('Invoke Jolokia list MBean in optimised mode:', paths) @@ -799,8 +802,8 @@ class JolokiaService implements IJolokiaService { loadJolokiaStoredOptions(): JolokiaStoredOptions { const item = localStorage.getItem(STORAGE_KEY_JOLOKIA_OPTIONS) const options: JolokiaStoredOptions = item ? JSON.parse(item) : {} - const maxDepth = options.maxDepth || DEFAULT_MAX_DEPTH - const maxCollectionSize = options.maxCollectionSize || DEFAULT_MAX_COLLECTION_SIZE + const maxDepth = options.maxDepth ?? DEFAULT_MAX_DEPTH + const maxCollectionSize = options.maxCollectionSize ?? DEFAULT_MAX_COLLECTION_SIZE return { maxDepth, maxCollectionSize } } diff --git a/packages/hawtio/src/plugins/shared/operations/Operations.tsx b/packages/hawtio/src/plugins/shared/operations/Operations.tsx index 3c36da97..787e7faf 100644 --- a/packages/hawtio/src/plugins/shared/operations/Operations.tsx +++ b/packages/hawtio/src/plugins/shared/operations/Operations.tsx @@ -10,17 +10,17 @@ import { createOperations } from './operation' export const Operations: React.FunctionComponent = () => { const { selectedNode } = useContext(PluginNodeSelectionContext) - if (!selectedNode || !selectedNode.objectName || !selectedNode.mbean) { + if (!selectedNode || !selectedNode.mbean) { return null } - const { objectName, mbean } = selectedNode + const { mbean } = selectedNode if (!mbean.op || isEmpty(mbean.op)) { return } - const operations = createOperations(objectName, mbean.op) + const operations = createOperations(mbean.op) const OperationList = () => ( diff --git a/packages/hawtio/src/plugins/shared/operations/operation.ts b/packages/hawtio/src/plugins/shared/operations/operation.ts index d522eb35..48ab7491 100644 --- a/packages/hawtio/src/plugins/shared/operations/operation.ts +++ b/packages/hawtio/src/plugins/shared/operations/operation.ts @@ -1,37 +1,50 @@ +import { eventService } from '@hawtiosrc/core' import { stringSorter, trimEnd } from '@hawtiosrc/util/strings' +import { log } from '../globals' import { OptimisedMBeanOperation, OptimisedMBeanOperations } from '../tree' /** * Factory function for Operation objects. */ -export function createOperations(objectName: string, jmxOperations: OptimisedMBeanOperations): Operation[] { +export function createOperations(jmxOperations: OptimisedMBeanOperations): Operation[] { const operations: Operation[] = [] - const operationMap: Record = {} + const errors: string[] = [] Object.entries(jmxOperations).forEach(([name, op]) => { if (Array.isArray(op)) { - op.forEach(op => addOperation(operations, operationMap, name, op)) + op.forEach(op => addOperation(operations, name, op, errors)) } else { - addOperation(operations, operationMap, name, op) + addOperation(operations, name, op, errors) } }) + if (errors.length > 0) { + eventService.notify({ + type: 'danger', + message: `Please try increasing max depth for Jolokia in the Connect preferences. Failed to load operations: ${errors.join( + ', ', + )}.`, + duration: 30 * 1000, // 30 sec. + }) + } return operations.sort((a, b) => stringSorter(a.readableName, b.readableName)) } -function addOperation( - operations: Operation[], - operationMap: Record, - name: string, - op: OptimisedMBeanOperation, -): void { - const operation = new Operation( - name, - op.args.map(arg => new OperationArgument(arg.name, arg.type, arg.desc)), - op.desc, - op.ret, - op.canInvoke, - ) - operations.push(operation) - operationMap[operation.name] = operation +function addOperation(operations: Operation[], name: string, op: OptimisedMBeanOperation, errors: string[]) { + try { + const operation = new Operation( + name, + op.args.map(arg => new OperationArgument(arg.name, arg.type, arg.desc)), + op.desc, + op.ret, + op.canInvoke, + ) + operations.push(operation) + } catch (error) { + // Error can happen when max depth for Jolokia LIST is too small and part of + // the returned MBeans are compressed in a string form. In that case, the user + // needs to increase max depth for Jolokia requests in Connect preferences. + log.error('Operations - Error creating operation:', name, error) + errors.push(name) + } } export class Operation {