Currently hawtio uses JMX to discover which MBeans are present and then dynamically updates the navigation bars and tabs based on what it finds. The UI is updated whenever hawtio reloads the mbeans JSON; which it does periodically or a plugin can trigger explicitly.
So you can deploy the standard hawtio-web.war; then as you deploy more services to your container, hawtio will update itself to reflect the suitable plugins in the UI.
Relying on JMX for discovery doesn't mean though that plugins can only interact with JMX; they can do anything at all that a browser can. e.g. a plugin could use REST to discover UI capabilities and other plugins.
A hawtio plugin is anything that will run inside a browser. We've tried to keep hawtio plugins as technology agnostic as possible; so a plugin is just some combination of JS / HTML / CSS / markup / images and other content that can be loaded in a browser.
From a plugin developer's perspective a plugin is just a set of resources; usually at least one JavaScript file.
For all the plugins we've done so far we've picked AngularJS as the UI framework, which has nice a two-way binding between the HTML markup and the JS data model along with modularisation, web directives and dependency injection.
We're using TypeScript to generate the JS code to get syntax for modules, classes, interfaces, type inference and static type checking; but folks can use anything that compiles to JS (e.g. vanilla JS or JSLint / Google Closure, CoffeeScript or any of the JVM language → JS translators like GWT, Kotlin, Ceylon etc)
In terms of JS code, we're using JavaScript modules to keep things separated, so plugins can't conflict but they can work together if required. From an AngularJS perspective we're using AngularJS's modules and dependency injection; which makes it easy for plugins to interact with each other & share services between them. e.g. plugins which want to interact with or listen to changes in the MBean tree can be injected with the Workspace service etc.
If you want so see some example code, here's a log plugin designed to work with an MBean which queries the log statements from SLF4J/log4j, etc.
Thanks to the dependency injection of AngularJS different plugins can expose services and perform various kinds of integration and wiring together.
There are various ways of adding your own plugins to hawtio:
The simplest way to make plugins available is to statically link them inside the WAR hosting the hawtio web application.
e.g. if you create a maven WAR project and add the hawtio-web WAR dependency and use the maven war plugin you can then add your own plugins into the src/main/webapp/app directory.
Plugins can be packaged up as a separate deployment unit (WAR, OSGi bundle, EAR, etc) and then deployed like any other deployment unit.
The plugin then needs to expose a hawtio plugin MBean instance which describes how to load the plugin artifacts (e.g. local URLs inside the container or public URLs to some website). See the plugin examples for more details.
So plugins can be deployed into the JVM via whatever container you prefer (web container, OSGi, JEE).
To see how this works check out the plugin examples and detailed description.
For example WAR deployment units can easily be deployed in a web container such as Apache Tomcat. Just drop the plugin in the deploy directory along with the hawtio WAR. And hawtio will automatic detect the custom plugin.
The standalone hawtio application (hawtio-app) is also capable of using custom plugins as WAR files. This can be done by copying the plugin WARs to the plugins sub directory where hawtio-app is launched.
For example the current directory is myfolder
, where we create a sub directory named plugins
, and then copy our custom plugins as WAR files to that directory. And then just launch hawtio-app as usual.
myfolder$
mkdir plugins
cp ~/mycustomplugin.war plugins
java -jar hawtio-app-1.5.11.jar
You can copy as many custom plugins to the plugins
directory.
An important aspect however, is that the name of the WAR file must match the context-path name, that has been configured in the web.xml
file. For example the groovy-shell example plugin has configured groovy-shell-plugin
as its context-path, which means the name of the WAR file must be groovy-shell-plugin.war
. Here is the name configured here, which will be used as placeholder in the web.xml file.
We've not fully implemented this yet—but we can have a simple JSON registry inside the hawtio application which maps known MBean object names to external plugins. We can then auto-install plugins using trusted JSON repositories of plugins.
This has the benefit of not requiring any changes to the JVM being managed (other than Jolokia being inside).
Here is a sample JSON file to show the kind of thing we mean.
We could add a “plugin manager” plugin to allow users to add new plugins either into the JVM, some registry or purely on the client side with local storage. So rather like with jenkins you can install new plugins from a repository of well known plugins, we could add the same capability to hawtio.