Writing Your Own SonarQube Plug-ins – Part 3: Creating Widgets

In part 1 of this series here, I explained the basics of SonarQube plug-ins and how to start writing your own plug-in. In part 2 here, I explained how to define custom metrics and sensor classes to collect metric data (measures).

In part 3, I will show the basics of how to create custom widgets to present to users the information we are collecting from analysed projects.

EDIT: Source code for the simple plug-in shown during these posts can be obtained from GitHub here: https://github.com/deors/deors.plugins.sonarqube.idemetadata

Widgets in SonarQube are typically written in Ruby on Rails. SonarQube platform comes with a lot of existing widgets, views, parts, etc. that can be combined into dashboards, which will present different set of information based on roles, but also will allow to drilldown measures or issues from top-level projects to source code.

Part 3 – Creating Widgets

The objective for the widget we would like to create is to simply show collected project-level information in project’s dashboard: which type of project we have configured in the IDE, which dependencies exist with other projects, etc.

In part 1, when creating the plug-in class, we instructed SonarQube to find a widget definition contained in IDEMetadataDashboardWidget class.

A widget class is very simple to create:

  • Create a class extending org.sonar.api.web.AbstractRubyTemplate and implementing org.sonar.api.web.RubyRailsWidget.
  • Annotate the class with @org.sonar.api.web.UserRole. Add as parameter the roles that will have access to this widget: Admin, User, CodeViewer.
  • Optionally annotate the class with @org.sonar.api.web.Description. Add as parameter the description for the widget, as it will be showed in SonarQube dashboard configuration view. Tell the users what is your widget meant to do!
  • Implement getId() and getTitle() methods. Simply return a string with the widget id and title. The id should be unique and the title will later be showed in SonarQube dashboard configuration view.
  • Implement getTemplatePath() method. This method will return a string with the path where the Ruby page can be found. The path should be relative to the plug-in project classpath (starting with a forward slash). During development, however, it is useful to set the path as an absolute path in your file system. Doing that will allow for automatic refresh of changes in the widget while you are coding and testing it. But don’t forget to revert back to the relative path when you are ready to deploy the plug-in!

It’s really simple – it takes more time to explain it than to actually code it😉. See below the content of the widget class, without Javadocs to simplify the post.

@UserRole(UserRole.USER)
@Description("Shows IDE metadata configuration for the project, including project type, language support and configured frameworks")
public class IDEMetadataDashboardWidget extends AbstractRubyTemplate implements RubyRailsWidget {
    public String getId() {
        return "idemetadata";
    }
    public String getTitle() {
        return "IDE Metadata";
    }
    protected String getTemplatePath() {
        // uncomment next line for change reloading during development
        //return "c:/projects/xxxxx/src/main/resources/xxxxx/sonar/idemetadata/idemetadata_widget.html.erb";
        return "/xxxxx/sonar/idemetadata/idemetadata_widget.html.erb";
    }
}

Creating the View

Now it’s time to actually create the view. Views are created as Ruby on Rails pages. They are simple: even if you have not coded in Ruby on Rails before, you are probably familiarised with other templating engines so the jump to Rails should not be a challenge. Evenmore, the large amount of existing views that are available inside SonarQube are excellent to learn and apply patterns to your own views.

At the end, is HTML, styles and JavaScript what you are delivering to the clients, so just think with open mind what you can do with this mix of technologies. Do you want to use a JavaScript library because you like some of its visual components? You can. Are you a fan of Google charts and graphs? Use them. Are you a jQuery ninja? Unleash that power on your benefit.

If you don’t know where to start, pick an existing widget and make changes here and there, look at the existing JavaScript libraries to interact with SonarQube API, and you will be ready in no time.

Some pieces of advice that can help you to ease that journey:

  • You can place your own static resources (like images) in src/main/resources/static folder. Then you can refer to them from the widget with this code (note the reference to the plug-in id):
url_for_static(:plugin => 'idemetadata', :path => 'check-round-yes-small.png')
  • If you want to place an image in any place of the view, use the image_tag() function:
image_tag(url_for_static(:plugin => 'idemetadata', :path => 'check-round-yes-small.png'), :size => '16x16', :style => 'vertical-align:middle')
  • View consistency is very important. Don’t confuse your users and leverage the standard SonarQube styles. They are available to custom widgets as well and will help you to provide a consistent user interface.

Below you can see a short snippet of the view:

Project name (as configured in the IDE):

<div class="dashbox"> <table class="width100"> <tbody> <tr> <td> <h3>Project type and active frameworks:</h3> <table> <tbody> <tr> <td> <%= check_image('ide_is_java') -%> <span>Java VM</span> </td> </tr> ...

This image shows how the configuration view looks like when you are going to add a view into a dashboard:

sonar-plugin-1

And the images below are a couple of examples on how the view looks like once placed in a project’s dashboard, showing the results of the plugin IDE metadata files scan and analysis:

sonar-plugin-2

 sonar-plugin-3

What’s next

In the next and final post of this series, the part 4, I will explain how to execute the plug-in in development mode and how to install it in your production SonarQube instance, with the help of JRebel to speed up development.

Author: deors

senior technology architect in accenture, with a passion for technology related stuff, celtic music and the best sci-fi, among other thousand things!

5 thoughts on “Writing Your Own SonarQube Plug-ins – Part 3: Creating Widgets”

  1. I created a custom widget in Sonar to show some data for a particular project. There are 3 projects in the list and only one of them should display this widget. I tried setting the Widget Scope “@WidgetScope(value = PROJECT)”. Also tried not setting anything as default scope is supposed to be “Project”. I’m using v5.1.2 SonarQube. But it still shows up on all the projects with the same data.
    Is there any way I can get the “project name” from the Sonar Dashboard so that I can return different values in the widget for different project?

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s