| |||||||||||||||
Last
time [16], I introduced BlueJ [17],
an integrated Java environment that is used to teach object
orientation to students. BlueJ emphasizes classes and objects as
its basic units of interaction: it does not force the student to
learn Java's public static void main(String [] args)
method or worry about input/output prior to creating and
interacting with objects.
In the previous article, you also learned how to install BlueJ and how to select an appropriate J2SE SDK for use with BlueJ. Moving on, you toured BlueJ's GUI, where you discovered that BlueJ's main window divides into a menu bar, a project tool bar, a class diagram, an object bench, and a message area. Finally, you were introduced to some features, such as the object inspector and the class diagram's project description note icon, while developing a simple payroll application.
This article delves deeper into BlueJ. It begins by exploring BlueJ's debugging, documentation, executable JAR files, code pad, and unit testing features. The article next focuses on configuration, where you learn how to change configuration options from within BlueJ and outside of BlueJ. Continuing, the article shows you how to extend BlueJ and identifies several useful extensions. The article concludes by addressing some concerns about BlueJ.
Note: This series is based on BlueJ version 2.0.4 and J2SE 5.0 on the Windows 98 SE platform.
BlueJ provides quite a few features beyond those features that were explored in the previous article. For brevity, this section focuses only on BlueJ's debugging, documentation, executable JAR files, code pad, and unit testing features. Subsequent sections look at configuration and extension features. For applet-oriented and other features not explored in this series, I recommend studying the BlueJ tutorial: select the BlueJ Tutorial menu item from the Help menu.
First-year students face many challenges while learning how to use an IDE. After struggling to learn the IDE's editor, the compiler, and project execution, students often don't have sufficient time to also learn about the debugger (which can be quite complicated). And yet, learning how to use the debugger is important: debugging skills motivate students to fix coding mistakes right from the start. Recognizing time constraints, BlueJ's debugger isn't complicated. Its functionality is organized around setting breakpoints, stepping through the code, and inspecting variables.
Before we investigate the debugger, we need something to debug. The previous article's payroll application is not appropriate, because it works correctly. Instead, consider an application that converts integer values to strings of words (perhaps for check-printing purposes). That application's source code appears below.
// DigitsToWords.java
class DigitsToWords
{
public static void main (String [] args)
{
System.out.println (convertDigitsToWords
(327));
}
static String convertDigitsToWords (int integer)
{
if (integer < 0 || integer > 9999)
throw new IllegalArgumentException
("Out of range: " + integer);
if (integer == 0)
return "zero";
String [] group1 =
{
"one",
"two",
"three",
"four",
"five",
"six",
"seven",
"eight",
"nine"
};
String [] group2 =
{
"ten",
"eleven",
"twelve",
"thirteen",
"fourteen",
"fifteen",
"sixteen",
"seventeen",
"eighteen",
"nineteen"
};
String [] group3 =
{
"twenty",
"thirty",
"forty",
"fifty",
"sixty",
"seventy",
"eighty",
"ninety"
};
StringBuffer result = new StringBuffer ();
if (integer >= 1000)
{
int tmp = integer / 1000;
result.append (group1 [tmp - 1] +
" thousand");
integer -= tmp * 1000;
if (integer == 0)
return result.toString ();
result.append (" ");
}
if (integer >= 100)
{
int tmp = integer / 100;
result.append (group1 [tmp - 1] +
" hundred");
integer -= tmp * 100;
if (integer == 0)
return result.toString ();
result.append (" and ");
}
if (integer >= 10 && integer <= 19)
{
result.append (group2 [integer - 10]);
return result.toString ();
}
if (integer >= 20)
{
int tmp = integer / 10;
result.append (group3 [tmp - 1]);
integer -= tmp * 10;
if (integer == 0)
return result.toString ();
result.append ("-");
}
result.append (group1 [integer - 1]);
return result.toString ();
}
}
The source code above isn't commented, for brevity. The source
code also isn't commented because it contains a bug--when
confronted with 327, the application outputs three hundred
and thirty-seven instead of three hundred and
twenty-seven--and I hope to make it harder to find that
bug without using the debugger.
Start BlueJ and create a new project called
"DigitsToWords." Introduce a DigitsToWords
class and, via BlueJ's editor, replace the default source code with
the source code above.
Compile the project and let's go bug hunting. The first thing we
must do is establish a breakpoint at an appropriate location in the
source code, so that the debugger activates when execution reaches
the breakpoint. Accomplish that task by starting the editor and
clicking the mouse in the breakpoint area to the left of the line
containing System.out.println (convertDigitsToWords
(327));. In response, BlueJ displays a small icon in the
breakpoint area, as Figure 1 reveals.

Figure 1. BlueJ identifies breakpoints with small stop-sign
icons
After closing the editor, right-click the DigitsToWords class
icon and select void main(String []args) from the
pop-up menu. Respond to the "Method Call" dialog box by clicking the
OK button. After a few moments, the application starts running.
Execution continues until the breakpointed line is reached. When
that happens, the editor window opens with the breakpointed line
highlighted. Furthermore, the debugger window opens. Figure 2
illustrates both windows.

Figure 2. The small arrow icon in the editor window's breakpoint
area identifies the line that is about to be executed. Use the
debugger window to control this execution.
The debugger window divides into a menu bar, a threads window, a call sequence window, a static variables window, an instance variables window, a local variables window, and a command area:
args.
Because that variable has reference type (as indicated by
<object reference>), you must double-click the
variable to activate the Object Inspector dialog box and view the
variable's value. Of course, there is no value for
args--unless you passed something to this
application via the Method Call dialog box.Click the Step Into button. Execution proceeds into the
convertDigitsToWords() method: if (integer <
0 || integer > 9999) is highlighted as the next line to
execute.
Click the Step button to execute the if
statement; keep clicking Step until result.append (group3
[tmp - 1]); is highlighted. At this point, the local
variables window reveals 2 as the value of tmp.
Furthermore, group3 [2 - 1] references
"thirty" instead of "twenty". It seems we
have found our bug: instead of subtracting 1 from tmp,
we should be subtracting 2.
Documentation is a very important part of any Java project, be
it a BlueJ project or otherwise. BlueJ makes it possible to
generate browser-based documentation from the Javadoc comments
found in a project's source files. Accomplish this task by
selecting the Project Documentation menu item from the Tools
menu. After generating the documentation, BlueJ launches the
default web browser and the documentation displays. For example,
Figure 3 reveals the Mozilla Firefox browser displaying
documentation for the CEO class (part of the previous
article's payroll application).

Figure 3. Click a class link in the browser's left frame to view
that class's documentation
If you are only interested in viewing documentation for the
class whose source code is being entered via the editor, change the
setting from Implementation to Interface
in the drop-down list box on the editor's toolbar. The class's
documentation will generate and display in the editor window.
In addition to generating your own documentation, you might find yourself needing to access the documentation for the Java class libraries while entering source code. You can easily accomplish this task by selecting the Java Class Libraries menu item from the Help menu. In response, BlueJ launches the default web browser, which takes you to the Java class libraries documentation for the J2SE SDK associated with the currently executing version of BlueJ.
Students can distribute their BlueJ projects to instructors (and fellow students) by packaging those projects into JAR files. If a project is an application, its JAR file can be made executable.
To create a JAR file for the current project, first select the Create Jar File menu item from the Project menu. BlueJ responds by presenting the Create Jar File dialog box, as revealed in Figure 4.

Figure 4. Use Create Jar File to create non-executable or
executable JAR files
If the JAR file will not be executable, keep the default
"none (cannot be executed)" setting that is specified in
the Main class drop-down list box. Otherwise, select one of the
current project's classes as the main class--a class whose
main() method runs first when the application starts
up. For example, if you decide to store the payroll application in
an executable JAR file, choose RunPayroll as the main
class.
BlueJ gives you the opportunity to introduce one or more user libraries (custom packages, expressed as JAR files, ZIP files, or directories) into your projects. If you've chosen to introduce one or more of these user libraries into the current project, Create Jar File reveals a series of checkboxes, one per user library. Check each user-library checkbox for those user libraries that are used by the current project. Because I have not introduced any user libraries, Figure 4 does not show any user-library checkboxes. I'll show how to introduce user libraries later when I talk about configuration.
By default, only class files and documentation files are packaged into the JAR file. You can also include the source files by checking the "Include source" checkbox.
Click Continue when you're finished with the dialog box; a file chooser dialog box appears. Use the file chooser to select the location and name of the JAR file; BlueJ then creates that JAR. For the payroll application, select "payroll" as the JAR file's name (BlueJ automatically appends the ".jar" file extension).
After the JAR file has been created, it can be run from a
command window by invoking java with the
-jar command-line option. For example, invoke
java -jar payroll.jar to run the payroll application
from payroll.jar.
While learning a new language, students typically have many questions related to language syntax and semantics. It is not always necessary to write programs to answer these questions: sometimes you just want to execute some code fragment and see what happens. In the spirit of the old BASIC (Beginner's All-purpose Symbolic Instruction Code) interpreters, BlueJ offers the code pad to do just that.
By default, the code pad is not displayed. Show the code pad by selecting the Show Code Pad menu item from the View menu. The code pad appears to the right of the object bench. Because there's not much screen space for both the object bench and the code pad, you can change their sizes by adjusting their horizontal and vertical boundaries.
Use the code pad to evaluate expressions:
"BlueJ".length() and Math.min(4.3, 2.8)
are two examples. Figure 5 illustrates the code pad with these
expressions and their evaluations.

Figure 5. The code pad presents an expression's type alongside
the expression's value
Many expressions evaluate to objects. When that happens, the
code pad displays a small icon to the left of the object and its
type. For example, execute theBoss.getName(). As you
can see, you can specify the names of objects that are on the
object bench and invoke their methods. Figure 6 reveals that
method's returned object, the object's type, and the small
icon.

Figure 6. The code pad displays a small icon to signify an
object
Double-click the small icon to inspect the object's contents.
You can also drag the small icon to the object bench, to keep
working with the object. For example, drag the small icon on
"John Doe"'s left to the object bench. You'll be
prompted to enter the object's name before the object bench
displays the object's icon. As Figure 6 reveals, I chose the
unimaginative name for the object's name.
Along with expression evaluation, you can use the code pad to
execute single statements; for example:
System.out.println("Welcome to BlueJ");. The example's
output does not appear in the code pad. Instead, it displays in the
terminal window. To activate the terminal window, select Show
Terminal Window from the View menu.
The code pad can also execute multi-line statements and
sequences of statements. End each line (except for the final line)
by pressing the Shift+Enter key combination. That way, the line is
entered but not executed. End the final line by pressing Enter, and
the entire statement or sequence of statements will execute. For
practice, enter the following multi-line statement and observe its
output in the terminal window:
for (int i = 0; i < 10; i++)
System.out.println (Math.random ());
The previous multi-line statement shows that local variables can be used in the code pad. However, they will be discarded between inputs, so their usefulness lies only in the context of a single sequence of statements or a single multi-line statement.
The code pad also lets you access instance fields located on the object bench. However, you cannot create them from within the code pad, except to drag an object to the object bench for later use.
Testing complements debugging: debugging locates and fixes bugs that are detected during testing. Because BlueJ supports debugging, it should come as no surprise that BlueJ also supports testing.
BlueJ specifically supports unit testing, the testing of individual software units, methods, and classes in BlueJ. Unit testing is either ad hoc (where you interactively test individual methods) or systematic (where you create unit tests to automatically test your code). Because you'll probably tweak your code during unit testing, you will want to repeat unit tests, to gain confidence that recent changes to methods and classes have not broken existing functionality. BlueJ's tools for recording and replaying unit tests let you accomplish this task. This form of systematic unit testing is known as regression testing.
Regression testing has been around for some time, but has been
popularized by Erich Gamma's and Kent Beck's JUnit [19] regression testing framework.
BlueJ's support for regression testing is based on JUnit; this
support is manifested by way of BlueJ's junit.jar JAR
file.
Whether you intend to use regression testing by itself, or combine regression testing with ad hoc testing (to record interactive test sequences that automatically create JUnit test methods for later regression testing), you must first enable unit testing (I show how to enable unit testing when I talk about configuration). After unit testing has been enabled, BlueJ presents a Testing menu item on the Tools menu, a Show Test Results menu item on the View menu, a Create Test Class menu item on a compiled class's pop-up menu, and several controls on the project tool bar. These controls are illustrated in Figure 7.

Figure 7. The project toolbar presents controls for running and
recording unit tests
We'll work with these controls shortly, while unit testing the
payroll application's SalesPerson class. Before doing
that, however, I need to talk about test classes.
BlueJ relies upon test classes for carrying out unit tests. Each
test class associates with a project class, called the reference
class, and contains one or more test methods that each carry out a
specific test on the reference class. In order to unit test
SalesPerson, we must create a test class for that
reference class.
Right-click SalesPerson and select Create Test
Class from the pop-up menu. In response, BlueJ creates the
SalesPersonTest test class (BlueJ names a test class
by combining the reference class's name with a Test
suffix), and attaches the test class's icon to the reference
class's icon; dragging the reference class's icon results in the
test class's icon dragging right along. Figure 8 reveals the
SalesPerson reference class and
SalesPersonTest test class icons.

Figure 8. Test classes are identified by <<unit
test>>, by the Test suffix, and by
color
A newly created test class contains no test methods. We
introduce a test method into a test class by selecting Create Test
Method from the test class's pop-up menu. For example, let's
introduce a method into SalesPersonTest that tests
SalesPerson's inherited public String
getName() method.
Right-click SalesPersonTest and select Create Test
Method from the pop-up menu. BlueJ displays a New Test Method
dialog box, as shown in Figure 9, into which you enter the test
method's name.

Figure 9. BlueJ prepends test to the entered method
name if that name does not start with test
After choosing a name and clicking OK, all further interaction with BlueJ is recorded as part of the test. The project toolbar's recording indicator turns red, and the buttons to end or cancel this recording are enabled.
Complete the following steps to record a test for
getName():
SalesPerson object: Right-click the
SalesPerson class icon and select the constructor from the pop-up
menu. From the Create Object dialog box, enter
SalesEast as the instance name, "John
Doe" as the name, 500.0 as the weekly salary,
50.0 as the commission, and 15 as the
number of sold products. A SalesEast object icon appears on the
object bench.getName() inherited method from the pop-up menu. A
Method Result dialog box appears."John Doe", we keep the default equal
to assertion. Close this dialog box and click the project
toolbar's End button to end the recording. If you screw up
somewhere during the recording, click the Cancel button to
discard the recording and try again.After recording ends, a test method is added to
SalesPersonTest for testing getName().
Assuming that BlueJ has automatically compiled the class--the
class will not be compiled if the assertion expression contains an
error or if the test class was manually edited--we can test
getName(), as follows: right-click SalesPersonTest and
select the Test Name menu item from the pop-up menu. If the test
succeeds, a brief note indicating success appears in the main
window's message area: testName succeeded, for this
test. But if the test fails, if we choose the Test All menu item
(to execute all test methods in SalesPersonTest), or
if we click the project toolbar's Run Tests button (to execute
all test methods in all test classes), a Test Results window
appears. Figure 10 reveals this window after I chose Test
All.

Figure 10. Test Results displays a green bar if all tests are
successful
Test Results displays a summary of testing outcomes:
Note: There is much more to unit testing than space permits here. I recommend checking out BlueJ's testing tutorial (see Resources [20]) to learn more about unit testing.
BlueJ is a configurable product. Various configuration options, such as the editor's use of syntax highlighting and the interface language (English, French, and so on), can be modified. Some modifications can be made in a user context; all modifications can be made in an administrator context. This section explores configuration in each context.
Each BlueJ user can configure BlueJ to their own requirements. BlueJ creates a separate configuration file for the user: <USER_HOME>/.bluej/bluej.properties (Unix) or <USER_HOME>\bluej\bluej.properties (Windows). <USER_HOME> represents the user's home directory, such as c:\winnt\profiles\<USER_NAME>\ (under Windows NT). This file stores options that have been modified via BlueJ's Preferences dialog box.
Activate Preferences by selecting Preferences from the main window's Tools menu, or by selecting Preferences from the editor window's Options menu. This dialog box appears in Figure 11.

Figure 11. Use the Preferences dialog box to configure user
options
The Preferences dialog box presents a tabbed interface with Editor, Miscellaneous, Libraries, and Extensions tabs. Use these tabs to configure a variety of options:
Note: BlueJ does not update bluej.properties until program exit.
It's also possible to configure BlueJ for all users by changing
<BLUEJ_HOME>/lib/bluej.defs. This configuration file
contains a list of properties in the format
property-name = value. The property
names should not be changed, but the values may be changed to alter
the configuration. You should make a backup of this file before
changing its contents.
There are many options that can be modified: interface language,
URLs for BlueJ manuals and documentation, fonts, and so on. For
example, to change the interface language from English to French,
comment out the line bluej.language=english (by
prepending a # character to that line) and uncomment
the line #bluej.language=french. Figure 12 reveals
BlueJ's main window with a French interface.

Figure 12. BlueJ supports thirteen interface languages
Note: Although all properties in bluej.defs apply to all users on the system, properties in a user's bluej.properties file override the equivalent properties in bluej.defs.
BlueJ is an extensible product. You can introduce new functionality not present in the core system by creating extensions, JAR files whose classes interact with BlueJ via BlueJ's Extensions API, or using extensions developed by others. Once you have an extension JAR file, you copy that JAR file into one of three locations, which determines the extension's scope:
After copying the extension's JAR file to the appropriate directory, start BlueJ. If the extension associates with a specific project, open that project. The extension installs. As you'll discover, extensions can add menu items to BlueJ's Tools menu, along with the pop-up menus associated with class and object icons. Extensions can also add new panels to the Extensions tab on the Preferences dialog box. They can even interact with BlueJ's editor to retrieve and modify the text in source files.
The BlueJ site [21] presents a number of prebuilt extensions, including an extension to automatically check coding styles, a sequence diagram editor, a remote file manager, an extension manager, a class evaluator, and a submitter. Of the various listed extensions, only the submitter extension is distributed with BlueJ.
The submitter extension makes it possible for course tutors to have students submit their work from within the BlueJ environment, for assistance or assessment. What gets submitted (Java source files only, class files plus source files, and so on), how the submission occurs (file copy, email, file transfer via FTP, and so on), and to whom the submission is sent to can be configured by the course tutor. All that the student needs to configure, by way of the Extensions tab on the Preferences dialog box, are the name of the SMTP server for submissions sent by email, the student's email address, and the student's username. Learn more about the submitter extension, by reading the article "The BlueJ Submitter Extension" (see Resources [20]).
At some point, you will probably want to create your own Java-based extension. The BlueJ site offers a helpful article in this regard, "Writing Extensions For BlueJ" (see Resources [20]). That article walks you through the task of creating a simple extension. A link to the Extensions API is also presented.
The previous BlueJ article generated lots of feedback regarding BlueJ inadequacies. I have decided to conclude this series by responding to some of that feedback.
How does learning to use BlueJ help the student learn Java? Although the student might become expert at interacting with BlueJ, that same student might be lost when having to work with Java in a command-line-driven environment or when confronted with another IDE because the student hasn't really learned Java.
I believe that BlueJ's simplicity helps a student learn Java. In my experience, students new to Java (or new to computer programming, in general) have a harder time learning Java in a command-line-driven environment than in an IDE. Furthermore, feature-rich IDEs may intimidate beginners. BlueJ's simplicity helps beginners focus more on Java, without having to devote lots of time to learning an IDE.
I also believe that BlueJ's visualization and interaction techniques help a student learn Java. BlueJ's class diagram provides students with the big picture: they quickly see how all (or most, assuming the presence of user libraries) of the pieces of a Java project fit together. They can then drill down into the source code, for study or modification, by double-clicking the appropriate icon. Furthermore, the code pad can help the student master the syntax and semantics of Java expressions and statements.
In a multi-year or a multi-semester course, BlueJ would nicely fit into the first year or semester. After that, the instructor could introduce students to Java's command-line tools, where the student would develop a better understanding of packages and classpath. Moving forward, the student could be introduced to a powerful IDE, such as Eclipse or NetBeans (assuming the teaching institution can afford the IDE), preparing that student for the workforce.
Class diagrams are inadequate (only two relationships can be expressed). Furthermore, the object bench does not show relationships between objects. BlueJ's visualization tools should take advantage of Unified Modelling Language (UML), rather than pretend to be UML.
How does one properly structure a course without overloading the beginner student? Should the beginner be given a complete UML treatment from day one (and be required to learn many diagram types), or should the beginner be gently introduced to UML through limited exposure? BlueJ limits exposure to UML by providing a UML-like experience without wading deeply into UML. In a multi-year or multi-semester course, it might be more effective to fully immerse the student in UML after the first year/semester.
Note: Regarding BlueJ's object bench, I encountered an interesting article suggesting that Microsoft has copied this BlueJ feature into its Visual Studio product, "Microsoft Goes BlueJ" (see Resources [20]). I also discovered a response to that article in a blog [22].
BlueJ provides quite a few features, such as debugging, documentation, executable JAR files, code pad, and unit testing, beyond those features explored in the previous article.
Although you can use the built-in debugger to locate bugs that are discovered during unit testing, you cannot automatically employ unit testing: you must first configure BlueJ to activate that feature.
In addition to configuring BlueJ (from user and administrator contexts) to somewhat change BlueJ's behavior, you can extend BlueJ to introduce new features that increase its usefulness. BlueJ's included submitter extension allows students to submit their work to course tutors.
My previous BlueJ article generated feedback that took issue with BlueJ. I hope you found my responses to some of that feedback enlightening.
I have some homework for you to accomplish:
Next time, Java Tech focuses on the generics language feature.
The previous Java Tech article [16] presented you with some challenging homework on BlueJ. Let's revisit that homework and investigate solutions.
FactoryWorker class that
subclasses Employee. Factory workers receive a payment
based on a fixed amount per item they create. For example, a worker
receives five dollars for each created item. If the worker creates
100 items in a week, the worker's payment is 500 dollars. Extend
RunPayroll to include FactoryWorker.
Consult the FactoryWorker.java and
RunPayroll.java source codes in this article's
attached code file (see Resources [20]).
Links:
[1] http://www.java.net/author/jeff-friesen
[2] http://www.java.net/article/2005/08/29/java-tech-sweet-song-bluej-part-2#more_bluej_features
[3] http://www.java.net/article/2005/08/29/java-tech-sweet-song-bluej-part-2#debugger
[4] http://www.java.net/%3Fpage%3D2%2523documentation
[5] http://www.java.net/%3Fpage%3D2%2523executable_jar_files
[6] http://www.java.net/%3Fpage%3D2%2523the_code_pad
[7] http://www.java.net/%3Fpage%3D3%2523unit_testing
[8] http://www.java.net/%3Fpage%3D4%2523configure_the_bird
[9] http://www.java.net/%3Fpage%3D4%2523user_configuration
[10] http://www.java.net/%3Fpage%3D4%2523administrator_configuration
[11] http://www.java.net/%3Fpage%3D4%2523extend_bluej
[12] http://www.java.net/%3Fpage%3D4%2523a_harsh_bluej
[13] http://www.java.net/%3Fpage%3D4%2523conclusion
[14] http://www.java.net/%3Fpage%3D4%2523resources
[15] http://www.java.net/%3Fpage%3D4%2523answers_to_previous
[16] http://today.java.net/pub/a/today/2005/07/21/bluej.html
[17] http://www.bluej.org/
[18] http://www.java.net/%3Ccs_comment
[19] http://www.junit.org
[20] http://www.java.net/article/2005/08/29/java-tech-sweet-song-bluej-part-2#resources
[21] http://www.bluej.org
[22] http://blogs.msdn.com/danielfe/archive/2005/06.aspx
[23] http://www.java.net/today/2005/08/30/code.zip
[24] http://www.bluej.org/vs/vs-bj.html
[25] http://www.bluej.org/extensions/submitter/submitter.html
[26] http://www.bluej.org/tutorial/testing-tutorial.pdf
[27] http://bluej.org/doc/writingextensions.html
[28] http://javajeff.mb.ca