diff --git a/packages/hawtio/src/plugins/shared/jolokia-service.test.ts b/packages/hawtio/src/plugins/shared/jolokia-service.test.ts index 3d1769b4..79e82e39 100644 --- a/packages/hawtio/src/plugins/shared/jolokia-service.test.ts +++ b/packages/hawtio/src/plugins/shared/jolokia-service.test.ts @@ -94,4 +94,23 @@ describe('JolokiaService', () => { expect(options.maxDepth).toEqual(3) expect(options.maxCollectionSize).toEqual(10000) }) + + test('problematic JSON response from case hawtio/hawtio#3401', async () => { + const response = { + value: { + 'java.util.logging': { + 'type=Logging': { + class: 'sun.management.ManagementFactoryHelper$PlatformLoggingImpl', + desc: 'Information on the management interface of the MBean', + }, + }, + 'my-domain-with-vanishing-mbeans': { + 'type=Bean1': { + error: 'javax.management.InstanceNotFoundException: Bean1', + }, + }, + }, + } + jolokiaService.unwindListResponse(response.value) + }) }) diff --git a/packages/hawtio/src/plugins/shared/jolokia-service.ts b/packages/hawtio/src/plugins/shared/jolokia-service.ts index 6f9fcdfd..d5c66485 100644 --- a/packages/hawtio/src/plugins/shared/jolokia-service.ts +++ b/packages/hawtio/src/plugins/shared/jolokia-service.ts @@ -543,7 +543,7 @@ class JolokiaService implements IJolokiaService { * @param response response value from Jolokia LIST * @param path optional path information to restore the response to {@link OptimisedJmxDomains} */ - private unwindListResponse(response: unknown, path?: string[]): OptimisedJmxDomains { + unwindListResponse(response: unknown, path?: string[]): OptimisedJmxDomains { if (isOptimisedListResponse(response)) { // Post process cached MBean info const { cache, domains } = response diff --git a/packages/hawtio/src/plugins/shared/tree/node.ts b/packages/hawtio/src/plugins/shared/tree/node.ts index 98d3040d..683ddd97 100644 --- a/packages/hawtio/src/plugins/shared/tree/node.ts +++ b/packages/hawtio/src/plugins/shared/tree/node.ts @@ -23,8 +23,12 @@ export function isJmxDomains(value: unknown): value is OptimisedJmxDomains { export type OptimisedJmxDomain = Record +function isMBeanInfoOrError(value: unknown): boolean { + return isMBeanInfo(value) || isMBeanInfoError(value) +} + export function isJmxDomain(value: unknown): value is OptimisedJmxDomain { - return is(value, record(string(), define('MBeanInfo', isMBeanInfo))) + return is(value, record(string(), define('MBeanInfo', isMBeanInfoOrError))) } export interface OptimisedMBeanInfo extends Omit { @@ -47,6 +51,14 @@ export function isMBeanInfo(value: unknown): value is OptimisedMBeanInfo { ) } +export interface ErrorMBeanInfo { + error: string +} + +export function isMBeanInfoError(value: unknown): value is ErrorMBeanInfo { + return is(value, type({ error: string() })) +} + export interface OptimisedMBeanAttribute extends MBeanAttribute { canInvoke?: boolean }