Adding usability with ease
Recently, I have been working with using Java™ Swing to add graphical user interfaces (GUI) to some of my wsadmin Jython scripts. I was a little intimidated at first by the magnitude of the Java Swing Application Programming Interface (API). However, the more I work with the Swing API and Jython the more I am convinced that it can be easier to develop Jython Swing applications than it is to do the same thing using Java. This article, hopefully the first of many, will show how easy it can be to add a GUI to your wsadmin Jython scripts using Swing.
A simple example
To demonstrate, let’s start with the simplest example possible: What does it take to create a graphical application that displays the ubiquitous “Hello World” message:
- Make the appropriate Java Swing classes available to the script.
- Create (instantiate) a frame object.
- Create a label (with the desired text) and add it to the frame instance.
- Have the frame display itself.
For the purpose of this exercise, an example script to do this is shown in Listing 1.
Listing 1. HelloWorld.py
1|import javax.swing as swing 2|f = swing.JFrame( 'My first GUI' ) 3|f.setDefaultCloseOperation( swing.JFrame.EXIT_ON_CLOSE ) 4|f.add( swing.JLabel( 'Hello World' ) ) 5|f.pack() 6|f.setVisible( 1 ) 7|raw_input( 'Press <Enter> to terminate the application...' )
Table 1 provides a line by line description of the HelloWorld.py script.
Table 1. HelloWorld.py explained
|1||Get access to the Java Swing classes.|
|2||Instantiate a JFrame (highest level Swing container) with the specified title.|
|3||Define what action should be taken when the close icon is selected.|
|4||Instantiate a label (with the specified text) and add it to the frame object.|
|5||Resize the frame to display the contained objects (the text in the label).|
|6||Have the frame object display itself.|
|7||Display the message and wait for user input.|
To see what executing this script does for you, let’s first take a look at the command used to execute this script, which is shown in Figure 1. The result of executing this command is shown in Figure 2. (If you are unfamiliar with the wsadmin command, then you should either take a look at the Information Center documentation, or consider using the book that I helped write on the subject of using Jython with wsadmin to administer your WebSphere Application Server environment (see Resources).)
Figure 1. Using wsadmin to execute the HelloWorld.py script
Figure 2. HelloWorld graphical application
This might not look like much, but it is really quite powerful. For example, without any additional code, this application (window) can be moved, resized, maximized, minimized, or closed. If you drag the bottom right corner down and to the right to make the window larger, you can even see that the title bar of the window contains the text that was provided when the frame object was created (Figure 3).
Figure 3. A slightly larger HelloWorld window
So, is it really that simple? Not quite. There are lots of different classes in the Swing hierarchy, which means that in order to make use of these classes, you have to learn what classes exist, how and where they should be used, and – most importantly – how they can be used by your wsadmin Jython scripts. One of the most challenging aspects is the fact that event driven applications are almost always more complicated than typical application programs.
This doesn’t mean that you shouldn’t use a GUI to interact with the application’s users. It just means that you need to be aware of the challenges ahead.
An intermediate example
Let’s move on to a non-trivial script for a better understanding of some of the things that can be done with a wsadmin Jython administrative script. For example, Figure 4 is a snapshot of the kind of GUI that one of your WebSphere Application Server administration application scripts might display.
Figure 4. WebSphere Application Server cell hierarchy
I wondered what it would take to have a GUI show the port numbers that were configured for the current cell. In about 300 lines of Jython, this script enables you to use your mouse to select the various members in the cell and immediately display the associated port numbers for that server.
You see in the figure that this particular application includes a tree to display the cell hierarchy, and a table to show the associated port numbers and corresponding end point names. There is even a trivial menu that lets you make some simple choices.
Adding Swing to Jython
As with anything, how difficult it is to add Swing to Jython will depend on your skill level; if you are proficient in Java and Jython, it should be almost trivial. This is especially true if you have had any exposure to Java Swing applications. I have a strong and deep understanding of Jython, but not of Java. Yet, I was able to read and understand the example Java Swing code that I found, and was able to teach myself Swing by first doing a line by line translation from Java to Jython, and then experimenting to see how I could leverage Jython capabilities.
In my opinion, Jython has an enormous advantage over Java because of its dynamic typing, which enables you to experiment in an interactive session. Proponents of strongly typed languages see this as a disadvantage and generally prefer Java to dynamically typed languages such as Jython. Another disadvantage is that using Java enables you to deliver compiled class files instead of the source code used by Jython scripts. You will need to decide for yourself what you consider advantages and disadvantages.
Using Java classes in Jython scripts
I frequently find myself using an interactive wsadmin session to interact with the WebSphere Application Server scripting objects and other things. This dynamic interaction also enables you to work with any of the available class hierarchies. For example, here is an easy way to see how many things exist in the javax.swing hierarchy. It’s not a complete list, just a quick way to get an idea of what you are dealing with. To do this:
- Open a command prompt.
- Change directory to the WebSphere Application Server bin directory.
- Invoke the wsadmin command, specifying -conntype none and -lang jython.options.
- At the wsadmin prompt, type import javax.swing.
- At the next line, type dir (javax.swing) and watch the lines fly by.
- If you want to know how many items exist, type len( dir( javax.swing ) )
The result should be that there are 185 items in the class file. Figure 5 shows the first few lines of output generated from these statements.
Figure 5. Output of dir (javax.swing)
Not all of these things are Swing objects, but most of them are. If you are at all familiar with Java Swing, you will see the names of commonly used Swing classes for all sorts of GUI objects.
So, what good does this do you? Actually, quite a bit. You can use the Java features of introspection, and reflection to learn more about any of these objects. Additionally, you can use Jython syntax to easily access and manipulate these properties and attributes. Introspection and reflection enable you to dynamically delve into any object or class to find out about its attributes, methods, and base classes. Figure 6 offers a glimpse of what we can do and how it might be done.
Figure 6. Displaying the 1st ten item names in the JFrame class
Some detail will help explain what you see in Figure 6.
- You begin at the command prompt by invoking wsadmin and telling it to not connect to an application server (-conntype none) and that you want to use the Jython syntax (-lang jython).
- The next few lines of text are generated by the wsadmin utility, followed by the wsadmin interactive command prompt (wsadmin>). The first Jython statement that you type tells wsadmin that you want to access the JFrame class from the (Java) javax.swing library.
- Then things get interesting. Working from the inside out, the first thing that needs to be executed is the call to dir( JFrame ). The dir() function returns a list (sometimes called an array) of the names of the items in the JFrame class. The [ :10 ] is part of the Python syntax, called slicing, that is used to obtain a copy of the 1st ten elements of the list. This ten element list is then passed to the join string method, the purpose of which is to combine the list into a string with each element separated by a new line. The balance of the figure shows the result you get from printing this string.
Figure 7 shows an even more creative (and complex) example. Using something called list comprehension, you can obtain (and in this example, display) the names of the first ten executable (callable) JFrame properties.
Figure 7. Displaying the 1st ten executable JFrame properties
The main difference between Figures 6 and 7 is the assignment to the methods variable that is seen in each. In Figure 6, you use the result of calling the built-in dir() function to obtain the list of items in the JFrame class. In Figure 7, you use list comprehension, which is a compact syntax that describes exactly how a list should be built. This single statement is equivalent to the four statements seen in Figure 8.
Figure 8. Verbose statements equivalent to list comprehension seen in Figure 7
First, the methods variable is initialized as an empty list. Then, a for loop is used to iterate over the name and variable items from the vars( JFrame ) dictionary. A test is made to determine if the value is a reference to an executable object (callable()), and, if so, the name of this item is appended to the methods list. Finally, the same print statement is used to display the names of the 1st ten callable methods.
Looking back at the list comprehension assignment statement in Figure 7, you can see the corresponding iteration over the name (n) and value (v) for each item() from the vars( JFrame ) dictionary. Each iteration performs a call to the callable() function to determine if the value reference (v) is executable, and, if so, appends the item name (n) to the list that is being built.
How all this helps
Using this kind of information, you can quickly build a routine to display the class hierarchy for a specified class. Figure 9 shows a simple routine to display the name of each class, as well as the names of the ancestor classes. The vertical bars make the relationship of classes at the same level more obvious.
Figure 9. JFrame class hierarchy
This hierarchy is different from what is seen in the Java documentation for a JFrame class in that the earliest ancestor (java.lang.Object) in that documentation is outermost (that is, on the far left), and the class in question (JFrame) is innermost (that is, most indented and therefore far right). The code and corresponding output in Figure 9 starts at the specified class (JFrame) and works its way out, so the starting class is seen with the least indentation (that is, far left), and the earliest ancestor is indented the most (and, therefore, furthest right).
I hope this helps you begin to understand how easily you can add a GUI to your wsadmin scripts. Of course, this hasn’t been a complete discussion on the topic, but if it has piqued your interest, please let us know so we can follow up with additional installments.
- 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