Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
7c26d3f
ARTEMIS-5569 Include Monaco editor scripts locally
ViliusS Jul 22, 2025
be13d9e
Overload correct loader
ViliusS Jul 22, 2025
8744409
Reorganize dependencies
ViliusS Jul 25, 2025
34ca60a
Dependencies fixed
ViliusS Jul 26, 2025
9b6bb76
Extract workers
ViliusS Jul 26, 2025
33beba6
ARTEMIS-5443: Upgrade to yarn 4.9.2 and update yarn information in DE…
grgrzybek Jul 11, 2025
c73d9b0
ARTEMIS-5577: Adjust dev/peer dependencies for upcoming @hawtio/react…
grgrzybek Jul 16, 2025
7d52e61
ARTEMIS-5577: Switch to dynamic Hawtio plugin registration and initia…
grgrzybek Jul 16, 2025
330be7f
ARTEMIS-5546: Prevent rejected promises initialized in ArtemisService
grgrzybek Jul 16, 2025
4ed0c4b
ARTEMIS-5497: Synchronizing model changes on layout animation
grgrzybek Jul 22, 2025
83a0cb7
ARTEMIS-5580: Separate initialization and UI code
grgrzybek Jul 22, 2025
bef56cd
[build] With DISABLE_WS=1 webpack will start without hot reload
grgrzybek Jul 30, 2025
462b851
ARTEMIS-5443: Upgrade to @hawtio/react 1.10.0
grgrzybek Jul 30, 2025
0c76665
ARTEMIS-5577: Update "resolutions" to latest versions
grgrzybek Jul 30, 2025
2308745
[build] Use latest xml-formatter
grgrzybek Jul 30, 2025
f8476f9
ARTEMIS-5569: Use @hawtio/react 1.10.1 and do not bundle @monaco-edit…
grgrzybek Jul 30, 2025
0ca5d15
ARTEMIS-5600: Do not import _all_ icons from @patternfly/react-icons.…
grgrzybek Jul 30, 2025
8455938
[build] Fix typescript errors
grgrzybek Jul 30, 2025
fa6ad96
[build] Use corepack with frontend-maven-plugin and newer (a bit) nod…
grgrzybek Jul 30, 2025
513147b
ARTEMIS-5443: Upgrade to yarn 4.9.3
grgrzybek Aug 21, 2025
ee78d44
ARTEMIS-5443: Upgrade to Hawtio 1.10.2 and Jolokia.js 2.3.0
grgrzybek Aug 21, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 7 additions & 6 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,10 @@ artemis-console-extension/artemis-extension/packages/artemis-console-plugin/node
artemis-console-extension/artemis-extension/app/node_modules/**/*

# yarn (zero-installs)
artemis-console-extension/artemis-extension/.yarn/**/*
artemis-console-extension/artemis-extension/!.yarn/patches
artemis-console-extension/artemis-extension/!.yarn/plugins
artemis-console-extension/artemis-extension/!.yarn/releases
artemis-console-extension/artemis-extension/!.yarn/sdks
artemis-console-extension/artemis-extension/!.yarn/versions
artemis-console-extension/artemis-extension/.yarn/install-state.gz
.yarn/**
!artemis-console-extension/artemis-extension/.yarn/patches
!artemis-console-extension/artemis-extension/.yarn/plugins
!artemis-console-extension/artemis-extension/.yarn/releases
!artemis-console-extension/artemis-extension/.yarn/sdks
!artemis-console-extension/artemis-extension/.yarn/versions

Large diffs are not rendered by default.

Large diffs are not rendered by default.

16 changes: 15 additions & 1 deletion artemis-console-extension/artemis-extension/.yarnrc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,18 @@ plugins:
path: .yarn/plugins/@yarnpkg/plugin-licenses.cjs
spec: "https://raw.githubusercontent.com/mhassan1/yarn-plugin-licenses/v0.15.0/bundles/@yarnpkg/plugin-licenses.js"

yarnPath: .yarn/releases/yarn-4.9.1.cjs
packageExtensions:
# see: https://github.com/patternfly/patternfly-react/issues/11923
'@patternfly/react-code-editor@*':
peerDependencies:
'monaco-editor': '^0.52.2'
# this one is strange:
# - there's peer dependency to webpack, but I don't think it's necessary
# - suggested @module-federation/runtime doesn't refer to variables like __webpack_require__, so it doesn't look
# like direct replacement of @module-federation/utilities
'@module-federation/utilities@*':
peerDependenciesMeta:
'webpack':
'optional': true

yarnPath: .yarn/releases/yarn-4.9.3.cjs
125 changes: 119 additions & 6 deletions artemis-console-extension/artemis-extension/DEV.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ Everything besides the `pom.xml` is a [Javascript monorepository][3] containing

Artemis Console plugin (and application) depends on Hawtio because it is effectively a [Hawtio plugin][9]. That's why the most important dependency is:

"@hawtio/react": "^1.9.0"
"@hawtio/react": "^1.10.0"

To keep compatibility with Hawtio, versions of [Patternfly][10] and [React][11] packages should be aligned.

Expand All @@ -22,19 +22,123 @@ To make it easier to maintain consistent dependencies between Hawtio (which can
It's worth following some guidelines in the fascinating world of JavaScript build tools. This distinction is very important:

* _libraries_ - packages published to NPM registry and consumable by other packages/applications
* _applications_ - final deployables that use other packages which are not consumed further
* _applications_ - final deployables that use other packages and which are not consumed further

This separation determines the _bundlers_ that should be used to change original code into distributed code.

When using _bundlers_ for libraries, we have to be careful, because the libraries package will be consumed by projects using own configurations and own bundlers. That's why we use [tsup][6] = [esbuild][7] + [Rollup][8] for this task.
When using _bundlers_ for libraries, we have to be careful, because the library packages will be consumed by projects using own configurations and own bundlers. That's why we use [tsup][6] = [esbuild][7] + [Rollup][8] for this task.

When using _bundlers_ for applications, we need to ensure that all dependencies are included (bundled) in most optimal way (chunking, tersing, ...). That's why we use [Webpack][4] for this task (which may be replaced by [Rspack][12] at some point).

## Project structure

We use [Javascript monorepository][3] for better separation of library and application code.

Top level `package.json` declares `workspaces` field and _child_ `package.json` contain specific dependencies and scripts. Common dependencies are declared in parent `package.json`.
Top level `package.json` declares `workspaces` field and _child_ `package.json` contain specific dependencies and scripts.

We use `yarn` package manager and we can add dependencies to projects in a monorepo (_workspaces_) using:
```console
$ yarn workspace artemis-console-plugin add @hawtio/react
```

or simply:
```console
$ cd packages/artemis-console-plugin; yarn add @hawtio/react
```

However the recommended way is to use the `yarn workspace <workspace> add <dependency>` variant. The _classic_ one where we `cd` into a workspace usually works, but sometimes may cause problems with:
* top level `yarn.lock`
* nested `node_modules/` being created in given workspace (instead of _hoisting_ the dependency to monorepo root `node_modules/`).

## Project dependencies

[activemq-artemis-console Github repository](https://github.com/apache/activemq-artemis-console/) is a Maven project which ultimately builds a WAR archive to be used in [activemq-artemis](https://github.com/apache/activemq-artemis/).

Focusing on JavaScript only, artemis-extension is a monorepo, which contains:
* app: Application bundled by `webpack`
* packages/artemis-console-plugin: Library bundled by `tsup`

Adding Hawtio to the list, we have:

* `react`, `react-dom`, `react-router-dom`: NPM library packages from React
* `@patternfly/react-core` (and other `@patternfly/react-*` packages): NPM library packages which build on React and provide additional components - they depend on React using `peerDependencies`
* `@hawtio/react`: NPM library package that provides React/Patternfly components and own API to build Hawtio applications
* `packages/artemis-console-plugin`: NPM library package that uses `@hawtio/react`, React itself and Patternfly
* `app`: Ultimate application that will be packaged into WAR. It is bundled using `webpack` and uses `@hawtio/react` + `packages/artemis-console-plugin` libraries

The most important product of [activemq-artemis-console Github repository](https://github.com/apache/activemq-artemis-console/) is the WAR archive and JavaScript application bundled by `webpack`, but additionally `packages/artemis-console-plugin` package itself should eventually be published to NPM.

There may be existing _applications_ that could use both `@hawtio/react` **and** `packages/artemis-console-plugin` to provide "Hawtio with Artemis support".

That's why it is important to know how to manage dependencies in JavaScript applications. There's some confusion about how to use `dependencies` and `peerDependencies`. I'd like to suggest one rule for determining which one to use:

> Should a dependency version be determined by my `package.json` or rather by other packages that use my library as dependency?

In this case, both `@hawtio/react` and `packages/artemis-console-plugin` are effectively _component libraries_ that work with React (and Patternfly) and ultimately it is the final _application_ that uses React, Patternfly **and** Hawtio + artemis libraries. So `react`, `react-dom`, etc.:
* should be in `peerDependencies` of `@hawtio/react` and `packages/artemis-console-plugin`
* should be in `dependencies` of _applications_ bundles with Webpack

`@hawtio/react` usage may be more tricky. However it is definitely a _dependency_ of an application. But because a webpack-bundled application may use both `@hawtio/react` and `packages/artemis-console-plugin`, `packages/artemis-console-plugin` should use `@hawtio/react` as _peer dependency_ to let the application decide on the version...

These are recommendations, not strict rules, but without using _peer dependencies_ it is important to strictly align versions between the packages.

## Version changes in `package.json`

With `yarn` we have a great tool to review updates to versions - both in `devDependencies` and `dependencies` fields.

Here's an example of updates, where we can choose what we want to change and what we should leave:

```console
$ yarn upgrade-interactive
Press <up>/<down> to select packages. Press <enter> to install.
Press <left>/<right> to select versions. Press <ctrl+c> to abort.

? Pick the packages you want to upgrade. Current Range Latest

@patternfly/react-charts -------------------- ◉ ^7.4.9 ------- ◯ ^8.3.0 -------
@patternfly/react-code-editor --------------- ◉ ^5.4.18 ------ ◯ ^6.3.0 -------
@patternfly/react-core ---------------------- ◉ ^5.4.14 ------ ◯ ^6.3.0 -------
@patternfly/react-icons --------------------- ◉ ^5.4.2 ------- ◯ ^6.3.0 -------
@patternfly/react-styles -------------------- ◉ ^5.4.1 ------- ◯ ^6.3.0 -------
@patternfly/react-table --------------------- ◉ ^5.4.16 ------ ◯ ^6.3.0 -------
@patternfly/react-tokens -------------------- ◉ ^5.4.1 ------- ◯ ^6.3.0 -------
@patternfly/react-topology ------------------ ◉ ^5.4.1 ------- ◯ ^6.3.0 -------
@swc/core ----------------------------------- ◯ ^1.12.14 ----- ◉ ^1.13.3 ------
@testing-library/dom ------------------------ ◯ ^10.4.0 ------ ◉ ^10.4.1 ------
@testing-library/jest-dom ------------------- ◯ ^6.6.3 ------- ◉ ^6.6.4 -------
@types/node --------------------------------- ◯ ^24.0.14 ----- ◉ ^24.1.0 ------
@types/react-dom ---------------------------- ◉ ^18.3.7 ------ ◯ ^19.1.7 ------
@types/react -------------------------------- ◉ ^18.3.23 ----- ◯ ^19.1.9 ------
jest-environment-jsdom ---------------------- ◯ ^30.0.4 ------ ◉ ^30.0.5 ------
jest ---------------------------------------- ◯ ^30.0.4 ------ ◉ ^30.0.5 ------
react-dom ----------------------------------- ◉ ^18.3.1 ------ ◯ ^19.1.1 ------
react-router-dom ---------------------------- ◉ ^6.30.1 ------ ◯ ^7.7.1 -------
react --------------------------------------- ◉ ^18.3.1 ------ ◯ ^19.1.1 ------
> webpack ------------------------------------- ◯ ^5.100.2 ----- ◉ ^5.101.0 -----
```

`yarn` highlights which version updates will match specified range and what is the actual latest version. This is very important for major version updates, because we may want to stay at React 18 or Patternfly 5.

However `yarn upgrade-interactive` is not good for updates in `resolutions` fields. However we can use some scripting. Run this command in `artemis-console-extension/artemis-extension` (top-level directory of NPM monorepo):

```console
$ for d in $(jq -r '.resolutions|keys[]' package.json); do echo "=== $d"; npm view $d versions --json | jq -r '.|last'; done
=== @babel/runtime
8.0.0-beta.1
=== @jolokia.js/simple
2.2.4
=== @typescript-eslint/eslint-plugin
8.38.0
=== @typescript-eslint/parser
8.38.0
=== axios
1.11.0
=== braces
3.0.3
=== caniuse-lite
1.0.30001731
...
```

## Yarn package manager management

Expand All @@ -58,10 +162,19 @@ $ yarn set version 4.9.1 --yarn-path
➤ YN0000: Saving the new release in .yarn/releases/yarn-4.9.1.cjs
➤ YN0000: Done in 0s 448ms
```
6. To check what's the latest version of yarn run:
```console
$ corepack up
Installing yarn@4.9.2 in the project...
...
```
7. `packageManager` field will be upgraded, but we also have to call proper `yarn set version <version> --yarn-path` to update `.yarnrc.yml`.

With `yarn set version 4.9.1 --yarn-path`:
With `yarn set version 4.9.2 --yarn-path`:
* `packageManager` field is updated with selected version
* `yarnPath` field in `.yarnrc.yml` is updated to point to _downloaded_ version of Yarn which should be stored in SCM - by default it's `.yarn/releases/yarn-4.9.1.cjs` (for version 4.9.1)
* `yarnPath` field in `.yarnrc.yml` is updated to point to _downloaded_ version of Yarn which should be stored in SCM - by default it's `.yarn/releases/yarn-4.9.2.cjs` (for version 4.9.2)
* previous version of `.yarn/releases/yarn-*.cjs` will be removed
* `.yarn/releases/LICENSE-yarn.txt` will also be removed, so remember to restore it (and check if its content needs to be updated to match the licence information at the end of `.yarn/releases/yarn-4.9.2.cjs` file)

----
[1]: https://github.com/eirslett/frontend-maven-plugin
Expand Down
48 changes: 26 additions & 22 deletions artemis-console-extension/artemis-extension/app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,41 +10,45 @@
"replace-version": "replace __PACKAGE_VERSION_PLACEHOLDER__ $npm_package_version ./build/static/js -r --include=\"*.js\""
},
"dependencies": {
"@hawtio/react": "1.9.4",
"@patternfly/react-charts": "~7.4.9",
"@patternfly/react-code-editor": "~5.4.18",
"@patternfly/react-core": "~5.4.14",
"@patternfly/react-icons": "~5.4.2",
"@patternfly/react-styles": "~5.4.1",
"@patternfly/react-table": "~5.4.16",
"@patternfly/react-tokens": "~5.4.1",
"@patternfly/react-topology": "~5.4.1",
"artemis-console-plugin": "1.2.1",
"@hawtio/react": "^1.10.2",
"@monaco-editor/react": "^4.6.0",
"@patternfly/react-charts": "^7.4.9",
"@patternfly/react-code-editor": "^5.4.18",
"@patternfly/react-core": "^5.4.14",
"@patternfly/react-icons": "^5.4.2",
"@patternfly/react-styles": "^5.4.1",
"@patternfly/react-table": "^5.4.16",
"@patternfly/react-tokens": "^5.4.1",
"@patternfly/react-topology": "^5.4.1",
"artemis-console-plugin": "workspace:*",
"d3": "^7.9.0",
"monaco-editor": "^0.52.2",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-router-dom": "^6.30.0"
"react-router-dom": "^6.30.1"
},
"devDependencies": {
"@hawtio/backend-middleware": "^1.0.6",
"@swc/core": "^1.7.26",
"copy-webpack-plugin": "^12.0.2",
"@swc/core": "^1.13.3",
"@types/react": "^18.3.23",
"body-parser": "^2.2.0",
"copy-webpack-plugin": "^13.0.0",
"css-loader": "^7.1.2",
"css-minimizer-webpack-plugin": "^7.0.0",
"html-webpack-plugin": "^5.6.0",
"mini-css-extract-plugin": "^2.9.1",
"css-minimizer-webpack-plugin": "^7.0.2",
"html-webpack-plugin": "^5.6.3",
"mini-css-extract-plugin": "^2.9.2",
"monaco-editor-webpack-plugin": "^7.1.0",
"os-browserify": "^0.3.0",
"path-browserify": "^1.0.1",
"react-dev-utils": "^12.0.1",
"replace": "^1.2.2",
"source-map-loader": "^5.0.0",
"style-loader": "^4.0.0",
"swc-loader": "^0.2.6",
"terser-webpack-plugin": "^5.3.10",
"webpack": "^5.99.0",
"webpack-cli": "^5.1.4",
"webpack-dev-server": "^5.2.1",
"webpack-manifest-plugin": "^5.0.0"
"terser-webpack-plugin": "^5.3.14",
"webpack": "^5.101.0",
"webpack-cli": "^6.0.1",
"webpack-dev-server": "^5.2.2",
"webpack-manifest-plugin": "^5.0.1"
},
"eslintConfig": {
"extends": [
Expand Down
72 changes: 50 additions & 22 deletions artemis-console-extension/artemis-extension/app/src/bootstrap.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,33 +14,61 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { hawtio, Hawtio, connect, jmx, keycloak, oidc, rbac, runtime, configManager } from '@hawtio/react'
import React from 'react'
import ReactDOM from 'react-dom/client'
import { artemis } from 'artemis-console-plugin';
import 'artemis-console-plugin/styles';

// Register builtin plugins
import { configManager, HawtioInitialization, TaskState } from '@hawtio/react/init'

keycloak();
oidc();
connect();
jmx();
rbac();
runtime();
// Hawtio itself creates and tracks initialization tasks, but we can add our own. 'Loading UI' initialization
// task nicely controls the initialization phase at _application_ level
configManager.initItem('Loading UI', TaskState.started, 'config')

// Register the plugin under development
artemis();
// Create root for rendering React components. More React components can be rendered in single root.
const root = ReactDOM.createRoot(document.getElementById('root') as HTMLElement)

// Basic UI that shows initialization progress without depending on PatternFly.
// It is imported and rendered in fully synchronous way.
root.render(<HawtioInitialization verbose={true} />)

// See package.json "replace-version" script for how to replace the version placeholder with a real version
configManager.addProductInfo('Artemis Console', '__PACKAGE_VERSION_PLACEHOLDER__');

// Bootstrap Hawtio
hawtio.bootstrap();

const root = ReactDOM.createRoot(document.getElementById('root') as HTMLElement);
root.render(
<React.StrictMode>
<Hawtio />
</React.StrictMode>,
);

// Initialization phase is finished. We could already bootstrap Hawtio, but this is the stage, where we register
// built-in Hawtio plugins and our examples (custom plugins).
// From now on, we use dynamic `import()` instead of static `import` and we can import _full_ Hawtio packages:
// '@hawtio/react' and '@hawtio/react/ui'
import('@hawtio/react').then(async m => {
// The heavier non-UI part of Hawtio was loaded/evaluated, so we have access to built-in plugins
// We can register all default (built-in) Hawtio plugins
// m.registerPlugins()

// but we can also choose which built-in plugins to use
m.keycloak();
m.oidc();
m.connect();
m.jmx();
m.rbac();
m.runtime();

// Register the plugin under development with await, so hawtio.bootstrap() is aware of this plugin
await import('artemis-console-plugin').then(async m => {
m.artemis()
})

// hawtio.bootstrap() will wait for all init items to be ready, so we have to finish 'loading'
// stage of UI. UI will be rendered after bootstrap() returned promise is resolved
configManager.initItem('Loading UI', TaskState.finished, 'config')

// finally, after we've registered all custom and built-in plugins, we can proceed to the final stage:
// - bootstrap(), which finishes internal configuration, applies branding and loads all registered plugins11111
// - rendering of <Hawtio> React component after bootstrap() finishes
m.hawtio.bootstrap().then(() => {
import('@hawtio/react/ui').then(m => {
root.render(
<React.StrictMode>
<m.Hawtio />
</React.StrictMode>
)
})
})
})
46 changes: 46 additions & 0 deletions artemis-console-extension/artemis-extension/app/src/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,50 @@
#root {
height: 100%;
}
.hwt-loading {
padding: 0.2em 0.5em;
}
.hwt-loading h4 {
margin: 0.3em 0;
}
.hwt-loading h4.ready {
margin: 0.3em 0;
color: black;
}
.hwt-loading h4.not-ready {
color: #adafb6;
}
.hwt-loading ul {
list-style-type: none;
padding: 0;
margin: 0;
}
.hwt-loading li {
margin: 0.1em 0 0.1em 0.5em;
}
.hwt-loading li span {
width: 2em;
display: inline-block;
}
.hwt-loading li.not-ready {
color: #adafb6;
}
.hwt-loading li.ready {
color: black;
}

.tick {
padding: 0 2px;
}
.tick-skipped {
color: #dddfe6;
}
.tick-finished {
color: green;
}
.tick-error {
color: red;
}
.tick-started {
color: #adafb6;
}
Loading