A JBoss Project
Red Hat

Developers

We love contributions. This page is intended to help you get started hacking on the code, it contains various information on technology and tools together with code walk-throughs.

Welcome and enjoy! Its hawt, but stay cool! :)

Hawtio 2.x Overview! Ooh, shiny shiny... look here!

Building the code

Check out How To Build The Code if you want to start hacking on the source.

Architecture

hawtio is a single page application which is highly modular and capable of dynamically loading plugins based on the capability of the server.

You may want to check out:

Developer Tools

The following are recommended if you want to contribute to the code

JavaScript Libraries

For those interested in contributing or just learning how to build single page applications, here is a list of the various open source libraries used to build hawtio:

  • AngularJS is the web framework for performing real time two-way binding of HTML to the model of the UI using simple declarative attributes in the HTML.
  • jolokia is the server side / JVM plugin for exposing JMX as JSON over HTTP. It's awesome and is currently the only server side component of hawtio.
  • TypeScript is the language used to implement the console; it compiles to JavaScript and adds classes, modules, type inference & type checking. We recommend IntelliJ IDEA EAP 12 or later for editing TypeScript—especially if you don't use Windows or Visual Studio (though there is a Sublime Text plugin too).
  • angular ui is a library of AngularJS additions and directives
  • d3 is the visualization library used to do the force layout graphs (for example the diagram view for ActiveMQ)
  • cubism implements the real-time horizon charts
  • dagre for graphviz style layouts of d3 diagrams (e.g. the Camel diagram view).
  • ng-grid an AngualrJS based table/grid component for sorting/filtering/resizing tables
  • marked for rendering Github-flavoured Markdown as HTML
  • DataTables for sorted/filtered tables (though we are migrating to ng-grid as its a bit more natural for AngularJS)
  • DynaTree for tree widget
  • jQuery small bits of general DOM stuff, usually when working with third-party libraries which don't use AngularJS
  • Twitter Bootstrap for CSS
  • Toastr for notifications

We're not yet using it but these look handy too:

API documentation

If you are interested in working on the code the following references and articles have been really useful so far:

Developer Articles, Forums and Resources

Code Walkthrough

If you fancy contributing—and we love contributions!—the following should give you an overview of how the code hangs together:

How the Tabs Work

Tabs can dynamically become visible or disappear based on the following:

  • the contents of the JVM
  • the plugins,
  • and the current UI selection(s).

Plugins can register new top-level tabs by adding to the topLevelTabs on the workspace which can be dependency injected into your plugin via AngularJS Dependency Injection.

The isValid() function is then used to specify when this top-level tab should be visible.

You can register subLevelTabs which are then visible when the right kind of MBean is selected.

For more detail check out the plugin documentation.

Enable Source Maps for Easier Debugging

We recommend you enable Source Maps in your browser (e.g. in Chrome) for easier debugging by clicking on the bottom-right Settings icon in the JavaScript Console and enabling Source Maps support such as in this video.

Notes on Using IDEA

To help IDEA navigate to functions in your source and to avoid noise, you may want to ignore some JavaScript files in IDEA so that they are not included in the navigation. Go to Settings/Preferences -> File Types -> Ignore Files then add these patterns to the end:

*.min.js;*-min.js

Ignoring these files will let IDEA ignore the minified versions of the JavaScript libraries.

Then select the generated webapp/app/app.js file in the Project Explorer, right-click and select Mark as Plain Text so that it is ignored as being JavaScript source. This hint came from this forum thread, hopefully there will be a nicer way to do all this one day!

Handy AngularJS debugging tip

Open the JavaScript Console and select the Console tab so you can type expressions into the shell. Select part of the DOM of the scope you want to investigate Right click and select Inspect Element In the console type the following

s = angular.element($0).scope()

You have now defined a variable called s which contains all the values in the active AngularJS scope so you can navigate into the scope and inspect values or invoke functions in the REPL, etc.

Handy JQuery debugging tip

Open the JavaScript Console and select the Console tab so you can type expressions into the shell. Select a DOM element (e.g., button) for which you want to check what jquery event handlers are attached. In the console type:

jQuery._data($0, "events")

You'll get array of events. When you expand the events and go to “handler” member (e.g., click->0->handler), you can:

  • in Firebug right click function() and select Inspect in Script Panel
  • in Chrome dev tools right click function() and select Show Function Definition

to see the body of handler method.

Handy AngularJS programming tips

Use a nested scope object to own state for 2 way binding

When binding models to HTML templates; its always a good idea to use a level of indirection between the $scope and the property. So rather than binding to $scope.name, bind to $scope.entity.name then have code like

$scope.entity = { "name": "James" };

This means to that to reset the form you can just do

$scope.entity = {};

And you can then refer to the entire entity via $scope.entity. Another reason for doing this is that when you have lots of nested scopes; for example when using nested directives, or using includes or layouts, you don't get inheritence issues; since you can acess $scope.entity from child scopes fine.

When working with $routeParams use the $scope.$on

Its often useful to use $routeParams to get the URI template parameters. However due to the rules on who gets the $routeParams injected when using layouts and so forth, the $routeParams can be empty.

So put all code that uses $routeParams inside the $routeChangeSuccess callback:

$scope.$on('$routeChangeSuccess', function(event, routeData){
  // process $routeParams now...
});

Local Storage

hawtio uses local storage to store preferences and preferred views for different kinds of MBean type and so forth.

You can view the current Local Storage in the Chrome developer tools console in the Resources / Local Storage tab.

If you ever want to clear it out in Chrome on OS X you'll find this located at ~/Library/Application Support/Google/Chrome/Default/Local Storage.

Updating the hawtio website

The website is automatic build and updated on each commit. There is a CI job on circleci that runs

https://circleci.com/gh/hawtio/hawtio

The task runs the script ci-website.sh that builds the website. If anything goes wrong, the errors are usully shown in the CI job output (link above).