Skip to content

Commit

Permalink
fix(Jolokia): Support native Jolokia 2.1.x optimization mode (fixes #…
Browse files Browse the repository at this point in the history
…3663) (#1221) (#1222)

(cherry picked from commit a7ec911)
  • Loading branch information
grgrzybek authored Nov 14, 2024
1 parent 2dc355d commit 4e2ea4e
Show file tree
Hide file tree
Showing 5 changed files with 92 additions and 24 deletions.
4 changes: 2 additions & 2 deletions packages/hawtio/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
"dependencies": {
"@hawtio/camel-model-v4_4": "npm:@hawtio/camel-model@~4.4.3",
"@hawtio/camel-model-v4_8": "npm:@hawtio/camel-model@~4.8.1",
"@jolokia.js/simple": "^2.1.7",
"@jolokia.js/simple": "^2.1.8",
"@module-federation/utilities": "^3.1.16",
"@monaco-editor/react": "^4.6.0",
"@patternfly/react-charts": "~7.3.0",
Expand All @@ -57,7 +57,7 @@
"@types/react-router-dom": "^5.3.3",
"dagre": "^0.8.5",
"eventemitter3": "^5.0.1",
"jolokia.js": "^2.1.7",
"jolokia.js": "^2.1.8",
"jquery": "^3.7.1",
"js-logger": "^1.6.1",
"jwt-decode": "^4.0.0",
Expand Down
7 changes: 6 additions & 1 deletion packages/hawtio/src/plugins/rbac/tree-processor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,13 @@ export const rbacTreeProcessor: TreeProcessor = async (tree: MBeanTree) => {
const mbeans = tree.flatten()
const listMethod = await jolokiaService.getListMethod()
switch (listMethod) {
case JolokiaListMethod.NATIVE:
case JolokiaListMethod.OPTIMISED: {
log.debug('Process JMX tree: optimised list mode')
if (listMethod === JolokiaListMethod.NATIVE) {
log.debug('Process JMX tree: native list mode')
} else {
log.debug('Process JMX tree: optimised list mode')
}
// Check if RBACDecorator has been already applied to the MBean tree at server side.
const decorated = Object.values(mbeans).every(node => node.isRBACDecorated())
if (decorated) {
Expand Down
33 changes: 32 additions & 1 deletion packages/hawtio/src/plugins/shared/jolokia-service.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ describe('JolokiaService', () => {
await expect(jolokiaService.getJolokiaUrl()).resolves.toBeNull()
}, 10000)

test('getJolokia - optimised', async () => {
test('getJolokia - optimised (mbean)', async () => {
jolokiaService.getJolokiaUrl = jest.fn(async () => '/test')
Jolokia.prototype.list = jest.fn(
(path?: string | string[] | jolokia.RequestOptions, opts?: SimpleRequestOptions) => {
Expand All @@ -42,11 +42,34 @@ describe('JolokiaService', () => {
return null
},
)
Jolokia.prototype.version = jest.fn((opts?: SimpleRequestOptions) => {
;(opts!.success! as SimpleResponseCallback)({
agent: 'test',
protocol: '7.3',
info: {},
config: {},
})
})

await expect(jolokiaService.getJolokia()).resolves.not.toThrow()
await expect(jolokiaService.getListMethod()).resolves.toEqual(JolokiaListMethod.OPTIMISED)
})

test('getJolokia - optimised (native)', async () => {
jolokiaService.getJolokiaUrl = jest.fn(async () => '/test')
Jolokia.prototype.version = jest.fn((opts?: SimpleRequestOptions) => {
;(opts!.success! as SimpleResponseCallback)({
agent: 'test',
protocol: '8.0',
info: {},
config: {},
})
})

await expect(jolokiaService.getJolokia()).resolves.not.toThrow()
await expect(jolokiaService.getListMethod()).resolves.toEqual(JolokiaListMethod.NATIVE)
})

test('getJolokia - default', async () => {
jolokiaService.getJolokiaUrl = jest.fn(async () => '/test')
Jolokia.prototype.list = jest.fn((...params: (string[] | string | SimpleRequestOptions)[]) => {
Expand Down Expand Up @@ -82,6 +105,14 @@ describe('JolokiaService', () => {
)
return null
})
Jolokia.prototype.version = jest.fn((opts?: SimpleRequestOptions) => {
;(opts!.success! as SimpleResponseCallback)({
agent: 'test',
protocol: '7.3',
info: {},
config: {},
})
})

await expect(jolokiaService.getJolokia()).resolves.not.toThrow()
await expect(jolokiaService.getListMethod()).resolves.toEqual(JolokiaListMethod.DEFAULT)
Expand Down
50 changes: 41 additions & 9 deletions packages/hawtio/src/plugins/shared/jolokia-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,10 @@ const JOLOKIA_PATHS = ['jolokia', '/hawtio/jolokia', '/jolokia'] as const
export enum JolokiaListMethod {
/** The default LIST+EXEC Jolokia operations. */
DEFAULT,
/** The optimised list operations provided by Hawtio RBACRegistry MBean. */
/** The optimised list operation provided by Hawtio RBACRegistry MBean. */
OPTIMISED,
/** THe optimised list operation provided directly by Jolokia 2.1+ */
NATIVE,
/** Not determined. */
UNDETERMINED,
}
Expand Down Expand Up @@ -437,11 +439,38 @@ class JolokiaService implements IJolokiaService {
log.debug('Check if we can call optimised jolokia.list() operation')
// hawtio/hawtio-next#635: we pass an executor which accepts only resolve cb - we never call reject cb even
// on error, but we ensure that resolve cb is called

const path = escapeMBeanPath(this.config.mbean)
async function checkCapabilities(
successFn: SimpleResponseCallback,
errorFn: ErrorCallback,
options: SimpleRequestOptions,
) {
// check for Jolokia version (TODO: use single call)
await jolokia.version(onVersionSuccessAndError(successFn, errorFn, options))
// check for special MBean
await jolokia.list(path, onListSuccessAndError(successFn, errorFn, options))
}

return new Promise<void>(resolve => {
const successFn: SimpleResponseCallback = (value: JolokiaResponseValue) => {
// check if the MBean exists by testing whether the returned value has
// the 'op' property
if (isMBeanInfo(value) && isObject(value.op)) {
// check if this is a version response - since protocol version 8.0 we can get optimized response directly
if (this.config.method === JolokiaListMethod.NATIVE) {
resolve()
return
}
if (value && typeof value === 'object' && 'protocol' in value) {
const protocolVersion = value.protocol
if (parseFloat(protocolVersion as string) >= 8.0) {
this.config.method = JolokiaListMethod.NATIVE
log.debug('Jolokia list method:', JolokiaListMethod[this.config.method])
resolve()
}
// return without resolve
return
} else if (isMBeanInfo(value) && isObject(value.op)) {
// check if the MBean exists by testing whether the returned value has
// the 'op' property
this.config.method = JolokiaListMethod.OPTIMISED
} else {
// we could get 403 error, mark the method as special case,
Expand All @@ -458,10 +487,7 @@ class JolokiaService implements IJolokiaService {
resolve() // optimisation not happening
}

jolokia.list(
escapeMBeanPath(this.config.mbean),
onListSuccessAndError(successFn, errorFn, { fetchError: this.fetchError(resolve) }),
)
checkCapabilities(successFn, errorFn, { fetchError: this.fetchError(resolve) })
})
}

Expand Down Expand Up @@ -582,8 +608,14 @@ class JolokiaService implements IJolokiaService {
}
case JolokiaListMethod.DEFAULT:
case JolokiaListMethod.UNDETERMINED:
case JolokiaListMethod.NATIVE:
default: {
log.debug('Invoke Jolokia list MBean in default mode:', paths)
if (method === JolokiaListMethod.NATIVE) {
options.listCache = true
log.debug('Invoke Jolokia list MBean in native mode:', paths)
} else {
log.debug('Invoke Jolokia list MBean in default mode:', paths)
}
const listOptions = onListSuccessAndError(
value => {
// For empty or single list, the first path should be enough
Expand Down
22 changes: 11 additions & 11 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2019,7 +2019,7 @@ __metadata:
dependencies:
"@hawtio/camel-model-v4_4": "npm:@hawtio/camel-model@~4.4.3"
"@hawtio/camel-model-v4_8": "npm:@hawtio/camel-model@~4.8.1"
"@jolokia.js/simple": "npm:^2.1.7"
"@jolokia.js/simple": "npm:^2.1.8"
"@module-federation/utilities": "npm:^3.1.16"
"@monaco-editor/react": "npm:^4.6.0"
"@patternfly/react-charts": "npm:~7.3.0"
Expand Down Expand Up @@ -2047,7 +2047,7 @@ __metadata:
jest-environment-jsdom: "npm:^29.7.0"
jest-fetch-mock: "npm:^3.0.3"
jest-watch-typeahead: "npm:^2.2.2"
jolokia.js: "npm:^2.1.7"
jolokia.js: "npm:^2.1.8"
jquery: "npm:^3.7.1"
js-logger: "npm:^1.6.1"
jwt-decode: "npm:^4.0.0"
Expand Down Expand Up @@ -2382,12 +2382,12 @@ __metadata:
languageName: node
linkType: hard

"@jolokia.js/simple@npm:^2.1.7":
version: 2.1.7
resolution: "@jolokia.js/simple@npm:2.1.7"
"@jolokia.js/simple@npm:^2.1.8":
version: 2.1.8
resolution: "@jolokia.js/simple@npm:2.1.8"
dependencies:
jolokia.js: "npm:^2.1.7"
checksum: 10/26bc017c64df1600325f5185c39d48f600d0f3e43c5bed9e79c738c9f248eba03c9bf8a68303d7aee9bfcb9f34d44cafba705f4c5ebdd74adfdda238b29826f3
jolokia.js: "npm:^2.1.8"
checksum: 10/b60f874c93c55444998702e2948c7b5821cdecce8e12d93506260ca5787bb6d7fad81542cbf509cd9112360b6c31839bab970669b77df57d48459b1aa434ace3
languageName: node
linkType: hard

Expand Down Expand Up @@ -10210,10 +10210,10 @@ __metadata:
languageName: node
linkType: hard

"jolokia.js@npm:^2.1.7":
version: 2.1.7
resolution: "jolokia.js@npm:2.1.7"
checksum: 10/7e10e0b842c96853ea2815d46cc7cea278470d259d8660711fbfda58c3a730764790ee28dd9ad346ebcb8324bd500f109408675f19d8c0a75578703522956d91
"jolokia.js@npm:^2.1.8":
version: 2.1.8
resolution: "jolokia.js@npm:2.1.8"
checksum: 10/4dd3db2954abbaf875a3630591257056c866a201df5f3bab36148eee9e2e1520061c3b14d6873f3f0af71b2938323ecaa9540a9e37c3d952711bee077b99aca5
languageName: node
linkType: hard

Expand Down

0 comments on commit 4e2ea4e

Please sign in to comment.