Skip to main content

Using Pluglets in IBM Rational Software Architect

Dave Kelsey (d_kelsey@uk.ibm.com), Software Engineer, IBM
Dave Kelsey is an Advisory Software Engineer for IBM UK. Dave was involved in the Modelware European Consortium Project, which integrated Rational Software Architect into the other modeling technologies used for the various experiments on Model Driven Development.

Summary:  This article introduces the pluglet facilities contained within IBM® Rational® Software Architect version 6.0. It shows you how to get started with pluglets, and suggests where pluglets may be useful. The article was written in conjunction with using Rational Software Architect 6.0.1. It is targeted at an audience with experience in using Rational Software Architect or Eclipse for Java™ development. Part of the article requires knowledge of writing plug-ins for Eclipse, however.

Date:  14 Nov 2006
Level:  Intermediate
Activity:  557 views

Introduction

Pluglets in IBM® Rational® Software Architect may be a feature you have overlooked. The concept in itself is simple, yet it is one of those ideas that provides many useful facilities for you when you're using Rational Software Architect. This article will describe pluglets, ideas for their use, and some hints and tips about using them. We hope that this will increase your awareness of, and help you to start using, this facility.

A pluglet is a Java™ class that has a main entry point. It can be executed like a normal Java class within Rational Software Architect, and can access all of the standard Java APIs. The clever bit is that a pluglet can access Eclipse Plug-in API's, and thus you can interact with resources within Rational Software Architect without having to write a plug-in and test it through a runtime workbench. This opens up all sorts of possibilities to make working with Rational Software Architect quicker. You can use pluglets to:

  • Test and understand an Rational Software Architect API without having to write a plug-in and launch a runtime workbench
  • Write simple macros or scripts in Java to extend the functionality of Rational Software Architect
  • Write macros or scripts that interact and control systems outside of Rational Software Architect (so long as you have plug-ins that provides a suitable API), or get these outside systems to interact seamlessly with Rational Software Architect and its facilities.
  • Test your plug-ins in a runtime workbench rather than write another unit test plug-in.

Information available on pluglets

Rational Software Architect has information on pluglets in various places. There is a tutorial in the Tutorials Gallery under the Do and Learn section, showing you how to create your first pluglet.

The Samples Gallery has a couple of pluglet examples. If you use the Pluglet wizard to create your new pluglet, you can select from samples within this wizard as well. These samples show you how to do things like:

  • Model Interrogation
  • Editor Extensions

It is worth installing these samples to get familiar with them. This article will not go into specifics of coding Rational Software Architect or Eclipse APIs (although examples may be shown using them), but rather focus on the ins and outs of writing pluglets in general. Further help and information can be found in the Help contents (select Help > Extending Rational Software Architect functionality > Extending your Java environment with pluglets).

To get to the JavaDoc that shows you which APIs you have available to you as a pluglet, follow these steps.

  1. Click Pluglets API.
  2. Scroll down to the Pluglets Packages and click com.ibm.xtools.pluglets.
  3. Click Pluglet in the class summary. This produces a list of methods that you can call from a pluglet.

The Pluglet project

I recommend using the wizard to create your pluglet projects and new pluglet classes. The wizard will create a pluglet.xml containing the basic import for you.

The important part is making sure that the pluglet.xml file in your project contains all of the plug-ins for the APIs that you are going to need when coding your pluglet. To get a list of the plug-in names that you can import, select Help > About IBM Rational Software Development Platform and click Plug-in Details. There is no code completion to help you here. Since it is an XML file, you do get help for creating elements and attribute tags, but not the content of the import attribute.

To ensure that you have typed the pluglet import correctly, and that the plug-in exists, you can expand the Pluglet Plug-in dependencies folder in your pluglet project and look for JARs relating to that plug-in. The order of these JARs appears to follow the order specified in plugin.xml, so if you added an import to the bottom, check at the end of the dependencies folder.


Writing a pluglet

Pluglets are very similar to normal Java programs: you have a main class that implements a main entry point. The following code is a hello world example of a pluglet demonstrating this.

import com.ibm.xtools.pluglets.Pluglet;
public class Simple extends Pluglet {
public void plugletmain(String[] args) {
out.println(
"Pluglet \"Simple\" is not yet implemented."); //$NON-NLS-1$
}
}

Here we see how to output to the Rational Software Architect Console, by using the out property of your class to write to the console.

Your class will have some other facilities available to you. These are documented under the pluglet API. Apart from out, which is identical to System.out, the other methods you are likely to use are the dialog methods of inform, prompt, question, confirm, error, and warning. These provide some standard dialogs and are easy to use. For example, to display the dialog shown in Figure 1, you would code the following:

Inform("press OK to continue");


Figure 1. The TestTasks dialog with an OK button
TestTasks dialog says "Press OK to continue"

In addition, to display the prompt shown in Figure 2, you would create this code:

String info = prompt("Enter some information");


Figure 2. Prompting for string information
Dialog prompts "Enter some information"

Handling exceptions

In the first release of Rational Software Architect 6.0, any runtime exception or error that was not caught would not be displayed, so you were not easily able to determine why your pluglet failed. Rational Software Architect 6.0.1 has fixed this. Any uncaught exception is displayed as a Popup to the user, and is also appended to the pluglet console.

It is still advisable that you catch all exceptions and handle them appropriately, as shown in the following code.

 
 try {
…
try {
…
}
catch(IOException ioe) {
// do something specific with an IOException
}
}
catch (Throwable e) {
// inform of the exception
inform("Exception occured: " + e.getMessage());
// output the stack trace for it, plus any nested exceptions
e.printStackTrace(out);
while (e.getCause() != null) {
out.println("\n caused by: ");
e = e.getCause();
e.printStackTrace(out);
}
}


Running and debugging a pluglet

Before you can execute a pluglet, it needs to be registered as part of the Internal Tools section within the Run menu. The pluglet environment provides a mechanism for registering a pluglet (if it is not already registered) and executing it in one go. To execute a pluglet in this manner, you right-click the pluglet to bring up the context menu, then select Run > Pluglet, as in Figure 3.


Figure 3. Registering and executing a pluglet
Executing the pluglet registers it automatically

This will register and execute the pluglet. Sometimes, however, this may not be the way you want to launch the pluglet. For example, a pluglet is capable of determining if an item or items are selected in a view, but if you have highlighted the pluglet you want to run you have lost what you have previously highlighted.

In order to be able to run a pluglet which can determine highlighted items in a view, you first need to register the pluglet, and then execute it using menu actions. This allows you to keep the view visible easily, and to ensure that whatever is selected in the view remains selected.

Registering a pluglet

To register a pluglet, follow these steps.

  1. Click Run > Internal Tools > Internal Tools to get the dialog shown in Figure 4.

Figure 4. Using the Internal Tools dialog to register and run a new pluglet
Provide a Name and Location for the pluglet
  1. Click New to define a new pluglet registration and give it a name.
  2. Next, click Browse Workspace, which will provide a list of pluglet projects and the pluglets that they contain, as shown in Figure 5.

Figure 5. Selecting a workplace pluglet
Select the pluglet project from the left pane, then a pluglet from the right
  1. Select your pluglet and click OK.
  2. Finally, click Apply and Close.

You have now registered the pluglet.

Pluglet execution via the menu

  1. Now select Run > Internal Tools and select the pluglet that you have just registered in order to run it.

Debugging

There is no debugger, so you should use the old debugging method of coding out.println. Note also that there is no equivalent err property.


Running pluglet code on a different thread

When a pluglet is executed, it runs on the Rational Software Architect (User Interface) UI thread. This is OK if your pluglet runs very quickly, but if it is a long running-process (or interacts with external resources, say on a network), then you don't want to execute on the UI thread.

Another potential problem, which may seem like an unlikely scenario but actually happened to me, was a deadlock that caused Rational Software Architect to hang. A pluglet running on the UI thread invoked an API that blocked waiting for a result. This API (invoking various other components) created a new thread, which in turn wanted to invoke a synchronous call on the UI thread. This resulted in the deadlock, because the UI thread was blocked waiting for the API to return. This is another good reason not to stay running on the UI thread.

You have a couple of choices in moving your pluglet code off the UI thread:

  • Create a new thread in your pluglet and execute the code there
  • Use facilities provided by Rational Software Architect to execute the code on a different thread

Using a thread is quick and easy. Also, if you want to invoke any of the dialogs provided by the pluglet class, you can do so, because these are actually executed on the UI thread.

 
import com.ibm.xtools.pluglets.Pluglet;
public class SimpleThread extends Pluglet implements Runnable {
public void plugletmain(String[] args) {
Thread t = new Thread(this);
t.run();
out.println("This may not appear until the other thread has
ended");
out.println("main thread ended");
out.flush();
}

/* (non-Javadoc) @see java.lang.Runnable#run() */
public void run() {
out.println("This could be be output first");
inform("press ok to continue");
out.println("Hi there from the other thread");
}
}

Note the output on the pluglet console :

This could be be output first (Ok on the prompt is now pressed)
Hi there from the other thread
This may not appear until the other thread has ended
main thread ended

This isn't what we expected. The output from the main thread is not seen until after the pluglet terminates, even though the main thread should have ended before you had a chance to click OK on the prompt. So let's try another program.

import com.ibm.xtools.pluglets.Pluglet;
public class Delay1 extends Pluglet {
public void plugletmain(String[] args) {
out.println(
"Pluglet \"Delay1\" issuing a message."); //$NON-NLS-1$
out.flush();
try {
synchronized (this) {
wait(5000);
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace(out);
}
}
}

In this case, the output doesn't appear on the console for five seconds. So we see another issue with running on the UI Thread and outputting information to the console: the whole pluglet has to end before any output from the main thread is sent to the console. The solution, again, is to run everything from a different thread.

Another way to run pluglet code on the non-UI thread is to use the IProgressService.busyCursorWhile facility. This blocks the main thread but executes the code on another thread. It displays a busy cursor for a brief period of time, but after that it then displays a progress bar, which you can control from your pluglet code. If you wish, you can also have (within the code) dialog boxes that will overlay the progress bar.

To use this, you first need the following entries in pluglet.xml:

<import plugin="org.eclipse.ui"/>
<import plugin="org.eclipse.core.runtime"/>


The following code shows an example of using the busyCursorWhile:

public class ShowAProgress extends Pluglet {
public void plugletmain(String[] args) {
IProgressService progressService =
PlatformUI.getWorkbench().getProgressService();
try {
progressService.busyCursorWhile(new IRunnableWithProgress() {
public void run(IProgressMonitor monitor) {
performAction(monitor);
}
});
}
catch (InvocationTargetException e) {
}
catch (InterruptedException e) {
}
}

protected void performAction(IProgressMonitor monitor) {
monitor.beginTask("The main task", 3);
monitor.subTask("Waiting for the First Second");
waitASecond();
monitor.worked(1);
monitor.subTask("Waiting for the Second Second");
waitASecond();
monitor.worked(1);
monitor.subTask("Waiting for the Third Second");
waitASecond();
monitor.worked(1);
inform("All Seconds done");
monitor.done();
}

private void waitASecond() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
}
}

Accessing external JARs and project classes from pluglets

If you select the properties of your pluglet project, you will see that it can do all of the things a Java project can. Since this is so, you may be tempted to add project references to internal or external JARs as well. If you do this, you will find that you can write code in your pluglet that references the classes and APIs in these external packages, and it will compile acceptably and even provide code completion.

However, as soon as you try to run the code, it will fail with a "java.lang.NoClassDefFoundError". The best solution to this is to create a plug-in for the external JARs that you wish to access.

Trapping output from APIs that use System.out or System.err

If you do call an API that sends its output to System.out or System.err (in fact, I came across this exact situation in a plug-in that created its own console), you may wish to trap the information returned. This is easy to do by redirecting System.out or System.err to write to a ByteArrayOutputStream, as shown in the following code:

 
ByteArrayOutputStream baos = new ByteArrayOutputStream();
PrintStream savedOut = System.out;
System.setOut(new PrintStream(baos));

// Invoke the API

System.setOut(savedOut);
out.println(baos.toString());
baos.reset();


Example 1: Using pluglets to test your plugins

OK, so you have written your plug-in and want to try it out. Pluglets would be an obvious choice, but after your runtime workbench has started and you have created a Pluglet project, you find you cannot add your plug-in to the pluglet.xml file. When you add the entry into pluglet.xml, you still cannot access your plug-in code. If you look at the error log you will see entries similar to the following:

 IRJP0001E Workspace deployed plug-in "TestPlugletPlugin" is missing its runtime 
  library "TestPlugletPlugin.JAR". 

This is because the pluglet engine is actually looking for the JAR file for the plug-in. You can solve this problem by packaging your plug-in into a JAR file and placing it in the appropriate place, as defined by the plugin.xml within your plug-in project. The easiest way to do this is using the Export to JAR facility.

This also allows you to save the JAR creation description, which makes it easy to create and recreate the JAR file as needed. When you create the JAR file, only include the generated class files and resources. Once you have the JAR file and you have added your plug-in to pluglet.xml, confirm that everything is correct by expanding the Pluglets plug-in dependencies tree within your pluglet project to ensure that the JAR file is present.

Debugging and hot code fixing

You can debug your plug-in code as normal, but you can also do hot code replacement as well. That is, you can do the following without having to restart:

  • Modify the behaviour of a method
  • Change a method signature
  • Add a new method and modify your pluglet within the runtime workbench

In order for hot code fixing to work, you need to launch your runtime workbench with -Xj9 in your VM arguments of the Command Line Settings, as shown in Figure 6.


Figure 6. Adding -Xj9 to the VM Arguments
Providing the command line settings

To understand how to achieve full hot code fixing, you need to understand the workings of the environment. The pluglet engine uses the JAR file within the editor for your pluglet code. It is used to error check the pluglet code, and it provides code completion. It is not used for the execution of the pluglet. Pluglet execution is taken from the binary files within your plug-in project.

If you want to change a method behaviour, all you need to do is modify the source code of your plug-in (even while executing the pluglet) and the code will be hot replaced if possible.

If you want to change a method signature or add a method, you modify the source, but once you save it you must rebuild your.JAR file. To pick up the changes in your pluglet, you will need to modify the pluglet and save it once (or perhaps refresh the pluglet project) to force the environment to detect a change in the JAR file.


Example 2: Using pluglets as a macro environment

MODELWARE is a project co-funded by the European Commission under the "Information Society Technologies" Sixth Framework Programme (2002-2006). Information included in this document reflects only the author’s views. The European Commission is not liable for any use that may be made of the information contained herein.

As part of the Modelware project I was involved in (http://www.modelware-ist.org ), we needed a way to interact with Rational Software Architect resources: Projects, Files, Models, elements in models, and diagram images. In addition, we had to construct simple macros that accessed these resources and passed them to external tools (and other internal mechanisms, such as the transformation engine) to process and create resources back within the Rational Software Architect workspace.

To help facilitate this, a plug-in was created that was specifically targeted to providing high-level tasks to pluglets. These tasks provided a simple API that was designed to make writing pluglet scripts simple and quick. The API was not designed for performance, but for ease of use. It also works in a manner that ensures that the specific environment works. For example, the ModelManager tasks create copies of models rather than reference the original ones in memory.

The Rational Software Architect Tasks package was split into five separate sections, as shown in Table 1.


Table 1. Splitting the Rational Software Architect tasks into separate sections
TasksDescription
Resource TasksProvide interaction with Rational Software Architect Resources: Projects, Folders, and Files
ModelManager TasksObtain in memory objects of Rational Software Architect UML2 Models, Profiles, Elements inside of selected models and diagrams stored in model and profile files in the workspace
Rational Software Architect Model TasksGet Diagrams and a Pure UML2 (no diagram information) model from an in memory
Rational Software Architect Model Transformation TasksInvoke the Standard Rational Software Architect Transformations
Pluglet TasksProvide useful general facilities for pluglets such as more dialogs and easy mechanisms to run pluglet code on a different thread

The Tasks package does not provide any easy methods for manipulating the models. This is best done using transforms or the UML2 API.

The Tasks plug-in package is available with this article (see the Download section), and consists of a code plug-in and a documentation plug-in that can be installed into Rational Software Architect (for example, in the <Rational Software Architect_INSTALL_DIR>\eclipse directory). Also included is a sample project with examples of using the tasks package.

The following code example shows how to write a macro that can extract all diagrams from a selected Rational Software Architect model, and then store them in a project. To run this macro, follow these steps.

  1. Open your model in Model Explorer.
  2. Select the model element
  3. Invoke the macro by selecting Run > Internal Tools.
  4. You will be prompted to provide the folder to which to save your results.
  5. Use the navigator to find the saved JPG files and double click on them to view them.
 import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.uml2.Model;
import com.ibm.mdbi.tasks.TaskException;
import com.ibm.mdbi.tasks.rsa.ModelManagerTasks;
import com.ibm.mdbi.tasks.rsa.PlugletTasks;
import com.ibm.mdbi.tasks.rsa.RSAModelTasks;
import com.ibm.mdbi.tasks.rsa.RunnablePluglet;
import com.ibm.xtools.pluglets.Pluglet;

public class EDiags extends Pluglet implements RunnablePluglet {
public void plugletmain(String[] args) {
try {
PlugletTasks.INSTANCE.runPlugletWithProgress(this);
}
catch (TaskException pe) {
pe.printStackTrace(out);
}
}

public void performAction(IProgressMonitor monitor) {
boolean beginTask = false;
try {
Model model = ModelManagerTasks.INSTANCE.getSelectedModel();
if (model != null) {
String[] location = getFolder();
if (location[0] != null) {
monitor.beginTask("Extracting Diagrams", 1);
beginTask = true;
monitor.subTask("retrieving JPG diagrams from model");
RSAModelTasks.INSTANCE.getAllDiagrams(model, "JPG",
location[0], "diagrams");
monitor.worked(1);
inform("Diagrams saved");
}
}
else {
inform("No Model Selected");
}
}
catch (Throwable e) {
inform("Exception '" + e.getClass().getName() + "' occurred.
See console for full details");
e.printStackTrace(out);
while (e.getCause() != null) {
out.println("\n caused by: ");
e = e.getCause();
e.printStackTrace(out);
}
}
finally {
if (beginTask) {
monitor.done();
}
}
}

private String[] getFolder() {
return PlugletTasks.INSTANCE.allFolderSelectDialog("Select a
Folder to store diagrams");
}
}


Conclusion

Rational Software Architect pluglets provide some great facilities for the user. Hopefully this article has given you a good starting place for how you can use pluglets and what you might use them for.


Acknowledgements

I would like to thank Catherine Griffin and Nicki Watson for reviewing this article.



Download

DescriptionNameSizeDownload method
Sample plugins for this articleArticleCodeRSAPluglets.zip344KB HTTP

Information about download methods


Resources

Learn

Get products and technologies

Discuss

About the author

Dave Kelsey is an Advisory Software Engineer for IBM UK. Dave was involved in the Modelware European Consortium Project, which integrated Rational Software Architect into the other modeling technologies used for the various experiments on Model Driven Development.

Comments (Undergoing maintenance)



Trademarks  |  My developerWorks terms and conditions

Help: Update or add to My dW interests

What's this?

This little timesaver lets you update your My developerWorks profile with just one click! The general subject of this content (AIX and UNIX, Information Management, Lotus, Rational, Tivoli, WebSphere, Java, Linux, Open source, SOA and Web services, Web development, or XML) will be added to the interests section of your profile, if it's not there already. You only need to be logged in to My developerWorks.

And what's the point of adding your interests to your profile? That's how you find other users with the same interests as yours, and see what they're reading and contributing to the community. Your interests also help us recommend relevant developerWorks content to you.

View your My developerWorks profile

Return from help

Help: Remove from My dW interests

What's this?

Removing this interest does not alter your profile, but rather removes this piece of content from a list of all content for which you've indicated interest. In a future enhancement to My developerWorks, you'll be able to see a record of that content.

View your My developerWorks profile

Return from help

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=Rational, Java technology
ArticleID=173469
ArticleTitle=Using Pluglets in IBM Rational Software Architect
publish-date=11142006
author1-email=d_kelsey@uk.ibm.com
author1-email-cc=clarkega@us.im.com

My developerWorks community

Tags

Help
Use the search field to find all types of content in My developerWorks with that tag.

Use the slider bar to see more or fewer tags.

Popular tags shows the top tags for this particular content zone (for example, Java technology, Linux, WebSphere).

My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere).

Use the search field to find all types of content in My developerWorks with that tag. Popular tags shows the top tags for this particular content zone (for example, Java technology, Linux, WebSphere). My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere).

Rate a product. Write a review.

Special offers