Comment lines: Step into the Swing era, Part 2

Build upon your scripting foundation

This article continues the discussion of adding a GUI to wsadmin Jython scripts using Swing to make your IBM® WebSphere® Application Server system admin scripts more user friendly. This content is part of the IBM WebSphere Developer Technical Journal.

Share:

Bob Gibson (bgibson@us.ibm.com), Advisory software engineer, IBM

Author photoBob Gibson is an Advisory Software Engineer who has over a quarter-century experience in numerous software-related roles at IBM, including Architect, Developer, Tester, Instructor, and Technical Support. He is currently a team leader for the technical support group responsible for IBM's WebSphere Distributed Application Server. He holds both a Bachelor of Science degree in Engineering Science and a Master of Science degree in Computer Science from the University of Virginia.



20 June 2012

Also available in Chinese

Why use graphical Jython scripts

After the publication of the Part 1, someone asked me if learning about Jython Swing was worth the effort. I answered with a resounding yes! Using this technology enables you to create administrative scripts that can be tailor made for your specific needs.

Some might point out that the IBM WebSphere Application Server administrative console can be used to display, modify, or even create any kind of WebSphere resource that you might need, and that text-oriented Jython wsadmin scripts could also be used to automate the manipulation of WebSphere Application Server environments. While both of these points are true, creating a GUI administrative script enables you to limit the type and amount of information that is displayed to the user, and present it in a way that makes sense for your situation. Using Swing with your Jython scripts, you get to decide what information about your environment you want to display and how you want your users to interact with it. That’s a real benefit that’s missing from other methods.

This article takes a step beyond the prior installment with additional details to provide you with a more solid and practical starting point for your own wsadmin script and GUI development.


Where to start

Simplified code

For the purpose of providing a more straightforward picture of the application described, the code segments presented in this article do not include comment blocks or blank lines.

Part 1 showed how easy it can be to create a trivial graphical application. Of course, that “quick and dirty” example didn’t demonstrate any best practices for script development. This time, let’s start with a solid foundation and provide a simple script template that might be useful as a starting point for your own application development. A simple Jython Swing script is shown in Listing 1.

Listing 1. template.py
 1|import java
 2|from   java.awt    import EventQueue
 3|from   javax.swing import JFrame
 4|class template :
 5|    def __init__( self ) :
 6|        frame = JFrame( 'template' )
 7|        frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE )
 8|        frame.pack()
 9|        frame.setVisible( 1 )
10|class Runnable( java.lang.Runnable ) :
11|    def __init__( self, fun ) :
12|        self.runner = fun
13|    def run( self ) :
14|        self.runner()
15|if __name__ == '__main__' :
16|    EventQueue.invokeLater( Runnable( template ) )
17|    raw_input( '\nPress <Enter> to terminate the application: ' )
18|else :
19|    print 'Error: This script should be executed, not imported.\n'
20|    print 'Usage: wsadmin -f %s.py' % __name__

Table 1 provides a line by line description of the template.py script.

Table 1. template.py explained
LinesDescription
1-3Identify the library/module classes to be used by your application.
4-9Define the user class that displays the graphical application.
10-14Define the Runnable class that delays the instantiation of your application class until the Swing Event Dispatch Thread is ready for it.
15-20Statements that verify the script was executed and not imported. If the script was executed, delay the instantiation of your user class, and wait. If the script was imported, display a message, and the appropriate usage instructions.

You’re probably already familiar with the import statements found in lines 1-3. If you have questions, or need a refresher, take a look at the IBM Press book WebSphere Application Server Administration using Jython.

Using SwingUtilities.invokeLater()

Many Java Swing examples use SwingUtilities.invokeLater() instead of EventQueue.invokeLater(). Reading the Java doc for this method shows us that “As of 1.3 this method is just a cover for java.awt.EventQueue.invokeLater().”

One question you might have could be: why do you need to import classes from both the java.awt and the javax.swing libraries? This relates to the fact that the original graphical user subsystem, called the Abstract Windowing Toolkit (AWT), provides some classes that continue to be useful, and are used by the Swing classes -- and, therefore, your applications. The AWT classes are found in the java.awt class hierarchy, and the Java Swing classes are found in the javax.swing class hierarchy.

Jython compiler

Technically, the other code is executed by the Jython compiler to verify the syntax, and build the symbol table. But we’re not going to worry about that. If you’re interested in that, take a look at some compiler construction books.

Skipping over the middle sections for a moment, let’s take a look at lines 15-20. This is where the execution of the script appears to begin. When a Jython script is executed, the __name__ global variable is assigned the value of __main__. If the script is imported, then the value of this variable will be the name of the imported module or file. Therefore, the statement in line 15 uses this fact to determine if the script was executed or imported. When the check succeeds, the EventQueue.invokeLater() class method is used to delay the instantiation of your user class (named “template” in this instance) until the Swing environment is ready for it. This is followed by the raw_input() method to cause the script to wait for user input while the Swing framework runs on a separate thread. (This statement isn’t needed in a non-wsadmin Jython interpreter.)

Sample scripts

The sample scripts referred to in this article are also included for download use.

The Runnable() class (lines 10-14) is required by the invokeLater() method and provides the mechanism used to defer the instantiation of your application class until the Swing framework is ready to do so.

This leaves your application class, the description for which is shown on lines 4-9. This simple class instance creates a JFrame object and provides a string title for it. A call to the setDefaultCloseOperation() method is then used to indicate what should happen when the user clicks on the close icon in the upper right corner of your application. You then have a method call that tells the frame object to make itself visible. (Those more familiar with Java™ than Jython, might be surprised by the use of the value 1 rather than true. The version of Jython provided with wsadmin doesn’t include the Boolean type, so an integer value of 1 is used to represent the value of true, and 0 is used for false.)


Using the JFrame class

You don’t have to use the JFrame class if you really don’t want to. Swing books and tutorials generally identify four top-level classes that can be used as the starting point for your applications: JApplet, JDialog, JFrame, and JWindow. Because we won’t have an opportunity to cover the JApplet class (used for browser applications) or JDialog class in this article, let’s take a look at what is required to create a JWindow application in Jython as an alternative to JFrame.

Listing 2 contains the statement modifications (in bold type) that need to be made to transform template.py (Listing 1) to Window.py. (You can see how easy it is to reuse your existing template.py script as a basis for new applications.)

Listing 2. Window.py changes
 1|...
 3|from   javax.swing import JWindow
 4|class Window :
 5|    def __init__( self ) :
 6|        win = JWindow()
 7|#       win.setSize( 200, 200 )
 8|        win.setVisible( 1 )
 9|...
15|    EventQueue.invokeLater( Runnable( Window ) )
16|...

What happens when you execute this script? Nothing, apparently, because you only see the message displayed in the command prompt window. What actually happens is that a JWindow is created and displayed. Unfortunately, it happens to have a width and height of 0 pixels, which is both uninteresting and extremely difficult to see. If you uncomment line 7, by replacing the ”#“ with a blank space and re-running the script, you’ll see a very empty box in the upper left corner of your display.

So, if you are really ambitious and want to build a GUI application from a completely clean slate, you might consider using the JWindow class as your starting point. I, on the other hand, find it much easier to build my applications based on a more traditional appearance, so I will be using a JFrame class as my starting point in almost all of these examples, at least for the time being.


Calling the setSize() method

You might wonder why you didn’t need to call the setSize() method in the template.py script in Listing 1. Looking back, you’ll find that line 8 is a call to the pack() method and not the setSize() method required in Window.py. What does that do for you? To find out, let’s start with the documentation for the JFrame class, and search for the pack() method. Interestingly enough, it shows up in the section labeled Methods inherited from class java.awt.Window. Clicking on the pack link takes you to the method description, which states “Causes this Window to be sized to fit the preferred size and layouts of its subcomponents.”

So, the reason you didn’t need to call the setSize() method in template.py is because calling the pack() method essentially does this for you.


Using the Swing and AWT class hierarchies

In case you’re wondering if you need to memorize the Swing and AWT class hierarchies, the answer is no. I tend to build on the work of others, and depend heavily on the Swing documentation. If you’re wondering whether wsadmin can help you investigate and learn more about the methods and attributes that exist in the Swing hierarchy, the answer is yes, absolutely. Let’s take a look at how this might be done.

Previously, a simple function called classes was defined that was used to display the class hierarchy for a specified class. To make this more useful, I extended it and created a function called classInfo() that can be used to display the class hierarchy, as well as the names of methods and attributes (or subset thereof) that exist at each level of the class hierarchy. Figure 1 shows an example call to this function that requests information about the JFrame hierarchy, and the names of any methods that have “etSize” anywhere in the method name (case insensitive). (In case you are interested, I used the –profile command line option to identify the fully qualified path to my classInfo.py file, so the wsadmin command looked like: wsadmin –conntype none –profile classInfo.py.)

Figure 1. JFrame hierarchy with etSize methods
Figure 1. JFrame hierarchy with etSize methods

The methods that have this sequence of characters somewhere in the name are indicated by lines that use “>” instead of the “|”. Java programmers will recognize the ubiquitous getter and setter naming convention that is used for methods for an attribute named size (that is, getSize() and setSize(), respectively).

This same classInfo function can be used to display the same JFrame hierarchy and the occurrences of any attributes containing “size” somewhere in the name. Figure 2 demonstrates this. Notice how the attributes are indicated using “*” instead of “>” or “|”.

The only occurrence in which you are interested at the moment is the “size” attribute that is defined in the java.awt.Container class.

Figure 2. JFrame hierarchy with “size” attributes
Figure 2. JFrame hierarchy with “size” attributes

One way this helps you is that you can use this routine (or something similar) to find out more about the class hierarchy, including the methods and attributes defined at various class levels. Then, you can investigate how best to use this information. One of the most useful things you can do with it is use it to help you write more concise applications. Figure 3 demonstrates multiple ways that the size attribute of a JFrame object can be checked and set.

Figure 3. JFrame sizing
Figure 3. JFrame sizing

First, you use the traditional setter method, setSize(), to define the desired width and height of the object instance, followed by a call to the getter method, getSize(), to display the current object size.

Next, you see how the initial size of the newly instantiated JFrame object defaults to a width and height of 0 pixels. Then, an assignment statement is used (rather than a setter method call) to define the desired object width and height. This results in the same settings that occur when the traditional setter method was used.

Finally, you see how the assignment to the size attribute can be made as part of the instantiation of the JFrame object. This is one of the most useful aspects of Jython for your Swing applications. As we progress with these articles, you will see just how often this technique can be used to make your scripts more clear and concise. This can make the lives of those who develop and maintain your applications significantly easier and better.


Conclusion

This article provided a good foundation for your administrative scripts, and provided you with information about how you can investigate information about the Swing class hierarchy. You can use this information to decide how you want to leverage Jython to create more robust and user friendly administrative applications. Hopefully, you will find this article interesting and will continue with future installments that will help you step through the Swing era.


Download

DescriptionNameSize
Sample scriptsSwingEra-Part2.zip2 KB

Resources

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 WebSphere on developerWorks


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=WebSphere
ArticleID=821650
ArticleTitle=Comment lines: Step into the Swing era, Part 2
publish-date=06202012