Debug and trace Rational Software Architect patterns and transformations

Techniques for effective problem determination

Although highly effective, the IBM Rational® Software Architect pattern and transformation engines can be a bit overwhelming. As in all software development, patterns and transformations require testing after implementation. Problems are almost always inevitable. In this article, learn about two well-known Eclipse techniques for problem determination, tracing and debug, for patterns and transformations. And explore standard practices for pattern authoring and packaging, to enable you to help yourself and to assist support teams when necessary.

Share:

Jim Bonanno (bonanno@us.ibm.com), Senior Software Developer, IBM, Software Group

Jim BonannoJim Bonanno is a senior software developer working with the Strategy and Innovation team. Jim has a long history of UI technologies, most recently Web applications. Current interests include On Demand and SOA technologies. Hobbies outside of work include kayaking, mountain biking, and jet skis. You can reach Jim at bonanno@us.ibm.com.



Murray Beaton (beatonm@ca.ibm.com), Senior Software Developer, IBM, Software Group

Murray BeatonMurray Beaton is a senior software developer working with the SWG Technology Strategy and SOA Innovation team. His focus has been the creation and adoption of reusable assets surrounding the IBM On Demand and SOA initiatives. Contact Murray at beatonm@ca.ibm.com.



25 April 2006

Introduction

This article discusses best practices and techniques to debug and trace patterns and transformations in Rational Software Architect.

Rational Software Architect provides frameworks to support model-driven design through the Unified Modeling Language 2 (UML2) implementation and through its pattern and transformation engines. Many articles cover the implementation of a pattern, profile, and transform plug-in. This article focuses on the testing phase only.

Debugging and tracing are not new concepts. Most developers -- especially Eclipse developers -- likely have some experience with them. In this article, you discover how to most effectively apply tracing and debugging into Rational Software Architect patterns and transformations.

Tracing can be a powerful tool that, when incorporated with established guidelines, can help diagnose the cause of defects. Plug-in users can easily enable tracing to produce a trace file that can be analyzed to determine the root cause of an issue.

Debug is similar in that you get a detailed look at what is occurring during execution, but it is real-time analysis.

Tracing can provide data in a form that can be reused for more than problem analysis. Trace also simplifies the role of both end users and developers, since the developer of the plug-in is not required to reproduce the run-time scenario to gain insight into the problem.

In general, trace and debug are method-level concepts. You want to know when a method is called, who called it, the parameters it was called with, and its return value. Setting a breakpoint in a method or emitting trace statements are not technically challenging, but determining which methods are of interest can be, especially if you are unfamiliar with the underpinnings of a framework.

The first part of this article is a crash course on the critical methods involved during pattern validation and expansion and transformation. These methods are commonly called "hot spots." This article also shows you how to leverage the built-in trace capabilities of the patterns and transformations infrastructure shipped with Rational Software Architect to update these methods with trace capability. If you are interested in more real-time analysis, we'll show how to set breakpoints and analyze the data of interest in the debugger.

Effectively tracing and debugging patterns and transformations requires that the plug-in source code be available. The patterns and transformations in the developerWorks' series, "Architecting on demand solutions" and discussed in Patterns Solutions typically ship with source. Because source makes trace and debug possible, we've included a short section highlighting how to package plug-ins that contain source code.

Pattern and transformation hot spots

Hot spots are critical methods that are involved during pattern validation and expansion, and transformation. When patterns and transformations are created, hot spot methods are generated with convenient To-Do's. These remind you to update this piece of code, depending on your scenario. To-Do's, like other informative messages, are visible in the Eclipse Task View.

Patterns help improve developer productivity by generating code and automating the development of SOA applications through reuse. Patterns describe solutions to recurring problems.

When a pattern is defined and generated, a number of hot spots exist. They center on the pattern parameter implementation classes or on the behavior that occurs when a parameter value is bound. This behavior is commonly called pattern expansion and has accompanying methods generated by the name of expand for each pattern parameter, as shown in Figure 1.

Figure 1. Pattern parameter expand methods
patter parameter expand methods

Every pattern parameter has expand methods generated. However, if you've specified dependencies between parameters, additional hot spot methods by the name of update are generated as well. Update methods are used to perform additional tasks or expansion when both parameters are bound. Figure 2 shows the presence of update methods due to a dependency between Parameter1 and Parameter2.

Figure 2. Parameter dependency update methods
parameter dependency update methods

In addition to the expansion and update code, a common method of interest to pattern authors is isValid. This method is responsible for determining whether proposed parameters (using drag) are acceptable as objects to be bound. By default, the pattern framework only ensures that the UML type of the proposed object matches the UML type of the pattern parameter. In real life, more validation is typically required, so authors override this method to put more stringent controls on what can and cannot be bound. Figure 3 shows a sample overridden isValid method, but its implementation is merely a call to its super class.

Figure 3. Pattern parameter isValid override
pattern paramenter override

Transformations are also generated with a number of hot spots. The only mandatory hot spot for transformations (assuming the transformation is generated using the UI tooling) is in the createTarget method for each rule added. This rule is responsible for accepting objects passed during invocation of the transform, and transforming/processing these objects as per the transformation scenario. It's also quite common for transformation authors to override the canAccept or the getAcceptCondition methods to limit the number of objects they process.

For more details and samples of the pattern and transformation methods mentioned in this section, see the developerWorks article, "Content authoring demystified."

Rules accept UML objects of a particular UML type, as specified during creation of the rule, but this is often too broad. Transform authors generally are interested in specific types of class, or classes, that have certain annotations. CanAccept and getAcceptCondition help facilitate this filtering. Figure 4 shows a sample overridden createTarget method.

Figure 4. Transformation rule createTarget
transformation rule

Not all the methods just mentioned exist for each and every pattern and transformation you encounter. They are key items to pay special attention to during trace and debug initiatives.

Adding deployed plug-ins to a workspace

To debug or trace a plug-in, it must be available to your workspace. Any Rational Software Architect run-time plug-in is available to be imported into a user workspace. If the plug-in was shipped with its source, as is typically the case with the pattern and transformation plug-ins, you can also browse and inspect the source code. Figure 5 shows importing an existing plug-in into the workspace.

Figure 5. Import Rational Software Architect plug-in
Import RSA plug-in

In this example, both the plug-ins selected for import contain source zip files, as highlighted in Figure 6.

Figure 6. Imported plug-in with source zips
Imported plug-ins with source zips

The JAR file can be expanded to explore the included class files. When the class file is selected, Eclipse automatically displays the source from the source zip file, as shown in Figure 7.

Figure 7. Source shown for class files
source shown for class

Tracing overview

Tracing is a quick, effective means to debug an application. Establishing guidelines for how to add tracing as the plug-in is being developed can also help users of your plug-in debug issues and provide feedback, or just learn the plug-in internals. The pattern and transformation framework uses Eclipse's debug mode and the .options file to enable tracing, and also to document the different types of tracing available.

The trace messages will be written to System.out if the correct level of tracing is enabled. The amount and type of trace information can be limited to ensure only the pertinent pieces of information are displayed. If more information is needed, additional trace information can be enabled.

debug

The debug trace level is used to enable trace messages that do not fall into the other categories; it is the base level that is used for tracing. If the problem cannot be determined with this level, a more specific level of tracing will be enabled. When you have a problem, this level will typically be used to create the first log file.

debug/exception/catching
Used to enable trace messages when an exception is caught.
debug/exceptions/throwing
Used to enable trace messages when an exception is thrown in the code.
debug/methods/entering
Used to enable trace messages when a method is entered. This type of tracing can be helpful to see which methods are invoked during the execution of the plug-in.
debug/methods/exiting
Used to enable trace messages when a method is exited. This tracing level is typically used with debug/methods/entering. There can be cases when the exiting trace message will not be traced because the method has multiple exit points.
debug/transform/configuration
Used to trace messages during the configuration phase of the transform. This level of detail can be enabled to help determine that the configuration step is correctly setting up the execution of the transform.
debug/transform/execute
Used to enable trace messages during the execute phase of the transform.
debug/patterns/execution
Used to enable trace messages during the execution phase of the pattern.

Adding trace capability to plug-in source

Eclipse establishes a best practice of an .options file that is typically packaged with the plug-in to document the supported tracing levels and the tracing that is enabled by default. The goal is to add tracing to your pattern and transform that is consistent with the existing framework, enabling your patterns and transformation to behave the same as the patterns and transformations that are shipped with Rational Software Architect.

The com.ibm.xtools.common.core package provides an internal utility class that supports tracing that is enabled through the .options file. If available, this class can be used or you can create your own tracing utility class that supports the same options. (See Download for an implementation.) The trace messages are written to System.out, but only if the level of tracing is supported.

Listing 1 shows a typical .options file.

Listing 1. Example .options file
# Debugging options for the com.ibm.xtools.sample.uml2javatrace plug-in

# Turn on general debugging for the plug-in
com.ibm.xtools.sample.uml2javatrace/debug=true

# Trace when exceptions are caught and thrown
com.ibm.xtools.sample.uml2javatrace/debug/exceptions/catching=false
com.ibm.xtools.sample.uml2javatrace/debug/exceptions/throwing=false

# Trace when methods are entered and exited
com.ibm.xtools.sample.uml2javatrace/debug/methods/entering=false
com.ibm.xtools.sample.uml2javatrace/debug/methods/exiting=false

The code to create the trace strings programmatically might look like Listing 2.

Listing 2. Trace strings
/** Debugging problems */
public static final String DEBUG = Uml2javatracePlugin.getPluginId() + "/debug"; 
   //$NON-NLS-1$
/** Debugging EXCEPTIONS_CATCHING option */
public static final String EXCEPTIONS_CATCHING = DEBUG + "/exceptions/catching"; 
   //$NON-NLS-1$
/** Debugging EXCEPTIONS_THROWING option */
public static final String EXCEPTIONS_THROWING = DEBUG + "/exceptions/throwing"; 
   //$NON-NLS-1$
/** Debugging METHODS_ENTERING option */
public static final String METHODS_ENTERING = DEBUG + "/methods/entering"; 
   //$NON-NLS-1$
/** Debugging METHODS_EXITING option */
public static final String METHODS_EXITING = DEBUG + "/methods/exiting"; 
   //$NON-NLS-1$

The Plug-in class does not have a default implementation for the method getPluginId. This method returns a string with the plug-in's symbolic name, as shown in Listing 3.

Listing 3. Implementation of getSymbolicName
public static String getPluginId() {
   return Uml2javatracePlugin.getDefault().getBundle().getSymbolicName();
}

Listing 4 contains sample code demonstrating use of the trace methods. These methods all invoke the shouldTrace method and will not write to System.out unless the .options file is specified and the tracing level is enabled. The download for this article contains the JavaDoc for the Trace class.

Listing 4. Example trace code
public Object createTarget(ITransformContext ruleContext) {
		
  Trace.entering(Uml2javatracePlugin.getDefault(), METHODS_ENTERING, 
     this.getClass(),"createTarget" );
  try {
     // extract the class from the current context
     org.eclipse.uml2.Class traceClass = 
        (org.eclipse.uml2.Class)ruleContext.getSource();
	
 //put the class and it's operations in a map in preparation to call the JET template
     Map map = new HashMap();
     map.put("TRACE_CLASS", traceClass);
     List traceOps = new BasicEList();
     Iterator opIt = traceClass.getOwnedOperations().iterator();
     while (opIt.hasNext()) {
        Operation operation = (Operation)opIt.next();
        if (operation.hasKeyword("log")) {
           traceOps.add(operation);
        }
     }
     map.put("TRACE_OPS", traceOps);
			
     // Generate the source using the JET template, passing in the map object
     String fileContent = new JDKTraceTemplate().generate(map);			
     System.out.println(fileContent);
  }
   catch ( Exception ex ) {
      Trace.catching(Uml2javatracePlugin.getDefault(), METHODS_CATCHING, 
         this.getClass(),"createTarget", ex );
   }

   Trace.exiting(Uml2javatracePlugin.getDefault(), METHODS_EXITING, 
      this.getClass(),"createTarget" );
		
   return null;
}

You need to manually create and add the .options file to the project. The .options file then must be selected so it is included in the binary build of the plug-in, as shown in Figure 8.

Figure 8. Select .options file
select options file

Enabling trace capability in the runtime

A plug-in that supports tracing can display the trace messages directly in the console window of the main Eclipse run time. Launching a separate workbench is not required for tracing. When Rational Software Architect is launched, specify the -consolelog argument to open a separate console window for trace messages and reference an .options file with the appropriate debugging trace messages enabled. Listing 5 shows an example.

Listing 5. Using the –debug argument
"C:\Program Files\IBM\Rational\SDP\6.0\rationalsdp.exe" -debug "c:\program 
   files\IBM\Rational\SDP\6.0\.options" -consolelog

Launching the debug workbench

A separate workbench must be launched in Debug mode to debug the application and potentially suspend at the breakpoints that have been set. You can launch the workbench several ways in Eclipse, one of which is through the context pop-up menu shown in Figure 9.

Figure 9. Launching the debugger
launching the debugger

If you do not have an existing run-time workbench configured, create a new workbench by selecting Run-time Workbench > New. Select the Plug-ins tab and ensure Launch with all workspace and enabled external plug-ins is selected.

The amount of tracing varies per plug-in and is configurable using the run-time configuration. If a plug-in supports tracing by packaging an .options file, then the different levels of tracing that are available will be displayed. Select the Tracing tab, then select the plug-in tracing that you want to enable.

Figure 10 shows the available tracing for com.ibm.xtools.transform.core. Only the options that are set to true in the .options file for that plug-in will be selected in the right-hand column. These are the default options, but you can modify for finer granularity if desired.

Figure 10. Configure run-time workbench for trace
configure run-time workbench for trace

If the .options file from a plug-in in the workspace is included in the binary build, the tracing can be enabled on that plug-in as well. Such is the case with the com.ibm.xtools.sample.trace plug-in you previously imported. The plug-in's trace options are shown in Figure 11.

Figure 11. Enable tracing from a workspace plug-in
enable tracing from a workspace plug-ing

After completing the configuration, launch the debug workbench by selecting Debug.

The console shows the entering and exiting trace messages for the ClassParameter nested class. As shown in Listing 6, the debug message also shows that the isValid method is returning true.

Listing 6. Trace messages in the Console view
ENTERING com.ibm.xtools.sample.trace.patterns.tracepattern.
   TracePattern$ClassParameter#isValid(Proposed)
isValid is true
EXITING com.ibm.xtools.sample.trace.patterns.tracepattern.
   TracePattern$ClassParameter#isValid(Proposed)
ENTERING com.ibm.xtools.sample.trace.patterns.tracepattern.
   TracePattern$ClassParameter#isValid(Proposed)
isValid is true
EXITING com.ibm.xtools.sample.trace.patterns.tracepattern.
   TracePattern$ClassParameter#isValid(Proposed)
ENTERING com.ibm.xtools.sample.trace.patterns.tracepattern.
   TracePattern$ClassParameter#isValid(Proposed)
isValid is true
EXITING com.ibm.xtools.sample.trace.patterns.tracepattern.
   TracePattern$ClassParameter#isValid(Proposed)

Using the debugger

You'll use the integrated Java™ debugger to debug the patterns and transform plug-in. The debugger is well documented in the Help section, and you can find more information in Resources. So far we've covered how to start the workbench in debug mode and enable tracing. This section discusses using the debugger for a pattern and transform plug-in.

Setting the breakpoints

A breakpoint can be set in the Java perspective by double clicking the margin next to the desired line or right-click and use the pop-up menu to toggle the breakpoint, as in Figure 12.

Figure 12. Setting a breakpoint
setting a breakpoint

The execution of your program will suspend when the breakpoint is reached. If you are not already in the debug perspective, you will likely be prompted to switch. The displayed views in the debug perspective are configurable, but typically you'll see the debug view with the toolbar for debugging and several other views including variables, breakpoints, and the console, as shown in Figure 13.

Figure 13. Debug perspective
debug perspective

The debug view displays the stack frame for each suspended thread, as shown in Figure 14. The stack can be used to view the set of calls that resulted in suspending at this particular breakpoint. If the source code for each entry is available, then the source for the class and method can also be displayed.

The call stack displayed in Figure 14 is for a breakpoint set in the expand method of an AbstractPatternParameter implementation class. You can use this view to inspect the code that caused the expand method call, but that would require plug-ins shipped with source and imported into the workspace. The execution of this thread was suspended as a result of binding a UML class object with the name "MyClass" to the pattern.

Figure 14. Debug view
Debug view

The debug view provides the toolbars that are used to control the execution and individual stepping through the code. The first toolbar supports controlling the debug session, which includes start, suspend, terminate and disconnect. When the execution is suspended, the second toolbar supports individual stepping of the program -- step into, step over, step return.

Inspecting the values

The debugger also provides a variable view that you can use to display the variables that are visible when the execution is suspended after a breakpoint is reached. The variables view can be used to expand the data structures and drill down to see the data types and the actual values. The data structures can be nested, which again is indicated by the navigation tree.

For example, when developing a pattern a potential scenario is that the expand implementation is not correctly adding a desired abstraction relationship between two classifiers in your model. In this case you could set a breakpoint in one of the pattern hot spot methods: the expand(added) method in the AbstractPatternParameter implementation class. You can step individually through the lines of code, or you can also use the variable view to inspect the passed PatternParameterValue argument, as shown in Figure 15.

Figure 15. Using the debugger to inspect Value
Using the debugger to inspect Value

The debugger allows inspecting the value object, which is the added object that is bound to the pattern parameter. Notice the nested object of type ClassImpl with a name attribute with value MyClass. You can use the variable view to drill down to view the data types and values. Not only can the debugger be used to view the values, but the values can also be changed when the execution is suspended. This view can be very useful to help determine how to programmatically obtain a value that can be set on the UML object using the UI.

Hot code deployment

Launching a run-time workbench in debug mode can be quite slow, especially the first time, so relaunching in most cases is not desirable unless absolutely necessary. Configuring the workbench to use a Java Virtual Machine (JVM) that supports hot-deploy can eliminate the time spent continuously relaunching. Hot-deploy lets you immediately deploy and test modified code, provided that signatures for various constructs and similar have not changed.

Hot code deployment is easily configured in Rational Software Architect for the default JVM by specifying -Xj9 as one of the VM arguments during configuration of the run-time workbench, as shown in Figure 16.

Figure 16. Enabling hot-deploy
enabling hot deploy

Exporting a plug-in with source

The patterns featured in Architecting on demand solutions and Patterns Solutions typically ship with source. To export plug-ins into Reusable Asset Specification (RAS) assets containing their source, ensure that Include source with deployable binaries is selected. Upon compilation of the asset, the source zip will be packaged and included in the root of the plug-in.

The naming convention for the source zip is determined by the run-time zip for the plug-in itself, <JAR-name-up-until-the-last-dot>src.zip. For example, if the run-time JAR is specified as xyz.jar, then the source zip will be xyzsrc.jar.

The RAS asset is exported using the Export RAS Asset wizard, as shown in Figure 17.

Figure 17. Export RAS asset
Export RAS asset

The export of the RAS asset packages the JARs for all the included plug-ins. To ensure the RAS asset is built and packaged correctly, you should consider using shorter paths for your workspace location and class names. Failure to do so may cause problems on systems having limitations on file location lengths. The symptom is not easy to diagnose, however; it typically appears as a ClassNotFoundException during run time due to classes missing from the run-time JAR for your asset.

Summary

In this article, you learned about two aspects of your pattern and transform plug-in: tracing, and using the debugger to find and help determine problems. Guidelines have been established for adding tracing to pattern and transformation plug-ins. When adding trace capability to a plug-in, you should always consider two key factors: the information that's considered pertinent for problem determination and the appropriate level of trace detail necessary. When problems are encountered in the field, a user who can quickly enable tracing options within the plug-in can provide support teams with a wealth of information to investigate the issue.

You also explored how the debugger can be a powerful tool to find problems, to hot-deploy fixes, and to retest solutions. You also learned best practices for using the debugger in the context of debugging the patterns and transformation frameworks. Adding source to plug-ins gives you the ability to help you discover the solution to problems and create potential workarounds.


Download

DescriptionNameSize
debug sample codear-rsadebugcode.zip  ( HTTP | Download Director Help )90KB

Resources

Learn

Get products and technologies

Discuss

Comments

developerWorks: Sign in

Required fields are indicated with an asterisk (*).


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Information in your profile (your name, country/region, and company name) is displayed to the public and will accompany any content you post, unless you opt to hide your company name. You may update your IBM account at any time.

All information submitted is secure.

Choose your display name



The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

Required fields are indicated with an asterisk (*).

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


All information submitted is secure.

Dig deeper into Rational software on developerWorks


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=Rational
ArticleID=109343
ArticleTitle=Debug and trace Rational Software Architect patterns and transformations
publish-date=04252006