X

Geertjan's Blog

  • February 27, 2008

Getting Started Extending VisualVM (Part 2)

Geertjan Wielenga
Product Manager
Update on 30 May 2008: The code and steps in this blog entry have been updated to reflect the VisualVM 1.0 APIs. If you want to download the complete sources of the sample discussed here, get the VisualVM Sample Collection from the Plugin Portal.

In Getting Started Extending VisualVM (Part 1), yesterday, we used a DataSourceViewProvider to create a new DataSourceView. The latter was available to all types of applications shown in VisualVM. Today we'll create a new application type and... provide some functionality specifically for that type. First, we'll provide a new tab in the Overview section and we'll also provide a menu item, specifically for our application type.

Only those applications are recognized for which specific support has been provided. Otherwise, a default icon is shown and the default tabs are available. Let me stress at this point that for most applications, the default tabs are enough. See VisualVM: Free and Open Source Java Troubleshooter, to see what the default VisualVM provides. However, for GlassFish, or any other server, you probably want some subnodes for deployed applications. So, in scenarios where you have an application that has special needs, or for which you want to display specific information, you can (if you want to) create a new VisualVM "application type".

For this example, we will create a new application type for the Anagram Game that is bundled with the IDE. Typically, an application type is identified by its main class, which in the case of the Anagram Game is "com.toy.anagrams.ui.Anagrams". At the end, you'll have a new icon for the Anagram Game, with a new Overview tab (showing, for the sake of this simple example, a screenshot of the application), and a new "Show Anagram PID" menu item on the Anagram Game application type node, as shown in the illustration below:

The steps to take for these three entry points (i.e., application type, overview tab, and menu item), are as follows:

  1. Initialize the Entrypoints. In the module install class, as shown yesterday, initialize the three entry point implementations that you are about to create:

    package org.visualvm.demoapplicationtype;
    import org.openide.modules.ModuleInstall;
    public class Installer extends ModuleInstall {
    private static AnagramApplicationTypeProvider INSTANCE = new AnagramApplicationTypeProvider();
    @Override
    public void restored() {
    ApplicationTypeFactory.getDefault().registerProvider(INSTANCE);
    }
    @Override
    public void uninstalled() {
    ApplicationTypeFactory.getDefault().unregisterProvider(INSTANCE);
    }
    }

  2. Define the application type. Use the VisualVM Application Type Template for this purpose. As stated, we use the Anagram Game main class to determine that we want an application type to be created:

    import com.sun.tools.visualvm.application.Application;
    import com.sun.tools.visualvm.application.jvm.Jvm;
    import com.sun.tools.visualvm.application.type.ApplicationType;
    import com.sun.tools.visualvm.application.type.MainClassApplicationTypeFactory;
    public class AnagramApplicationTypeProvider extends MainClassApplicationTypeFactory {
    @Override
    public ApplicationType createApplicationTypeFor(Application app, Jvm jvm, String mainClass) {
    //TODO: Specify the name of the application's main class here:
    if ("com.toy.anagrams.ui.Anagrams".equals(mainClass)) {
    return new AnagramApplicationType(app.getPid());
    }
    return null;
    }
    }

    And here is the definition of the application type itself:

    import com.sun.tools.visualvm.application.type.ApplicationType;
    import java.awt.Image;
    import org.openide.util.Utilities;
    public class AnagramApplicationType extends ApplicationType {
    protected final int appPID;
    public AnagramApplicationType(int pid) {
    appPID = pid;
    }
    @Override
    public String getName() {
    return "Anagram";
    }
    @Override
    public String getVersion() {
    return "1.0";
    }
    @Override
    public String getDescription() {
    return "Application type for Anagram";
    }
    @Override
    public Image getIcon() {
    return Utilities.loadImage("com/sun/tools/visualvm/core/ui/resources/snapshot.png", true);
    }
    }

  3. Define the Overview Window Extension. Here we check that we're dealing with our application type. If so, the Overview extension is created:

    import com.sun.tools.visualvm.application.Application;
    import com.sun.tools.visualvm.application.type.ApplicationTypeFactory;
    import com.sun.tools.visualvm.application.views.ApplicationViewsSupport;
    import com.sun.tools.visualvm.core.ui.DataSourceViewPlugin;
    import com.sun.tools.visualvm.core.ui.DataSourceViewPluginProvider;
    class AnagramViewPluginProvider extends DataSourceViewPluginProvider<Application> {
    protected DataSourceViewPlugin createPlugin(Application application) {
    return new AnagramOverview(application);
    }
    protected boolean supportsPluginFor(Application application) {
    if (ApplicationTypeFactory.getApplicationTypeFor(application) instanceof AnagramApplicationType) {
    return true;
    }
    return false;
    }
    static void initialize() {
    ApplicationViewsSupport.sharedInstance().getOverviewView().
    registerPluginProvider(new AnagramViewPluginProvider());
    }
    static void uninitialize() {
    ApplicationViewsSupport.sharedInstance().getMonitorView().
    unregisterPluginProvider(new AnagramViewPluginProvider());
    }
    }

    And here is our new tab in the Overview window:

    import com.sun.tools.visualvm.application.Application;
    import com.sun.tools.visualvm.core.ui.DataSourceViewPlugin;
    import com.sun.tools.visualvm.core.ui.components.DataViewComponent;
    import com.sun.tools.visualvm.core.ui.components.ScrollableContainer;
    import javax.swing.JPanel;
    public class AnagramOverview extends DataSourceViewPlugin {
    AnagramOverview(Application application) {
    super(application);
    }
    public DataViewComponent.DetailsView createView(int location) {
    switch (location) {
    case DataViewComponent.TOP_RIGHT:
    JPanel panel = new JPanel();
    return new DataViewComponent.DetailsView("User Interface", null, 30,
    new ScrollableContainer(panel), null);
    default:
    return null;
    }
    }
    }

    Now we need to initialize our new tab, using the lines in bold below:

    public class Installer extends ModuleInstall {
    private static AnagramApplicationTypeFactory INSTANCE = new AnagramApplicationTypeFactory();
    @Override
    public void restored() {
    ApplicationTypeFactory.getDefault().registerProvider(INSTANCE);AnagramViewPluginProvider.initialize();
    }
    @Override
    public void uninstalled() {
    ApplicationTypeFactory.getDefault().unregisterProvider(INSTANCE);AnagramViewPluginProvider.uninitialize();
    }
    }

  4. Define the Menu Item. Use the VisualVM Action Template for this purpose. Then tweak it, if necessary, as shown below. Here, again we check for our application type and then create the menu item:

    import com.sun.tools.visualvm.application.Application;
    import com.sun.tools.visualvm.application.type.ApplicationTypeFactory;
    import com.sun.tools.visualvm.core.ui.actions.SingleDataSourceAction;
    import java.awt.event.ActionEvent;
    import javax.swing.Action;
    import javax.swing.JOptionPane;
    public class AnagramAction extends SingleDataSourceAction<Application> {
    public AnagramAction() {
    super(Application.class);
    putValue(Action.NAME, "Show Anagram PID");
    putValue(Action.SHORT_DESCRIPTION, "Demoes a menu item");
    }
    @Override
    protected void actionPerformed(Application application, ActionEvent arg1) {
    JOptionPane.showMessageDialog(null, application.getPid());
    }
    //Here you can determine whether the menu item is enabled,
    //depending on the data source type that is selected. In this
    //example, the menu item is enabled for all types within
    //the current data source:
    @Override
    protected boolean isEnabled(Application application) {
    if (ApplicationTypeFactory.getApplicationTypeFor(application) instanceof AnagramApplicationType) {
    return true;
    }
    return false;
    }
    }

    And here is the registration in the layer.xml file, which initializes our action as a menu item:

        <folder name="VisualVM">
    <folder name="ExplorerPopupSelection">
    <file name="org-visualvm-demoapplicationtype-AnagramAction.instance">
    <attr name="SystemFileSystem.localizingBundle" stringvalue="org.visualvm.demoapplicationtype.Bundle"/>
    <attr name="position" intvalue="3000"/>
    </file>
    </folder>
    </folder>

This should give you enough of a start to create your own application types with some functionality specific to the type in question.

Update on 30 May 2008: The code and steps in this blog entry have been updated to reflect the VisualVM 1.0 APIs. If you want to download the complete sources of the sample discussed here, get the VisualVM Sample Collection from the Plugin Portal.

Join the discussion

Comments ( 10 )
  • KlausStake Wednesday, February 27, 2008

    Hi Geertjan,

    thanks a lot for this series. I appreciate very much.

    I have question about the nodes in the Applications View/Window. Do you think/know if it's possible to add additional subnodes under your application? Something like this:

    - Local

    -- Tomcat

    -- Glassfish

    -- Anagram Game

    --- Anagram's subnode1

    ---- Anagram's subsubnode1_1

    --- Anagram's subnode2

    Never mind if you don't know the answer.

    Thanks anyway,

    Klaus


  • Geertjan Wednesday, February 27, 2008

    Hi Klaus. The answer is "Yes". If you look at the GlassFish sources (in the 'plugins' topfolder on visualvm.dev.java.net), you will see that that's already available for GlassFish. I will blog about this soon.


  • Thorbj&oslash;rn Ravn Andersen Wednesday, August 26, 2009

    It would be very nice if jvisualvm could ask the application for an icon and a description (fine with the actual class in parenthesis after), since this will allow us to ask the users to use jvisualvm without any configuration and we would like to see some runtime information.


  • Winston Thursday, November 25, 2010

    Hi,

    Very new to VislualVM, so i got stuck on the layer.xml part. Where do i find that file or do i have to create it?

    Thank you

    Winston


  • Geertjan Wielenga Thursday, November 25, 2010

    When you create a new module, there's a checkbox for creating the layer.xml file.


  • guest Sunday, October 12, 2014

    hi Geertjan,

    Thank you for your post. Trying to follow instructions, but got stack on attempt to add dependency on "VisualVM-Application” and “VisualVM-Core". I can add them fine, but just after I press OK button on properties dialog, dependencies are renamed "com.sun.tools.visualvm.application" and "com.sun.tools.visualvm.core" and point to non-exiting jars in my home folder: "/home/user/com-sun-tools-visualvm-core.jar" & "/home/user/com-sun-tools-visualvm-application.jar". I have tried with different vernsion of IDE - 8.0 and 7.4 and have tried with a couple of versions of VisualVM platform - 1.3.8 and latest trunk - all the same.

    As that is my first attempt to use NetBeans, it feels to me like I'm missing something very obvious, but can't figure it out. Something with dependencies setup in IDE?


  • Geertjan Sunday, October 12, 2014

    You're referring to a blog entry from 2008..?


  • Stas Sunday, October 12, 2014

    hi Geertan, well, yes 2008, but it's looks all still valid and up-to-date :) Apparently found what was the problem. This was all because of FX Wrapper dependency in the platform:

    https://netbeans.org/bugzilla/show_bug.cgi?id=242564

    took me a while...


  • Geertjan Monday, October 13, 2014

    I would very highly recommend to not trust any code written in 2008 in a blog. If it works, then that's pure coincidence. But, seriously, not a good idea to use code written in a blog in 2008.


  • Stas Monday, October 13, 2014

    hi Geertjan, well, I would not trust to any code anywhere in internet, doesn't matter how old is that. Just saying that post still looks very useful. Thanks for all your efforts writing it!


Please enter your name.Please provide a valid email address.Please enter a comment.CAPTCHA challenge response provided was incorrect. Please try again.