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
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
|1-3||Identify the library/module classes to be used by your application.|
|4-9||Define the user class that displays the graphical application.|
|10-14||Define the Runnable class that delays the instantiation of your application class until the Swing Event Dispatch Thread is ready for it.|
|15-20||Statements 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.
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.
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
__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.)
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
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
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
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
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.
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.
|Sample scripts||SwingEra-Part2.zip||2 KB|
- Comment lines: Step into the Swing Era
- Scripting from scratch: Creating a Jython administrative script for IBM WebSphere Application Server
- Scripting the application serving environment (wsadmin)
- WebSphere Application Server Administration using Jython
- Java Swing, 2nd Edition
- Java Foundation Classes in a Nutshell
- Swing: A Beginner’s Guide
- The Java Swing Tutorials
- The javax.swing package
- IBM developerWorks WebSphere