Explore Java SE 6 Features
Contributed
and
maintained by
This hands-on lab takes you through the key features new in JavaSE 6,
the current major release of Java SE platform. Java SE 6 features and
enhancements to the platform are summarized in the Umbrella JSR(JSR 270)
The key features includes:
- XML & Web Services
- Scripting Language Support
- Desktop and Deployment
- Monitoring and Management
- Compiler Access
- Pluggable Annotations
- Java DB and Database Support
- Security
Yet, due to the limited time, the lab will focus on some of the
features listed above. In this lab, you will also learn how to use
Netbeans as your Java development environment.
Expected duration: 120 minutes
Prerequisites
This hands-on lab assumes you have some basic knowledge of, or
programming experience with, the following technologies.
- Java programming
- Some JavaScript exposure would be useful but not required
Software
Needed
Before you begin, you need to install the following software on your
computer.
- Java Standard Development Kit (JDK™) version 6 (download)
- If you already have installed JDK 6, you
can skip this.
- The name of the installation file is as following
- jdk-6-windows-i586-p.exe (Windows)
- jdk-6-linux-i586.bin (Linux)
- jdk-6-solaris-i586.sh (Solaris x86)
- jdk-6-solaris-amd64.sh (Solaris x64)
- NetBeans IDE 5.5 (download)
- Install either NetBeans IDE
5.5 or NetBeans IDE 5.5 with
JDK 6.0 Bundle
- 1510_javase6.zip (download)
- It contains this document and the lab contents
- Download it and unzip in a directory of your choice
OS platforms you can use
- Windows
- Solaris x86, Solaris Sparc
- Linux
Resources
Where to send questions or feedback's on this lab
If you have any questions or feedback on this lab, please send them
to the following email alias - please be advised that this alias is set
up for addressing issues/questions directly related to this lab not
for answering general Java SE 6 questions.
Lab Exercises
You will need an internet connection for Exercise 0 in which you will
do further installation and configuration. From Exercise 1, you
can
proceed without an internet connection.
Exercise 0: Install and Configure the Lab
Environment
In this exercise, we are going to use JDK
6 and Netbeans as our Java development environment. You are also going
to install JavaScript plug-ins for Netbeans. Make sure you have
downloaded and installed the software
mentioned above before
you start.
- Install JDK 6
- Install Netbeans 5.5
- Setting the PATH variable
- Install addtional NetBeans
module
(0.1)
Install JDK 6
In this step, you are going to install JDK 6 on Solaris x86 system.
1. Open a command line console. Move jdk-6-solaris-i586.sh to the
directory where you want to install JDK.
2. Type the name of JDK installation file to install, you may need to
chmod of it.
$ chmod +x jdk-6-solaris-i586.sh
$
./jdk-6-solaris-i586.sh |
3. You will be show the software license. Read through, hit
<space> to scroll. Type '
yes' to install or '
no' to exit.
. . . . . .
For inquiries please contact: Sun Microsystems, Inc., 4150
Network Circle, Santa Clara, California 95054, U.S.A.
Do you agree to the above license terms? [yes or no]
|
4. The JDK will create a directory call
jdk1.6.0
in your current directory and installs the the JDK in there.
(0.2)
Install Netbeans 5.5
1. Open a command line console, type in the name of the netbeans
installation file, again, you may need to chmod it. In the example
below, the name of the netbeans file
is '
netbeans-5_5-solaris-x86.bin'
$ chmod +x
netbeans-5_5-solaris-x86.bin
$ ./netbeans-5_5-solaris-x86.bin
|
2. You will see the NetBeans welcome screen. Click '
Next >'
to proceed.

Figure-0.20: Netbeans 5.5 welcome screen
3. Next comes the license screen. Click on '
I accept the terms in
the license agreement' if you agree with the license. Click '
Next >'
to proceed.

Figure-0.21: Netbeans 5.5 license information
4. Select the installation directory. Use the '
Browse' button to
browse to the location where you wish to install NetBeans. Click '
Next >' to proceed

Figure-0.22: Choose Netbeans 5.5 installation directory
5. Now select the JDK you wish to use NetBeans with. There may be
more than one version available as shown below. If your JDK is not
listed
in the 'List of suitable JDK' window, use the 'Browse' button to browse
to the
<JDK_6_Installation> directory
of the JDK. Click 'Next >' to proceed

Figure-0.23: Select JDK Home Directory
6. A confirmation screen will appear with the location of where
NetBeans 5.0 will be installed and the total disk space it will occupy.
Click '
Next >' to proceed to
the next screen.

Figure-0.24: Confirm Screen of installation information
7. NetBeans will now be installed

Figure-0.25: Netbeans installing screen
8. You have successfully installed NetBeans 5.0. Click on 'Finish' to
dismiss the screen

Figure-0.26: Netbeans installation finish screen
(0.3)
Setting PATH Variable
Add the following to your PATH variable
<Netbeans_Installation>/bin
<JDK_6_Installation>/bin
1. For Solaris/Linux system, type
the following. (assume you are using bash shell)
$ export
PATH=<Netbeans_Installation>/bin:<JDK_6_Installation>/bin:$PATH
|
Replace
<Netbeans_Installation>
and
<JDK_6_Installation>
with the respective directories.
2. For Windows
users, type the following
> set
PATH=<Netbeans_Installation>/bin;<JDK_6_Installation>/bin;%PATH%
|
Replace
<Netbeans_Installation>
and
<JDK_6_Installation>
with the respective directories.
(0.4)
Install addtional Netbeans module
In the this lab, we are going to use the management plugin and
javascript editor
plugin of Netbeans, here are the steps to follow in order to
install it.
1. Select Netbeans menu item '
Tools'->'
Update Center', you'll get the
update center wizard, select '
Check
the Web for Available Updates and New Modules', and select all
the update servers, click '
Next>'.
If you connect to internet through a proxy, click '
Proxy Configuration...' to set the
proxy.

Figure-0.40: Netbeans Update Center Wizard
2. Once connected to the update servers, Netbeans
lists all the available plugins/updates that haven't been installed on
your system yet. Select '
JMX',
click '
Add>' button, then
click '
Next>'
Figure-0.41: Select plugins you want to
install
3. After accept the agreement shown in the next screen, Netbeans starts
to install the plugin you just selected. When you're done, click '
Next>'
Figure-0.42: Installing plugin from
update center
4. Netbeans gives you a report on what plugins have
just been installed. Click 'Finish', Netbeans will automatically update
itself to apply the new installed plugins.
Figure-0.43: Report of plugins which
have just been installed
Now you should have the menu item '
Management'
on your menu bar. Now let's install the JavaScript Editor
5. This time, we install JavaScript Editor plugin from a module file of
netbeans plugin(.nbm) on the local disk. Select menu item '
Tools'->'
Update Center', select checkbox '
Install Manually Downloaded Modules',
click '
Next>'
Figure-0.44: Install netbeans plugin
from .nbm file
6. Add '
com-liguorien-jseditor.nbm'
to '
Modules to Install', the
.nbm file is located in
<Unzip_Labfile_Directory>,
click '
Next>'
Figure-0.45: Select the installation
file
7. The rest steps are exactly the same as
step 2
to
step 4
Exercise 1: Scripting Language Support
One of the often requested feature on
the Java platform is integration with the various scripts languages.
Script writers benefit from the vast Java libraries. They can now
develop powerful scripts quickly by making use of these libaries. Java
novices can use the script environment to learn about Java APIs and
test interactions between classes. This benefit is mutual. Java
applications can be made more flexible and extensible by allowing their
behaviour to be modified or functions to be extended by scripts.
There have been may projects on the
Internet to script java. Some of the notable ones include:
Java SE 6 now provides a scripting
framework. What the framework does is
that it allows Java to integrated with any scripting engine. This
integration is bi-directional. What this means is that not only can you
access Java classes from your favourite scripting environment, you can
invoke and export Java objects into scripts from within a Java program.
In this exercise, we will look at how you
can access Java classes from scripts, how you can access scripts from
Java code. Also we will see the usage of jrunscript script interpreter.
(1.1)
Using jrunscript
jrunscript is a script language
independent shell. jrunscript will default to JavaScript. You can
specify a different script through the '-l' option.
1. Open a terminal, set PATH variable as here
2. Change to
<Unzip_Labfile_Directory>/exerices/ex1/interactive_shell directory
3. Type 'jrunscript'(without the quotes)
to enter into the interative shell. You will see the following:
4. jrunscript initializes the script
engine with built-in functionsThese include simple file system utility
functions,
process utilities (exec, exit etc.), a few XML utilities and some
simple IO functions. See here
for a complete list. Try a few of these commands by following the
session below:
js> date
sun.org.mozilla.javascript.internal.InterpretedFunction@1787038
js> date()
January 15, 2007 3:34:22 PM CST
js> ls()
js> cat("test.txt")
hello world
js>
|
5. Creating a Java object. We will now
create a java.io.File object. Type in the following:
js> var file = new File("test.txt")
js>
|
6. You can access static and non-static
members (if any) from the object itself. Type in the following:
7. We can also access all public method
from a Java object. Try the following and also any other methods in File
class.
js> file.getName()
test.txt
js> file.canRead()
true
js> file.getAbsolutePath()
/export/home/joey/HOL/javase6/exercises/ex1/interactive_shell/test.txt
js>
|
8. JavaBean properties can be access by
dropping the the
'get' or 'is' from the method name. For example, getAbsolutePath() will
become absolutePath and isDirectory() becomes directory. Try the
following and also any other methods in File
class.
js> file.directory
false
js> file.absolutePath
/home/HOL/javase6/exercises/ex1/interactive_shell/test.txt
js>
|
9. You can examine a method's singnature
and overloads by entering the name of the method. In the following
example, we enter listFiles
to list out all the overloaded listFiles
methods:
js> file.listFiles
java.io.File[] listFiles(java.io.FileFilter)
java.io.File[] listFiles()
java.io.File[] listFiles(java.io.FilenameFilter)
js>
|
10. Another useful feature is the ability
to print out all methods
from a Java object using the for loop. In JavaScript we will use the
for/in loop. Type in the following:
js> for (method in file) {
println(method); }
exists
usableSpace
parentFile
mkdir
totalSpace
setExecutable
toString
canExecute
wait
setReadable
setReadOnly
getCanonicalPath
. . . . . .
|
11. Create a JFrame object from javax.swing package as shown
js> var frame = new JFrame("my
frame")
script error: sun.org.mozilla.javascript.internal.EcmaError:
ReferenceError: "JFrame" is not defined. (<STDIN>#1) in
<STDIN> at line number 1
js>
|
We have to import the javax.swing
package before using. However, importing packages in JavaScript (or
Rhino) is slightly different from Java. To import any package, you need
to preceed the package's name with the JavaScript variable call Packages.
Rhino also provides a JavaScript funtion call importPackage(). importPackage()
is similar to the import statement in Java. So if we wish
to import javax.swing, we
would have to type the following:
js>
importPackage(Packages.javax.swing)
js> var frame = new JFrame("my frame")
js> var button = new JButton("Press me")
js> var panel = new JPanel()
js> panel.add(button)
javax.swing.JButton[,0,0,0x0,invalid,alignmentX=0.0,alignmentY=0.5,border=javax.swing.plaf.BorderUIResource$CompoundBorderUIResource@1fee6fc,flags=296,maximumSize=,minimumSize=,preferredSize=,defaultIcon=,disabledIcon=,disabledSelectedIcon=,margin=javax.swing.plaf.InsetsUIResource[top=2,left=14,bottom=2,right=14],paintBorder=true,paintFocus=true,pressedIcon=,rolloverEnabled=true,rolloverIcon=,rolloverSelectedIcon=,selectedIcon=,text=Press
me,defaultCapable=true]
js> frame.add(panel,
"North")
js> frame.pack()
js>
frame.setVisible(true)
js>
|
At this a JFrame similar to the one shown
below will be displayed. The JFrame is not shown untill the
setVisible(true) method is called. This way of using JavaScript is very
useful in debugging Java code.

Figure-1.10: JFrame created by JavaScript through jrunscript
Note that the default imported Java
packages java.io, java.net and java.lang are NOT imported by default in
JavaScript.
12. Many of the Java APIs and
functionalities like event listeners
work with interfaces and threads. We can implement
Java interfaces using JavaScript. To implement a Java interface, we do
the following:
- Define a Java script object with function and properties whose
name matche the methods of the Java interface that we are implementing.
The Java script object takes the following form {propertyName: value}
- Create an object of the Java interface. Pass the JavaScript
object that we have created in the constructor
Here is an example of creating a thread.
Type in the following:
js>
importPackage(Packages.java.lang)
js> var runit = { run: function() { println("Running... "); } }
js> var run = Runnable(runit)
js> var thread = new Thread(run)
js> thread.start()
js> Running...
|
Try it yourself
Add an ActionListener to the
variable button
so that when presed, the listener should close the JFrame.
You can use the JFrame
and JButton
object created from the previous example.
13. The JavaScript environment that comes
with Java SE 6 comes with two additional JavaScript objects. They are jlist and jmap.
These are convenience holder objects for java.util.List and java.util.Map. Below
are examples of how you would use them. Type in the following:
js> var props =
jmap(System.properties)
js> println(props["java.class.path"])
/usr/jdk/instances/jdk1.6.0/lib/tools.jar:/usr/jdk/instances/jdk1.6.0/classes
js> importPackage(Packages.java.util)
js> var arrayList = new ArrayList(3)
js> arrayList.add("Java")
true
js> arrayList.add("SQL")
true
js> var list = jlist(arrayList)
js> println(list[0])
Java
js> println("length = " + list.length)
length = 2
js> println(list[2])
undefined
js>
|
14.
Type CTRL+D or exit(0)
to exit from jrunscript
(1.2)
Invoking JavaScripts from Java applications
The scripting API in Java SE 6 provides
classes for Java programs to load and execute scripts. Developers can
pass Java objects from the Java program into these scrpts; the scripts
can then manipulate these Java objects. This is a very useful feature.
Imagine we have a word processor that is written in Java. Using the
scripting features in Mustang, we can now build a framework into our
word processors so that new meun items can be add with scripts. One
good example fo this is StarOffice/OpenOffice.
The javax.script
package contains all the scripting classes. These classes provides the
following functionalities:
- Execution - executing a script
- Binding - exposing Java objects into the script environment
- Compilation - the script to be executed is compiled. More
efficient if the script is to be executed many times. However this is
not a mandatory feature, so you will need to check if compilation is
supported by the script engine
- Invocation - invoking a particular function in the script. This
is an optional feature.
Now we will look at how to invoke a
script programatically
1. Let's create a project in Netbeans
first. Launch Netbeans, select
menu 'File'->'New Project...', you'll get the
following frame:

Figure-1.20: Netbeans New Project frame
2. Select 'General' in 'Categories', and 'Java Application' in 'Projects', click 'Next>'
3. In the 'Name and Location'
step, specify Project Name as 'ScriptSample',
select 'Set as Main Project'
and 'Create Main Class'
checkboxes, accept the default configurations. Click 'Finish'

Figure-1.21: Netbeans Name and
Location frame for creating ScriptSample project
4. Netbeans has created a new project
named 'ScriptSample' and the
class named 'ScriptSample.Main'
for you. In the 'projects' tag on the left side, extend project 'ScriptSample'->'Source Packages'->'ScriptSample', then click 'Main.java', you will have the source
code of Main.java opened in the editor frame as below.

Figure-1.22: Source code of Main.java in ScriptSample project
5. Now let's try to launch JavaScripts
within Java code. First we are going to create an instance of
ScriptEngineManager. add the following code to the main() method
public static void
main(String[] args) {
ScriptEngineManager
manager = new ScriptEngineManager();
}
|
6. Lookup an instance of a script engine.
JavaScript is the default supported script engine. You could get a
specific script engine by either file extension, mime type or name.
public static void
main(String[] args) {
ScriptEngineManager manager = new
ScriptEngineManager();
ScriptEngine
engine = manager.getEngineByName("js");
}
|
7. Use various eval() overloads,
you can launch javascript within the java code. add the following code
to the main() method.
ScriptEngineManager manager
= new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("js");
try {
engine.eval(new
FileReader("<Unzip_Labfile_Directory>/exercises/ex1/myscript.js"));
} catch
(FileNotFoundException ex) {
ex.printStackTrace();
} catch (ScriptException ex)
{
ex.printStackTrace();
}
|
Replace <Unzip_Labfile_Directory>
with the actually directory you unzip the lab file. Here we launch a
very simple javascript myscript.js as below
8. Launch ScriptSample.Main by either
selecting menu item 'Run'->'Run Main Project' or clicking 'Run Main
Project' button on the toolbar. You'll get the follow output in the
output window at the bottom.

Figure-1.23: Output for evaluating myscript.js
You'll see the output is 'undefined',
since in myscript.js, we just print out the now variable which is
undefined yet.
9. Expose Java objects into the
scripting script. In the following code snippet, we bind the name 'now' to a java.util.Date object. The script
will be able to access the Date
object as variable 'now' in
scripts. Add the following code in main() method
ScriptEngineManager manager
= new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("js");
try {
SimpleBindings bindings = new SimpleBindings();
//Create
a Date object
Date date
= new Date();
//Bind
date to now
bindings.put("now", date);
engine.eval(new
FileReader("/export/home/joey/HOL/javase6/exercises/ex1/myscript.js"));
} catch (FileNotFoundException ex) {
|
10. Create a binding that is
automatically visible to every script executed by the engine.
SimpleBindings bindings =
new SimpleBindings();
//Create a Date object
Date date = new Date();
//Bind date to now
bindings.put("now", date);
engine.put("now", new
Date());
//"now" will be visible when
myscript.js is executed
engine.eval(new
FileReader("/export/home/joey/HOL/javase6/exercises/ex1/myscript.js"));
|
11. Launch ScriptSample.Main by either
selecting menu item 'Run'->'Run
Main Project' or clicking 'Run Main Project' button on the toolbar.
You'll get the follow output in the output window at the bottom.

Figure-1.24: Output of ScriptSample
Now, you'll see that altought we didn't
change any code of myscript, the Date instance has been bound to the 'now' variable in the script.
(1.3)
Integrating scripts into your Java application
1. Open script_integration
project in Netbeans. script_integration
is located under <Unzip_Labfile_Directory>/exercises/ex1.
- First we will get an instance of JavaScript
engine and run a simple hello world JavaScript.Open RunHelloScript.java
under integratejs
package. Open the ToDo
window by selecting menu item 'Window'->'To Do'.
- 3. Create an instance of the scripting manager. Double click on
'//TODO Create an instance of script
engine manager' and type the
following
//TODO Create an instance
of script engine manager
ScriptEngineManager
manager = new ScriptEngineManager(); |
- Request an instance of JavaScript engine from the script
manager. Doublie click on '//TODO Get
an instance of the JavaScript
script engine' and type the following
//TODO Get an instance of
the JavaScript script
engine
ScriptEngine engine =
manager.getEngineByName("js");
|
- The helper class JavaScriptLoader.loadScript()
will help
us load the approriate JavaScript required by the exercise. If you are
interested in looking at JavaScriptLoader
class, it is located
in <Unzip_Labfile_Directory>/exercises/ex2/script_integration/src/jsutil
directory.
- loadScript() method
will return the full path of the JavaScript
file. We will pass this to the script engine to be executed. Double
click on '//TODO Executes the script'
and type the following
//TODO Executes the script
engine.eval(new
FileReader(fn));
|
- Now execute the RunHelloScript
file. Right click on RunHelloScript.java
and seelct Run File in the
context menu.You will
see the following JavaScript loader dialog
- Navigate
to <Unzip_Labfile_Directory>/exercises/ex1/script_integration/src/js.
Click
on 'hello.js'
and click 'Open', you'll see
'hello world' is printed in the output as following:
2. Now
we will create a JFrame
with a single JButton.
We will then install an event handler for the button in
JavaScript.
- Open RunBindingsScript
under integratejs
package. Open the ToDo window.
- Do it
yourself
Double click on '//TODO Get an instance of JavaScript engine' in the To
Do window. Add some code to get instance of JavaScript script engine.
- We will now create a script binding object. Double click on
'//TODO Create a script binding object'.
Type the following
//TODO Create a script
binding object
SimpleBindings bindings =
new SimpleBindings();
|
- Bind the name "FRAME"
to RunBindingsScript object. Double click
on '//TODO Bind this object to FRAME'.
Type the following
//TODO Bind this object to
FRAME
bindings.put("FRAME", this);
engine.setBindings(bindings,
ScriptContext.ENGINE_SCOPE);
|
Assume that
engine
is the name of your script engine that you have created previously. If
that is not the name of your script engine, then change the variable
engine
to your script engine variable name
- Do it
yourself
Double click on '//TODO Evaluate the script' in the To Do window. Add
in
some code to evalute the returned JavaScript file. The name of the
JavaScript file is in fn.
- Now we will invoke a method call 'registerListener'
from the JavaScript to handle the button pressed. Double click on
'//TODO Invoke the registerListener
function' and type the following
//TODO Invoke the
registerListener function
if (!(engine instanceof
Invocable)) {
JOptionPane.showMessageDialog(this, "The " +
engine.getFactory().getEngineName()
+ " script engine does not support the Invocable interface.\nCannot
register listener"
, "Cannot register", JOptionPane.ERROR_MESSAGE);
return;
}
try {
Invocable
inv = (Invocable)engine;
inv.invokeFunction("registerListener", (Object)null);
} catch (Exception e) {
JOptionPane.showMessageDialog(this, e, "Exception",
JOptionPane.ERROR_MESSAGE);
}
|
- Open bindings.js
in the editor by double clicking on bindings.js
node. bindings.js
is located under js
package. The bindings.jsis an
empty file. Now type the following in the file
importPackage(Packages.java.awt);
importPackage(Packages.java.awt.event);
function registerListener() {
FRAME.addActionListener(listener);
}
function unregisterListener() {
FRAME.removeActionListener(listener);
}
var action = { actionPerformed:
function(aEvt) {
print ("Event handled from
JavaScript");
var button = aEvt.source;
if (button.foreground ==
Color.BLUE) {
button.setForeground(Color.RED);
button.setText("Pressed");
} else {
button.setForeground(Color.BLUE);
button.setText("Press Me");
}
}
}
var listener = new ActionListener(action);
|
- Now run the RunBindingsScript.java
file. When the
JavaScript loader dialog box opens, select bindings.js
from <Unzip_Labfile_Directory>/exercises/ex2/script_integration/src/js
- A frame with a button
will appear. When you press on the
button, the text and text color will change to 'Pressed' and red
respectively. See below for a screen shot
- Close the frame to exit the application.
Summary
Java scripting supports really opens up the Java platform to developers
who do not know Java but want to use the vast libraries that the Java
platform offers. Java also benefits from scripting byallowing
developers to extend the Java platform and applications with scripts.
Exercise 2: Desktop Feature Enhancement
(2.1)
Desktop Integration
The Desktop API allows a Java
application to launch associated
applications registered on the native desktop to handle a URI or
a
file. The Desktop class supports the following operations:
- Launching the default browser
- Launching the default email client
- Launching the default application to handle file open, file
edit and file print
Here are some pointers on using the Desktop API
1. Let's create a project in Netbeans first. Launch Netbeans, select
menu 'File'->'New Project...', you'll get the following frame:

Figure-2.10: Netbeans New Project frame
2. Select '
General' in '
Categories', and '
Java Application' in '
Projects', click '
Next>'
3. In the '
Name and Location'
step, specify Project Name as '
Desktop',
select '
Set as Main Project'
and '
Create Main Class'
checkboxes, accept the default configurations. Click '
Finish'

Figure-2.11: Name and Location step for creating a new project with
Netbeans
4. Netbeans has created a new project named '
Desktop' and a class named '
Desktop.Main' for you. In the
'projects' tag on the left side, extend project '
Desktop'->'
Source Packages'->'
Desktop', then click '
Main.java', you will have the source
code of Main.java opened in the editor frame as below.

Figure-2.12: Open Desktop.Main source code in Netbeans
5. Now, we're going to use the Desktop API in Main.java. First, we need
to check if the Desktop API is support on a particular operating
system. Add the following code in the main() method of Main.java.
(Modified code is highlighted in red)
public static void
main(String[] args) {
if
(!Desktop.isDesktopSupported()) {
System.err.println("Your operating system does not support Desktop
API");
System.exit(-1);
}
} |
6. Next, we need to get an instance of Desktop if it is supported. Add
the follow code as being highlighted in red
if
(!Desktop.isDesktopSupported()) {
System.err.println("Your operating system does not
support Desktop API");
System.exit(-1);
}
Desktop desktop =
Desktop.getDesktop();
|
7. Using the following code to check if a particular operation is
supported
Desktop desktop =
Desktop.getDesktop();
if
(!desktop.isSupported(Desktop.Action.PRINT)) {
System.err.println("It appears that your desktop does not support the
print operation");
}
|
Other operations include Desktop.Action.BROWSE, Desktop.Action.MAIL,
Desktop.Action.EDIT, Desktop.Action.OPEN. All the operations which
could be supported by the desktop API can be found
here
8. Now let's launch the default mail client with a target email
address. Add the code to the main() method as following.
if
(!desktop.isSupported(Desktop.Action.PRINT)) {
System.err.println("It appears that your desktop
does not support the print operation");
}
if
(desktop.isSupported(Desktop.Action.MAIL)) {
try {
desktop.mail(new URI("mailto:handsonlabs-javase6@yahoogroups.com"));
} catch (IOException ex) {
ex.printStackTrace();
} catch (URISyntaxException ex) {
ex.printStackTrace();
}
}
|
9. Launch the Desktop project by selecting menu item '
Run'->'
Run Main Project', or clicking the '
Run Main Project' button on the tool
bar. You'll see your system default mailer to be opened with the email
address filled. For Windows platform, it could be Outlook; for Solaris
and Linux, it could be Evolution or ThunderBird as shown below:

Figure-2.13: System default mail launched by Desktop API
Try it yourself
Add code to the sample code above to open a webpage with system default
browser.
(2.2)
Splash Screen Support
Splash screens are the log that you see
when an application starts up. When you start NetBeans for this lab,
you may have noticed an orange window appears with the NetBeans icon
display and a progress bar at the bottom indicating the progress of the
startup. Prior to Java SE 6, a developer who wishes to create splash
screens for their Java application have to create a JWindow component,
then manually load the image.
Java SE 6 changed all this with splah screen support. You specify which
image you want to use as your splash screen, and Java SE 6 will do the
rest. There are two ways of specify the splash screen. Let's try them
both.
1. When launching your Java application, you can specify the splash
screen by command line
java
-splash:<splash screen image>. Now we are going to add a
splash creen to the jdk demos.
2. Open a terminal, set PATH variable as
here
3. Change the directory to <Unzip_Labfile_Directory>/exerices/ex2
4. Type the following
| $ java -splash:splash.jpg -jar <JDK_6_Installation>/demo/jfc/FileChooserDemo/FileChooserDemo.jar |
You will see that splash.jpg shows before the FileChooserDemo is
launched.
5. Also, if you want to
pack your application as a jar file, put the following properteies in
the MANIFEST.MF will set the splash screen to your application
Manifest-Version: 1.0
Main-Class: org.foo.MyApplication
SplashScreen-Image: splash.gif |
Some times, you need to decorate the splash screen, like using the
progress bar, updating text. The SplashScreen API provides additional
methods for
decorating the splash screen with additional text or animations. Now
let's add a splash screen to Netbeans sample application-Anagram Game.
6. Launch your Netbeans, select Menu '
File'->'
New Project', you will get the
'Choose Project' screen. As following, select '
Sample'->'
General' in the '
Categories' table, '
Anagram Game' in the 'Projects'
table, then click '
Next>'

Figure-2.20: Netbeans 'Choose Project' Screen
7. Accept the default setting of project location, or put the new
created project to the location as you wish, click '
Finish'

Figure-2.21: Netbeans 'Name and Location' Screen
8. In the 'projects' tag on the left side, extend project '
Anagram Game'->'
Source Packages'->'
com.toy.anagrams.ui', then click '
Anagrams.java', you will get the
Netbeans GUI
Builder Matisse's design view as below

Deselect Show
Figure-2.23: Matisse design view for Anagram Game
9. Click the 'Source' button on top of the design view frame, switch to
the source code.

Figure 2.24: Soure code of Anagram Game project
10. Let the program sleep 10 seconds before the UI starts, so that
there will be enough time for the splash screen show up. Add the
following code(
in red) to
the main() method
public static void
main(String[] args) {
try {
Thread.sleep(10000);
} catch
(InterruptedException ex) {
ex.printStackTrace();
}
new Anagrams().setVisible(true);
}
|
11. Now, use Netbeans to launch the application, and set the splash
screen. In the project tag, right click at '
AnagramGame', select '
Properties' from the context menu.
You'll get the '
Project Properties'
dialog for Anagram Game as shown below. Select '
Run', fill the '
VM Options' by '
-splash:<Unzip_Labfile_Directory>/exercises/ex2/splash.jpg'
(replace <Unizp_Labfile_Directory> with the directory path you
actually unzip the lab file).

Figure-2.25: Project Properties dialog of Anagram Game project
8. Select menu item 'Run'->'Run Main Project' or click the 'Run Main
Project' button on the tool bar to launch the Anagram Game you created.
Now you'll see the splash screen lasts for 10 seconds before the UI of
Anagram Game actually shows up.

Figure-2.26: Splash screen for Anagram Game without any prompt
information
9. Now let's add some text to the splash screen, so that the users
would have some ideas of what's going on before they get to see the
application. First, we need to get the instance of the splash screen.
Add the following code to the main() method of Anagram Game as below.
(Modified code is highlighted in red)
try {
SplashScreen
splash = SplashScreen.getSplashScreen();
Thread.sleep(10000);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
|
10. Then get the Graphics or Graphic2D instance from the splash screen.
Add the following code to the main() method as below. (Modified code is
highlighted in red)
try {
SplashScreen splash = SplashScreen.getSplashScreen();
Graphics2D g =
splash.createGraphics();
Thread.sleep(10000);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
|
11. Now, with the Graphics2D context, you could add some prompt text to
the splash screen, or do more complicated rendering as you wish. Add
the following code to the main() method as below. (Modified code is
highlighted in red)
try {
SplashScreen splash = SplashScreen.getSplashScreen();
Graphics2D g = splash.createGraphics();
g.setColor(Color.RED);
g.drawString("Anagram Game v1.1 starting...", 20, 20);
splash.update();
Thread.sleep(10000);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
|
12. Select menu item 'Run'->'Run Main Project' or click the 'Run
Main Project' button on the tool bar to launch project Anagram Game
again, you'll see now there's some prompt text on the top left of the
screen.

Figure-2.27: Splash Screen with prompt text on the top left
(2.3)
Tray Icon
A tray icon is an icon that is
added to the system tray when the representing application is running.
Most modern operating system supports this
type of application. Typical tray icon applications includes weather,
RSS, email notifications, etc. Until recently, it is quite difficult to
create Java based tray
icons applications. Java SE 6 now supports tray icon development with
the
TrayIcon API.
Now let's add a Tray Icon for the anagram game project we created in
exercise 2.2.
1. First, we need to check if Tray Icon is supported on your platform.
Add the following code to the main() method of Anagrams.java class we
created in exercise 2.2. (Modified code is highlighted in red)
. . . . . .
new Anagrams().setVisible(true);
if
(SystemTray.isSupported()) {
}
|
2. Next, get the System Tray Instance,
if it is supported.
if
(SystemTray.isSupported()) {
SystemTray
tray = SystemTray.getSystemTray();
}
|
3. Now, we are going to create a TrayIcon representing Anagram Game. A
TrayIcon object represents a
tray icon that can be added to the
system
tray A
TrayIcon can have a tooltip (text), an image, a popup menu, and a set
of listeners associated with it. First, let's create the image and
popup menu. Add the following code to the main() method.
if
(SystemTray.isSupported()) {
SystemTray tray = SystemTray.getSystemTray();
Image
trayImg =
Toolkit.getDefaultToolkit().getImage("/usr/share/pixmaps/webeyes.png");
PopupMenu
popup = new PopupMenu();
MenuItem
defaultItem = new MenuItem("Exit");
defaultItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
});
popup.add(defaultItem); |
Here, out popup menu only has one menu item to do exit, you may add
more items to the popup menu by yourself. We suppose that you're
working on a Solaris 10 X86 platform, so that you could find
webeyes.png in the specific directory, if not, please specify the image
you want to set for your TrayIcon.
4. Then we need to reate a TrayIcon object with the image, popup menu
created above, and set tooltip at the meanwhile. Set the image autosize
to true, so that the image shows on the task bar will be autosized
according to the panel it is located at. Add the following code.
popup.add(defaultItem);
TrayIcon anagramIcon = new
TrayIcon(trayImg, "Anagram Game", popup);
anagramIcon.setImageAutoSize(true);
try {
tray.add(anagramIcon);
} catch (AWTException ex) {
ex.printStackTrace();
}
|
5. Launch the anagram game by selecting Netbeans menu item '
Run'->'
Run Main Project' or clicking the
'Run Main Project' button on the toolbar. You will now see, when the
anagram game is launched, there's a icon located at the status bar of
your desktop. Move your mouse into the icon, you'll get the tooltip.
Right click the icon, you'll get the popup menu, which contains the
exit menu item.
Summary
In this exercise, you have learned the
desktop feature enhancements of Java SE 6, including Desktop
Integration, Splash Screen and Tray Icon.
return to the top
Exercise 3: Writing and Processing Custom
Annotations
Note:
This exercise is based on ideas
developed by Kohsuke Kawaguchi
on args4j.
You can find his original blog on args4j here
Annotations is one of the new features that was introduced to
the Java.
Annotations allows you to annotate or mark all or parts of you Java
classes with information that can be used by tools to generate other
wrapper or utility classes, configure database resources or perhaps
just embedding information lice copyright, license or the author's name
in the class file. Annotations will be used extensively in
EJB 3 and JavaEE 5 to help simplify the platform.
In this exercise we will learn the following
- Write custom annotations
- Process our custom annotations
(3.1)
Need to know
Most of the Java applications that we develop require us to set some
options at the command line like so:
java org.fred.MyJavaApp -filename
myfile.txt -config config.properties
|
where
-filename and
-config
are options for
MyJavaApp.
However parsing commad line options, though simple, is laborious and
boring. In this exercise we are going to use annotations to help use
automatically generate an options processor to parse the command line
options. Here is what we are going to do:
1. This is the command line, with the options that we are going to
process:
| java
org.fred.MyJavaApp -filename myfile.txt -config config.properties
-server myserver |
2. Assume that we are going to parse
-filename
-config
and
-server
option in your Java application. Write a Java class with 3 public
members of type String, each corresponding to a parameter like so
public
class MyOptions {
public String fileName
public String configFile;
public String server;
} |
We will refere to
MyOptions as
an
option bean
3. We now map each of these fields to the option switch by our
custom annotation call
option.option
has one field call name which is used to indicate the command line
switch that we are
interested in. We annotate
MyOptions
like so:
public
class MyOptions {
@Option(name="-filename")
public String fileName
@Option(name="-config")
public String configFile;
@Option(name="-server")
public String server;
} |
The
Option
now maps the values of the option to a field; for example, the value of
-filename
switch, the value
myfile.txt
in the above example, will be assigned to
fileName
member.
4.
MyOption class
will be compiled with our custom options processor:
| javac -d classes -processor
options.OptionProcessor
MyOptions.java |
options.OptionsProcessor is our
custom options processor.
5. OptionsProcessor will
generate a class call
MyOptionsProcessor
which will be used to process our 3 option switches. MyOptionsProcessor
has a static method call
process()
which takes in the command line options that we which to process. It
then returns an instance of
MyOptions
will all its fields populated with values from the switches. The
process()
method has the following signature:
| public static MyOptions
process(String[] args) |
The name of the processor class and the return type of
process()
is dependent on the option bean class. If the option bean class is call
SuperDuperOptions,
then the processor class will be called
SuperDuperOptionsProcessor
and
process() will now return
an instance of
SuperDuperOptions.
6. You can now use
MyOptionsProcessor
in your application like so:
public
static void main(String[] args) {
MyOptions opts = MyOptionsProcessor.process(args);
//Do something with the options
.... |
7. Limitations: the following are some features that we will not be
considering in this exercise
- No error checking
- Can only annotate String members
- Can only work with option beans in the default package
- Will only process options with the following format: option_name option_value;
for example -filename myfile.txt
(3.2)
Steps to follow
Open args_processing project.
This project can be found under
<Unzip_Labfile_Directory>/exercises/ex3.
1. Develop a custom annotation called Option
- Right click 'args_processing'
node in the 'Projects' tab
window on the leftside. Select 'New'->'File/Folder...' in the context menu.
- Choose 'Java Classes'
in 'Categories' list. Choose 'Java Annotation Type' in 'File Types' list, click 'Next>'
- Set name as 'Option',
package as 'options', click 'Finish'
- Now Option.java is opened in Netbeans editor, modify the code
as following
package options;
import
java.lang.annotation.*;
@Retention(value=RetentionPolicy.SOURCE)
@Target(ElementType.FIELD)
public @interface Option {
String name();
}
|
The Option annotation has one field call
name.
The annotation is only used to annotate fields (indicated by
@Target(
ElementType.
FIELD)
and will only be visible in the source (indicated by
@Retention(
RetentionPolicy.
SOURCE).
2. Develop the annotation processor
- Open OptionProcessor.java in Netbeans editor by double clicking
'OptionProcessor.java' under 'args_processing'->'Source Packages'->'option'
- Open ToDo window by selecting Netbeans menu item 'Window'->'To Do'
- The AbstractProcessor
class provides support for developing annotation processor. Double
click on '//TODO extends AbstractProcessor' and type the following
public class
OptionProcessor extends
AbstractProcessor
|
NetBeans will highlight the class OptionProcessor in red complain about
methods not implemented, ignore this error for now.
- AbstractProcessor requires
two pieces of information; the first is the list of annotations
that this processor will process and the second piece of information is
the Java source version that we will support. In our case, the source
will be 1.5 onwards and the fully qualified class name of the option
will be 'option.Option'. Double
click on '//TODO Add annotation types
and source version' in the ToDo
window and type the following:
@SupportedAnnotationTypes({"options.Option"})
@SupportedSourceVersion(SourceVersion.RELEASE_6)
public class OptionProcessor extends AbstractProcessor
|
- The second method that we are going to implement is the process()
method. The method has the following
signature:
public boolean
process(Set<? extends TypeElement> annotations, RoundEnvironment
roundEnv);
|
Here is an explanation of the parameters and return values:
Parameters:
annotations - the annotation types
requested to be processed
roundEnv - environment for information about the current and prior round
Returns
whether or not the set of annotations
are claimed by this processor
- Double click on '//TODO add
process() method' in the ToDo
window and type the following:
public boolean
process(Set<? extends TypeElement> annotations, RoundEnvironment
roundEnv) {
Messager messager = processingEnv.getMessager();
values = new HashMap<String, String>();
//Loop through the annotations that we are going to
process
//In this case there should only be one: Option
for (TypeElement te: annotations) {
//Get the members that are
annotated with Option
for (Element e:
roundEnv.getElementsAnnotatedWith(te))
//Process the members
processAnnotation(e, messager);
}
if (values.size() > 0)
try {
//Generate the option process class
generateOptionProcessor(processingEnv.getFiler());
} catch (Exception e) {
messager.printMessage(Diagnostic.Kind.ERROR, e.getMessage());
}
return (true);
}
|
After type (or pasting) the code into
OptionProcessor
class, NetBeans may compain of missing class. Fix this by importing the
appropriate packages.
The member
processingEnv,
of type
ProcessingEnvironment,
is a member inherited from AbstractProcessor.processingEnv
provides access to the processing environment. In the process method,
we see that we are requesting a
Messager
from processingEnv.
A
Messager
is used by the annotation processing to report errors, warning and
other messages.
- After you have fixed the imports, there should only be 1 error
left; this is the processAnnotation()
method. Double click on '//TODO add
processAnnotation() method' and
type the following:
private
void processAnnotation(Element element, Messager msg) {
//Get the Option annotation on the member
Option opt = element.getAnnotation(Option.class);
//Get the class name of the option bean
className = element.getEnclosingElement().toString();
//Check if the type in the member is a String. If not we igonre it
if (!element.asType().toString().equals(String.class.getName())) {
msg.printMessage(Diagnostic.Kind.WARNING
, element.asType() + " not
supported. " + opt.name() + " not processed");
return;
}
//Save the option switch and the member's name in a hash set
//Eg. -filename (option switch) mapped to fileName (member)
values.put(opt.name(), element.getSimpleName().toString());
} |
- generateOptionProcessor
is the code generator. After we have processed all the options, we use
this method to generate the options processor class.
3. Packaging the processor
- Right click on Source Packages
directory select File/Folder.
Scroll to Other under the Categories window. Select Folder from File Types.
- Click Next to proceed.
In the Folder Name text field,
enter the following folder name 'META-INF/services',
click 'Finish'
- META-INF/services directory will now
be created. This is shown as a package in the Projects window.
- Now right click on the services directory and create a file
call javax.annotation.processing.Processor.
You can create an empty file from the Other
category as above.
- Double click to open the javax.annotation.processing.Processor file
and type in the fully qualified class name of our options processor 'options.OptionProcessor'
- Your should now get the following:
- Build the args_processing
project by selecting Netbeans menu item 'Build'->'Build Main Project', if it is
currently NOT the main
project, right click 'args_processing',
select 'Set Main Project'.
4. Testing the annotation processor
- Open the test_option
project under <lab_home>/exercises/ex3
directory
- Fix any reported reference problem
- Adding the option processor jars to this project
- Right click on test_option
project node and select Properties
- Select Libraries
when
the properites dialog is displayed
- Click 'Add Project...'
- When the Add Project dialog is displayed, select
args_processing
project. If you do not see args_processing project displayed, navigate
to <Unzip_Labfile_Directory>/exercises/ex3
directory
- Click on 'Add Project JAR
Files', you should see as following
- If the args_processing.jar
file is not found, it means that you have not build the args_processing project. Go back here to build the project before
continuing.
- Right click 'test_option'
node in the Projects tab window, select 'New'->'Java Class...' in the
context menu
- Set 'Class Name' as 'MyOptions', leave the 'Package' as default package
- Modify MyOptions.java as following:
import options.Option;
public class MyOptions {
@Option(name="-file")
public
String fileName;
@Option(name="-server")
public
String server;
@Option(name="-config")
public
String configFile;
}
|
- Create a class call Main
under the default package. Modify it as the following code:
public class Main {
public
static void main(String[] args) {
//MyOptionsProcessor will be generated by OptionProcessor
MyOptions options = MyOptionsProcessor.process(args);
System.out.println("filename = " + options.fileName);
System.out.println("server = " + options.server);
System.out.println("config = " + options.configFile);
}
}
|
- Right click on the test_option
package node and build the project. The project will now be compile
with our option processor. You should see the following output:
- The following file call MyOptionProcessor.java
will be generated. This file is found in <Unzip_Labfile_Directory>/exercises/ex3/test_option/build/classes
directory
/* Generated on Thu Jan 25
00:11:56 CST 2007 */
public class MyOptionsProcessor {
public static MyOptions process(String[] args) {
MyOptions options = new
MyOptions();
int idx = 0;
while (idx < args.length) {
if
(args[idx].equals("-file")) {
options.fileName = args[++idx];
idx++;
continue;
}
if
(args[idx].equals("-server")) {
options.server = args[++idx];
idx++;
continue;
}
if
(args[idx].equals("-config")) {
options.configFile = args[++idx];
idx++;
continue;
}
System.err.println("Unknown option: " + args[idx++]);
}
return (options);
}
}
|
- Now we need to enter the option -file, -server
and/or -config
in the command line when we execute Main.
Right click on test_option
package node and select Properties
again.
- Select the Run node and type the following
- Main Class: type in Main
- Arguments: -file
somefile.txt -server myserver.com:8080 -config myconfig.properties
- Right click 'test_option',
run the project again, you'll now see the arguments printed in the
output as following:
Summary
In this exercise, you have exercised various features of "FireBug"
debugger. You also learned how to use HTTP POST method instead of
HTTP GET method.
Exercise 4: Java Management
eXtentions(JMX) Enhancement
Java SE 6 introduces numerous JMX
enhancements.
This lab consists of the following exercises:
(4.1)
Writing MXBeans
MXBeans provide a convenient way to
bundle related values together in an MBean without requiring clients to
be specially configured to handle the bundles when interacting with
that MBean. This is an incremental change, because MXBeans already
existed in J2SE 5.0, in the package
java.lang.management. What's new is that users can now define their
own MXBeans, in addition to the standard set defined in
java.lang.management.
The key idea behind MXBeans is that types
such as java.lang.management.MemoryUsage
that are referenced in the MXBean interface,
java.lang.management.MemoryMXBean in this case, get mapped
into a standard set of types, the so-called Open Types that are defined
in the package javax.management.openmbean. The exact mapping rules
appear in the MXBean specification, but to oversimplify we could say
that simple types like int or String are unchanged, while complex types
like MemoryUsage get mapped to the standard type CompositeDataSupport.
In this particular case, we are going to
use both MBean and MXBean to take snapshot for a resource of type
Queue<String>, so that we could see the advantage of MXBean in
handling bundled values.
1. Open MXBean
NetBeans project.
- Select 'File'->'Open Project'. The Open Project dialog box appears.
- Browse down to <Unzip_Labfile_Directory>/exercises/ex4
directory.
- Select MXBean
- Click Open Project Folder.
The MXBean
project node appears under Projects tab
window.
2. Extend MXBean project in the
'Projects' tab window, exend 'Source
Packages'->'mxbeans',
double click 'Main.java', and
the source code of Main.java
is now opened in the source editor window of Netbeans as following
package mxbean;
import java.util.Queue;
import java.util.concurrent.ArrayBlockingQueue;
public class Main {
public Main() {
}
public static void main(String[] args) {
Queue<String> queue =
new ArrayBlockingQueue<String>(10);
queue.add("Request-1");
queue.add("Request-2");
queue.add("Request-3");
// Wait forever
System.out.println("Waiting...");
try {
Thread.sleep(Long.MAX_VALUE);
} catch
(InterruptedException ex) {
ex.printStackTrace();
}
}
}
|
3. In case we're going to take snapshot
for the Queue, we need a QueueInfo class representing the snapshot.
- Right click 'MXBean'
project in the projects tab window.
- Select 'New'->'Java Class...' in the context menu.
- Set 'Class Name' as 'QueueInfo', and Package as 'mxbean'
- Add the following code to the created QueueInfo.java
package mxbean;
import java.util.Date;
public class QuequeInfo {
private
final Date timestamp;
private
final int size;
private
final String head;
/** Creates a new instance of QuequeInfo */
public QuequeInfo(Date now, int qsize, String qhead)
{
timestamp = now;
size = qsize;
head = qhead;
}
public
Date getTimestamp() {
return timestamp;
}
public
int getSize() {
return size;
}
public
String getHead() {
return head;
}
}
|
4. Now, we need to create a Standard
MBean to see if you can monitor the Queue by taking snapshot, and do
clear for the Queue.
- Right click 'MXBean'
project in the projects tab window.
- Select 'New'->'File/Folder...' in the context menu.
- Select 'Management' in
the 'Categories' table, 'JMX MBeans' in the 'File Types' table, click 'Next>'
- Set 'Class Name' as 'QueueSampler', 'Package' as 'mxbean', click 'Next>'
- Select 'Standard MBean',
click 'Next>'
- In the 'Specify Attributes'
step, since we don't have primary type attributes, so directly click 'Next>'
- In the 'Specify Operations'
step, set clearQueue() as the
following
- Skip the 'Implement
Notification Emitter Interface' by directly clicking 'Next>', in 'Specify JUnit Test' step click 'Finish'
5. Netbeans created two Java files for
you: the MBean interface named 'QueueSamplerMBean'
and the MBean implementation named 'QueueSampler'.
add the following code to the QueueSamplerMBean.java
package mxbean;
/**
* Interface QueueSamplerMBean
* QueueSampler Description
* @author root
*/
public interface QueueSamplerMBean
{
public
QueueInfo getQueueInfo();
/**
* newOperation0 Description
*/
public void clearQueue();
}
|
6. Now, we are going to implement the
MBean interface, modify QueueSampler.java as following
package mxbean;
import java.util.Date;
import java.util.Queue;
import javax.management.*;
/**
* Class QueueSampler
* QueueSampler Description
* @author root
*/
public class QueueSampler implements QueueSamplerMBean {
private
Queue<String> queue;
public QueueSampler(Queue<String> aqueue) {
queue = aqueue;
}
/**
* newOperation0 Description
*/
public void clearQueue() {
synchronized(queue) {
queue.clear();
}
}
public
QueueInfo getQueueInfo() {
synchronized(queue) {
return new QueueInfo(new Date(), queue.size(), queue.peek());
}
}
}
|
You'll see, considering of the thread safe, the code lock the queue
when taking snapshot.
7. Now we have created the MBean, it's time for us to register it to
the platform MBeanServer. Add the following code to Main.java
public static void
main(String[] args) {
// Create the Queue Sampler MBean
Queue<String> queue = new
ArrayBlockingQueue<String>(10);
queue.add("Request-1");
queue.add("Request-2");
queue.add("Request-3");
// Get
the Platform MBean Server
MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
try {
// Construct the ObjectName for the MBean we will register
ObjectName name = new
ObjectName("com.example.mxbeans:type=QueueSampler");
QueueSampler mxbean = new QueueSampler(queue);
// Register the Queue Sampler MXBean
mbs.registerMBean(mxbean, name);
} catch
(MalformedObjectNameException ex) {
ex.printStackTrace();
} catch
(NullPointerException ex) {
ex.printStackTrace();
} catch
(Exception e) {
e.printStackTrace();
}
// Wait forever
System.out.println("Waiting...");
try {
Thread.sleep(Long.MAX_VALUE);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
|
8. Now, we have craeted the MBean and registered it
to the MBeanServer. Let's launch Main.java and connect JConsole to it.
Select Netbeans menu item '
Run'->'
Run Main Project with JConsole...'
or click the 'Run Main Project with Local Management' button on the
toolbar, you'll get JConsole launched, and have it connected to MXBean
project instance already. If you don't have the managment plugin
installled in Netbeans, you could launch JConole by commandline.
9. The above snapshot shows the overview information of JVM instance,
on which MXBean project is running. Let's take a look at the our own
MBeans. Switch to the '
MBeans'
tag, extend '
mxbean'->'
QueueSampler'->'
Attributes' as following
We all notice that in the case of QueueSampler is an MBean, JConsole
has no idea of QueueInfo, so it shows '
Unavailable' for attribute
QueueInfo. We can solve this problem by redefining QueueSampler as
MXBean.
10. Rename MBean interface QueueSamplerMBean to MXBean interface
QueueSamplerMXBean.
- Right click on QueueSampleMBean.java
in the 'Project' tab window on
the left
- In the context menu, select 'Refactor'->'Rename...'
- Fill the 'New Name'
with 'QueueSamplerMXBean',
click 'Next>'
- Now Netbean refactor engine has changed the name of
QueueSamplerMBean to QueueSamplerMXBean, including every place it is
referenced.
11. It's done. Launch MXBean project,
and connect JConsole with it again, as
step 8
shows. Now you'll see that JConsole recongines the type of QueueInfo
attribute.
Note that the type of QueueInfo is listed as
javax.management.openmbean.CompositeData
12. Double click QueueInfo value:
javax.managment.openmbean.CompositeDataSupport,
you'll get detailed information contained in QueueInfo. By clicking '
Refresh' button, you'll see the
timestamp updates.
So, we could tell from the exercise above, that the creation of MXBean
is pretty much the same as Standard MBean, expect that it requires the
interface named as '<SomeThing>MXBean'.
(4.2)
Using Descriptors
Descriptors give you a convenient way to attach arbitrary extra
metadata to your MBeans. This is an incremental change because
Descriptors have always existed in the JMX API, but only in conjunction
with Model MBeans. In Java SE, Descriptors are available with all types
of MBeans.
For most constructors in the classes MBean*Info (MBeanInfo,
MBeanAttributeInfo, etc), a parallel constructor has been added with
the same parameters plus an additional Descriptor parameter. Likewise
for OpenMBean*InfoSupport. The MBean*Info and OpenMBean*InfoSupport
classes contain now a getDescriptor() method.
Open MBeans return information about default and legal values from
the getDefaultValue(), getLegalValues(), getMaxValue(), getMinValue()
methods of OpenMBeanParameterInfo and OpenMBeanAttributeInfo. This
information is now also present in the corresponding Descriptors, and
other types of MBean can also return the information in their
Descriptors.
A new annotation DescriptorKey can be used to add information to the
Descriptors for a Standard MBean (or MXBean) via annotations in the
Standard MBean (or MXBean) interface. This makes it possible for a tool
that generates Standard MBeans from an existing management model to
include information from the model in the generated MBean interfaces,
rather than in separate files.
For example, with this definition...
@Documented
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Units {
@DescriptorKey("units")
String value();
}
...you can define an annotation @Units that you can then use like
this...
public interface CacheMBean {
@Units("Whatsits")
public int getUsed();
}
1. Now let's start to create some
descriptors for project 'MXBean' we use in
4.1 in
Netbeans. Open MXBean project in Netbeans, the project is located at
<Unzip_Labfile_Directory>/exercises/ex4.
2. Right click 'MXBean' in the 'Projects' tab
window, select '
New'->'
File/Folder...' in the context menu.
3. Select 'Java Classes' in the '
Categories'
list, '
Java Annotation Type' in
the 'File Types' list as below, click '
Next>'
4. Set '
Author' as '
Class Name', and '
mxbean' as '
Package', click '
Finish'
5. Open Author.java in the editor by double clicking '
Author.java' node under '
MXBean'->'
Source Packages'->'
mxbean', modify the code as
following:
package mxbean;
import
java.lang.annotation.*;
import
javax.management.DescriptorKey;
@Documented
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Author {
@DescriptorKey("author")
String
value();
}
|
6. Create another two annotations:
Version.java and
DisplayName.java in the same way as
above steps. Editor the two annotations as following:
package mxbean;
import
java.lang.annotation.*;
import
javax.management.DescriptorKey;
@Documented
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Version {
@DescriptorKey("version")
String
value();
}
|
package mxbean;
import
java.lang.annotation.*;
import
javax.management.DescriptorKey;
@Documented
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface DisplayName {
@DescriptorKey("displayName")
String
value();
}
|
7. Open QueueSamplerMXBean.java in the editor by double clicking it.
Annotate the MXBean interface as following:
package mxbean;
@Author("Mr Bean")
@Version("1.0")
public interface QueueSamplerMXBean
{
@DisplayName("GETTER:
QueueSample")
public QueueInfo getQueueInfo();
@DisplayName("OPERATION:
clearQueue")
public void clearQueue();
}
|
8. Launch the application, and connect JConsole to it. Either select
Netbeans menu item '
Run'->'
Run Main Project with JConsole...'
or click '
Run Main Project with Local
Management' button on the tool bar, you'll get JConsole
connected with Main.java. Go to the MBeans tab, expand the mxbeans node
and
select the QueueSampler node, you should see the fields "
author" and "
version" in the MBeanInfo
Descriptor table as following.
9. Extend 'Attributes'->'QueueInfo', you should see '
displayName: GETTER: QueueInfo' in
the '
Descriptor' table
10. Extend 'Operations'->'clearQueue', you should see '
displayName: OPERATION: clearQueue'
in the '
Descriptor' table
11. Close JConsole, Main.java exits as well.
Summary
In this exercise, we learnd how to create MXBean and how to create
Descriptors for MBeans(MXBeans).
How to send questions/feedback's on this lab
Congratulations! You have
successfully finished the lab. If you have anyquestions or
feedback's on this lab, please send them to handsonlabs-javase6@yahoogroups.com.
Thanks!
Volunteers who can help others on this lab (via email) are
needed.
If
you have a few spare cycles and willing to help others, please add
yourself to the list by sending an email to handsonlabs-javase6-subscribe@yahoogroups.com