<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="http://feeds.feedburner.com/~d/styles/atom10full.xsl" type="text/xsl" media="screen"?><?xml-stylesheet href="http://feeds.feedburner.com/~d/styles/itemcontent.css" type="text/css" media="screen"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0">
    <title type="html">Core Java Technologies Tech Tips</title>
    <subtitle type="html">Tips for using core Java SE APIs</subtitle>
    <id>http://blogs.sun.com/CoreJavaTechTips/feed/entries/atom</id>
            
        <link rel="alternate" type="text/html" href="http://blogs.sun.com/CoreJavaTechTips/" />
        <updated>2008-07-13T05:21:57-07:00</updated>
    <generator uri="http://roller.apache.org" version="4.0.0.12 (BSC) (20080529122544)">Apache Roller Weblogger</generator>
        <link rel="self" href="http://feeds.feedburner.com/corejavatechtips" type="application/atom+xml" /><entry>
        <id>http://blogs.sun.com/CoreJavaTechTips/entry/launch_java_applications_from_assembly</id>
        <title type="html">Launch Java Applications from Assembly Language Programs</title>
        <author><name>dananourie</name></author>
        <link rel="alternate" type="text/html" href="http://feeds.feedburner.com/~r/corejavatechtips/~3/325246548/launch_java_applications_from_assembly" />
        <published>2008-07-02T15:21:27-07:00</published>
        <updated>2008-07-02T15:21:27-07:00</updated> 
        <category term="/TechTip" label="TechTip" />
        <category term="assembly" scheme="http://rollerweblogger.org/ns/tags/" />
        <category term="java" scheme="http://rollerweblogger.org/ns/tags/" />
        <category term="language" scheme="http://rollerweblogger.org/ns/tags/" />
        <category term="programs" scheme="http://rollerweblogger.org/ns/tags/" />
        <summary type="html">Here I deal with the technique for
invoking Java programs from an ASM process through a demo
application that calls a Java method from assembly language code.</summary>
        <content type="html">&lt;p&gt;by &lt;a href="http://today.java.net/pub/au/491"&gt;Biswajit Sarkar&lt;/a&gt;&lt;/p&gt; 
  &lt;p&gt;&lt;a href="http://java.sun.com/j2se/1.4.2/docs/guide/jni"&gt;Java
Native Interface&lt;/a&gt; (JNI) is a mechanism that can be used to
establish communication between native language programs and the
Java virtual machine. The documentation for JNI and the technical
literature on JNI deal extensively with interactions between the
JVM and C/C++ code. The Java SDK even provides a utility to
generate a header file to facilitate calling C/C++ programs from
Java code. However, there is hardly any mention of Java and
&lt;i&gt;assembly language&lt;/i&gt; code working together. In an &lt;a href="http://today.java.net/pub/a/today/2006/10/19/invoking-assembly-language-from-java.html"&gt;
earlier article&lt;/a&gt; I showed how assembly language programs can be
called from Java applications. Here I deal with the technique for
invoking Java programs from an ASM process through a demo
application that calls a Java method from assembly language code.
The Java method brings up a Swing &lt;code&gt;JDialog&lt;/code&gt; to show that
it has, indeed, been launched.&lt;/p&gt; 
  &lt;p&gt; &lt;/p&gt; 
  &lt;h3 id="why-java-with-asm"&gt;Why Java with ASM?&lt;/h3&gt; 
  &lt;p&gt;JNI is essential to the implementation of Java, since the JVM
needs to interact with the native platform to implement some of its
functionality. Apart from that, however, use of Java classes can
often be an attractive supplement to applications written in other
languages, as Java offers a wide selection of APIs that makes
implementation of advanced functions very simple.&lt;/p&gt; 
  &lt;p&gt;Some time ago, I was associated with an application to collect
real-time data from a number of sources and save them in circular
buffers so that new data would overwrite old data once the buffer
got filled up. If a designated trigger event was sensed through a
digital input, a fixed number of data samples would be saved in the
buffers so that a snapshot of pre- and post-trigger data would be
available. The original application was written in assembly
language. After the application was used for a few months, it was
felt that it would be very useful to have the application mail the
snapshots to authorized supervisors whenever the trigger event
occurred. Of course, it would have been possible to write this
extension in assembly, but the team felt that in that particular
instance it was easier to write that extension in Java and hook it
up with the ASM program. As I had earlier worked with ASM-oriented
JNI, I knew this could be done and, indeed, the project was
implemented quickly and successfully.&lt;/p&gt; 
  &lt;p&gt;I am sure there are many legacy applications written in assembly
language that could benefit from such add-ons. However, it is not
only for old applications in need of renovation that JNI can prove
useful. Although it may seem unlikely to some of us, assembly
language is still used for writing selected portions of new
programs. In an &lt;a href="http://developers.sun.com/solaris/articles/x86_assembly_lang.html"&gt;
article&lt;/a&gt; published not very long ago, the author says, &amp;quot;I have
found that many of Sun's partners still use assembly language in
their products to ensure that hot code paths are as efficient as
possible. While compilers are able to generate much more efficient
code today, the resulting code still doesn't always compete with
hand-coded assembly written by an engineer that knows how to
squeeze performance out of each microprocessor instruction.
Assembly language remains a powerful tool for optimization,
granting the programmer greater control, and with judicious use can
enhance performance.&amp;quot; Clearly, in such &amp;quot;mixed language&amp;quot;
applications the ability to use Java with ASM can be useful.&lt;/p&gt; 
  &lt;p&gt;Note that the technique shown here can also be used to call Java
code from languages other than ASM. If &lt;code&gt;JInvoke&lt;/code&gt; is
rewritten as a .dll, code written in FORTRAN, for instance,
can link to it and call a Java method.&lt;/p&gt; 
  &lt;p&gt;I have used JNI with legacy ASM code in two ways:&lt;br /&gt;&lt;/p&gt; 
  &lt;ul&gt; 
    &lt;li&gt;Functional enhancement: Mail-enabling an existing ASM
application, as mentioned earlier.&lt;/li&gt; 
    &lt;li&gt;Interface enhancement: Adding interactive user interface
(mostly AWT, but some Swing as well).&lt;/li&gt; 
  &lt;/ul&gt; 
  &lt;p&gt;These enhanced applications have run on Windows 2000 and XP. The
Java versions used were 1.3, 1.4, and 1.6. In all cases the
applications worked smoothly.&lt;/p&gt; 
  &lt;p&gt;&lt;a href="http://today.java.net/pub/a/today/2007/10/04/launch-java-applications-from-assembly-language-programs.html"&gt;Read the rest of this article . . . &lt;/a&gt;&lt;br /&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/corejavatechtips/~4/325246548" height="1" width="1"/&gt;</content>
    <feedburner:origLink>http://blogs.sun.com/CoreJavaTechTips/entry/launch_java_applications_from_assembly</feedburner:origLink></entry>
    <entry>
        <id>http://blogs.sun.com/CoreJavaTechTips/entry/add_logging_at_class_load</id>
        <title type="html">Add Logging at Class Load Time with Java Instrumentation</title>
        <author><name>dananourie</name></author>
        <link rel="alternate" type="text/html" href="http://feeds.feedburner.com/~r/corejavatechtips/~3/313089503/add_logging_at_class_load" />
        <published>2008-06-16T08:17:05-07:00</published>
        <updated>2008-06-16T08:17:05-07:00</updated> 
        <category term="/TechTip" label="TechTip" />
        <category term="java" scheme="http://rollerweblogger.org/ns/tags/" />
        <category term="logging" scheme="http://rollerweblogger.org/ns/tags/" />
        <category term="stack" scheme="http://rollerweblogger.org/ns/tags/" />
        <category term="trace" scheme="http://rollerweblogger.org/ns/tags/" />
        <summary type="html">This article shows how to implement&amp;nbsp; a Java agent, which
transparently adds entry and exit logging to all methods in all
your classes with the standard Java Logging API. Additionally,&amp;nbsp; the article demonstrates how to make the
original Hello World program behave like the logging Hello World by
manipulating the byte code when it is loaded.</summary>
        <content type="html">&lt;p&gt;by &lt;a href="http://today.java.net/pub/au/661"&gt;Thorbjørn Ravn Andersen&lt;/a&gt;&lt;/p&gt; 
  &lt;p&gt;When you're trying to analyze why a program failed, a very valuable
piece of information is what the program was actually doing when it
failed. In many cases, this can be determined with a stack trace, but
frequently that information is not available, or perhaps what you
need is information about the data that was being processed at the
time of failure.&lt;/p&gt; 
  &lt;p&gt;Traditionally this means using a logging framework like &lt;a href="http://logging.apache.org/log4j/"&gt;log4j&lt;/a&gt; or the &lt;a href="http://java.sun.com/javase/6/docs/api/java/util/logging/package-summary.html"&gt;
Java Logging API&lt;/a&gt;, and then writing and maintaining all
necessary log statements manually. This is very tedious and error-prone, and well-suited for automation. Java 5 added the &lt;a href="http://java.sun.com/javase/6/docs/api/java/lang/instrument/Instrumentation.html"&gt;
Java Instrumentation&lt;/a&gt; mechanism, which allows you to provide
&amp;quot;Java agents&amp;quot; that can inspect and modify the byte code of the
classes as they are loaded.&lt;/p&gt; 
  &lt;p&gt;This article will show how to implement such a Java agent, which
transparently will add entry and exit logging to all methods in all
your classes with the standard Java Logging API. The example used
is Hello World:&lt;/p&gt; 
  &lt;pre&gt;&lt;code&gt;public class HelloWorld {
    public static void main(String args[]) {
        System.out.println("Hello World");
    }
}
&lt;/code&gt;
&lt;/pre&gt; 
  &lt;p&gt;And here is the same program with entry and exit log statements
added:&lt;/p&gt; 
  &lt;pre&gt;&lt;code&gt;import java.util.Arrays;
import java.util.logging.Level;
import java.util.logging.Logger;

public class LoggingHelloWorld {
    final static Logger _log = Logger.getLogger(LoggingHelloWorld.class.getName());

    public static void main(String args[]) {
        if (_log.isLoggable(Level.INFO)) {
            _log.info("&amp;gt; main(args=" + Arrays.asList(args) + ")");
        }
        System.out.println("Hello World");
        if (_log.isLoggable(Level.INFO)) {
            _log.info("&amp;lt; main()");
        }
    }
}
&lt;/code&gt;
&lt;/pre&gt; 
  &lt;p&gt;The default logger format generates output similar to:&lt;/p&gt; 
  &lt;pre&gt;&lt;code&gt;2007-12-22 22:08:52 LoggingHelloWorld main
INFO: &amp;gt; main(args=[])
Hello World
2007-12-22 22:08:52 LoggingHelloWorld main
INFO: &amp;lt; main()
&lt;/code&gt;
&lt;/pre&gt; 
  &lt;p&gt;Note that each log statement is printed on two lines. First, a
line with a time stamp, the provided log name, and the method in
which the call was made, and then a line with the provided log
text.&lt;/p&gt; 
  &lt;p&gt;The rest of the article will demonstrate how to make the
original Hello World program behave like the logging Hello World by
manipulating the byte code when it is loaded. The manipulation
mechanism is the Java Instrumentation API added in Java 5.&lt;/p&gt; 
  &lt;p&gt;&lt;a href="http://today.java.net/pub/a/today/2008/04/24/add-logging-at-class-load-time-with-instrumentation.html"&gt;Read the rest of this article&lt;/a&gt;. &lt;br /&gt;&lt;/p&gt; 
  &lt;p&gt; &lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/corejavatechtips/~4/313089503" height="1" width="1"/&gt;</content>
    <feedburner:origLink>http://blogs.sun.com/CoreJavaTechTips/entry/add_logging_at_class_load</feedburner:origLink></entry>
    <entry>
        <id>http://blogs.sun.com/CoreJavaTechTips/entry/source_code_analysis_using_java</id>
        <title type="html">Source Code Analysis Using Java 6 APIs</title>
        <author><name>dananourie</name></author>
        <link rel="alternate" type="text/html" href="http://feeds.feedburner.com/~r/corejavatechtips/~3/294477855/source_code_analysis_using_java" />
        <published>2008-05-20T12:06:52-07:00</published>
        <updated>2008-05-20T12:06:52-07:00</updated> 
        <category term="/TechTip" label="TechTip" />
        <category term="6" scheme="http://rollerweblogger.org/ns/tags/" />
        <category term="analysis" scheme="http://rollerweblogger.org/ns/tags/" />
        <category term="compiler" scheme="http://rollerweblogger.org/ns/tags/" />
        <category term="java-se" scheme="http://rollerweblogger.org/ns/tags/" />
        <category term="jdk" scheme="http://rollerweblogger.org/ns/tags/" />
        <category term="processing" scheme="http://rollerweblogger.org/ns/tags/" />
        <summary type="html">In this article, you'll explore the features of each of these APIs
and go on to develop a simple demo application that verifies
certain Java coding rules on a set of source code files supplied as
input.</summary>
        <content type="html">&lt;p&gt;
by &lt;a href="http://today.java.net/pub/au/638"&gt;Seema Richard&lt;/a&gt;, &lt;a href="http://today.java.net/pub/au/647"&gt;Deepa Sobhana&lt;/a&gt;

&lt;/p&gt;&lt;p&gt;
Have you ever thought of how tools like Checkstyle or FindBugs perform a static code analysis, or how Integrated Development Environments (IDEs) like NetBeans or Eclipse execute quick code fixes or find the exact references of a field declared in your code? In many cases, IDEs have their own APIs to parse the source code and generate a standard tree structure, called an Abstract Syntax Tree (AST) or &amp;quot;parse tree,&amp;quot; which can be used for deeper analysis of the source elements. The good news is that it is now possible to accomplish the said tasks plus a lot more with the help of three new APIs introduced in Java as part of the Java Standard Edition 6 release. The APIs that might be of interest to developers of Java applications that need to perform source code analysis are the Java Compiler API (JSR 199), the Pluggable Annotation Processing API (JSR 269), and the Compiler Tree API.
&lt;/p&gt;&lt;p&gt;
In this article, we explore the features of each of these APIs and go on to develop a simple demo application that verifies certain Java coding rules on a set of source code files supplied as input. This utility also shows the coding violation messages as well as the location of violated source code as output. Consider a simple Java class that overrides the equals() method of the Object class. The coding rule to be verified is that every class that implements the equals() method should also override the hashcode() method with the proper signature. You can see that the TestClass class below does not define the hashcode() method, even though it has the equals() method.
&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre&gt;public class TestClass implements Serializable {&lt;br /&gt; int num;&lt;br /&gt;&lt;br /&gt; @Override&lt;br /&gt;  public boolean equals(Object obj) {&lt;br /&gt;        if (this == obj)&lt;br /&gt;                return true;&lt;br /&gt;        if ((obj == null) || (obj.getClass() != this.getClass()))&lt;br /&gt;                return false;&lt;br /&gt;        TestClass test = (TestClass) obj;&lt;br /&gt;        return num == test.num;&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;Let us go on and analyze this class as part of the build process
with the help of these three APIs.&lt;/p&gt;
&lt;h3 id="invoking-the-compiler-from-code-the-java-compiler-api"&gt;Invoking the Compiler from Code: The Java Compiler API&lt;/h3&gt;
&lt;p&gt;We all use the &lt;code&gt;javac&lt;/code&gt; command-line tool for
compiling Java source files to class files. Then why do we need an
API to compile Java files? Well, the answer is quite simple: as the
name describes, this new standard API lets us invoke the compiler
from our own Java applications; i.e., you can programmatically
interact with the compiler and thereby make compilation part of
application-level services. Some typical uses of this API are
listed below.&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;
&lt;p&gt;The compiler API helps application servers to minimize the time
taken to deploy applications, for example, by avoiding the overhead
of using an external compiler for compiling the servlet sources
generated from the JSP pages.&lt;/p&gt;
&lt;/li&gt;&lt;li&gt;
&lt;p&gt;Developer tools like IDEs and code analyzers can invoke the
compiler from within the editor or build tools that significantly
reduce the compile time.&lt;/p&gt;
&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;The Java compiler classes are packaged under the
&lt;code&gt;javax.tools&lt;/code&gt; package. The &lt;code&gt;ToolProvider&lt;/code&gt;
class of this package provides a method called
&lt;code&gt;getSystemJavaCompiler()&lt;/code&gt; that returns an instance of
some class that implements the &lt;code&gt;JavaCompiler&lt;/code&gt; interface.
This compiler instance can be used to create a compilation task
that will perform the actual compilation. The Java source files to
be compiled will be then passed to the compilation task. For this,
the compiler API provides a file manager abstraction called
&lt;code&gt;JavaFileManager&lt;/code&gt;, which allows Java files to be
retrieved from various sources, such as the file system, databases, memory, and so on. In this sample, we use &lt;code&gt;StandardFileManager&lt;/code&gt;, a
file manager based on &lt;code&gt;java.io.File&lt;/code&gt;. The standard file
manager can be acquired by calling the
&lt;code&gt;getStandardFileManager()&lt;/code&gt; method of the
&lt;code&gt;JavaCompiler&lt;/code&gt; instance. The code snippet for the
above-mentioned steps is shown below:&lt;/p&gt;

&lt;pre&gt;//Get an instance of java compiler&lt;br /&gt;JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();&lt;br /&gt;&lt;br /&gt;//Get a new instance of the standard file manager implementation&lt;br /&gt;StandardJavaFileManager fileManager = compiler.&lt;br /&gt;        getStandardFileManager(null, null, null);&lt;br /&gt;        &lt;br /&gt;// Get the list of java file objects, in this case we have only &lt;br /&gt;// one file, TestClass.java&lt;br /&gt;Iterable compilationUnits1 = &lt;br /&gt;        fileManager.getJavaFileObjectsFromFiles(&amp;quot;TestClass.java&amp;quot;);&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;
&lt;p&gt;A diagnostic listener can be optionally passed to the
&lt;code&gt;getStandardFileManager()&lt;/code&gt; method to produce diagnostic
reports of any non-fatal problems. In this code snippet, we pass
&lt;code&gt;null&lt;/code&gt; values, since we are not collecting the
diagnostics from the tool. For details of the other parameters
passed to these methods, please refer to the &lt;a href="http://java.sun.com/javase/6/docs/api/javax/tools/JavaCompiler.html"&gt;
Java 6 API.&lt;/a&gt; The &lt;code&gt;getJavaFileObjectsfromFiles()&lt;/code&gt;
method of the &lt;code&gt;StandardJavaFileManager&lt;/code&gt; returns all the
&lt;code&gt;JavaFileObject&lt;/code&gt; instances that correspond to the
supplied Java source files.&lt;/p&gt;&lt;p&gt;&lt;a href="http://today.java.net/pub/a/today/2008/04/10/source-code-analysis-using-java-6-compiler-apis.html"&gt;Read the rest of this article&lt;/a&gt;&lt;br /&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/corejavatechtips/~4/294477855" height="1" width="1"/&gt;</content>
    <feedburner:origLink>http://blogs.sun.com/CoreJavaTechTips/entry/source_code_analysis_using_java</feedburner:origLink></entry>
    <entry>
        <id>http://blogs.sun.com/CoreJavaTechTips/entry/swingset3_nimbus_and_java_se</id>
        <title type="html">Nimbus Look and Feel in Java SE 6 Update 10 Beta</title>
        <author><name>dananourie</name></author>
        <link rel="alternate" type="text/html" href="http://feeds.feedburner.com/~r/corejavatechtips/~3/277021556/swingset3_nimbus_and_java_se" />
        <published>2008-04-24T09:41:41-07:00</published>
        <updated>2008-05-27T10:21:44-07:00</updated> 
        <category term="/TechTip" label="TechTip" />
        <category term="10" scheme="http://rollerweblogger.org/ns/tags/" />
        <category term="java_se" scheme="http://rollerweblogger.org/ns/tags/" />
        <category term="nimbus" scheme="http://rollerweblogger.org/ns/tags/" />
        <category term="swing" scheme="http://rollerweblogger.org/ns/tags/" />
        <category term="swingset3" scheme="http://rollerweblogger.org/ns/tags/" />
        <category term="update" scheme="http://rollerweblogger.org/ns/tags/" />
        <summary type="html">Discover the changes and improvements included in Nimbus in the Java SE 6 Update 10.</summary>
        <content type="html">&lt;p&gt;&lt;i&gt;By Ethan Nicholas&lt;/i&gt; &lt;br /&gt;&lt;/p&gt;
&lt;!-- BEGIN SEPARATOR --&gt;
&lt;div class="hr"&gt;&lt;hr /&gt;&lt;/div&gt;
&lt;!-- END SEPARATOR --&gt;
&lt;p&gt;When the venerable &lt;a href="http://java.sun.com/docs/books/tutorial/figures/uiswing/lookandfeel/MetalLAF.gif"&gt;Metal 
look and feel&lt;/a&gt; for Swing first debuted, its main aesthetic
competition was the &lt;a href="http://upload.wikimedia.org/wikipedia/en/9/90/Am_windows95_desktop.png"&gt;Windows 
95 interface&lt;/a&gt;.  Given the state of graphical user interfaces a decade
ago, Metal was an attractive and elegant alternative to the other common
interfaces of the time.&lt;/p&gt;
&lt;p&gt;The updated &lt;a href="http://java.sun.com/docs/books/tutorial/figures/uiswing/lookandfeel/OceanLAF.gif"&gt;Ocean&lt;/a&gt; 
theme in Java SE 5 helped to keep Metal a viable choice up to the
present day, but it's time for Swing's cross-platform look and feel to get an
overhaul.&lt;/p&gt;
&lt;p&gt;Enter the &lt;a href="https://nimbus.dev.java.net/"&gt;Nimbus Look and Feel&lt;/a&gt;.  A
brand new, modern look and feel based on &lt;a href="http://javadesktop.org/articles/synth/"&gt;Synth&lt;/a&gt;, Nimbus provides a
polished look to applications which choose to use it.  And because Nimbus is
drawn entirely using Java 2D vector graphics, rather than static bitmaps, it's
tiny (only 56KB!) and can be rendered at arbitrary resolutions.&lt;/p&gt;
&lt;!-- BEGIN G20 COMPONENT V.9 --&gt;
&lt;div class="g20 g20r1 g20v9"&gt;
&lt;div class="g20w1" style="width: 665px;"&gt;

&lt;div class="g20w2"&gt;
&lt;div style="background: transparent url(http://java.sun.com/developer/technicalArticles/javase/java6u10/images/metal.gif) no-repeat scroll 0% 0%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; width: 654px; height: 400px;" class="imgbox imgcenter"&gt;&lt;img height="400" border="0" width="654" style="display: none;" alt="SwingSet3 in Metal" src="http://java.sun.com/developer/technicalArticles/javase/java6u10/images/metal.gif" /&gt;&lt;/div&gt;
&lt;div class="small" style="text-align: center;"&gt;Figure 3: SwingSet3 in Metal&lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;!-- END G20 COMPONENT V.9 --&gt;
&lt;span class="sp20"&gt;&amp;nbsp;&lt;/span&gt;&lt;br /&gt;
&lt;!-- BEGIN G20 COMPONENT V.9 --&gt;
&lt;div class="g20 g20r1 g20v9"&gt;
&lt;div class="g20w1" style="width: 665px;"&gt;

&lt;div class="g20w2"&gt;
&lt;div style="background: transparent url(http://java.sun.com/developer/technicalArticles/javase/java6u10/images/nimbus.gif) no-repeat scroll 0% 0%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; width: 654px; height: 400px;" class="imgbox imgcenter"&gt;&lt;img height="400" border="0" width="654" style="display: none;" alt="SwingSet3 in Nimbus" src="http://java.sun.com/developer/technicalArticles/javase/java6u10/images/nimbus.gif" /&gt;&lt;/div&gt;
&lt;div class="small" style="text-align: center;"&gt;Figure 4: SwingSet3 in Nimbus&lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;!-- END G20 COMPONENT V.9 --&gt;   
&lt;span class="sp10"&gt;&amp;nbsp;&lt;/span&gt;&lt;br /&gt;
&lt;p&gt;For compatibility reasons, Metal is still the default Swing look and feel, but
updating applications to use Nimbus couldn't be simpler.  It only takes a single
line of code:&lt;/p&gt;
&lt;!-- BEGIN PC1 COMPONENT V.2 --&gt;
&lt;div class="pc1 pc1v2"&gt;
&lt;div class="pc1w1"&gt;&lt;div class="pc1w2"&gt;&lt;div class="pc1w3 cornerBL"&gt;&lt;div class="pc1w4"&gt;   
&lt;pre&gt;UIManager.setLookAndFeel(&amp;quot;com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel&amp;quot;);&lt;/pre&gt;
&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;!-- END PC1 COMPONENT V.2 --&gt;
&lt;p&gt;You can also force Nimbus to be the default look and feel by specifying
&lt;code&gt;-Dswing.defaultlaf=com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel&lt;/code&gt;.
on the  command line.  A more permanent way to set the property is to add&lt;/p&gt;
&lt;!-- BEGIN PC1 COMPONENT V.2 --&gt;
&lt;div class="pc1 pc1v2"&gt;
&lt;div class="pc1w1"&gt;&lt;div class="pc1w2"&gt;&lt;div class="pc1w3 cornerBL"&gt;&lt;div class="pc1w4"&gt;   
&lt;pre&gt;swing.defaultlaf=com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel&lt;/pre&gt;
&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;!-- END PC1 COMPONENT V.2 --&gt;
&lt;p&gt;to the file &lt;code&gt;&amp;lt;JAVA_HOME&amp;gt;/lib/swing.properties&lt;/code&gt;.  You will have to create
the swing.properties file if it does not already exist.&lt;/p&gt;
&lt;p&gt;For further reading about Nimbus, take a look at &lt;a href="http://java.sun.com/javase/downloads/ea/6u10/nimbus.jsp"&gt;the Nimbus early
access page.&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/corejavatechtips/~4/277021556" height="1" width="1"/&gt;</content>
    <feedburner:origLink>http://blogs.sun.com/CoreJavaTechTips/entry/swingset3_nimbus_and_java_se</feedburner:origLink></entry>
    <entry>
        <id>http://blogs.sun.com/CoreJavaTechTips/entry/jslider_appearance_improvements</id>
        <title type="html">JSlider Appearance Improvements</title>
        <author><name>dananourie</name></author>
        <link rel="alternate" type="text/html" href="http://feeds.feedburner.com/~r/corejavatechtips/~3/264207223/jslider_appearance_improvements" />
        <published>2008-04-04T13:34:02-07:00</published>
        <updated>2008-04-04T13:34:02-07:00</updated> 
        <category term="/TechTip" label="TechTip" />
        <category term="code_samples" scheme="http://rollerweblogger.org/ns/tags/" />
        <category term="java" scheme="http://rollerweblogger.org/ns/tags/" />
        <category term="java_se" scheme="http://rollerweblogger.org/ns/tags/" />
        <category term="tips" scheme="http://rollerweblogger.org/ns/tags/" />
        <summary type="html">Learn how you can change any of the three
  defaults in JSlider: the direction of the scrollbar, and whether tick marks should
  appear, and what to show next to them.</summary>
        <content type="html">&lt;p&gt;by John Zukowsi &lt;/p&gt;
&lt;p&gt;The &lt;code&gt;JSlider&lt;/code&gt; component is a popular component for selecting a value from
  a numerical range. While some people might think of a &lt;code&gt;JScrollBar&lt;/code&gt; for
  numerical input, that really serves the purpose of scrolling around a
  viewport, not data input. By default, the input range of a &lt;code&gt;JSlider&lt;/code&gt; is
  &lt;code&gt;0&lt;/code&gt; to &lt;code&gt;100&lt;/code&gt;, with an initial value of &lt;code&gt;50&lt;/code&gt;. You can change any of the three
  defaults, the direction of the scrollbar, and whether tick marks should
  appear and what to show next to them. You'll look at all of these
  possible features.&lt;/p&gt;

&lt;p&gt;First off is the basic &lt;code&gt;JSlider&lt;/code&gt;, just creating it and adding it to a
  screen, preserving all the defaults. Nothing fancy here, but builds the
  basics for what to build on for the remaining examples. The &lt;code&gt;SliderSample&lt;/code&gt;
  program actually has four sliders; two horizontal and two vertical.&lt;/p&gt;
  
&lt;pre&gt;import javax.swing.*;
import java.awt.*;

public class SliderSample {
  public static void main(final String args[]) {
    Runnable runner = new Runnable() {
      public void run() {
        JFrame frame = new JFrame("Sample Sliders");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        JSlider js1 = new JSlider();
        JSlider js2 = new JSlider();
        js2.setInverted(true);
        JSlider js3 = new JSlider(JSlider.VERTICAL);
        js3.setPaintLabels(true);
        JSlider js4 = new JSlider(JSlider.VERTICAL);
        js4.setInverted(true);
        frame.add(js1, BorderLayout.NORTH);
        frame.add(js2, BorderLayout.SOUTH);
        frame.add(js3, BorderLayout.WEST);
        frame.add(js4, BorderLayout.EAST);
        frame.setSize(300, 200);
        frame.setVisible(true);
      }
    };
    EventQueue.invokeLater(runner);
  }
}&lt;/pre&gt;
&lt;p&gt;Compiling and running the program shows a screen with four sliders on
  it. While you cannot tell from the screen, the ones in the &lt;code&gt;EAST&lt;/code&gt; and
  &lt;code&gt;SOUTH&lt;/code&gt; regions of the &lt;code&gt;BorderLayout&lt;/code&gt; are actually inverted. So, for the
  horizontal sliders, &lt;code&gt;0&lt;/code&gt; is on the left for the top one and &lt;code&gt;100&lt;/code&gt; is on the
  left for the inverted bottom one. For the vertical sliders, &lt;code&gt;0&lt;/code&gt; is on
  the bottom for the left one and on the top for the inverted right one.&lt;/p&gt;

&lt;p&gt;&lt;img src="http://blogs.sun.com/CoreJavaTechTips/resource/first.png" width="300" height="200" /&gt;&lt;/p&gt;
&lt;p&gt;By default, there is no indicator on the slider for what its value is.
  Instead, you would just ask the slider its value at some later time, or
  attach a listener to the control to be told the value upon movement.
  Ignoring the import lines, here is a listener that reports the value
  when the user stops dragging the slider knob. The &lt;code&gt;getValueIsAdjusting()&lt;/code&gt;
  method reports true while the user still has the knob selected with the
  mouse.&lt;/p&gt;
&lt;pre&gt; public class SliderChangeListener implements ChangeListener {
    public void stateChanged(ChangeEvent changeEvent) { 
      Object source = changeEvent.getSource();
      JSlider theJSlider = (JSlider)source;
      if (!theJSlider.getValueIsAdjusting()) { 
        System.out.println ("Slider changed: " + theJSlider.getValue());
      } 
    } 
  } &lt;/pre&gt;
&lt;p&gt;Not showing a value on the slider makes it somewhat useless, though you
  can certainly work with it where the exact value doesn't matter and the
  user can see results based upon relative position. To help in making the
  slider more useful, you can show tick marks with labels. There are two
  classes of tick marks, major and minor ones. Major and minor are just
  classifications for the length and positioning of the lines drawn for
  the tick mark, where major tick marks are longer than minor ones. To
  enable tick marks, you have to call &lt;code&gt;setPaintTicks(true)&lt;/code&gt;, and, say how
  far apart the tick marks should appear. By default, the spacing is
  zero, resulting in no tick marks drawn, even when paint ticks is true.
  Adding the appropriate lines to the earlier program will show tick
  marks on the top and left sliders, with major ticks every 10 and
  minor ones at the midpoint between them.&lt;/p&gt;
&lt;pre&gt;  
  js1.setPaintTicks(true);
  js1.setMajorTickSpacing(10);
  js1.setMinorTickSpacing(5);

  js3.setPaintTicks(true);
  js3.setMajorTickSpacing(10);
  js3.setMinorTickSpacing(5); &lt;/pre&gt;

&lt;p&gt;&lt;img src="http://blogs.sun.com/CoreJavaTechTips/resource/ticks.png" width="300" height="200" /&gt;&lt;/p&gt;
&lt;p&gt;Showing tick marks certainly helps, but showing labels makes things
  most useful. Adding &lt;code&gt;setPaintLabels(true)&lt;/code&gt; calls will show labels at
  the major tick marks. By default, the labels are their respective
  cardinal numbers, so with a major tick mark at value &lt;code&gt;0&lt;/code&gt;, the associated
  label is string &amp;quot;0,&amp;quot; and so on for &amp;quot;10,&amp;quot;, &amp;quot;20,&amp;quot;, all the way to &amp;quot;100.&amp;quot;&lt;/p&gt;
&lt;p&gt;&lt;img src="http://blogs.sun.com/CoreJavaTechTips/resource/labels.png" width="400" height="300" /&gt;&lt;/p&gt;

&lt;p&gt;Instead of showing the cardinal numbers, you can provide a label table:
  &lt;code&gt;setLabelTable(Dictionary labels)&lt;/code&gt;. In the table, you would map integer
  values to different components to show as the label. In generic-speak,
  that would be &lt;code&gt;Dictionary&amp;lt;Integer, JComponent&amp;gt;&lt;/code&gt;, though the method
  isn't explicitly defined to require the key-value pair to be such.
  Typically, the mapping is &lt;code&gt;Integer&lt;/code&gt; object to &lt;code&gt;JLabel&lt;/code&gt;. As the Swing
  component set predates the &lt;code&gt;Collections&lt;/code&gt; framework, the method takes
  a &lt;code&gt;Dictionary&lt;/code&gt;, not a &lt;code&gt;Map&lt;/code&gt;, so remember to use a &lt;code&gt;Hashtable&lt;/code&gt; for the label
  table. Here's one label table setup that shows text roughly every
  eleven positions. At the ends are colored diamond icons, instead of
  text, to help show that that are labels not text strings that can go
  at each position.&lt;/p&gt;

&lt;pre&gt;
   Hashtable&amp;lt;Integer, JComponent&amp;gt; table =
      new Hashtable&amp;lt;Integer, JComponent&gt;();
    table.put(new Integer(0), new JLabel(
      new DiamondIcon(Color.RED)));
    table.put(new Integer(11), new JLabel("Eleven"));
    table.put(new Integer(22), new JLabel("Twenty-Two"));
    table.put(new Integer(33), new JLabel("Thirty-Three"));
    table.put(new Integer(44), new JLabel("Fourty-Four"));
    table.put(new Integer(55), new JLabel("Fifty-Five"));
    table.put(new Integer(66), new JLabel("Sixty-Six"));
    table.put(new Integer(77), new JLabel("Seventy-Seven"));
    table.put(new Integer(88), new JLabel("Eighty-Eight"));
    table.put(new Integer(100), new JLabel(
      new DiamondIcon(Color.BLACK)));
     js4.setLabelTable(table);
     js4.setPaintLabels(true); &lt;/pre&gt;
&lt;p&gt;&lt;img src="http://blogs.sun.com/CoreJavaTechTips/resource/eleven.png" width="400" height="300" /&gt;&lt;/p&gt;
&lt;p&gt;The definition for the &lt;code&gt;DiamondIcon&lt;/code&gt; will be shown at end with the
  full class definition.&lt;/p&gt;
&lt;p&gt;Notice that the slider in the eastern area of the screen was used for
  the label table. Had the southern slider been used instead, the label
  text would overlap. Keep that in mind when you work with slider labels.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://blogs.sun.com/CoreJavaTechTips/resource/elevenBottom.png" width="400" height="300" /&gt;&lt;/p&gt;

&lt;p&gt;One last thing you can do to affect the display. You can hide the
  track that the knob slides on. Just call the &lt;code&gt;setPaintTrack(&lt;/code&gt;) method,
  with a setting of false. Here, the bottom slider has its track hidden.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://blogs.sun.com/CoreJavaTechTips/resource/hidden.png" width="400" height="300" /&gt;&lt;/p&gt;
&lt;p&gt;There isn't that much more you can do to customize the look of the
  &lt;code&gt;JSlider&lt;/code&gt;, but as you've seen there is certainly quite a bit you can do.
  From adding tick marks and labels to hiding the track, you've seen the
  most significant features. If you want to get really fancy, consider
  creating a custom UI for the component and show it as a dial instead of
  a line. Sounds like an idea for a future tip.&lt;/p&gt;
&lt;p&gt;Here's the final and complete source used to generate the samples. You
  will need to work backwards to remove code sections to return back to
  the first screen shot.&lt;/p&gt;
&lt;pre&gt;
import javax.swing.*;
import javax.swing.event.*;
import java.awt.*;
import java.util.Hashtable;

public class SliderSample {
  public static void main(final String args[]) {
    Runnable runner = new Runnable() {
      public void run() {
        JFrame frame = new JFrame("Sample Sliders");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        ChangeListener listener = new SliderChangeListener();
        JSlider js1 = new JSlider();
        js1.setPaintLabels(true);
        js1.setPaintTicks(true);
        js1.setMajorTickSpacing(10);
        js1.setMinorTickSpacing(5);
        js1.addChangeListener(listener);
        JSlider js2 = new JSlider();
        js2.setInverted(true);
	js2.setPaintTrack(false);
        js2.addChangeListener(listener);
        JSlider js3 = new JSlider(JSlider.VERTICAL);
        js3.setPaintLabels(true);
        js3.setPaintTicks(true);
        js3.setMajorTickSpacing(10);
        js3.setMinorTickSpacing(5);
        js3.addChangeListener(listener);
        JSlider js4 = new JSlider(JSlider.VERTICAL);
        js4.setInverted(true);
        Hashtable&amp;lt;Integer, JComponent&amp;gt; table =
          new Hashtable&amp;lt;Integer, JComponent&amp;gt;();
        table.put(new Integer(0), new JLabel(
          new DiamondIcon(Color.RED)));
        table.put(new Integer(11), new JLabel("Eleven"));
        table.put(new Integer(22), new JLabel("Twenty-Two"));
        table.put(new Integer(33), new JLabel("Thirty-Three"));
        table.put(new Integer(44), new JLabel("Fourty-Four"));
        table.put(new Integer(55), new JLabel("Fifty-Five"));
        table.put(new Integer(66), new JLabel("Sixty-Six"));
        table.put(new Integer(77), new JLabel("Seventy-Seven"));
        table.put(new Integer(88), new JLabel("Eighty-Eight"));
        table.put(new Integer(100), new JLabel(
          new DiamondIcon(Color.BLACK)));
        js4.setLabelTable(table);
        js4.setPaintLabels(true);
        js4.addChangeListener(listener);
        frame.add(js1, BorderLayout.NORTH);
        frame.add(js2, BorderLayout.SOUTH);
        frame.add(js3, BorderLayout.WEST);
        frame.add(js4, BorderLayout.EAST);
        frame.setSize(400, 300);
        frame.setVisible(true);
      }
    };
    EventQueue.invokeLater(runner);
  }
  public static class SliderChangeListener implements ChangeListener {
    public void stateChanged(ChangeEvent changeEvent) { 
      Object source = changeEvent.getSource();
      JSlider theJSlider = (JSlider)source;
      if (!theJSlider.getValueIsAdjusting()) { 
        System.out.println ("Slider changed: " + theJSlider.getValue());
      } 
    } 
  }
  public static class DiamondIcon implements Icon {
    private Color color;
    private boolean selected;
    private int width;
    private int height;
    private Polygon poly;
    private static final int DEFAULT_WIDTH = 10;
    private static final int DEFAULT_HEIGHT = 10;

    public DiamondIcon(Color color) {
      this(color, true, DEFAULT_WIDTH, DEFAULT_HEIGHT);
    }

    public DiamondIcon(Color color, boolean selected) {
      this(color, selected, DEFAULT_WIDTH, DEFAULT_HEIGHT);
    }

    public DiamondIcon(Color color, boolean selected,
        int width, int height) {
      this.color = color;
      this.selected = selected;
      this.width = width;
      this.height = height;
      initPolygon();
    }

    private void initPolygon() {
      poly = new Polygon();
      int halfWidth = width / 2;
      int halfHeight = height / 2;
      poly.addPoint(0, halfHeight);
      poly.addPoint(halfWidth, 0);
      poly.addPoint(width, halfHeight);
      poly.addPoint(halfWidth, height);
    }

    public int getIconHeight() {
      return height;
    }

    public int getIconWidth() {
      return width;
    }

    public void paintIcon(Component c, Graphics g, int x, int y) {
      g.setColor(color);
      g.translate(x, y);
      if (selected) {
        g.fillPolygon(poly);
      } else {
        g.drawPolygon(poly);
      }
      g.translate(-x, -y);
    }
  }
}

&lt;/pre&gt;
&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/corejavatechtips/~4/264207223" height="1" width="1"/&gt;</content>
    <feedburner:origLink>http://blogs.sun.com/CoreJavaTechTips/entry/jslider_appearance_improvements</feedburner:origLink></entry>
    <entry>
        <id>http://blogs.sun.com/CoreJavaTechTips/entry/using_generics_with_wildcards_and</id>
        <title type="html">Using Generics With Wildcards and Extends</title>
        <author><name>dananourie</name></author>
        <link rel="alternate" type="text/html" href="http://feeds.feedburner.com/~r/corejavatechtips/~3/249176750/using_generics_with_wildcards_and" />
        <published>2008-03-10T16:56:23-07:00</published>
        <updated>2008-06-26T14:08:57-07:00</updated> 
        <category term="/TechTip" label="TechTip" />
        <category term="extends" scheme="http://rollerweblogger.org/ns/tags/" />
        <category term="generics" scheme="http://rollerweblogger.org/ns/tags/" />
        <category term="java" scheme="http://rollerweblogger.org/ns/tags/" />
        <summary type="html">Learn how to use generics with Wildcards and Extends.</summary>
        <content type="html">&lt;p&gt;By John Zukowski

&lt;/p&gt; 
  &lt;p&gt;Java 2 Platform, Standard Edition 5.0 (J2SE 5.0) introduced
generics to the Java programming language and platform. In the
simplest case and typical usage, generics allow for the
identification of what you want to store in a collection. So instead
of saying that your program has a &lt;code&gt;List&lt;/code&gt; of

&lt;code&gt;Objects&lt;/code&gt;, you can now specify that you have a
&lt;code&gt;List&lt;/code&gt; of &lt;code&gt;String&lt;/code&gt; objects or some other class
type. Then, if you accidentally try to add something to the
&lt;code&gt;List&lt;/code&gt; that is of the wrong type, the compiler notifies
you of the error and it can be fixed at compile time, rather than
having to wait until you run the program and the program reaches the
point in code where the fetch operation produces a runtime casting
exception. &lt;/p&gt; 
  &lt;p&gt;This brings up a second benefit of generics. Iterators now become
typesafe. The &lt;code&gt;next()&lt;/code&gt; method of the

&lt;code&gt;Iterator&lt;/code&gt; interface returns the typesafe version of the
next element of the collection.

&lt;/p&gt; 
  &lt;p&gt;But this is not a tip about the use of generics, which a &lt;a href="http://java.sun.com/developer/JDCTechTips/2005/tt0315.html#1" title="2005 tip"&gt;2005 Core Java Technologies Tip&lt;/a&gt; explained. Most
people don't fully understand the use of the &lt;code&gt;extends&lt;/code&gt;
keyword when using generics. A typical example shown to explain the
use of &lt;code&gt;extends&lt;/code&gt; has to do with drawing shapes. Instead,
this tech tip will use an example that uses Swing components so that
you do not have to create extra new classes. In a very limited case,
the class hierarchy for Swing button components is shown here, with
&lt;code&gt;Object&lt;/code&gt; as the real root: &lt;/p&gt; 
  &lt;pre&gt;Component
|- Container
   |- JComponent
      |- AbstractButton
         |- JButton
         |- JMenuItem
            |- JCheckBoxMenuItem
            |- JMenu
            |- JRadioButtonMenuItem
         |- JToggleButton
            |- JCheckBox
            |- JRadioButton
&lt;/pre&gt; 
  &lt;p&gt;One thing that all &lt;code&gt;AbstractButton&lt;/code&gt; subclasses share
in common is a &lt;code&gt;getText()&lt;/code&gt; method. So in the spirit of
generics, you can define a method that takes a &lt;code&gt;List&lt;/code&gt; of
&lt;code&gt;AbstractButton&lt;/code&gt; items and return a &lt;code&gt;List&lt;/code&gt; of
the &lt;code&gt;String&lt;/code&gt; labels of those buttons. Here's the first
version of such a method:


&lt;/p&gt; 
  &lt;pre&gt;  public static List&amp;lt;String&amp;gt; getLabels(List&amp;lt;AbstractButton&amp;gt; list) {
    List&amp;lt;String&amp;gt; labelList = new ArrayList&amp;lt;String&amp;gt;(list.size());
    for (AbstractButton button: list) {
      labelList.add(button.getText());
    }
    return labelList;
  }
&lt;/pre&gt; 
  &lt;p&gt;And here is how you might use the method. First, define a
&lt;code&gt;List&lt;/code&gt; of &lt;code&gt;AbstractButton&lt;/code&gt; types, fill it up,
and call the method:


&lt;/p&gt; 
  &lt;pre&gt;  List&amp;lt;AbstractButton&amp;gt; buttonList =
      new ArrayList&amp;lt;AbstractButton&amp;gt;();
  buttonList.add(new JButton("Hello"));
  buttonList.add(new JCheckBox("World"));
  buttonList.add(new JRadioButton("Hola"));
  buttonList.add(new JMenuItem("Mundo"));

  List&lt;string&gt; labels = getLabels(buttonList);
  System.out.println(labels);
&lt;/string&gt;&lt;/pre&gt; 
  &lt;p&gt;&amp;quot;Hola, Mundo&amp;quot; is the Spanish translation of &amp;quot;Hello, World,&amp;quot;
according to Google. The results of the &lt;code&gt;println()&lt;/code&gt; call
is as follows:

&lt;/p&gt; 
  &lt;pre&gt;[Hello, World, Hola, Mundo]
&lt;/pre&gt; 
  &lt;p&gt;With a &lt;code&gt;List&lt;/code&gt; of &lt;code&gt;AbstractButtons&lt;/code&gt;,
everything functions fine, but this breaks down when the
&lt;code&gt;List&lt;/code&gt; is of something else, specifically a subclass. One
would logically think that with a &lt;code&gt;List&lt;/code&gt; of
&lt;code&gt;JButton&lt;/code&gt; items, everything would work fine, because
&lt;code&gt;JButton&lt;/code&gt; is a subclass of &lt;code&gt;AbstractButton&lt;/code&gt;.
Shouldn't you be able to call

&lt;code&gt;getLabels(List&amp;lt;AbstractButton&amp;gt;)&lt;/code&gt; with a
&lt;code&gt;List&lt;/code&gt; of a subclass of &lt;code&gt;AbstractButton&lt;/code&gt;?

&lt;/p&gt; 
  &lt;pre&gt;  List&amp;lt;JButton&amp;gt; buttonList = ...
  // ... Fill list ...
  List&amp;lt;String&amp;gt; labels = getLabels(buttonList);

&lt;/pre&gt; 
  &lt;p&gt;Well, that isn't the case. Because this is a compile-time check,
and because the definition of &lt;code&gt;getLabels()&lt;/code&gt; is defined to
accept only an &lt;code&gt;AbstractButton List&lt;/code&gt;, you cannot pass
anything else to it. The compilation-time error message follows:

&lt;/p&gt; 
  &lt;pre&gt;GetList.java:13: getLabels(java.util.List&amp;lt;javax.swing.AbstractButton&amp;gt;)
  in GetList cannot be applied to (java.util.List&amp;lt;javax.swing.JButton&amp;gt;)

    List&amp;lt;String&amp;gt; labels = getLabels(buttonList);
                          ^
1 error

&lt;/pre&gt; 
  &lt;p&gt;And this is where the &lt;code&gt;extends&lt;/code&gt; keyword comes in
handy. Instead of defining the &lt;code&gt;getLabels()&lt;/code&gt; method to
accept only an &lt;code&gt;AbstractButton&lt;/code&gt; list, define it to accept
any &lt;code&gt;List&lt;/code&gt; of &lt;code&gt;AbstractButton&lt;/code&gt; subclasses:


&lt;/p&gt; 
  &lt;pre&gt;    public static List&amp;lt;String&amp;gt; getLabels(
      List&amp;lt;? extends AbstractButton&amp;gt; list) {
&lt;/pre&gt; 
  &lt;p&gt;The wildcard &lt;code&gt;?&lt;/code&gt; here says that the method doesn't
care what the exact class type is, as long as it is a subclass of
&lt;code&gt;AbstractButton&lt;/code&gt;. Here's a complete example that puts all
the pieces together:


&lt;/p&gt; 
  &lt;pre&gt;import java.util.*;
import javax.swing.*;

public class GetList {
  public static void main(String args[]) {
    List&amp;lt;JButton&amp;gt; buttonList =
      new ArrayList&amp;lt;JButton&amp;gt;();
    buttonList.add(new JButton("Hello"));
    buttonList.add(new JButton("World"));
    buttonList.add(new JButton("Hola"));
    buttonList.add(new JButton("Mundo"));

    List&lt;string&gt; labels = getLabels(buttonList);
    System.out.println(labels);

  }

  public static List&amp;lt;String&amp;gt; getLabels(
        List&amp;lt;? extends AbstractButton&amp;gt; list) {
    List&amp;lt;String&amp;gt; labelList = new ArrayList&amp;lt;String&amp;gt;(list.size());
    for (AbstractButton button: list) {
      labelList.add(button.getText());
    }
    return labelList;
  }
}

&lt;/string&gt;&lt;/pre&gt; 
  &lt;p&gt;Now, when you are defining your own classes and methods with
generics and are thinking of accepting an abstract class as the
generic argument, or any superclass, remember to use wildcards so
that the same method works best with subclasses too.

&lt;/p&gt; 
  &lt;p&gt;For more information on generics, see two earlier tutorials by
Gilad Bracha: &lt;a href="http://java.sun.com/j2se/1.5/pdf/generics-tutorial.pdf"&gt;a 2004
tutorial (PDF)&lt;/a&gt; and the generics lesson in the online &lt;a href="http://java.sun.com/docs/books/tutorial/extra/generics/"&gt;Java
Tutorial&lt;/a&gt;.


&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/corejavatechtips/~4/249176750" height="1" width="1"/&gt;</content>
    <feedburner:origLink>http://blogs.sun.com/CoreJavaTechTips/entry/using_generics_with_wildcards_and</feedburner:origLink></entry>
    <entry>
        <id>http://blogs.sun.com/CoreJavaTechTips/entry/getting_to_know_boxlayout</id>
        <title type="html">Getting to Know BoxLayout</title>
        <author><name>dananourie</name></author>
        <link rel="alternate" type="text/html" href="http://feeds.feedburner.com/~r/corejavatechtips/~3/234035888/getting_to_know_boxlayout" />
        <published>2008-02-12T15:37:33-08:00</published>
        <updated>2008-02-12T15:37:33-08:00</updated> 
        <category term="/TechTip" label="TechTip" />
        <category term="applications" scheme="http://rollerweblogger.org/ns/tags/" />
        <category term="desktop" scheme="http://rollerweblogger.org/ns/tags/" />
        <category term="gui" scheme="http://rollerweblogger.org/ns/tags/" />
        <category term="java" scheme="http://rollerweblogger.org/ns/tags/" />
        <category term="layout" scheme="http://rollerweblogger.org/ns/tags/" />
        <category term="managers" scheme="http://rollerweblogger.org/ns/tags/" />
        <category term="swing" scheme="http://rollerweblogger.org/ns/tags/" />
        <summary type="html">Learn how and when to use the BoxLayout manager, plus how to make use of the Box struts and glue components.</summary>
        <content type="html">&lt;p&gt;One of the standard layout managers that come with the Java platform is
  &lt;code&gt;BoxLayout&lt;/code&gt;. This allows you to layout a single row or column of components
  in a container. This may sound like a not-so-complicated layout manager,
  but with the help of &lt;code&gt;Box&lt;/code&gt; and its glue and struts, you'd think that would
  be enough, but there is even more. The vertical and horizontal alignment
  of the underlying components allows even more control of the positioning
  of components within the container. Here, we'll look at all these aspects.&lt;/p&gt;

&lt;h3&gt;Typical Usage&lt;/h3&gt;
&lt;p&gt;BoxLayout is unlike most layout managers which just require you to create 
  the layout manager, and associate the layout manager with the &lt;code&gt;Container&lt;/code&gt;.
  Instead, the &lt;code&gt;BoxLayout&lt;/code&gt; constructor requires you to pass the &lt;code&gt;Container&lt;/code&gt;
  into the constructor of the layout manager, thus having a reference to the
  other component in each of them. This can be awkward sometimes, and 
  makes the use of the &lt;code&gt;Box&lt;/code&gt; container more popular, since all you have to
  do is ask for a horizontally or vertically laid out &lt;code&gt;Box&lt;/code&gt; through one of
  its &lt;code&gt;static&lt;/code&gt; methods:&lt;/p&gt;

&lt;pre&gt;  Box vertical = Box.createVerticalBox();
  Box horizontal = Box.createHorizontalBox();&lt;/pre&gt;
&lt;p&gt;Both are using &lt;code&gt;BoxLayout&lt;/code&gt; under the covers, placing added components
  on the proper access, depending upon direction. A vertical box
  places everything into a single column, whereas a horizontal box
  places everything in a row. Comparing &lt;code&gt;BoxLayout&lt;/code&gt; (and thus &lt;code&gt;Box&lt;/code&gt;) to
  &lt;code&gt;GridLayout&lt;/code&gt; requires a quick comment. When placing a bunch of components
  in a &lt;code&gt;GridLayout&lt;/code&gt; controlled container, all the components are expected
  to be the same size. With &lt;code&gt;BoxLayout&lt;/code&gt;, that isn't the case, and the
  maximum preferred size of the component is honored.&lt;/p&gt;

&lt;h3&gt;Struts and Glue&lt;/h3&gt;
&lt;p&gt;The Box class offers the creation of two supporting components, one
  a strut, or fixed-size filler area, the other glue for an expandable area.
  The use of these allows you to place components within a container, either
  a fixed-distance apart with a strut, or a growing/shrinking area based upon
  available space, with glue. The same task can be done with &lt;code&gt;GridBagConstraints&lt;/code&gt;
  and &lt;code&gt;GridBagLayout&lt;/code&gt;, though not as easily.&lt;/p&gt;
&lt;p&gt;To demonstrate, this first program creates a 25 pixel strut between the
  top two components and a 10 pixel strut between the bottom two.&lt;/p&gt;
&lt;pre&gt;
import java.awt.*;
import javax.swing.*;
public class VerticalBoxTest {
  public static void main(String args[]) {
    JFrame frame = new JFrame("Vertical Box");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    Box box = Box.createVerticalBox(); 
    box.add(new Button("Top"));
    box.add(Box.createVerticalStrut(25));
    box.add(new Button("Middle"));
    box.add(Box.createVerticalStrut(10));
    box.add(new Button("Bottom"));
    frame.add(box, BorderLayout.CENTER);
    frame.setSize(300, 200);
    frame.setVisible(true);
  }
}&lt;/pre&gt;
&lt;p&gt;Once you compile and run it, notice how the components change in size
  when the window size increased or decreased. The distance between the
  components remain unchanged, to match the reserved strut space. This
  example uses a &amp;lt;code&amp;gt;Button&amp;lt;/code&amp;gt; instead of a &lt;code&gt;JButton&lt;/code&gt; to avoid an explanation
  of component alignment until a little later.&lt;/p&gt;

&lt;p&gt;&lt;img src="http://blogs.sun.com/CoreJavaTechTips/resource/vBoxBefore.png"&gt;&lt;br&gt;
  &lt;img src="http://blogs.sun.com/CoreJavaTechTips/resource/vBoxAfter.png"&gt;&lt;/p&gt;
&lt;p&gt;Working with a horizontal box and glue produces similar results,
  though this time the glue grows in size to take up added space, instead
  of staying a fixed size, with the strut.&lt;/p&gt;
&lt;pre&gt;
import java.awt.*;
import javax.swing.*;
public class HorizontalBoxTest {
  public static void main(String args[]) {
    JFrame frame = new JFrame("Horizontal Box");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    Box box = Box.createHorizontalBox();
    box.add(Box.createHorizontalGlue());
    box.add(new JButton("Left"));
    box.add(new JButton("Right"));
    frame.add(box, BorderLayout.NORTH);
    box = Box.createHorizontalBox();
    box.add(new JButton("Left"));
    box.add(Box.createHorizontalGlue());
    box.add(new JButton("Right"));
    frame.add(box, BorderLayout.CENTER);
    box = Box.createHorizontalBox();
    box.add(new JButton("Left"));
    box.add(new JButton("Right"));
    box.add(Box.createHorizontalGlue());
    frame.add(box, BorderLayout.SOUTH);
    frame.setSize(300, 200);
    frame.setVisible(true);
  }
}&lt;/pre&gt;
&lt;p&gt;&lt;img src="http://blogs.sun.com/CoreJavaTechTips/resource/hBoxBefore.png"&gt;&lt;br&gt;
   &lt;img src="http://blogs.sun.com/CoreJavaTechTips/resource/hBoxAfter.png"&gt;&lt;/p&gt;

&lt;p&gt;Trying not to confuse you too much, but the example is back to
  using &lt;code&gt;JButton&lt;/code&gt; components.&lt;/p&gt;
&lt;h3&gt;Alignment&lt;/h3&gt;
&lt;p&gt;Life gets interesting with &lt;code&gt;Box/BoxLayout&lt;/code&gt; when the components within the
  container are a different size or the height/width of the container is
  wider than necessary for a vertical box or taller than necessary with a
  horizontal one. In other words, if you have a tall column, where do
  components of a different width end up? And, if you have a wide row
  with components of a different height, how about them?&lt;/p&gt;

&lt;p&gt;This is where the different alignments of a component come into play.
  Each Swing component has an &lt;code&gt;X-alignment&lt;/code&gt; setting and a &lt;code&gt;Y-alignment&lt;/code&gt; setting
  thanks to its &lt;code&gt;get/setAlignmentX()&lt;/code&gt; and &lt;code&gt;get/setAlignmentY()&lt;/code&gt; methods. The
  range of each setting is from &lt;code&gt;0&lt;/code&gt; to &lt;code&gt;1.0&lt;/code&gt;, inclusive, where &lt;code&gt;0&lt;/code&gt; represents left
  or top alignment and &lt;code&gt;1&lt;/code&gt; represents right or bottom alignment, depending
  upon direction of &lt;code&gt;BoxLayout&lt;/code&gt;. There are constants available in the
  &lt;code&gt;Component&lt;/code&gt; class so you don't really need to know what the values are
  for right and left alignment. However, it does help to know if you
  might want something in between.&lt;/p&gt;

&lt;p&gt;To demonstrate the right, left, center nature of different size buttons
  in a vertical box, the following program creates three boxes, one each
  filled with left, center, and right aligned buttons.&lt;/p&gt;
&lt;pre&gt;
import java.awt.*;
import javax.swing.*;

public class AlignX {

  private static Container makeIt(String labelChar, float alignment) {
    Box box = Box.createVerticalBox();

    for (int i=1; i&amp;lt;6; i++) {
      String label = makeLabel(labelChar, i*2);
      JButton button = new JButton(label);
      button.setAlignmentX(alignment);
      box.add(button);
    }
    return box;
  }

  private static String makeLabel(String s, int length) {
    StringBuffer buff = new StringBuffer(length);
    for (int i=0; i&amp;lt;length; i++) {
      buff.append(s);
    }
    return buff.toString();
  }

  public static void main(String args[]) {
    JFrame frame = new JFrame("X Alignment");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    Container panel1 = makeIt("L", Component.LEFT_ALIGNMENT);
    Container panel2 = makeIt("C", Component.CENTER_ALIGNMENT);
    Container panel3 = makeIt("R", Component.RIGHT_ALIGNMENT);

    frame.setLayout(new FlowLayout());
    frame.add(panel1);
    frame.add(panel2);
    frame.add(panel3);

    frame.pack();
    frame.setVisible(true);
  }
}&lt;/pre&gt;
&lt;p&gt;&lt;img src="http://blogs.sun.com/CoreJavaTechTips/resource/alignX.png"&gt;&lt;/p&gt;
&lt;p&gt;Now, let us mix things up a little and have one vertical box with three
  buttons, one for each alignment. The screen width will be wide, to make
  sure there is extra space available. Conceptually thinking, one would
  expect the component with left alignment to be aligned to the left of
  the container and the one with right alignment to be aligned to the
  right of the container. That would be wrong though. When there are
  different component alignments, they are aligned to the center of
  the container. So, for left alignment, that component will have its
  left edge on the invisible center line of the container. For right
  alignment, it is the right edge.&lt;/p&gt;
&lt;p&gt;Here's the program to demonstrate:&lt;/p&gt;
&lt;pre&gt;
import java.awt.*;
import javax.swing.*;

public class AlignX2 {

  public static void main(String args[]) {
    JFrame frame = new JFrame("X Alignment");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    Box box = Box.createVerticalBox();
    JButton button = new JButton("LL");
    button.setAlignmentX(Component.LEFT_ALIGNMENT);
    box.add(button);
    button = new JButton("CC");
    button.setAlignmentX(Component.CENTER_ALIGNMENT);
    box.add(button);
    button = new JButton("RR");
    button.setAlignmentX(Component.RIGHT_ALIGNMENT);
    box.add(button);
    frame.add(box, BorderLayout.CENTER);

    frame.setSize(300, 200);
    frame.setVisible(true);}
}
&lt;/pre&gt;
&lt;p&gt;And, the corroborating screen:&lt;/p&gt;

&lt;p&gt;&lt;img src="http://blogs.sun.com/CoreJavaTechTips/resource/alignDiffX.png"&gt;&lt;/p&gt;
&lt;p&gt;Working in the other direction has top alignment aligning the top
  of the component to the imaginary center line, or in other words below
  the center. &lt;/p&gt;
&lt;p&gt;Mixing up alignments in this fashion works fine, but just takes some
  getting used to, as the alignment isn't necessarily where you would
  expect it to be, unless all the alignments are the same, and then it
  does align to the container border, as opposed to the container center
  line.&lt;/p&gt;
&lt;p&gt;If you are still confused, feel free to modify the earlier programs
  and try even more combinations of &lt;code&gt;x&lt;/code&gt; and &lt;code&gt;y&lt;/code&gt; alignment. Of course, if
  all this baffles you, there is always &lt;code&gt;GridBagLayout&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;******&lt;/p&gt;
&lt;a href="http://slurl.com/secondlife/Sun%20Microsystems/127/26/62"&gt;SDN Chat: Meet the Writers of java.sun.com&lt;/a&gt;&lt;br&gt;
Please join us in &lt;a href="http://slurl.com/secondlife/Sun%20Microsystems/127/26/62"&gt;Sun's Developer Playground&lt;/a&gt; in &lt;a href="http://www.secondlife.com"&gt;Second Life&lt;/a&gt; on Thursday, &lt;b&gt;February 14 at 10am PST&lt;/b&gt; to meet the writers of java.sun.com. Ed Ort, Dana Nourie, Janice Heiss, and Laureen Hudson will be inworld to discuss their adventures in writing for one of the industry's most popular websites and to share the technologies and trends they'll be keeping their eyes on in 2008. And, for the first time, SMI Press is pleased to offer attendees one of three new SMI Press books for free! 
&lt;/p&gt;&lt;br&gt;&lt;img src="http://feeds.feedburner.com/~r/corejavatechtips/~4/234035888" height="1" width="1"/&gt;</content>
    <feedburner:origLink>http://blogs.sun.com/CoreJavaTechTips/entry/getting_to_know_boxlayout</feedburner:origLink></entry>
    <entry>
        <id>http://blogs.sun.com/CoreJavaTechTips/entry/sorting_strings</id>
        <title type="html">Sorting Strings</title>
        <author><name>dananourie</name></author>
        <link rel="alternate" type="text/html" href="http://feeds.feedburner.com/~r/corejavatechtips/~3/221873025/sorting_strings" />
        <published>2008-01-23T13:41:51-08:00</published>
        <updated>2008-01-23T13:41:51-08:00</updated> 
        <category term="/TechTip" label="TechTip" />
        <category term="java" scheme="http://rollerweblogger.org/ns/tags/" />
        <category term="sorting" scheme="http://rollerweblogger.org/ns/tags/" />
        <category term="strings" scheme="http://rollerweblogger.org/ns/tags/" />
        <summary type="html">Sorting strings with the Java platform can be thought of
as an easy task, but there is much more thought that should
be put into it when developing programs for an international
market. </summary>
        <content type="html">by John Zukowski
&lt;p&gt;

Sorting strings with the Java platform can be thought of
as an easy task, but there is much more thought that should
be put into it when developing programs for an international
market. If you're stuck in the English-only mindset, and you
think your program works fine because it shows that the string
tomorrow comes after today, you might think all is great. But,
once you have a Spanish user who wants mañana to be sorted
properly, if all you use is the default &lt;code&gt;compare()&lt;/code&gt; method of String
for sorting, the ñ character will come after the z character
and will not be the natural Spanish ordering, between the n character
and o character. That's where the Collator class of the &lt;code&gt;java.text&lt;/code&gt;
package comes into play.
&lt;/p&gt;
&lt;p&gt;
Imagine a list of words
&lt;ul&gt;
&lt;li&gt; first
&lt;li&gt; mañana
&lt;li&gt; man
&lt;li&gt; many
&lt;li&gt; maxi
&lt;li&gt; next
&lt;/ul&gt;
&lt;/p&gt;
&lt;p&gt;
Using the default sorting mechanism of &lt;code&gt;String&lt;/code&gt;, its &lt;code&gt;compare()&lt;/code&gt; method,
this will result in a sorted list of:
&lt;ul&gt;
&lt;li&gt; first
&lt;li&gt; man
&lt;li&gt; many
&lt;li&gt; maxi
&lt;li&gt; mañana
&lt;li&gt; next
&lt;/ul&gt;
&lt;/p&gt;
&lt;p&gt;
Here, mañana comes between maxi and next. In the Spanish world, what
should happen is mañana should come between many and maxi as the ñ character
(pronounced eñe) comes after the n in that alphabet. While you could write
your own custom sort routine to handle the ñ, what happens to your program
when a German user comes around and wants to use their own diacritical
marks, or what about just a list of design patterns with façade? Do
you want façade before or after factory? (Essentially treating the
ç with the little cedilla hook the same as c or different.)
&lt;/p&gt;
&lt;p&gt;

That's where the &lt;code&gt;Collator&lt;/code&gt; class comes in handy. The &lt;code&gt;Collator&lt;/code&gt; class
takes into account language-sensitive sorting issues and doesn't just
try to sort words based upon their ASCII/Unicode character values.
Using &lt;code&gt;Collator&lt;/code&gt; requires understanding one additional property before
you can fully utilize its features, and that is something called
strength. The strength setting of the &lt;code&gt;Collator&lt;/code&gt; determines how
strong (or weak) a match is used for ordering. There are four possible
values for the property: PRIMARY, SECONDARY, TERTIARY, and IDENTICAL.
What actually happens with each is dependent on the locale. Typically
what happens is as follows. In reverse order, IDENTICAL strength means
just that, the characters must be identical for them to be treated the
same. TERTIARY typically is for ignoring case differences. SECONDARY
is for ignoring diacritical marks, like n vs. ñ. PRIMARY is like
IDENTICAL for base letter differences, but has some differences when
handling control characters and accents. See the &lt;code&gt;Collator&lt;/code&gt; javadoc
for more information on these differences and decomposition mode rules.
&lt;/p&gt;
&lt;p&gt;
To work with &lt;code&gt;Collator&lt;/code&gt;, you need to start by getting one. You can either
call &lt;code&gt;getInstance()&lt;/code&gt; to get one for the default locale, or pass the
specific &lt;code&gt;Locale&lt;/code&gt; to the &lt;code&gt;getInstance()&lt;/code&gt; method to get a locale for
the one provided. For instance, to get one for the Spanish language,
you would create a Spanish &lt;code&gt;Locale&lt;/code&gt; with new &lt;code&gt;Locale("es")&lt;/code&gt; and then
pass that into &lt;code&gt;getInstance()&lt;/code&gt;:
&lt;/p&gt;
&lt;pre&gt;
 Collator esCollator =
   Collator.getInstance(new Locale("es"));
&lt;/pre&gt;
&lt;p&gt;
Assuming the default &lt;code&gt;Collator&lt;/code&gt; strength for the locale is sufficient,
which happens to be SECONDARY for Spanish,
you would then pass the &lt;code&gt;Collator&lt;/code&gt; like any &lt;code&gt;Comparator&lt;/code&gt; into the
&lt;code&gt;sort()&lt;/code&gt; routine of &lt;code&gt;Collections&lt;/code&gt; to get your sorted &lt;code&gt;List&lt;/code&gt;:
&lt;/p&gt;
&lt;pre&gt;
 Collections.sort(list, esCollator);
&lt;/pre&gt;
&lt;p&gt;
Working with the earlier list, that now gives you a proper
sorting with the Spanish alphabet:
&lt;/p&gt;
&lt;ul&gt;

&lt;li&gt; first
&lt;li&gt; man
&lt;li&gt; many
&lt;li&gt; mañana
&lt;li&gt; maxi
&lt;li&gt; next
&lt;/ul&gt;
&lt;/p&gt;
&lt;p&gt;
Had you instead used the US Locale for the &lt;code&gt;Collator&lt;/code&gt;, mañana would
appear between man and many since the ñ is not its own letter.
&lt;/p&gt;
&lt;p&gt;
Here's a quick example that shows off the differences.
&lt;/p&gt;
&lt;pre&gt;
import java.awt.*;
import java.text.*;
import java.util.*;
import java.util.List; // Explicit import required
import javax.swing.*;

public class Sort {
 public static void main(String args[]) {
   Runnable runner = new Runnable() {
     public void run() {
       String words[] = {"first", "mañana", "man",
                         "many", "maxi", "next"};
       List&lt;String&gt; list = Arrays.asList(words);
       JFrame frame = new JFrame("Sorting");
       frame.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
       Box box = Box.createVerticalBox();
       frame.setContentPane(box);
       JLabel label = new JLabel("Word List:");
       box.add(label);
       JTextArea textArea = new JTextArea( list.toString());
       box.add(textArea);
       Collections.sort(list);
       label = new JLabel("Sorted Word List:");
       box.add(label);
       textArea = new JTextArea(list.toString ());
       box.add(textArea);
       Collator esCollator = Collator.getInstance(new Locale("es"));
       Collections.sort(list, esCollator);
       label = new JLabel("Collated Word List:");
       box.add(label);
       textArea = new JTextArea(list.toString());
       box.add(textArea);
       frame.setSize(400, 200);
       frame.setVisible(true);
     }
   };
   EventQueue.invokeLater (runner);
 }
}
&lt;/pre&gt;
&lt;p&gt;&lt;center&gt;
&lt;img src="http://blogs.sun.com/CoreJavaTechTips/resource/sorting.png"&gt;
&lt;/p&gt;&lt;/center&gt;
&lt;p&gt;
One last little bit of information about collation. The
&lt;code&gt;Collator&lt;/code&gt; returned by the &lt;code&gt;getInstance()&lt;/code&gt; call is typically an instance
of &lt;code&gt;RuleBasedCollator&lt;/code&gt; for the supported languages. You can use
&lt;code&gt;RuleBasedCollator&lt;/code&gt; to define your own collation sequences. The javadoc
for the class describes the rule syntax more completely, but lets say
you had a four character alphabet and wanted the order of the letters
to be CAFE instead of ACEF, your rule would look something like:
&lt;/p&gt;
&lt;pre&gt;
 String rule =
   "&lt; c, C &lt; a, A &lt; f, F &lt; e, E";
 RuleBasedCollator collator = new RuleBasedCollator(rule);
&lt;/pre&gt;
&lt;p&gt;
This defines the explicit order as cafe, with the different letter
cases shown. Now, for a list of words of ace, cafe, ef, and face,
the resultant sort order is cafe, ace, face, and ef with the new rules:
&lt;/p&gt;
&lt;pre&gt;
import java.text.*;
import java.util.*;

public class Rule {
 public static void main(String args[]) throws ParseException {
   String words[] = {"ace", "cafe", "ef", "face"};
   String rule ="&lt; c, C &lt; a, A &lt; f, F &lt; e, E";
   RuleBasedCollator collator = new RuleBasedCollator(rule);
   List&lt;String&gt; list = Arrays.asList(words);
   Collections.sort(list, collator);
   System.out.println(list);
 }
}
&lt;/pre&gt;
&lt;p&gt;
After compiling and running, you see the words sorted with the new
rules:
&lt;/p&gt;
&lt;pre&gt;
&gt; javac Rule.java
&gt; java Rule
[cafe, ace, face, ef]
&lt;/pre&gt;
&lt;p&gt;
After reading the rule syntax some more in the javadocs, try to expand the
alphabet and work with the different diacritical marks, too.
&lt;/p&gt;
&lt;p&gt;
Now, when developing programs for the global world, your programs
can be better prepared to suit the local user. Be sure to keep strings
in resource bundles, too, as shown in an earlier tip:
&lt;/p&gt;
&lt;p&gt;
&lt;a href"http://java.sun.com/developer/TechTips/1998/tt0521.html#tip2"&gt;Earlier tip&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
*********&lt;p&gt;
&lt;img src="http://www.sun.com/images/l2/l2_try-glassfish.gif" align="left"&gt;
&lt;a href="http://java.sun.com/javaee/community/campaigns/iphone-012008/welcome.jsp"&gt;Connect and Participate With GlassFish&lt;/a&gt;&lt;br&gt;

Try GlassFish for a chance to win an iPhone. This sweepstakes ends on March 23, 2008. Submit your entry today. &lt;/p&gt;
&lt;br clear="all"&gt;
&lt;p&gt; 
&lt;a href="http://java.sun.com/developer/media/deepdivebluray.jsp"&gt;Foote on Blu-ray Disc Java&lt;/a&gt; In this video interview, Sun's Blu-ray Disc Java (BDJ) architect Bill Foote talks about this powerful technology and shows some examples of BDJ code and applications. &lt;A href="https://hdcookbook.dev.java.net"&gt;Download the code&lt;/a&gt;
&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/corejavatechtips/~4/221873025" height="1" width="1"/&gt;</content>
    <feedburner:origLink>http://blogs.sun.com/CoreJavaTechTips/entry/sorting_strings</feedburner:origLink></entry>
    <entry>
        <id>http://blogs.sun.com/CoreJavaTechTips/entry/quiz_answers</id>
        <title type="html">Quiz Answers</title>
        <author><name>dananourie</name></author>
        <link rel="alternate" type="text/html" href="http://feeds.feedburner.com/~r/corejavatechtips/~3/213319558/quiz_answers" />
        <published>2008-01-08T09:38:25-08:00</published>
        <updated>2008-01-08T09:38:25-08:00</updated> 
        <category term="/TechTip" label="TechTip" />
        <summary type="html">Answers to Quiz</summary>
        <content type="html">&lt;b&gt;Answers&lt;/b&gt;
&lt;/p&gt;
&lt;p&gt;
1. Given two objects &lt;code&gt;one&lt;/code&gt; and &lt;code&gt;two&lt;/code&gt; of &lt;code&gt;BigDecimal&lt;/code&gt; type, how do you multiply the two factors to calculate a product in object &lt;code&gt;three&lt;/code&gt;? Answer: D&lt;br&gt;
To generate the product of two variables of &lt;code&gt;BigDecimal&lt;/code&gt; type, use the &lt;code&gt;multiply()&lt;/code&gt; method of &lt;code&gt;BigDecimal&lt;/code&gt;. This was shown in &lt;a href="http://java.sun.com/mailers/techtips/corejava/2007/tt0707.html#2" target="_blank"&gt;&lt;/a&gt;"The Need for &lt;code&gt;BigDecimal&lt;/code&gt;"&lt;/a&gt; (July 2007), which also discussed formatting and rounding issues.
&lt;/p&gt;
&lt;p&gt;
2. In order to write the line &lt;code&gt;System.out.println("Pi = " + PI)&lt;/code&gt;, what must the import statement be so that the compiler will locate &lt;code&gt;PI&lt;/code&gt; in the &lt;code&gt;Math&lt;/code&gt; class? Answer: C&lt;br&gt;
Use static import statements to tell the compiler about constants and methods you wish to use without explicitly specifying the class they come from. See &lt;a href="http://java.sun.com/developer/JDCTechTips/2004/tt1005.html#1" target="_blank"&gt;&lt;/a&gt;"Using Static Imports for Constants and Methods"&lt;/a&gt; (October 2004) for more information on working with static imports.
&lt;/p&gt;
&lt;p&gt;
3. When using an enhanced &lt;code&gt;for&lt;/code&gt; loop (also known as a &lt;code&gt;foreach&lt;/code&gt; statement), what interface must the element following the colon (:) implement in order for the construct to compile and execute appropriately? Answer: B&lt;br&gt;
The argument must implement the &lt;code&gt;Iterable&lt;/code&gt; interface, which consists of a single method, to get an iterator:
&lt;/p&gt;
&lt;p&gt;
&lt;code&gt;  Iterator&lt;T&gt; iterator()&lt;/code&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://java.sun.com/developer/JDCTechTips/2005/tt0505.html#2" target="_blank"&gt;"The Enhanced &lt;code&gt;For&lt;/code&gt; Loop"&lt;/a&gt; (May 2005) started the discussion of using the enhanced &lt;code&gt;for&lt;/code&gt; loop. The use of &lt;code&gt;Iterable&lt;/code&gt; was discussed later in &lt;a href="http://java.sun.com/mailers/techtips/corejava/2007/tt0907.html#1" target="_blank"&gt;"Using Enhanced For-Loops With Your Classes"&lt;/a&gt; (September 2007).
&lt;/p&gt;
&lt;p&gt;
4. When two Swing components overlap in their display area, how do you control which component is drawn on top? Answer: C&lt;br&gt;
Z-order represents the layering of the components on the screen, where x and y coordinates are for horizontal and vertical positioning, respectively. By calling the &lt;code&gt;setComponentZOrder()&lt;/code&gt; method of the &lt;code&gt;Container&lt;/code&gt; for each component that overlaps, you can explicitly control which components are drawn on top of which other components. See &lt;a href="http://java.sun.com/developer/JDCTechTips/2005/tt0118.html#1" target="_blank"&gt;"Let There Be Z-Order" tip&lt;/a&gt; (January 2005) for additional information on controlling the z-order layering.
&lt;/p&gt;
&lt;p&gt;
5. What is the best way to monitor the progress of image reading when using the Java Image I/O API? Answer: C&lt;br&gt;
Although you can certainly display progress with a &lt;code&gt;Progress Monitor&lt;/code&gt;, the best way to set up notification of such progress is by using a &lt;code&gt;IIOReadProgressListener&lt;/code&gt;. &lt;a href="http://java.sun.com/mailers/techtips/corejava/2007/tt0207.html#2" target="_blank"&gt;"Monitoring Image I/O Events"&lt;/a&gt; (February 2007) covered this notification as well as region-update notifications.
&lt;/p&gt;
&lt;p&gt;&lt;img src="http://feeds.feedburner.com/~r/corejavatechtips/~4/213319558" height="1" width="1"/&gt;</content>
    <feedburner:origLink>http://blogs.sun.com/CoreJavaTechTips/entry/quiz_answers</feedburner:origLink></entry>
    <entry>
        <id>http://blogs.sun.com/CoreJavaTechTips/entry/january_2008_core_java_tech</id>
        <title type="html">January 2008 Core Java Tech Tips Quiz</title>
        <author><name>dananourie</name></author>
        <link rel="alternate" type="text/html" href="http://feeds.feedburner.com/~r/corejavatechtips/~3/213319559/january_2008_core_java_tech" />
        <published>2008-01-08T09:37:29-08:00</published>
        <updated>2008-01-08T09:39:52-08:00</updated> 
        <category term="/TechTip" label="TechTip" />
        <category term="api" scheme="http://rollerweblogger.org/ns/tags/" />
        <category term="java" scheme="http://rollerweblogger.org/ns/tags/" />
        <category term="swing" scheme="http://rollerweblogger.org/ns/tags/" />
        <summary type="html">We've made it through another year, and it's time for another tech tips quiz.</summary>
        <content type="html">by John Zukowski
&lt;p&gt;
We've made it through another year, and it's time for another tech tips quiz. The last two -- &lt;a href="http://java.sun.com/mailers/techtips/corejava/2006/tt0620.html#2" target="_blank"&gt;June 2006&lt;/a&gt;
 and &lt;a href="http://java.sun.com/developer/JDCTechTips/2005/tt0913.html#2" target="_blank"&gt;September 2005&lt;/a&gt; -- were popular refreshers of past tips and tricks. Here are another five questions for you. Don't look too far ahead, as the answers are at the end of this entry.
&lt;/p&gt;
&lt;p&gt;
1. Given two objects &lt;code&gt;one&lt;/code&gt; and &lt;code&gt;two&lt;/code&gt; of &lt;code&gt;BigDecimal&lt;/code&gt; type, how do you multiply the two factors to calculate a product in object &lt;code&gt;three&lt;/code&gt;?
&lt;/p&gt;
&lt;p&gt;
 a. &lt;code&gt;BigDecimal three = one * two;&lt;/code&gt;&lt;br&gt;
 b. &lt;code&gt;BigDecimal three = one.*(two);&lt;/code&gt;&lt;br&gt;
 c. &lt;code&gt;BigDecimal three = one.times(two);&lt;/code&gt;&lt;br&gt;
 d. &lt;code&gt;BigDecimal three = one.multiply(two);&lt;code&gt;&lt;br&gt;
&lt;/p&gt;
&lt;p&gt;
2. In order to write the line &lt;code&gt;System.out.println("Pi = " + PI)&lt;/code&gt;, what must the import statement be so that the compiler will locate &lt;code&gt;PI&lt;/code&gt; in the &lt;code&gt;Math&lt;/code&gt; class?
&lt;/p&gt;
&lt;p&gt;
 a. &lt;code&gt;import java.lang.Math;&lt;/code&gt;&lt;br&gt;
 b. &lt;code&gt;import java.lang.Math.PI;&lt;/code&gt;&lt;br&gt;
 c. &lt;code&gt;import static java.lang.Math.PI;&lt;/code&gt;&lt;br&gt;
 d. &lt;code&gt;import final java.lang.Math.PI;&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;
&lt;p&gt;
3. When using an enhanced &lt;code&gt;for&lt;/code&gt; loop (also known as a &lt;code&gt;foreach&lt;/code&gt; statement), what interface must the element following the colon (:) implement in order for the construct to compile and execute appropriately?
&lt;/p&gt;
&lt;p&gt;
 a. &lt;code&gt;Enumeration&lt;/code&gt;&lt;br&gt;
 b. &lt;code&gt;Iterable&lt;/code&gt;&lt;br&gt;
 c. &lt;code&gt;Iterator&lt;/code&gt;&lt;br&gt;
 d. &lt;code&gt;Collection&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;
&lt;p&gt;
4. When two Swing components overlap in their display area, how do you control which component is drawn on top?
&lt;/p&gt;
&lt;p&gt;
 a. The component added to the container first is drawn on top.&lt;br&gt;
 b. The component added to the container last is drawn on top.&lt;br&gt;
 c. You call the &lt;code&gt;setComponentZOrder()&lt;/code&gt; method of the container.&lt;br&gt;
 d. You call the &lt;code&gt;setComponentZOrder()&lt;/code&gt; method for each component.&lt;br&gt;
&lt;/p&gt;
&lt;p&gt;
5. What is the best way to monitor the progress of image reading when using the Java Image I/O API?
&lt;/p&gt;
&lt;p&gt;
 a. Create a &lt;code&gt;FilteredReader&lt;/code&gt; subclass to count the bytes.&lt;br&gt;
 b. Attach a &lt;code&gt;ProgressMonitorListener&lt;/code&gt; to the &lt;code&gt;ImageReader&lt;/code&gt; to report progress.&lt;br&gt;
 c. Attach an &lt;code&gt;IIOReadProgressListener&lt;/code&gt; to the &lt;code&gt;ImageReader&lt;/code&gt; for progress reporting.&lt;br&gt;
 d. Register a &lt;code&gt;Runnable&lt;/code&gt; with the &lt;code&gt;ImageReader&lt;/code&gt; and tell it how frequently to execute.&lt;br&gt;
&lt;/p&gt;
&lt;p&gt;Check your answers &lt;a href="http://blogs.sun.com/CoreJavaTechTips/entry/quiz_answers"&gt;here&lt;/a&gt;.&lt;img src="http://feeds.feedburner.com/~r/corejavatechtips/~4/213319559" height="1" width="1"/&gt;</content>
    <feedburner:origLink>http://blogs.sun.com/CoreJavaTechTips/entry/january_2008_core_java_tech</feedburner:origLink></entry>
    <entry>
        <id>http://blogs.sun.com/CoreJavaTechTips/entry/placing_components_on_tabs2</id>
        <title type="html">Placing Components on Tabs</title>
        <author><name>dananourie</name></author>
        <link rel="alternate" type="text/html" href="http://feeds.feedburner.com/~r/corejavatechtips/~3/210661353/placing_components_on_tabs2" />
        <published>2008-01-02T11:36:08-08:00</published>
        <updated>2008-01-02T11:36:08-08:00</updated> 
        <category term="/TechTip" label="TechTip" />
        <category term="applications" scheme="http://rollerweblogger.org/ns/tags/" />
        <category term="desktop" scheme="http://rollerweblogger.org/ns/tags/" />
        <category term="java" scheme="http://rollerweblogger.org/ns/tags/" />
        <category term="swing" scheme="http://rollerweblogger.org/ns/tags/" />
        <summary type="html">Learn how to create a &lt;code&gt;JTabbedPane&lt;/code&gt; component container that accepts components placed within a panel for each tab.</summary>
        <content type="html">&lt;br&gt;by John Zukowski

&lt;p&gt;The &lt;code&gt;JTabbedPane&lt;/code&gt; component is a special Swing
container that accepts components to be placed within a panel for
each tab. Select a tab to see that tab's components. Technically
speaking, one component is associated with each tab. However, that
component is typically a panel that contains others. Identification
for each tab is done with title text and an icon, settable per tab.
The first Core Java Technologies Tech Tip to discuss the
&lt;code&gt;JTabbedPane&lt;/code&gt; component was published in July 2001, with
a &lt;a
href="http://java.sun.com/developer/JDCTechTips/2001/tt0712.html#tip
1" target="_blank"&gt;simple introductory tip&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;The methods of &lt;code&gt;JTabbedPane&lt;/code&gt; to support the use of
components on tabs are as follows: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;public void setTabComponentAt(int index, Component component)&lt;/code&gt;
&lt;li&gt;&lt;code&gt;public Component getTabComponentAt(int index)&lt;/code&gt;
&lt;li&gt;&lt;code&gt;public int indexOfTabComponent(Component tabComponent)&lt;/code&gt;
&lt;/ul&gt;

&lt;p&gt;The first method associates the component with a tab; the second
gets it back; and the last one tells you which tab is associated
with the component, if any. Typically, you use only the first
method, but the others are available. &lt;/p&gt;

&lt;p&gt;To get started with the task at hand, it is helpful to have an
Icon implementation that draws a little x on it. You could just use
the letter x as the button label, but you should avoid that option.
Typically, when a user sees an x in a box, this
signals a command to close a window, so it serves as a good
indicator for closing a tab. &lt;/p&gt;

&lt;pre&gt;
class CloseIcon implements Icon {
  public void paintIcon(Component c, Graphics g, int x, int y) {
    g.setColor(Color.RED);
    g.drawLine(6, 6, getIconWidth() - 7, getIconHeight() - 7);
    g.drawLine(getIconWidth() - 7, 6, 6, getIconHeight() - 7);
  }
  public int getIconWidth() {
    return 17;
  }
  public int getIconHeight() {
    return 17;
  }
}
&lt;/pre&gt;

&lt;p&gt;Before creating the special tab component, let's put together the
program's framework, one that creates a frame with a
&lt;code&gt;JTabbedPane&lt;/code&gt; on it and adds a number of tabs:&lt;/p&gt;

&lt;pre&gt;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class CloseTabs {
  public static void main(String args[]) {
    Runnable runner = new Runnable() {
      public void run() {
        JFrame frame = new JFrame("JTabbedPane");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        JTabbedPane jtp = new JTabbedPane();
        frame.add(jtp, BorderLayout.CENTER);
        for (int i=0; i&lt;5; i++) {
          JButton button = new JButton("Card " + i);
          jtp.add("Btn " + i, button);
          // new CloseTabButton(jtp, i);
        }
        frame.setSize(400, 200);
        frame.setVisible(true);
      }
    };
    EventQueue.invokeLater(runner);
  }
}
&lt;/pre&gt;

&lt;p&gt; This program creates five tabs, each with a &lt;code&gt;JButton&lt;/code&gt;
on it. The tab title is "Btn" followed by the tab position.  &lt;/p&gt;

&lt;p&gt;&lt;center&gt;
&lt;img src="http://blogs.sun.com/CoreJavaTechTips/resource/original.png"&gt;
&lt;/center&gt;&lt;/p&gt;

&lt;p&gt;The program will run fine without doing anything else, but it
doesn't have the close button on each tab. To add a close button to
the tab, you need to retain the tab's title text and icon, while
adding a button with the &lt;code&gt;CloseIcon&lt;/code&gt; previously shown.
(The
example does not use the tab's icon, but the class definition
includes one so that it can be reused beyond this example.) As the
final part of the definition, you need an
&lt;code&gt;ActionListener&lt;/code&gt; for the button to handle when it is
pressed, so that when the user presses the button, the tab is
removed from the pane. &lt;/p&gt;

&lt;pre&gt;
class CloseTabButton extends JPanel implements ActionListener {
  private JTabbedPane pane;
  public CloseTabButton(JTabbedPane pane, int index) {
    this.pane = pane;
    setOpaque(false);
    add(new JLabel(
        pane.getTitleAt(index),
        pane.getIconAt(index),
        JLabel.LEFT));
    Icon closeIcon = new CloseIcon();
    JButton btClose = new JButton(closeIcon);
    btClose.setPreferredSize(new Dimension(
        closeIcon.getIconWidth(), closeIcon.getIconHeight()));
    add(btClose);
    btClose.addActionListener(this);
    pane.setTabComponentAt(index, this);
  }
  public void actionPerformed(ActionEvent e) {
    int i = pane.indexOfTabComponent(this);
    if (i != -1) {
      pane.remove(i);
    }
  }
}
&lt;/pre&gt;

&lt;p&gt;You can now reuse the &lt;code&gt;CloseTabButton&lt;/code&gt; in your own
tabbed panes. &lt;/p&gt;
&lt;p&gt;
&lt;center&gt;
&lt;img src="http://blogs.sun.com/CoreJavaTechTips/resource/close.png"&gt;
&lt;/center&gt;&lt;/p&gt;

&lt;p&gt;
For more information on the use of tabbed panes, see the &lt;a href="http://java.sun.com/tutorial/uiswing/components/tabbedpane.html" target="_blank"&gt;How to Use Tabbed
Panes&lt;/a&gt; lesson in The Java Tutorial.
&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/corejavatechtips/~4/210661353" height="1" width="1"/&gt;</content>
    <feedburner:origLink>http://blogs.sun.com/CoreJavaTechTips/entry/placing_components_on_tabs2</feedburner:origLink></entry>
    <entry>
        <id>http://blogs.sun.com/CoreJavaTechTips/entry/tech_days_comes_back_to</id>
        <title type="html">Tech Days Comes Back to the USA</title>
        <author><name>dananourie</name></author>
        <link rel="alternate" type="text/html" href="http://feeds.feedburner.com/~r/corejavatechtips/~3/204116303/tech_days_comes_back_to" />
        <published>2007-12-12T13:45:35-08:00</published>
        <updated>2007-12-12T13:45:35-08:00</updated> 
        <category term="/News" label="News" />
        <category term="days" scheme="http://rollerweblogger.org/ns/tags/" />
        <category term="ee" scheme="http://rollerweblogger.org/ns/tags/" />
        <category term="glassfish" scheme="http://rollerweblogger.org/ns/tags/" />
        <category term="gosling" scheme="http://rollerweblogger.org/ns/tags/" />
        <category term="java" scheme="http://rollerweblogger.org/ns/tags/" />
        <category term="sessions" scheme="http://rollerweblogger.org/ns/tags/" />
        <category term="solaris" scheme="http://rollerweblogger.org/ns/tags/" />
        <category term="tech" scheme="http://rollerweblogger.org/ns/tags/" />
        <summary type="html">On January 9 &amp; 10, the Tech Days Conference will be in Atlanta Georgia. (FREE!)</summary>
        <content type="html">On January 9 &amp; 10, the Tech Days Conference will be in Atlanta Georgia. (FREE!)
&lt;/p&gt;
&lt;p&gt;
Advance your development ability and shape your future with cutting-edge technical education; Sun Tech Days are loaded with practical information, examples of real-world solutions, and hands-on training. Whatever your focus, you'll find sessions to take your skills to the next level and advance your career.
&lt;/p&gt;
&lt;p&gt;
In addition, Tech Days has hands-on labs to ensure you can use specific technologies, and so you can ask the questions you need to. There will also be a Q &amp; A session with James Gosling, and a Featured Keynote by Jeet Kaul.
&lt;/p&gt;
&lt;p&gt;
The sessions that will be covered:
&lt;/p&gt;
&lt;p&gt;
    &lt;b&gt; Java Development Tracks&lt;/b&gt;
&lt;ul&gt;
    &lt;li&gt;  Java EE 6 and GlassFish
    &lt;li&gt; Java SE 6 Top 10 features, Java SE 7 and OpenJDK
    &lt;li&gt; Next Generation Web and Java Server Faces
    &lt;li&gt; Consumer JRE: Java on Every Desktop OR Java Performance Myths
    &lt;li&gt; Java ME: Extreme GUI Makeover for Mobile Phones
    &lt;li&gt; SOA using OpenESB and JCAP
    &lt;li&gt; Java Scripting: JavaFX Script and JRuby &lt;/ul&gt;
&lt;/p&gt;
&lt;p&gt;
    &lt;b&gt;Solaris Development Track&lt;/b&gt; 
    &lt;li&gt; What Makes Solaris Interesting?
    &lt;li&gt; Sun Studio Tools
    &lt;li&gt; OpenSolaris Security Frameworks
    &lt;li&gt; Integrating ZFS Into Your Applications
    &lt;li&gt; Security Features in Solaris
    &lt;li&gt; How To Develop Solaris Parallel Applications
    &lt;li&gt; Solaris Networking For Developers &lt;/ul&gt;
&lt;/p&gt;
&lt;p&gt;
If you're not familiar with Tech Days and want to learn more, check out the website. In addition to information on this particular event in Georgia, there is also information and resources from previous Tech Days events, including videos, presentations, and more.
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://developers.sun.com/events/techdays/2008/US_ATL.jsp"&gt;Sun Tech Days&lt;/a&gt;
&lt;img src="http://feeds.feedburner.com/~r/corejavatechtips/~4/204116303" height="1" width="1"/&gt;</content>
    <feedburner:origLink>http://blogs.sun.com/CoreJavaTechTips/entry/tech_days_comes_back_to</feedburner:origLink></entry>
    <entry>
        <id>http://blogs.sun.com/CoreJavaTechTips/entry/new_certification_courses</id>
        <title type="html">New Certification Courses</title>
        <author><name>dananourie</name></author>
        <link rel="alternate" type="text/html" href="http://feeds.feedburner.com/~r/corejavatechtips/~3/204116304/new_certification_courses" />
        <published>2007-12-10T10:46:11-08:00</published>
        <updated>2007-12-10T10:46:11-08:00</updated> 
        <category term="/News" label="News" />
        <category term="6" scheme="http://rollerweblogger.org/ns/tags/" />
        <category term="certification" scheme="http://rollerweblogger.org/ns/tags/" />
        <category term="java" scheme="http://rollerweblogger.org/ns/tags/" />
        <category term="jdk" scheme="http://rollerweblogger.org/ns/tags/" />
        <summary type="html">Read about and sign up for these two new certification courses.</summary>
        <content type="html">New Certification Courses

&lt;a href="http://www.sun.com/training/catalog/courses/CX-310-065.xml"&gt;Sun Certified Programmer for the Java Platform, Standard Edition 6&lt;/a&gt;-- The Sun Certified Programmer for Java Platform, Standard Edition 6 certification exam is for programmers experienced using the Java programming language. Achieving this certification provides clear evidence that a programmer understands the basic syntax and structure of the Java programming language and can create Java technology applications that run on server and desktop systems using Java SE 6.&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://www.sun.com/training/catalog/courses/CX-310-066.xml"&gt;Sun Certified Programmer for the Java Platform, Standard Edition 6 Upgrade Exam (CX-310-066)&lt;/a&gt;-- The Sun Certified Programmer for Java Platform, Standard Edition 6 certification exam is for programmers experienced using the Java programming language. Achieving this certification provides evidence that a programmer understands the basic syntax and structure of the Java programming language and can create Java technology applications that run on server and desktop systems using Java Platform, Standard Edition 6 Sun strongly recommends that all new candidates interested in becoming a Sun Certified Java Programmer (SCJP) take this new version of the certification exam, rather than a previous version. In this way, candidates can demonstrate that they are knowledgeable in the latest technology. Sun also recommends that those certified on a previous version of SCJP update their credentials by taking the SCJP 6 Upgrade exam.
&lt;/p&gt;
&lt;p&gt;
******
&lt;p&gt;
&lt;a href="http://slurl.com/secondlife/Sun%20Microsystems/172/162/91" target="_blank"&gt;&lt;img src="http://www.sun.com/images/l2/l2_dananouri_sl.gif" alt="Sun Microsystems Developer Playground - Dana Nourie" width="100" height="88" border="0" style="float: left; margin-right: 10px" /&gt;&lt;/a&gt;

&lt;b&gt;&lt;a href="http://slurl.com/secondlife/Sun%20Microsystems/172/162/91" target="_blank"&gt;Sun Microsystems Developer Playground&lt;/a&gt;&lt;/b&gt;&lt;br /&gt;
Join Dana Nourie December 18th, Tues 9 AM PST and 7 PM PST, in &lt;a href="http://www.secondlife.com" target="_blank"&gt;Second Life&lt;/a&gt; at the &lt;a href="http://slurl.com/secondlife/Sun%20Microsystems/172/162/91" target="_blank"&gt;Sun Microsystems Developer Playground&lt;/a&gt; to discover how easy it is to learn the Java platform through web programming. Watch a demo and have your questions answered.
&lt;/p&gt;
******&lt;img src="http://feeds.feedburner.com/~r/corejavatechtips/~4/204116304" height="1" width="1"/&gt;</content>
    <feedburner:origLink>http://blogs.sun.com/CoreJavaTechTips/entry/new_certification_courses</feedburner:origLink></entry>
    <entry>
        <id>http://blogs.sun.com/CoreJavaTechTips/entry/get_netbeans_6</id>
        <title type="html">Using Callable to Return Results From Runnables</title>
        <author><name>dananourie</name></author>
        <link rel="alternate" type="text/html" href="http://feeds.feedburner.com/~r/corejavatechtips/~3/204116305/get_netbeans_6" />
        <published>2007-12-03T14:59:53-08:00</published>
        <updated>2007-12-04T10:45:06-08:00</updated> 
        <category term="/TechTip" label="TechTip" />
        <category term="callable" scheme="http://rollerweblogger.org/ns/tags/" />
        <category term="netbeans" scheme="http://rollerweblogger.org/ns/tags/" />
        <category term="runnables" scheme="http://rollerweblogger.org/ns/tags/" />
        <summary type="html">Learn about the Callable interface, and its call method to return an Object.</summary>
        <content type="html">by John Zukowski

&lt;p&gt;The &lt;code&gt;Runnable&lt;/code&gt; interface has been around since the
beginning of time for the Java platform. It allows you to define a
task to be completed by a thread. As most people probably know
already, it offers a single method &lt;code&gt;run()&lt;/code&gt; that accepts
no arguments and returns no values, nor can it throw any checked
exceptions. If you need to get a value back from the now-completed
task, you must use a method outside the interface and wait for some
kind of notification message that the task completed. For example,
the following demonstrates what you might do for just such a
scenario:

&lt;pre&gt;
  Runnable runnable = ...;
  Thread t = new Thread(runnable);
  t.start();
  t.join();
  String value = someMethodtoGetSavedValue()
&lt;/pre&gt;

&lt;p&gt;Nothing is inherently wrong with this code, but it can be done
differently now, thanks to the &lt;code&gt;Callable&lt;/code&gt; interface
introduced in J2SE 5.0. Instead of having a &lt;code&gt;run()&lt;/code&gt;
method, the &lt;code&gt;Callable&lt;/code&gt; interface offers a
&lt;code&gt;call()&lt;/code&gt; method, which can return an Object or, more
specifically, any type that is introduced in the genericized form:

&lt;pre&gt;
  public interface Callable&amp;lt;V&amp;gt; {
     V call() throws Exception;
  }
&lt;/pre&gt;

&lt;p&gt;Because you cannot pass a &lt;code&gt;Callable&lt;/code&gt; into a
&lt;code&gt;Thread&lt;/code&gt; to execute, you instead use the
&lt;code&gt;ExecutorService&lt;/code&gt; to execute the &lt;code&gt;Callable&lt;/code&gt;
object. The service accepts &lt;code&gt;Callable&lt;/code&gt; objects to run by
way of the &lt;code&gt;submit()&lt;/code&gt; method:

&lt;pre&gt;
  &amp;lt;T&amp;gt; Future&amp;lt;T&amp;gt; submit(Callable&amp;lt;T&amp;gt; task)
&lt;/pre&gt;

&lt;p&gt;As the method definition shows, submitting a Callable object to
the &lt;code&gt;ExecutorService&lt;/code&gt; returns a &lt;code&gt;Future&lt;/code&gt;
object. The &lt;code&gt;get()&lt;/code&gt; method of &lt;code&gt;Future&lt;/code&gt; will
then block until the task is completed. This is the equivalent of
the &lt;code&gt;join()&lt;/code&gt; call in the first example. Actually, it is
the equivalent of both the &lt;code&gt;join()&lt;/code&gt; call and the get
value call as &lt;code&gt;get()&lt;/code&gt; returns the value calculated by the
&lt;code&gt;Callable&lt;/code&gt; instance.

&lt;p&gt;To demonstrate, the following example creates separate
&lt;code&gt;Callable&lt;/code&gt; instances for each word passed in on the
command line and sums up their length. Each &lt;code&gt;Callable&lt;/code&gt;
will just calculate the sum of its individual word. The set of
&lt;code&gt;Future&lt;/code&gt; objects are saved to acquire the calculated
value from each. If the order of the returned values needed to be
preserved, a &lt;code&gt;List&lt;/code&gt; could be used instead.

&lt;pre&gt;
import java.util.*;
import java.util.concurrent.*;

public class CallableExample {

  public static class WordLengthCallable
        implements Callable {
    private String word;
    public WordLengthCallable(String word) {
      this.word = word;
    }
    public Integer call() {
      return Integer.valueOf(word.length());
    }
  }

  public static void main(String args[]) throws Exception {
    ExecutorService pool = Executors.newFixedThreadPool(3);
    Set&amp;lt;Future&amp;lt;Integer&amp;gt;&amp;gt; set = new HashSet&amp;lt;Future&amp;lg;Integer&amp;gt;&amp;gt;();
    for (String word: args) {
      Callable&amp;lt;Integer&amp;gt; callable = new WordLengthCallable(word);
      Future&amp;lt;Integer&amp;gt; future = pool.submit(callable);
      set.add(future);
    }
    int sum = 0;
    for (Future&amp;lt;Integer&amp;gt; future : set) {
      sum += future.get();
    }
    System.out.printf("The sum of lengths is %s%n", sum);
    System.exit(sum);
  }
}
&lt;/pre&gt;

&lt;p&gt;The &lt;code&gt;WordLengthCallable&lt;/code&gt; saves each word and uses the
word's length as the value returned by the &lt;code&gt;call()&lt;/code&gt;
method. This value could take some time to generate but in this case
is known immediately. The only requirement of &lt;code&gt;call()&lt;/code&gt; is
the value is returned at the end of the call. When the
&lt;code&gt;get()&lt;/code&gt; method of &lt;code&gt;Future&lt;/code&gt; is later called,
the &lt;code&gt;Future&lt;/code&gt; will either have the value immediately if
the task runs quickly, as in this case, or will wait until the value
is done generating. Multiple calls to &lt;code&gt;get()&lt;/code&gt; will not
cause the task to be rerun in the thread.

&lt;p&gt;Because the goal of the program is to calculate the sum of all
word lengths, it doesn't matter in which order the
&lt;code&gt;Callable&lt;/code&gt; tasks finish. It is perfectly OK if the last
task completes before the first three. The first &lt;code&gt;get()&lt;/code&gt;
call to &lt;code&gt;Future&lt;/code&gt; will just wait for the first task in the
&lt;code&gt;Set&lt;/code&gt; to complete. This does not block other tasks from
running to completion separately. It is just waiting for that one
thread or task to complete.

&lt;p&gt;This particular example uses a fixed-size thread pool for the
&lt;code&gt;ExecutorService&lt;/code&gt;, but any available service will do.

&lt;p&gt;For more information on the use of executors and thread pools,
see the &lt;a
href="http://java.sun.com/tutorial/essential/concurrency/executors.h
tml"&gt;Executors lesson&lt;/a&gt; in the Java Tutorial. The
SwingWorker class is another example of a
&lt;code&gt;Runnable&lt;/code&gt; object that works with a &lt;code&gt;Future&lt;/code&gt;,
though in a slightly different way. See the &lt;a
href="http://java.sun.com/tutorial/uiswing/concurrency/worker.html"&gt;
Worker Threads and SwingWorker lesson&lt;/a&gt; for more information on
that.

&lt;/p&gt;



************&lt;br&gt;
&lt;p&gt;
&lt;a href="http://www.netbeans.org"&gt;&lt;img src="http://blogs.sun.com/JavaFundamentals/resource/dlNB.gif" align="left" border="0"&gt;NetBeans 6.0&lt;/a&gt; Integrated Development Environment (IDE) increases developer productivity with a smarter, faster editor, Ruby/JRuby/Ruby on Rails support, enhancements for improved Swing development, a new Visual Game Designer, updated Data Binding support, integrated Profiling, and more. &lt;a href="http://www.netbeans.org"&gt;Download NetBeans 6.0&lt;/a&gt;
&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/corejavatechtips/~4/204116305" height="1" width="1"/&gt;</content>
    <feedburner:origLink>http://blogs.sun.com/CoreJavaTechTips/entry/get_netbeans_6</feedburner:origLink></entry>
    <entry>
        <id>http://blogs.sun.com/CoreJavaTechTips/entry/using_the_mbeanregistration_interface_to</id>
        <title type="html">Using the MBeanRegistration Interface to Manage MBean Life Cycles</title>
        <author><name>dananourie</name></author>
        <link rel="alternate" type="text/html" href="http://feeds.feedburner.com/~r/corejavatechtips/~3/204116306/using_the_mbeanregistration_interface_to" />
        <published>2007-11-28T12:29:36-08:00</published>
        <updated>2007-11-28T12:43:49-08:00</updated> 
        <category term="/TechTip" label="TechTip" />
        <category term="cycles" scheme="http://rollerweblogger.org/ns/tags/" />
        <category term="jmx" scheme="http://rollerweblogger.org/ns/tags/" />
        <category term="life" scheme="http://rollerweblogger.org/ns/tags/" />
        <category term="mbean" scheme="http://rollerweblogger.org/ns/tags/" />
        <category term="mbeanregistration" scheme="http://rollerweblogger.org/ns/tags/" />
        <summary type="html">This technical tip focuses using the &lt;code&gt;MBeanRegistration&lt;/code&gt; interface to manage Management Bean (MBean) life cycles.</summary>
        <content type="html">&lt;p&gt;

By &lt;a href="http://blogs.sun.com/jmxetc" target="_blank"&gt;Daniel Fuchs&lt;/a&gt;

&lt;p&gt;The &lt;a href="http://java.sun.com/javase/technologies/core/mntr-mgmt/javamanagement/"&gt;Java Management Extensions (JMX)&lt;/a&gt; have been present in the JDK since J2SE 5.0. In JDK 6, Sun has added a new advanced JMX sample to the JDK &lt;code&gt;sample&lt;/code&gt; directory. The new sample -- &lt;code&gt;$JDK_HOME/sample/jmx/jmx-scandir&lt;/code&gt; -- builds on the &lt;a href="http://java.sun.com/javase/technologies/core/mntr-mgmt/javamanagement/best-practices.jsp"&gt;JMX best practices&lt;/a&gt; and discusses some usual JMX patterns, and some pitfalls to avoid, when you design a management interface with JMX.

&lt;p&gt;In particular, the &lt;code&gt;jmx-scandir&lt;/code&gt; sample shows all the different use cases that can be solved by implementing the &lt;code&gt;&lt;a href="http://java.sun.com/javase/6/docs/api/javax/management/MBeanRegistration.html"&gt;MBeanRegistration&lt;/a&gt;&lt;/code&gt; interface.

&lt;p&gt;This technical tip will focus on one such use case: using the &lt;code&gt;MBeanRegistration&lt;/code&gt; interface to manage Management Bean (MBean) life cycles. Readers who are not familiar with JMX and the notion of MBeans should follow the &lt;a href="http://java.sun.com/docs/books/tutorial/jmx/index.html"&gt;JMX trail&lt;/a&gt; from the &lt;a href="http://java.sun.com/docs/books/tutorial/"&gt;Java Tutorials&lt;/a&gt; before going any further.

&lt;p&gt;&lt;b&gt;The MBeanRegistration Interface&lt;/b&gt;

&lt;p&gt;The &lt;code&gt;&lt;a href="http://java.sun.com/javase/6/docs/api/javax/management/MBeanRegistration.html"&gt;MBeanRegistration&lt;/a&gt;&lt;/code&gt; interface is a callback interface. It can be implemented by MBeans, which need to perform specific actions when being registered to or unregistered from their &lt;a href="http://java.sun.com/javase/6/docs/api/javax/management/MBeanServer.html"&gt;&lt;code&gt;MBeanServer&lt;/code&gt;&lt;/a&gt;. When an MBean implements &lt;code&gt;MBeanRegistration&lt;/code&gt;, methods defined in that interface will be called by the &lt;code&gt;MBeanServer&lt;/code&gt; before and after the MBean is registered and unregistered from the &lt;code&gt;MBeanServer&lt;/code&gt;.

&lt;p&gt;An MBean that implements the &lt;code&gt;MBeanRegistration&lt;/code&gt; interface will obtain a reference to the &lt;code&gt;MBeanServer&lt;/code&gt; in which it is being registered, will have a chance to obtain -- and possibly change -- its own &lt;code&gt;&lt;a href="http://java.sun.com/javase/6/docs/api/javax/management/ObjectName.html"&gt;ObjectName&lt;/a&gt;&lt;/code&gt; before being registered, and will get an opportunity to accept or reject its own registration or unregistration.

&lt;p&gt;In the following code extract, the &lt;code&gt;Rack&lt;/code&gt; MBean implements the &lt;code&gt;MBeanRegistration&lt;/code&gt; interface:

&lt;pre&gt;
------------------------------------------------------------------
package jmxtechtip;

public interface RackMBean {
   /... defines methods exposed for management .../
}
------------------------------------------------------------------
package jmxtechtip;

public class Rack implements RackMBean, MBeanRegistration {
    /... implements RackMBean methods .../
    /... implements MBeanRegistration methods .../
}
------------------------------------------------------------------
&lt;/pre&gt;

&lt;p&gt;The MBean interface does not extend &lt;code&gt;MBeanRegistration&lt;/code&gt;. Only the concrete MBean class implements it. Indeed, it would be a violation to expose the methods defined in &lt;code&gt;MBeanRegistration&lt;/code&gt; through the management interface, since the &lt;code&gt;MBeanRegistration&lt;/code&gt; methods are designed to be called only by the &lt;code&gt;MBeanServer&lt;/code&gt; at registration time.

&lt;p&gt;This technical tip will show you how to implement the methods of &lt;code&gt;MBeanRegistration&lt;/code&gt; to register and unregister dependent MBeans.

&lt;p&gt;&lt;b&gt;The Racks and Cards Use Case&lt;/b&gt;

&lt;p&gt;Let's assume you are designing a JMX application that will expose a piece of equipment hardware. Your equipment has a rack -- represented by a &lt;code&gt;RackMBean&lt;/code&gt;. The rack itself has a number of slots where cards can be plugged in. When plugged in, each card is represented by a &lt;code&gt;CardMBean&lt;/code&gt; or by a subclass of &lt;code&gt;CardMBean&lt;/code&gt;.

&lt;p&gt;In this example, assume that the &lt;code&gt;RackMBean&lt;/code&gt; is completely responsible for creating and registering &lt;code&gt;CardMBean&lt;/code&gt; instances. The class &lt;code&gt;Card&lt;/code&gt; can be extended to provide &lt;code&gt;Card&lt;/code&gt;-specific implementation. The class &lt;code&gt;Rack&lt;/code&gt; can be extended to override its &lt;code&gt;createCard(...)&lt;/code&gt; method.

&lt;p&gt;Here are the aims you are trying to achieve:

&lt;p&gt;* In the class &lt;code&gt;Rack&lt;/code&gt;, when a &lt;code&gt;RackMBean&lt;/code&gt; is being registered, discover which slots already contain cards, and create and register a &lt;code&gt;CardMBean&lt;/code&gt; for each of them.

&lt;p&gt;* In the class &lt;code&gt;Rack&lt;/code&gt;, when a &lt;code&gt;RackMBean&lt;/code&gt; is being unregistered, unregister all its corresponding instances of &lt;code&gt;Card&lt;/code&gt;.

&lt;p&gt;* In the class &lt;code&gt;Card&lt;/code&gt;, ensure that a &lt;code&gt;CardMBean&lt;/code&gt; can only be registered by a &lt;code&gt;Rack&lt;/code&gt;, and ensure that a &lt;code&gt;CardMBean&lt;/code&gt; can only be unregistered by a &lt;code&gt;Rack&lt;/code&gt;, and not by, for example, a client JMX application calling &lt;code&gt;MBeanServer.unregisterMBean(...)&lt;/code&gt; directly for a &lt;code&gt;CardMBean&lt;/code&gt;.

&lt;p&gt;Note: The intent here is not to show how to model a rack or a card. The author chose racks and cards only for the sake of the example, because their relationship is easy to understand.

&lt;p&gt;&lt;b&gt;Implementing the &lt;code&gt;MBeanRegistration&lt;/code&gt; Interface&lt;/b&gt;

&lt;p&gt;The following code snippet shows how the &lt;code&gt;Rack&lt;/code&gt; MBean could implement the &lt;code&gt;MBeanRegistration&lt;/code&gt; interface:

&lt;pre&gt;
 /**
  * A Rack contains Cards.
  */
 public class Rack implements RackMBean, MBeanRegistration {

     // MBeans must be multi-thread safe.
     // 'rackName' and 'server' will be set at registration time, so you
     // must therefore take care of synchronization issues.
     // Use 'volatile' to make sure that you always use an accurate value.
     //
     // Name of this rack, extracted from the ObjectName.
     private volatile String rackName;
         // The MBeanServer in which this MBean is registered
     private volatile MBeanServer server;
         // An array of slots that may be occupied (and contain a card) or may be
     // unoccupied. slots[i]==null means that slot 'i' is unoccupied.
     private final Card[] slots;
         /**      * Creates a new rack.
      * @param slotCount Total number of slots.      **/
     public Rack(int slotCount) {
         if (slotCount &lt; 0)
             throw new IllegalArgumentException(Integer.toString(slotCount));
         this.slots = new Card[slotCount];
         ...
     }

     // --------------------------------------------------------------------
     // *Implementation of the MBeanRegistration Interface*
     // --------------------------------------------------------------------
         /**
      * Allows the MBean to perform any operations it needs before
      * being registered in the MBean server.
      * If any exception is raised, the MBean will not be registered
      * in the MBean server.
      *
      * RackMBean uses this method to check the validity of the supplied
      * ObjectName, and in particular that it corresponds to a valid rack.
      *
      * It also uses this method to obtain a reference to the MBeanServer in
      * which it is registered.
      *
      * @param server -- The MBean server in which the MBean will be registered.
      * @param name -- The object name of the MBean. In this implementation, the
      * supplied name must not be null.
      *
      * @return -- The name under which the MBean is to be registered. If null,
      * the registration will fail.
      *
      * @throws Exception -- This exception will be caught by the MBean
      * server and rethrown as an MBeanRegistrationException.
      */
      *public ObjectName preRegister(MBeanServer server, ObjectName name)
         throws Exception {*
         // A null ObjectName is not allowed. Let MBeanServer throw
         // the exception.
         if (name == null)             return null;
                 // Get rackname.
         rackName = name.getKeyProperty(RACK_KEY);
         if (rackName == null)
             throw new MalformedObjectNameException("missing rack name: " + name);
                 if (!isValidRack(rackName))
             throw new IllegalArgumentException(rackName + ": not a valid rack");
                 this.server = server;
         return name;
     }

     /**
      * Allows the MBean to perform any operations needed after having
      * been registered in the MBean server or after the registration
      * has failed.
      *
      * If the registration is successful, the Rack MBean will
      * register all its related CardMBeans.
      *
      * @param registrationDone -- Indicates whether or not the MBean
      * has been successfully registered in the MBean server.
      * The value false means that the registration has failed.
      */
     *public void postRegister(Boolean registrationDone) {*
                 if (!registrationDone) return;
                 for (int i = 0; i &lt; slots.length; i++) {
             final String cardType = discoverCardType(i);
             if (cardType != null) {
                 try {
                     final Card card = createCard(i, cardType);
                     final ObjectName cardName = createCardName(rackName, i);
                         // Avoid calling an MBeanServer operation
                         // from within a synchronized block.
                     card.registerSelf(server, cardName);
                                         synchronized (slots) {
                         slots[i] = card;
                     }
                 } catch (Exception x) {
                     LOG.warning("Couldn't create CardMBean for " +
                             cardType + "[" + i + "]");
                 }
             }
         }
             }

     /**
      * Allows the MBean to perform any operations it needs before being
      * unregistered by the MBean server
      *
      * The RackMBean uses this method to unregister all its related
      * CardMBeans. If for some reason, unregistration of one of these
      * MBeans fails, the RackMBean will no be unregistered either.
      *
      * @throws Exception -- This exception will be caught by the MBean
      * server and rethrown as an MBeanRegistrationException.
      */
      *public void preDeregister() throws Exception {*
         for (int i=0; i&lt;slots.length; i++) {
             final Card card;
             synchronized (slots) {
                 card = slots[i];
             }
                         if (card == null)                 continue;
                         // Avoid calling an MBeanServer operation from
                         // within a synchronized block.
             card.unregisterSelf();
                         synchronized (slots) {
                 slots[i] = null;
             }
         }
     }

     /**
      * Allows the MBean to perform any operations needed after
      * having been unregistered in the MBean server.
      *
      * In this implementation, you simply reset the internal
      * server variable.
      */
     *public void postDeregister() {*
         // In the general case, an MBean will be garbage collected
         // after it's been unregistered. Here you make the assumption that
         // this object might be reused by the application code that created
         // it, and you thus reset its internal variables to the value
         // they had before its registration in the MBean server.
         //
         // This is an implementation choice and not a general rule.
                 rackName = null;
         server   = null;
     }

     // ------------------------------------------------------------
     // *End of MBeanRegistration*
     // ------------------------------------------------------------
         /**
      * Discovers what kind of card is in the given slot.
      * If no card is plugged in, returns null.
      **/
     private String discoverCardType(int slot) { ... }
      /**
      * Check that the provided rackName corresponds to a rack that can
      * be modeled by this class.
      **/
     private boolean isValidRack(String rackName) { ... }
         /**
      * Create a new instance of Card for the given cardType at the
      * given slot.
      * Can be overridden by subclasses to create subclasses of Card.
      **/
     protected Card createCard(int i, String cardType) {
         return new Card(i, cardType);
     }

     // ------------------------------------------------------------
     // Static stuff
     // ------------------------------------------------------------
         /**
      * Creates an ObjectName for the card contained in rack 'rackName'
      * at slot 'slot'.
      **/
     public static ObjectName createCardName(String rackName, int slot)         throws MalformedObjectNameException {
         final String domain = Card.class.getPackage().getName();
         final String type = Card.class.getSimpleName();
         final ObjectName name =             new ObjectName(domain + ":type=" + type + "," +
                            RACK_KEY + "=" + rackName + ",slot=" + slot);
         return name;
     }
         /**
      * Returns the rack name embedded in the given ObjectName.
      **/
     public static String getRackName(ObjectName name) {
         final String rackName = name.getKeyProperty(RACK_KEY);
         if (rackName == null)
             throw new IllegalArgumentException("missing rack name: " + name);
         return rackName;
     }
         // A logger for this class
     private final static Logger LOG = Logger.getLogger(Rack.class.getName());
         /** This key is used in ObjectNames to indicate a rack name **/
     public static String RACK_KEY = "rack";
     }
&lt;/pre&gt;

&lt;p&gt;In &lt;code&gt;preRegister &lt;#preRegisterRack&gt;&lt;/code&gt;, the &lt;code&gt;Rack&lt;/code&gt; MBean obtains a reference to the &lt;code&gt;MBeanServer&lt;/code&gt; in which it is registered, and a reference to its own &lt;code&gt;ObjectName&lt;/code&gt;. It can check that the supplied &lt;code&gt;ObjectName&lt;/code&gt; is valid -- in this example, it is considered valid if it contains the &lt;code&gt;rack&lt;/code&gt; key -- and that it can indeed model the rack that it is asked to model. Here, this is supposed to be done by the &lt;code&gt;isValidRack(...)&lt;/code&gt; method, whose implementation is not shown. If these conditions are not met, the &lt;code&gt;Rack&lt;/code&gt; MBean will throw an exception, thus refusing to be registered.

&lt;p&gt;In &lt;code&gt;postRegister &lt;#postRegisterRack&gt;&lt;/code&gt;, the &lt;code&gt;Rack MBean&lt;/code&gt; checks whether registration was successful. If it wasn't, it stops here. Otherwise, it will discover which slots already have a card plugged in, and for each of those, it will create and register a &lt;code&gt;CardMBean&lt;/code&gt;. However, instead of using plain &lt;code&gt;MBeanServer.registerMBean(...)&lt;/code&gt;, it calls a package-protected method on the created &lt;code&gt;Card&lt;/code&gt; instance -- in this example, &lt;code&gt;Card.registerSelf() &lt;#registerSelf&gt;&lt;/code&gt;.

&lt;p&gt;This method has been created with logic such that a CardMBean can only be registered in the &lt;code&gt;MBeanServer&lt;/code&gt; by invoking its &lt;code&gt;registerSelf(...)&lt;/code&gt; method.

&lt;p&gt;Note that &lt;code&gt;postRegister&lt;/code&gt; isn't supposed to throw an exception. You have thus protected all &lt;code&gt;Card&lt;/code&gt; MBean registrations by a &lt;code&gt;try { } catch { }&lt;/code&gt; block. This is OK because according to the application logic, &lt;code&gt;Card&lt;/code&gt; MBean registration is not expected to fail at this point. If it does, you will simply log a warning message. Had you wanted the &lt;code&gt;Rack&lt;/code&gt; MBean registration to fail whenever a &lt;code&gt;Card&lt;/code&gt; MBean couldn't be registered, you would have implemented the &lt;code&gt;Card&lt;/code&gt; registration logic in &lt;code&gt;preRegister &lt;#preRegisterRack&gt;&lt;/code&gt; instead. However, that logic would have been more complex, since you would have had to implement code to &lt;code&gt;rollback&lt;/code&gt; registration of already registered &lt;code&gt;Card&lt;/code&gt; MBeans in case one of them failed to be registered.

&lt;p&gt;In &lt;code&gt;preDeregister &lt;#preDeregisterRack&gt;&lt;/code&gt;, the &lt;code&gt;Rack&lt;/code&gt; MBean unregisters all &lt;code&gt;Card&lt;/code&gt; MBeans it has previously registered. Here again, instead of using plain &lt;code&gt;MBeanServer.unregisterMBean(...)&lt;/code&gt;, it calls a package-protected method on the registered &lt;code&gt;Card&lt;/code&gt; instance -- in this example, &lt;code&gt;Card.unregisterSelf() &lt;#unregisterSelf&gt;&lt;/code&gt;.

&lt;p&gt;This method has been created with logic such that a &lt;code&gt;Card&lt;/code&gt; MBean can only be unregistered from the &lt;code&gt;MBeanServer&lt;/code&gt; by invoking its &lt;code&gt;unregisterSelf(...)&lt;/code&gt; method. Simply calling &lt;code&gt;MBeanServer.unregisterMBean(...)&lt;/code&gt; would fail. This ensures that only the creator of the &lt;code&gt;Card&lt;/code&gt; MBean will be able to register and unregister it. If a JMX client attempts to directly call &lt;code&gt;MBeanServer.unregisterMBean(...)&lt;/code&gt; on a &lt;code&gt;Card&lt;/code&gt; MBean, it will fail.

&lt;p&gt;Now let's see how the &lt;code&gt;Card&lt;/code&gt; MBean uses its &lt;a href="http://java.sun.com/javase/6/docs/api/javax/management/MBeanRegistration.html"&gt;&lt;code&gt;MBeanRegistration&lt;/code&gt;&lt;/a&gt; interface. The following code snippet show how the &lt;code&gt;Card&lt;/code&gt; MBean was implemented:

&lt;pre&gt;
 /**
  * A Card is plugged in a Rack slot.
  */
 public class Card implements CardMBean, MBeanRegistration {

     // This MBean will accept to be registered or unregistered
     // only if 'isRegistrationAllowed' is 'true'.
     private volatile boolean isRegistrationAllowed = false;
         private volatile ObjectName  name;
     private volatile MBeanServer server;
         public Card(int occupiedSlot, String cardType) { ... }

     // This method sets 'isRegistrationAllowed' to 'true', calls
     // server.registerMBean(this, name), and finally sets
     // 'isRegistrationAllowed' back to false.
     //
     *void registerSelf(MBeanServer server, ObjectName name) throws JMException {*
         *isRegistrationAllowed = true;*
         try {
             this.server = server;
             this.name = name;
             this.name = server.registerMBean(this, name).getObjectName();
         } finally {
             *isRegistrationAllowed = false;*
         }
     }
     // This method sets 'isRegistrationAllowed' to 'true',
     // calls server.unregisterMBean(name), and finally sets
     // 'isRegistrationAllowed' back to false.
     //
     *void unregisterSelf() throws JMException {*
         *isRegistrationAllowed = true;*
         try {
             if (server != null &amp;&amp; server.isRegistered(name))
                 server.unregisterMBean(name);
             this.server = null;
             this.name = null;
         } finally {
             *isRegistrationAllowed = false;*
         }
     }
            /**
      * Allows the MBean to perform any operations it needs before being
      * registered in the MBean server.      *
      * *In this example, the CardMBean will refuse to be registered if
      * 'isRegistrationAllowed' is false -- which means that Card MBeans
      * can only be registered by {@link #registerSelf registerSelf()}.*
      *
      * {@code registerSelf()} is a package method which is only called by
      * {@link Rack}.
      */
     *public final ObjectName preRegister(MBeanServer server, ObjectName name) throws Exception {*
                 if (*!isRegistrationAllowed*)
             throw new IllegalStateException("Illegal registration attempt");
                     assert server == this.server &amp;&amp; name == this.name;

         return name;
     }

     /**
      * Allows the MBean to perform any operations needed after having
      * been registered in the MBean server or after the registration has
      * failed.
      * *The CardMBean does not need to do anything here.*
      * @param registrationDone -- Indicates whether or not the MBean
      * has been successfully registered in the MBean server. The value
      * 'false' means that the registration has failed.
      */
     *public void postRegister(Boolean registrationDone) {}*

     /**
      * Allows the MBean to perform any operations it needs before
      * being unregistered by the MBean server.
      * *The CardMBean will refuse to let itself be unregistered if
      * 'isRegistrationAllowed' is false, which means that Card MBeans
      * can only be unregistered by {@link #unregisterSelf unregisterSelf()}.*
      *
      * {@code unregisterSelf()} is a package method which is only called by
      * {@link Rack}.
      *
      * @throws Exception -- This exception will be caught by the MBean
      * server and rethrown as an MBeanRegistrationException.
      */
     *public final void preDeregister() throws Exception {*
         if (*!isRegistrationAllowed*)
             throw new IllegalStateException("Illegal unregistration attempt");                }

     /**
      * Allows the MBean to perform any operations needed after having been
      * unregistered in the MBean server.
      * *The CardMBean does not need to do anything here.*
      */
     *public void postDeregister() { }*

 }
&lt;/pre&gt;

&lt;p&gt;The logic in &lt;code&gt;preRegister &lt;#preRegisterCard&gt;&lt;/code&gt;, &lt;code&gt;preDeregister &lt;#preDeregisterCard&gt;&lt;/code&gt;, &lt;code&gt;registerSelf &lt;#registerSelf&gt;&lt;/code&gt;, and &lt;code&gt;unregisterSelf &lt;#unregisterSelf&gt;&lt;/code&gt; prevents the &lt;code&gt;Card&lt;/code&gt; MBean from being registered or unregistered by anybody but the &lt;code&gt;Rack&lt;/code&gt; MBean that created it. The &lt;code&gt;registerSelf&lt;/code&gt; and &lt;code&gt;unregisterSelf&lt;/code&gt; methods are kept package-protected so that only the &lt;code&gt;Rack&lt;/code&gt; MBean can call them. The &lt;code&gt;preRegister&lt;/code&gt; and &lt;code&gt;preDeregister&lt;/code&gt; methods are declared final, so that subclasses cannot change that logic.

&lt;p&gt;Note: If you expected that subclasses of &lt;code&gt;Card&lt;/code&gt; would need to perform some additional specific actions when being registered or unregistered, you would introduce a new protected hook specific to that purpose, as described in &lt;a href="http://www.martinfowler.com/bliki/CallSuper.html" target="_blank"&gt;Martin Fowler's note&lt;/a&gt;.

&lt;p&gt;However, using a simple &lt;code&gt;volatile boolean isRegistrationAllowed&lt;/code&gt; flag still leaves some room for thread contention. Indeed, when the &lt;code&gt;Rack&lt;/code&gt; MBean calls &lt;code&gt;unregisterSelf &lt;#unregisterSelf&gt;&lt;/code&gt;, another thread could sneak in and call &lt;code&gt;MBeanServer.unregisterMBean&lt;/code&gt; right after the &lt;code&gt;isRegistrationAllowed&lt;/code&gt; flag is set, but before &lt;code&gt;unregisterSelf&lt;/code&gt; completes.

&lt;p&gt;A better solution would thus be to store the &lt;code&gt;isRegistrationAllowed&lt;/code&gt; flag in a &lt;a href="http://java.sun.com/javase/6/docs/api/java/lang/ThreadLocal.html"&gt;&lt;code&gt;ThreadLocal&lt;/code&gt;&lt;/a&gt;.

&lt;p&gt;The following code snippet shows what would need to change in the &lt;code&gt;Card&lt;/code&gt; MBean implementation:

&lt;pre&gt;
     // initialization of isRegistrationAllowed flag:

     // private volatile boolean isRegistrationAllowed = false;
     //     =&gt; replaced by:
     private final static ThreadLocal&lt;Boolean&gt; isRegistrationAllowed =        new ThreadLocal&lt;Boolean&gt;() {
           @Override protected Boolean initialValue() {return false;}
     };
          // in registerSelf / unregisterSelf
     ....
         // isRegistrationAllowed = true;
         //     =&gt; replaced by:
    