| 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
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
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
Creating a new test
Each test needs:
- An entry in the plug-in's XML to provide the WebSphere MQ Explorer GUI with information to display for the test
- 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
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
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
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
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 NAME | ATTRIBUTE ACCESSOR | ATTRIBUTE DESCRIPTION |
---|
test id | getTestId() | String containing the unique identifier for your test, as specified in your plugin.xml | name | getTestName() | String containing the user-friendly name of the test, as specified in your plugin.xml | description | getDescription() | String containing the description of your test, as specified in your plugin.xml | documentation path | getFurtherInfoPath() | 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)
severity | an integer identifying the severity of the problem. should be one of the following: IMarker.SEVERITY_ERROR ,
IMarker.SEVERITY_WARNING or IMarker.SEVERITY_INFO | description | the string explaining the problem found by the test, to be displayed in the Problems View | qmgrname | the name of the queue manager where the problem was found | objectType | string 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:
PREFERENCE | RETURNS TRUE IF... | RETURNS FALSE IF... |
---|
PreferenceStoreManager.getIncludeHiddenQmgrsPreference() | you should include queue managers that have been hidden from the WebSphere MQ Explorer in the test | you 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 test | system 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.
Download Description | Name | Size | Download method |
---|
Code samples in zip format | sampletests.zip | 11 KB | FTP|HTTP |
Resources - Eclipse Plug-in Development Environment (PDE)
Overview of Eclipse PDE.
- Eclipse plug-in architecture
Explanation of how plug-ins extend the capabilities of Eclipse, and the use of XML in extension points.
- Using Java
A WebSphere MQ manual that outlines the MQ classes for Java.
- Download WebSphere MQ Explorer Healthcheck Plug-in (MH01)
A plug-in for WebSphere MQ Explorer that is a prerequisite for the steps in this article.
- WebSphere MQ product page
Product descriptions, product news, training information, support information, and more.
- WebSphere MQ documentation library
WebSphere MQ manuals in PDF format.
- WebSphere MQ V6 Information Center
A single Eclipse-based Web interface for all WebSphere MQ V6 documentation.
- developerWorks WebSphere Business Integration zone
For
developers, access to WebSphere Business Integration how-to articles,
downloads, tutorials, education, product info, and more.
- Trial downloads for IBM software products
No-charge trial downloads for selected IBM® DB2®, Lotus®, Rational®, Tivoli®, and WebSphere® products.
- Most popular WebSphere trial downloads
No-charge trial downloads for key WebSphere products.
- Safari Bookshelf: e-library designed
for developers
Complete
search and download access to thousands of technical books for a
one-time subscription fee. Free trial for new subscribers.
- WebSphere forums
Product-specific forums where you can ask questions and share your opinions with other WebSphere users.
- developerWorks blogs
Ongoing,
free-form columns by software experts, to which you can add your
comments. Check out Grady Booch's blog on software architecture.
|
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. |
Rate this page
| |