IBM
Skip to main content
    Country/region [select]      Terms of use
 
 
    
     Home      Products      Services & solutions      Support & downloads      My account     
skip to main content

developerWorks  >  WebSphere  >

Writing Java tests for your WebSphere MQ environment to use in MQ Explorer

developerWorks
Document options
Set printer orientation to landscape mode

Print this page

Email this page

E-mail this page

Document options requiring JavaScript are not displayed

Sample code


New site feature

Plan and design IT solutions with our new Architecture area


Rate this page

Help us improve this content


Level: Intermediate

Dale Lane (dale.lane@uk.ibm.com), Software Tester, WebSphere MQ, IBM

14 Dec 2005

One of the innovations in WebSphere MQ V6 is Eclipse-based administration tools, which lets you extend the WebSphere MQ Explorer toolset by using Eclipse plug-ins. This article shows you how to use simple Java and XML to write a plug-in that performs a custom validation on your WebSphere MQ environment.

Introduction

IBM® WebSphere® MQ environments can get very large and involve a great many object definitions. A system that lets you automate the examination of these object definitions can help to speed the development and debugging of a WebSphere MQ network.

WebSphere MQ Explorer is the name of the WebSphere MQ administration toolset for, and it enables you to to create, alter, and delete objects. Built on Eclipse, MQ Explorer can be extended using Eclipse plug-ins. This article shows you how to write a plug-in to perform checks on a WebSphere MQ environment, using as an example a plug-in that verifies that all objects conform to a corporate naming standard.

The plug-in will be written using a combination of Java™ and XML, and will implement checks that can be launched from the WebSphere MQ Explorer GUI. Results will be displayed in the Eclipse Problems View, from where they can categorised as Errors, Warnings, or Information.


Figure 1. WebSphere MQ Explorer GUI, showing the usage of the Problems View to display results of tests and checks
Figure 1

Prerequisites

This article assumes that you have WebSphere MQ Explorer installed on either Linux® or Microsoft® Windows®. It also assumes that you want to use the Eclipse workbench provided with WebSphere MQ Explorer. By default, the full workbench functionality of the Eclipse platform is disabled by WebSphere MQ Explorer. To enable the workbench, select Windows => Preferences => WebSphere MQ Explorer, select Startup in an Eclipse workbench, and then restart WebSphere MQ Explorer.


Figure 2. WebSphere MQ Explorer Preferences dialog, showing the setting to run the full Eclipse workbench
Figure 2

This article also uses the WebSphere MQ Explorer Healthcheck SupportPac (MH01) to reduce the Java development required for custom checks. You can download the MH01 SupportPac, which includes installation instructions, at the bottom of this article. It provides the following benefits:

  • Integration with the WebSphere MQ Explorer and Eclipse GUI -- GUI controls to run your new check are automatically included within the GUI; results found by your check are displayed in the Problems View and managed for you; any documentation you provide is displayed and launched as appropriate; and so on.
  • Basic threading model -- You can run your new check in the background while using the WebSphere MQ Explorer GUI, and in parallel with other tests, without considering threading implications in your code,

All that you need to do yourself is code the logic to check for problems, and describe how any potential issues that you find should be phrased.

Preparing the plug-in development environment

Eclipse Plug-in Development perspective

WebSphere MQ Explorer comes with the Eclipse Java IDE, which can be used to develop plug-ins. To switch to the Eclipse Plug-in Development Environment (PDE), select Window => Open Perspective => Other. The PDE gives you an overview of your development environment, an editor in which to edit Java and XML files, and a number of other useful views. For more information about the PDE, see Resources below.

Creating a new project

Create a new Plug-in Project for your code. Right-click in the Package Explorer by the newly added projects, and select New => Plug-in Project. For the purposes of this example, name the new project com.ibm.mq.explorer.healthcheck.samples.

Once created, open the automatically-generated plugin.xml for your new plug-in. Use the Dependencies tab to add the following plug-ins as dependencies for the new plug-in. These are a combination of some of the core Eclipse GUI plug-ins, and some of the projects used by WebSphere MQ:

  • com.ibm.mq.commonservices
  • com.ibm.mq.explorer.core
  • com.ibm.mq.explorer.healthcheck
  • com.ibm.mq.explorer.plugins
  • com.ibm.mq.explorer.ui
  • com.ibm.mq.internal.pcf
  • com.ibm.mq.internal.pcf.event
  • com.ibm.mq.runtime
  • org.eclipse.core.resources

Figure 3. Dependencies in the plugin.xml
Figure 3

Creating a new test

Each test needs:

  1. An entry in the plug-in's XML to provide the WebSphere MQ Explorer GUI with information to display for the test
  2. A Java class that carries out the test

Define a new test in XML

Open the plugin.xml for your plug-in. Use the Extensions tab to add the com.ibm.mq.explorer.healthcheck.MQtests to your project.

Right-click on the MQtests extension, and add a new test entry that will define your test:


Figure 4. New extension in plugin.xml
Figure 4

With the test item selected, enter the following information:

  • name -- a user-friendly name to display in the GUI when representing this check
  • class -- the fully-qualified name of the Java class you will write in the next step
  • id -- a unique identifier for this test (for example, the fully-qualified name of the Java class entered above)
  • description -- a short description of the test to display in the GUI
  • testset -- the name of a test set. The GUI lets you group tests into sets, which is useful when you have large numbers of tests, and lets you easily run a group of checks. If you enter the name of a set that does not exist, it will be created for you. This is optional, although recommended.
  • furtherinfo -- the location of an HTML page with more detailed information about this test and the results that it created. The GUI can display additional documentation to explain the results that they return, and provide guidance on what should be done to resolve the problem. Documentation should be provided in HTML, and can be identified as either:
    • internal to the plug-in -- Stored in the plug-in project providing the test itself. The location should be defined in the XML relative to the plugin.xml file itself; for example, doc/TestDoc.html.
    • External to the plug-in -- Stored on a Web server, allowing maintenance of the documentation separately from the test itself. Specify the location using a complete URL beginning with http://.

For example, enter the following to define a test that will verify naming conventions for your MQ environment:


Figure 5. plugin.xml extension
Figure 5

Clicking on the plugin.xml tab and look at the XML source. Your XML should look something like this:

<?xml version="1.0" encoding="UTF-8"?>
<?eclipse version="3.0"?>
<plugin
   id="com.ibm.mq.explorer.healthcheck.samples"
   name="Custom WebSphere MQ Tests"
   version="1.0.0"
   provider-name="IBM developerWorks"
   class="com.ibm.mq.explorer.healthcheck.samples.SamplesPlugin">

   <runtime>
      <library name="samples.jar">
         <export name="*"/>
      </library>
   </runtime>

   <requires>
      <import plugin="org.eclipse.ui"/>
      <import plugin="org.eclipse.core.runtime"/>
      <import plugin="com.ibm.mq.commonservices"/>
      <import plugin="com.ibm.mq.explorer.core"/>
      <import plugin="com.ibm.mq.explorer.healthcheck"/>
      <import plugin="com.ibm.mq.explorer.plugins"/>
      <import plugin="com.ibm.mq.explorer.ui"/>
      <import plugin="com.ibm.mq.internal.pcf"/>
      <import plugin="com.ibm.mq.internal.pcf.event"/>
      <import plugin="com.ibm.mq.runtime"/>
      <import plugin="org.eclipse.core.resources"/>
   </requires>
   <extension point="com.ibm.mq.explorer.healthcheck.MQtests">
      <test
         furtherinfo="doc/QueueNamesInfo.html"
         class="com.ibm.mq.explorer.healthcheck.samples.QueueNames"
         description="A sample test to check queue names against simple naming conventions."
         testset="Queues"
         name="Naming Conventions"
         id="com.ibm.mq.explorer.healthcheck.samples.QueueNames"/>
   </extension>
</plugin>

The MQtests XML is an interface defined in the Healthcheck plug-in, which enables Healthcheck to correctly find and load tests from multiple plug-ins. For more information about plug-in architecture, see the Eclipse article under Resources below.

Prepare the new test in Java

Create a new Java class from the Package Explorer, being sure to give it a name and package that is consistent with the location identified in the class attribute of the XML defined previously. The class should extend com.ibm.mq.explorer.healthcheck.objects.WMQTest.

The Problems View will continue to display any existing WebSphere MQ Explorer Healthcheck problems, alongside problems with your Java source. You can filter these out using the Problems View filter.

For the moment, do the minimum to get your Java class to compile, which is to create an empty class. We will return to the detailed implementation later.

package com.ibm.mq.explorer.healthcheck.samples;

import com.ibm.mq.explorer.healthcheck.objects.WMQTest;

/**
 * Empty test class - enough to compile.
 *
 * @author Dale Lane
 */
public class QueueNames extends WMQTest {

}

Prepare the documentation for the new test

Write the documentation that you want displayed in the GUI with the test. The documentation should be written in HTML and saved at the location specified in the plugin.xml file. As described previously, this could be local (inside this plugin, such as in a doc folder) or remote (on a Web server).


Figure 6. Project structure showing a location of the documentation HTML consistent with XML shown above
Figure 6

Deploy the test

From the Package Explorer, right-click on your project and select Export. Click Deployable plug-ins and fragments. In the Export dialog that opens, click Deploy as a directory structure and set the destination directory to the location of the Healthcheck plug-in installation. The default installation locations are C:\Program Files\IBM\WebSphere MQ\eclipse on Windows and /opt/mqm/eclipse/plugins/ on Linux.

Restart Eclipse. After reopening, return to the WebSphere MQ Explorer perspective using the Windows menu. Your new test should appear in the Navigator View tree, under the WebSphere MQ Healthcheck node in the Queues folder, as specified in plugin.xml. If you click on your new test in the tree, your HTML documentation should be displayed in the Content View page.

If your HTML documentation is not visible in the WebSphere MQ Explorer GUI, your HTML files were probably not included in the build of your plug-in. Add your HTML files to the build list by opening the build.properties file and selecting your documentation in the Binary Build list:


Figure 7. Build configuration
Figure 7

Once you have confirmed that the structure of your plug-in is working correctly, return to the PDE to provide the implementation for your test.

After any change to the Java code, you must repeat the previous deploy step to retest. Alternatively, during development, you can launch a test instance of Eclipse using Run As => Run-time Workbench, which lets you make and test changes without closing your development environment. You can then carry out the deploy step outlined above after your changes are complete.

Implement the new test in Java

Initial attempt

We will build up our test gradually, annotating the example source code with more detailed explanatory notes below. Our first attempt returns static data, and demonstrates the basic elements of the WMQTest interface:

package com.ibm.mq.explorer.healthcheck.samples;

import java.util.ArrayList;

import org.eclipse.core.resources.IMarker;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;

import com.ibm.mq.explorer.healthcheck.HealthcheckPlugin;
import com.ibm.mq.explorer.healthcheck.actions.WMQTestEngine;
import com.ibm.mq.explorer.healthcheck.objects.WMQTest;
import com.ibm.mq.explorer.healthcheck.objects.WMQTestResult;

/**
 * A sample skeleton implementation of a Healthcheck test.
 *
 * Download the source from Resources below.
 *
 * @author Dale Lane
 */
public class QueueNames extends WMQTest {

    // notice that no constructor is required

    /**
     * Starts the test.
     *
     * @param callback     handle to the test engine running the test
     * @param guimonitor  handle to the object monitoring the test,
     *                      provided to allow the test to periodically check
     *                      if the user has tried to cancel the test running
     *                      and provide additional user feedback
     */
    public void runTest(WMQTestEngine callback, IProgressMonitor guimonitor) {

        // start with the default implementation. this will store a handle
        // to the test engine that will be needed when we want to submit
        // any results at the end of the test
        super.runTest(callback, guimonitor);

        // start the progress monitor for this test
        String myName = getTestName();
        guimonitor.beginTask(myName, 10);
        guimonitor.subTask("Getting preferences for test");

        // prepare space to store any results we might want to return
        ArrayList testResults = new ArrayList();

        // generate nine meaningless test results
        for ( int i=0; i < 9; i++ ) {

            // update progress monitor
            guimonitor.subTask("Generating test result " + i + " of 9");

            // if the test has been cancelled, we break out of the
            //      for loop to return asap
            if ( isCancelled() )
                break;

            try {
                // wait here for two seconds to simulate lengthy test processing
                Thread.sleep(2000);
            } catch ( InterruptedException e ) {
                // unexpected exception
                Status internal_error = new Status(IStatus.ERROR,
                                        "com.ibm.mq.explorer.healthcheck.coretests",
                                        0,
                                        "Unexpected exception encountered while "
                                        + "waiting for test to return",
                                        e);
                HealthcheckPlugin.getPlugin().getLog().log(internal_error);
            }

            // create a fake result and add it to the list
            WMQTestResult nxtResult = new WMQTestResult(IMarker.SEVERITY_INFO, 
                                         "Blah blah blah test result number "
                                         + i + " here",
                                         "QMGR_1",
                                         "Queues");
            testResults.add(nxtResult);

            // increment progress monitor
            guimonitor.worked(1);
        }

        // update progress monitor
        guimonitor.subTask("Returning results to test engine");

        // return any results that this test has generated
        WMQTestResult[] finalresults = 
            (WMQTestResult[]) testResults.toArray(new WMQTestResult[testResults.size()]);
        testComplete(finalresults);

        // complete progress monitor
        guimonitor.done();
    }
}

Try using this example code to modify your own test object, and redeploy it to test. You should be able to run your test, and see the fake results it generates displayed in the Eclipse Problems View.

MQ-aware attempt

We will now add WebSphere MQ-specific code to the test object, allowing it to verify the names of queue objects.

This article is not intended as a tutorial for writing WebSphere MQ applications in Java. For more information about the Java API, see the manual Using Java. It can show you how to modify this example to access objects other than queues, and attributes other than the object names. However, the basic approach to writing code that integrates with the Explorer GUI remains the same:

package com.ibm.mq.explorer.healthcheck.samples;

import java.io.IOException;
import java.util.ArrayList;

import org.eclipse.core.resources.IMarker;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;

import com.ibm.mq.MQException;
import com.ibm.mq.MQQueueManager;
import com.ibm.mq.explorer.healthcheck.HealthcheckPlugin;
import com.ibm.mq.explorer.healthcheck.PreferenceStoreManager;
import com.ibm.mq.explorer.healthcheck.actions.WMQTestEngine;
import com.ibm.mq.explorer.healthcheck.objects.WMQTest;
import com.ibm.mq.explorer.healthcheck.objects.WMQTestResult;
import com.ibm.mq.explorer.ui.extensions.MQQmgrExtObject;
import com.ibm.mq.explorer.ui.internal.objects.ExplorerExtensionBase;
import com.ibm.mq.pcf.CMQC;
import com.ibm.mq.pcf.CMQCFC;
import com.ibm.mq.pcf.PCFMessage;
import com.ibm.mq.pcf.PCFMessageAgent;

/**
 * A sample test used to check Queue Names against naming conventions.
 * Queue names are checked if they begin with any of a set range of
 * prefixes, defined in this class. Any names which do not start with
 * one of the prefixes are output in an error.
 *
 * Download the source from Resources below.
 *
 * @author Dale Lane
 */
public class QueueNames extends WMQTest {

    /** Maintain a count of how many queue managers we are waiting for replies from. */
    private static int numberOfQmgrs = 0;

    /** Stores the accepted queue name prefixes. */
    private static final String[] ACCEPTED_Q_PREFIXES = { "SALES_",
                                                          "MARKETING_",
                                                          "SHIPPING_",
                                                          "INCOMING_",
                                                          "OUTGOING_" };

    /** Stores the user preference for whether hidden queue managers should be included. */
    boolean includeHiddenQmgrs = false;

    /** Stores the user preference for whether system queues should be included. */
    boolean includeSystemObjs  = false;

    /**
     * Starts the test.
     *
     * @param callback    handle to the test engine running the test
     * @param guimonitor  a handle to the object monitoring the test,
     *                    provided to allow the test to periodically check
     *                    if the user has tried to cancel the test running
     *                    and provide additional user feedback
     */
    public void runTest(WMQTestEngine callback, IProgressMonitor guimonitor) {

        // start with the default implementation. this will store a handle
        //  to the test engine that will be needed when we want to submit
        //  any results at the end of the test
        super.runTest(callback, guimonitor);

        // prepare space to store any results we might want to return
        ArrayList testResults = new ArrayList();

        // get from Preferences whether we should include hidden queue managers
        includeHiddenQmgrs = PreferenceStoreManager.getIncludeHiddenQmgrsPreference();
        // get from Preferences whether we should include system queues
        includeSystemObjs  = PreferenceStoreManager.getIncludeSysObjsPreference();

        // get a list of queue managers from the Explorer
        ArrayList allQmgrs;

        if (includeHiddenQmgrs){
            allQmgrs = ExplorerExtensionBase.getAllQueueManagers();
        }
        else {
            allQmgrs = ExplorerExtensionBase.getShownQueueManagers();
        }

        // how many queue managers are there?
        numberOfQmgrs = allQmgrs.size();

        // use the number of queue managers as a guide to track progress
        guimonitor.beginTask(getTestName(), numberOfQmgrs);

        // for each queue manager, submit a query
        for (int i=0; i < numberOfQmgrs; i++){

            // get next queue manager
            MQQmgrExtObject nextQueueManager = (MQQmgrExtObject) allQmgrs.get(i);

            // only submit queries to connected queue managers
            if (nextQueueManager.isConnected()){

                // get the name of the queue manager, for use in GUI
                String qmgrName = nextQueueManager.getName();

                // get a handle to a Java object representing the queue manager
                MQQueueManager qmgr = nextQueueManager.getMQQueueManager();

                try {
                    // get a PCF message agent to handle sending PCF inquiry to
                    PCFMessageAgent agent = new PCFMessageAgent(qmgr);

                    // use PCF to submit an inquire queue names query
                    PCFMessage response = submitQueueNamesQuery(qmgrName, agent);

                    // did we get a response to the query?
                    if (response != null){
                        // get the queue names out of the reply
                        String[] qnames = (String[]) response.getParameterValue(CMQCFC.MQCACF_Q_NAMES);

                        // check each name
                        for (int j=0; j < qnames.length; j++){
                            boolean qnameOkay = checkQueueName(qnames[j]);

                            if (!qnameOkay){
                                // if a problem was found with the name, we generate an
                                //  error message, and add it to the collection to be
                                //  returned
                                testResults.add(generateTestResult(qnames[j], qmgrName));
                            }
                        }
                    }
                } catch (MQException e) {
                    // record error details
                    Status internal_error = new Status(
                            IStatus.ERROR,
                            "com.ibm.mq.explorer.healthcheck.coretests",
                            0,
                            "Error encountered while getting PCFMessageAgent to "
                                + qmgrName,
                            e);
                    HealthcheckPlugin.getPlugin().getLog().log(internal_error);
                }
            }

            // finished examining a queue manager
            guimonitor.worked(1);
        }

        // return any results that this test has generated
        WMQTestResult[] finalresults = 
            (WMQTestResult[]) testResults.toArray(new WMQTestResult[testResults.size()]);
        testComplete(finalresults);
    }

     
    /**
     * Used internally to submit INQUIRE_Q_NAMES query using PCF to given queue manager
     *
     * @param qmgrName   name of queue manager to submit query to
     * @param agent
     * @return          PCF response from queue manger
     */
    private PCFMessage submitQueueNamesQuery(String qmgrName, PCFMessageAgent agent){

        // build the pcf message
        PCFMessage inquireQNames = new PCFMessage(CMQCFC.MQCMD_INQUIRE_Q_NAMES);
        inquireQNames.addParameter(CMQC.MQCA_Q_NAME, "*");

        try {
            // send the message
            PCFMessage[] responseMsgs = agent.send(inquireQNames);

            // check if results received successfully
            if ( responseMsgs[0].getCompCode() == 0 ) {
                return responseMsgs[0];
            }
        } catch (IOException e) {
            // record error details
            Status internal_error = new Status(
                    IStatus.ERROR,
                    "com.ibm.mq.explorer.healthcheck.coretests",
                    0,
                    "Error encountered while sending INQUIRE_Q_NAMES PCF to "
                        + qmgrName,
                    e);
            HealthcheckPlugin.getPlugin().getLog().log(internal_error);

        } catch (MQException e) {
            // record error details
            Status internal_error = new Status(
                    IStatus.ERROR,
                    "com.ibm.mq.explorer.healthcheck.coretests",
                    0,
                    "Error encountered while sending INQUIRE_Q_NAMES PCF to "
                        + qmgrName,
                    e);
            HealthcheckPlugin.getPlugin().getLog().log(internal_error);
        }

        // for some reason, we don't have a response, so return null
        return null;
    }

     
    /**
     * Used internally to check the given queue name against the collection
     * of acceptable prefixes.
     *
     * @param queueName    queue name to check
     * @return          true if queue name is okay,
     *                    false otherwise
     */
    private boolean checkQueueName(String queueName){

        // if this is a system object (i.e. it has a name which begins with
        //   "SYSTEM.") we check the
        if ((queueName.startsWith("SYSTEM.")) || (queueName.startsWith("AMQ."))){
            if (!includeSystemObjs){
                // user has requested that we do not include system
                // objects in the test, so we return true to
                // avoid any problems being reported for this queue
                return true;
            }
        }

        // PCF response will white-pad the queue name, so we trim it now
        queueName = queueName.trim();

        // check the queue name against each of the acceptable prefixes
        //  in turn, returning true immediately if it is
        for (int i=0; i < ACCEPTED_Q_PREFIXES.length; i++){
            if (queueName.startsWith(ACCEPTED_Q_PREFIXES[i]))
                return true;
        }

        // we have checked against all accepted prefixes, without
        //  finding a match
        return false;
    }

    
    /**
     * Used internally to generate a test result for the given queue name.
     *
     * @param queueName    queue name that doesn't meet requirements
     * @param qmgrName     name of queue manager that hosts the queue
     * @return         generated test result
     */
    private WMQTestResult generateTestResult(String queueName, String qmgrName){
        return new WMQTestResult(IMarker.SEVERITY_ERROR,
                                 "Queue (" + queueName.trim() + ") "
                                    + "does not begin with "
                                    + "a known prefix",
                                 qmgrName,
                                 "Queues");
    }
}

Notes on above source code

Skip to next section.

Creating your test object

As specified previously, your test should extend WMQTest. WebSphere MQ Explorer will instantiate the test object using the provided constructor WMQTest(). There is no need to subclass this constructor.

Test Attributes

The table below specifies some of the attributes of the WMQTest superclass, together with their accessor methods. These attributes are not intended to be changed by subclass implementations, but may be useful for output.

ATTRIBUTE NAMEATTRIBUTE ACCESSORATTRIBUTE DESCRIPTION
test idgetTestId()String containing the unique identifier for your test, as specified in your plugin.xml
namegetTestName()String containing the user-friendly name of the test, as specified in your plugin.xml
descriptiongetDescription()String containing the description of your test, as specified in your plugin.xml
documentation pathgetFurtherInfoPath()String containing the location of the HTML documentation for your test, as specified in your plugin.xml

Creating a test result

When your test finds something that it wants to be returned to the user, it should create a test result object to describe the problem. Test results are implemented as WMQTestResult objects and should be created using new WMQTestResult(int severity, String description, String qmgrname, String objectType)

severityan integer identifying the severity of the problem. should be one of the following: IMarker.SEVERITY_ERROR, IMarker.SEVERITY_WARNING or IMarker.SEVERITY_INFO
descriptionthe string explaining the problem found by the test, to be displayed in the Problems View
qmgrnamethe name of the queue manager where the problem was found
objectTypestring giving the class of object where the problem can be found (e.g. "Queues", "Channels" etc.)

Launching the test

WebSphere MQ Explorer calls runTest(WMQTestEngine, IProgressMonitor) to start running your test. The main body of your test should be here.

The start of the runTest method should be a call to the default implementation of runTest with super.runTest(callback, guimonitor). This caches handles to the provided parameters, which are required for various background tasks.

The WMQTestEngine parameter provides a handle to the test engine running the test. The handle lets tests return results while a test is in progress, using the test engine's returnResult(WMQTestResult[], WMQTest) method:

Using the WMQTestEngine parameter to return interim results is optional, but may be useful for long-running tests. Alternatively, test results can be returned on test completion as outlined below.

The IProgressMonitor parameter provides a handle to the GUI feedback monitor being used for the current test run. It lets your test provide both textual feedback on the task and/or subtasks currently running, and a progress bar for completion.

The handle to the Progress Monitor is cached by the default implementation of runTest as mentioned above, so a handle to the Progress Monitor can also be accessed using the WMQTest method getGUIMonitor().

The Progress Monitor is a core Eclipse resource. For details on how to use it, see the Eclipse API documentation. Some useful methods are shown in the table below:

beginTask(String taskName, int numberOfStepsInTask)indicates that a task is starting, providing the name to display and the expected number of steps for use in progress bar
worked(int numberOfStepsCompleted)increments the progress bar by the provided number of steps
done()indicates that the task has been completed

Completing a test

A test is completed by calling testComplete(WMQTestResult[]) and passing it an array of test result objects. The testComplete method requires a handle to the test engine that started the test running, and will not work if the default implementation of runTest has not been called prior to the testComplete call, as described above.

You can return results at completion using this method in addition to, or as an alternative to, returning test results during a test run using returnResult, as explained above. However, any results that are returned twice will be displayed twice.

Even if your test uses the WMQTestEngine method returnResult to return all of its results, it must still call testComplete on completion in order to complete the test processing. An empty array of WMQTestResult objects can be provided in the testComplete method if there are no additional results to be returned.

Dealing with cancelling

The user is able to cancel individual tests while running, or the whole test run. The method isCancelled() can be used to check if a test should stop. A good test should regularly check to see whether it has been cancelled to avoid delaying the user unnecessarily.

If you try to cancel a test, but the test fails to return for an extended period of time, the test engine will force the test to stop by killing the thread that is running it. But do not rely on this method -- it is preferable that a test returns in time, enabling it to clean up any resources and return any test results generated.

Reporting errors

Errors encountered during a test run can be reported like this:

    Status internal_error = new Status(IStatus.ERROR,
                                       "com.ibm.mq.explorer.healthcheck.coretests",
                                       0,
                                       "Error encountered while doing something",
                                       event.getException());
    HealthcheckPlugin.getPlugin().getLog().log(internal_error);

The error will be written to the Eclipse Errors View, including the stack trace contained in a Java exception if provided. Uncaught exceptions and errors thrown as a result of running your test will be caught by the Healthcheck test engine and written to the Errors View in this way. Therefore it is a good idea to check the Errors View regularly when developing a new test.

User preferences

Tests should conform to the user preferences provided using the Eclipse Preferences dialog. Access the preferences using:

PREFERENCERETURNS TRUE IF...RETURNS FALSE IF...
PreferenceStoreManager.getIncludeHiddenQmgrsPreference()you should include queue managers that have been hidden from the WebSphere MQ Explorer in the testyou should exclude queue managers that have been hidden from the WebSphere MQ Explorer in the test
PreferenceStoreManager.getIncludeSysObjsPreference()system objects (objects which have names beginning with SYSTEM.) should be included in the testsystem objects (objects which have names beginning with SYSTEM.) should be excluded from the test

Complex tests

Test structure

As previously explained, the WMQTest method runTest defines the body of the test, and is called to start a test running.

The end of the runTest method does not imply the end of the test (which needs to be specified explicitly using testComplete), leaving test developers free to implement tests using asynchronous approaches to getting data to analyse.

For example, runTest can submit a request to get data about WebSphere MQ objects. The test execution can continue from the listener method that receives the reply. This essentially lets the test wait for data without test developers needing to implement thread waiting. The following pseudocode example demonstrates how you might approach this:

package com.ibm.mq.explorer.healthcheck.samples;

import java.util.ArrayList;

import org.eclipse.core.resources.IMarker;
import org.eclipse.core.runtime.IProgressMonitor;

import com.ibm.mq.explorer.healthcheck.HealthcheckPlugin;
import com.ibm.mq.explorer.healthcheck.PreferenceStoreManager;
import com.ibm.mq.explorer.healthcheck.actions.WMQTestEngine;
import com.ibm.mq.explorer.healthcheck.objects.WMQTestResult;
import com.ibm.mq.pcf.CMQC;

/**
 * Pseudo-code sample demonstrating an asynchronous approach to implementing a
 * Healthcheck test.
 *
 * @author Dale Lane
 */
public class QueuesTest extends WMQTest implements SomeListener {

    /** Used to store test results. */
    private ArrayList testresults = new ArrayList();

    /**
     * Used to start the test.
     *
     * @param callback     handle to the test engine running the test
     * @param guimonitor    handle to the object monitoring the test,
     *                     provided to allow the test to periodically check
     *                     if the user has tried to cancel the test running
     */
    public void runTest(WMQTestEngine callback, IProgressMonitor guimonitor) {

        super.runTest(callback, guimonitor);

        // reset all test stores
        testresults = new ArrayList();

        // initialise the progress bar part of the GUI used to show progress of
        //  this test
        guimonitor.beginTask(getTestName(), numqmgrs);

        // start the test!

        // send query
        PseudoQueueManager qmgrHandle = pseudoGetQueueManager();
        submitQmgrQuery(qmgrHandle, this, query);

        // note that the runTest method is now finished, but the test is not over!
    }


    /**
     * Used to process results received in response to query submitted by runTest.
     *
     * @param objects          data received
     */
    public void dataReponseReceived(ArrayList objects) {

        // analyse each of the replies in the collection received in the reply
        for ( int i = 0; i < objects.size(); i++ ) {
            PseudoQueue nxtQueue = (PseudoQueue) objects.get(i);
            analyseQueue(nxtQueue);

            // increment GUI progress bar used to show progress of this test
            getGUIMonitor().worked(1);
        }

        // now that we have got the data that we were waiting for, and have
        //  finished processing it, the test has really finished - we are
        //  nearly ready to call testComplete to mark the test finished

        // return the completed results
        WMQTestResult[] finalresults = 
            (WMQTestResult[]) testresults.toArray(new WMQTestResult[0]);
        testComplete(finalresults);
    }

    /**
     * Analyse the given queue. If any potential problems are found, a problem
     * marker is added to the testresults collection.
     *
     * @param queue       queue to analyse
     */
    private void analyseQueue(PseudoQueue queue) {

        // do something

        // add a problem marker to the collection
        if (problemFound) {
            testresults.add(new WMQTestResult(IMarker.SEVERITY_WARNING,
                                              "A problem was found with "
                                                + queueName,
                                              getQueueManagerName(queue),
                                              "Queues"));
        }
    }
}

If a manual wait/sleep is needed as a part of a test, you can use the object monitor for your test object when wanting to use the Java wait/notify methods. The threading of the Healthcheck test engine is implemented without using the object monitors of individual test objects.

Conclusion

This article showed you how to extend WebSphere MQ Explorer functionality by writing an Eclipse plug-in using Java. The article outlined the steps to write an extension that enables WebSphere MQ Explorer to verify that MQ object names use a predefined set of prefixes.

The complete Eclipse projects described in the article can be downloaded below and used as the starting point for developing your own custom tests. Unzip the file and import its contents into the Package Explorer by selecting Import Existing Project into Workspace, in place of creating a new project as described in the article.




Back to top


Download

DescriptionNameSizeDownload method
Code samples in zip formatsampletests.zip11 KBFTP|HTTP
Information about download methodsGet Adobe® Reader®


Back to top


Resources



Back to top


About the author

Dale Lane is a software engineer on the WebSphere MQ System Test team at the IBM Hursley Software Lab in the UK. Dale earned a Bachelor of Science degree in Computer Science at the University of Bath, UK, and is a Sun Java 2 Certified Programmer and IBM Certified WebSphere MQ System Administrator. You can contact Dale at dale.lane@uk.ibm.com.




Back to top


Rate this page


Please take a moment to complete this form to help us better serve you.



YesNoDon't know
 


 


12345
 


Back to top



    About IBMPrivacyContact