Thursday, April 30, 2009

VisualVM: JRuby and the Ruby to JVM Spectrum

As I have worked with JRuby, it has been interesting to observe the intersection of the Java and Ruby communities. Because JRuby potentially combines with best of the JVM with the best of Ruby, it is perhaps not surprising that JRuby leads to a greater intersection of the Java community and the Ruby community. For example, because I have been working primarily in Java in recent months, I probably would not have been aware of the major controversy in the Ruby community surrounding a single presentation given recently at the Golden Gate Ruby Conference (GoGaRuCo).

Many Rubyists like to focus on the Ruby advantages that JRuby brings to Java, but there is no denying that JRuby also brings advantages of the JVM to Ruby. One particular area of interest here is the impact of the JVM on JRuby performance. In How JRuby makes Ruby Fast, Charles Nutter demonstrates how JRuby's performance improves as more JVM features (server mode, JIT compiling, and so forth) are employed. Some strict Ruby compliance must be sacrificed for some of the performance improvements, but this flexibility to selectively choose between the best features of Ruby and the JVM is one of the endearing features of JRuby.

As described in the JRubyWiki topic Performance Tuning, JRuby performance can be tweaked with JVM arguments and properties. Although these properties and JVM arguments can be set on the command-line, there are times you may want to know which ones are being used or what the default settings are. This is where VisualVM makes things really easy.

VisualVM is included with recent versions of Sun's implementation Java SE 6. It in many ways serves as a replacement for JConsole and a host of command-line tools provided with Sun's SDK. In his post Can Your Ruby Do This?, Ola Bini points out how JRuby is able to take advantage of the built-in JMX support in Java SE 6 for automatic detection, monitoring, and management. Similarly, VisualVM can be used to monitor JRuby processes by virtue of them running in the JVM.

To demonstrate this, I'll use VisualVM to monitor the running JIRB (JRuby's Interactive Ruby) tool. With jirb started on my local machine (it could also be accessed remotely, but local is slightly easier), I see the running process when I start Visual VM (jvisualvm at the command line) as shown in the next screen snapshot.



In this case, the only other Java process running on my local machine is VisualVM itself. This also provides evidence that JIRB does indeed run as a Java process (using class org.jruby.Main). When I click on the JRuby process, I can see the JVM arguments used in conjunction with running jirb as shown next.



Because I had downloaded and installed the JConsole-like MBeans plug-in for VisualVM earlier, the JMX-exposed MBeans for JIRB are available. These are shown in the next screen snapshot in the MBeans tab (this tab is not available in VisualVM until it is explicitly downloaded and installed using Tools-->Plugins).



As the last image indicates, the JRuby process exposes a long list of configuration items for viewing. This allows VisualVM, JConsole, or any other JMX-enabled client to see how the JRuby runtime is configured in that particular case.

JRuby brings together the Java world and the Ruby world both in technical aspects and in people/community/political aspects.

Wednesday, April 29, 2009

jirb: Gentle Introduction to JRuby

If you haven't had the opportunity to work with Ruby or JRuby, the jirb tool provides an easy approach to playing with JRuby basic syntax and features.

In the article Accessorize Oracle Database with Ruby, I used screen shots of IRB (Interactive Ruby) to introduce Ruby for scripting. JIRB is the equivalent tool running on JRuby. In fact, in this blog post I will use the same examples in JIRB that I used in that OTN article with IRB to demonstrate Ruby on the JVM with JRuby.

In the OTN article (Figure 3), I demonstrated accessing Ruby predefined constants RUBY_PLATFORM, RUBY_VERSION, and RUBY_RELEASE_DATE in IRB. The next screen snapshot shows the same constants in JIRB along with an additional JRuby-specific constant JRUBY_VERSION.



The fact that the RUBY_PLATFORM constant is set to "java" provides a good clue about this actually being JRuby, but the existence of the JRUBY_VERSION constant (1.2) confirms that it is JRuby 1.2 being used.

I used the first figure (Figure 1) of the OTN Ruby article to demonstrate using Ruby mathematical operators in IRB. The next screen snapshot demonstrates the same mathematical operators in JIRB.



Figure 2 of the OTN article on Ruby demonstrated Ruby String functions in IRB. The next screen snapshot shows these same String functions in JIRB.



Finally, in the Figure 4 of the OTN article on Ruby, I demonstrated (as best as can be done in a static article) how clicking on tab twice brings up completion information in IRB. The same feature works in JIRB:



Besides demonstrating the tab-tab completion functionality of JIRB, this also demonstrates that even an integer (0) is an object in Ruby.


Getting Started with JRuby and JIRB

JRuby can be downloaded here. There are source and binary (jruby-bin-1.2.0.zip) downloads available. When the binary download is complete, it can be unzipped or opened into a directory of choice (such as C:\jruby-1.2.0 in my case. I like to set an environment variable JRUBY_HOME to point to this directory and then place %JRUBY_HOME%\bin on the Path. You can confirm correct setup by entering "jruby -v" on the console. If you see a JRuby version (such as 1.2) and a Ruby version (such as 1.8.6), the setup is correct. Running JIRB is as easy as typing "jirb" at the console prompt.

Tuesday, April 28, 2009

The Software Development Do-Gooder

Throughout my career, I have either caused unnecessary problems by being a software development do-gooder or have suffered delays ranging from minor to significant because of other software development do-gooders. The word do-gooder is a noun that more formally applies to someone who promotes common good, but I am using here in the more informal sense of someone who means well and tries to do a "good" thing, but ends up not doing as well as he or she would like because of lack of experience, naivety, or failure to consider practical aspects of what he or she is trying to do.

In this post, I articulate my perspective on the nature of what I call a software development do-gooder. I then talk about how to minimize the negative effects of the software development do-gooder while maintaining the positive aspects.

At a high level, the classic software development do-gooder is a person who wants to do "good" things above and beyond his or her normal tasks to improve the overall product. Because the do-gooder implements these well-intentioned actions outside of his or her own regularly assigned tasks, they are often done hurriedly and almost as a side thought rather than being well-planned and thought out. Negative consequences most commonly follow a do-gooder's actions when the do-gooder failed to consider all ramifications of a change that seemed simpler and less involved than it really is.

Examples of Software Development Do-Gooder Actions

There are numerous examples of actions that fit the this idea of a software development do-gooder. A small set of these are listed next.

"Fixing" code that is not well understood. It is easy as a software development do-gooder to see some code that appears to be blatantly incorrect and decide to fix it. If it turns out the code was actually (surprisingly) correct, then the "fix" might actually break it. Even if this mistake is quickly realized, there is wasted effort.

Applying best practices and standards hurriedly to another developer's code. I am a strong believer in best practices as evidenced by my articles on JSP Best Practices, More JSP Best Practices, and Basic JPA Best Practices. These are best used with engineering judgment (knowing when it is most appropriate to apply them) and are best used throughout development. The problem I have seen in this case is when an "improvement" is being made to meet a standard or best practice and working code is broken in the process. There are many specific examples in this context such as cleaning up seemingly dead code that is actually being used somewhere, improving an API that is actually used somewhere not expected, starting to make code changes that ripple much deeper into the code than expected (typically because of too tightly coupled code), and so forth.

Blurring Personal Preferences with Real Value It is sometimes difficult to distinguish between do-gooder actions intended to truly improve software from actions simply intended to employ one's personal coding and stylistic preferences. While the negative consequences of a well-meaning do-gooder's changes are not particularly welcome, they are easier to take than negative effects of changes that are merely opinionated and stylistic. An example of this is changing names of variables to meet one's own preferences and then requiring others to spend extra effort merging code with those trivial changes. It is easier to think that the code is better because of the name changes, but is it really or is it just better in one person's opinion?


Why the Do-Gooder Runs into Problems

In general, the do-gooder negative consequences seem to come out when the developer means well, but actually causes more trouble than good because he or she made one of these classic mistakes: underestimated the effort required for the fix or new effort; lacked understanding of code, technology, or domain; failed to realize effects of change on all stakeholders; addressed an issue more rapidly than the task really required; or failed to communicate with developers who could explain why something was done the way it was or what other unforeseen effects a given change would have.


Reducing the Negative Impact of the Do-Gooder

A Do-Gooder often actually ends up doing good things as intended. However, when the do-gooder does mess up, it is nice to have approaches to undo the bad.

Use Configuration Management Because many of the most costly results of a well-intentioned, but ultimately flawed, action are in code or other documentation and are often easily identifiable, it is helpful to have a decent configuration management (CM) system that allows changes to be rolled back to the previous known and correct state. With CM tools almost as prevalent as programming languages, there are many reasonable alternatives from which to choose an appropriate CM solution.

Unit Tests and Regression Tests Perhaps the best way to know if a seemingly innocent "improvement" has not broken a working system is to have unit tests and regression tests that prove the code still works as desired. Compiler checking will catch some errors, but the really costly ones are the subtle runtime errors introduced by do-gooder's seemingly minor change. Unit tests and regression tests can improve one's chances of catching these before committing them.

Clear Code A configuration management system and unit and regression tests are good tools for determining that a particular change has not had a bad effect and undoing an improper change. A good preventive step to avoid making unnecessary changes in the first place is to have clear code. Clear code is more likely to not tempt the do-gooder to try to tweak it or "improve" it unnecessarily. Clean code that works properly does not offer a lot of incentive to the do-gooder looking to do good.

Comments on Unorthodox Code Many developers believe strongly in letting the code speak for itself and reducing comments. I have no objection to this as long as the code is actually clear and clean as described in the last item. However, there are times when circumstances out of our control may dictate less clear code than we'd normally like. In such cases, especially when things are done that seem counter intuitive to traditional software development practices, it is important to comment on why the unorthodox approach is being used. At the very least, the comments will help the do-gooder know what was intended and perhaps the do-gooder's improvement will still be a good idea. On the other hand, the do-gooder may realize from the comment that there is no "easy" or "quick" way to remedy the convoluted code and won't even try until he or she is prepared to spend the required effort on the task. Code like this should be refactored with serious thought and not in a fly-by do-gooder approach.

Communication

As with many problems, the negative consequences of a do-gooder action can be reduced with better communication. Face-to-face discussions, e-mail, instant messaging, and the telephone all provide a quick way to find out if a do-gooder's proposed change is free of negative consequences. The do-gooder can also communicate after a change is made to let others know what it is and why it was made. Furthermore, steps such as using Java @Deprecated annotation and Javadoc tag @deprecated to more slowly introduce and communicate a particular change (such as removal of seemingly dead code) can also be advantageous.

Consider Real Value and Cost

The do-gooder should also consider what the actual value of a particular change is and compare that to known and potentially unknown costs and negative consequences.



Conclusion

In general, the software do-gooder often does many useful and truly good things. However, when the do-gooder is not careful, he or she can cause more problems and more trouble than the benefits of his or her action are worth. We don't want people to stop trying to do extra and we don't want to document and describe every little thing in intricate detail. However, we also want to take preventive measures to prevent and minimize the inadvertent negative consequences of a do-gooder's actions.

The do-gooder can minimize the frequency and severity of negative consequences by reducing naivety via better communication, through spending more time understanding the problem and its effects, by using configuration management tools, and by building and using unit and regression tests.

Monday, April 27, 2009

Groovy: JVM-based Scripting with Less Ceremony

My favorite use of Groovy is to write simple scripts that rely on Java classes or other features of the Java Virtual Machine (JVM) on which Groovy is running. The reduced ceremony approach of Groovy is particularly attractive in such situations.

To illustrate, I will show a couple examples of scripts that can be supported directly with Java classes, but with are much more concise and readable when written in Groovy. For each example, I'll first show the normal Java example followed by the Groovy equivalent. Along the way, I'll point out the Groovy features that make Groovy so script friendly.


Script Example #1: Use of InetAddress

There are several times when it is useful to know information about the network one is using as well as about individual hosts on that network. A particularly useful class in such situations is the java.net.InetAddress class. I have benefited from this class repeatedly when working with JMX on Linux. In particular, there is a known issue (occasionally) with Linux when a machine's loopback address is not configured to support localhost so that hostname -i produces an IP address other than 127.0.0.1.

Although there is an operating system command to look this information, there are some advantages to using a Java-based approach. First, when working with Java libraries and toolkits, it is often nice to use the same mechanisms they use in scripts to increase the likelihood of seeing similar results. Second, an operating system specific command does not, by its very nature, necessarily cross operating systems well. A Java-based script will generally run on any operating system for which a JVM is available.

I have blogged before about using InetAddress. My first regular Java example is based on the example provided in that blog post. Because there are some minor changes and for convenience, a slightly modified version of that example is shown here.


package dustin.examples;

import java.net.InetAddress;
import java.net.UnknownHostException;

/**
* This class demonstrates the InetAddress class.
*/
public class InetAddressDemonstrator
{
/**
* Run simple demonstration of the usefulness of the java.net.InetAddress
* class.
*
* @param aArgs The command line arguments; none expected.
*/
public static void main(final String[] aArgs)
{
InetAddress localhost = null;
try
{
localhost = InetAddress.getLocalHost();
System.out.println( "InetAddress: " + localhost );
System.out.println( "\ttoString: " + localhost.toString() );
System.out.println( "\tCanonicalHostName: "
+ localhost.getCanonicalHostName() );
System.out.println( "\tHost Name: " + localhost.getHostName() );
System.out.println( "\tHost Address: " + localhost.getHostAddress() );
System.out.println( "\tHost Bytes: " + localhost.getAddress() );
System.out.println( "\tHash Code: " + localhost.hashCode() );
}
catch (UnknownHostException unknownHostException) // checked exception
{
System.err.println( "Doh!! Unknown Host ("
+ unknownHostException.getClass().toString()
+ "): " + unknownHostException.getMessage() );
}
}
}


Besides the code itself that accesses InetAddress to provide information about the local host, additional code that is required for this example includes the two import statements, the class declaration code, the main function for the executable class, and the try-catch blocks for handling the checked exception java.net.UnknownHostException (different than java.rmi.UnknownHostException).

The output of running the above code looks like that shown in the next screen snapshot.



The relative "ceremony" code to actually desired executable code is even worse if only one call to an InetAddress instance is required. This is shown in the next code listing for a class that simply returns the localhost information without all the other details provided in the earlier code example.


package dustin.examples;

import java.net.InetAddress;
import java.net.UnknownHostException;

/**
* This class demonstrates the InetAddress class.
*/
public class InetAddressDemonstrator2
{
/**
* Run simple demonstration of the usefulness of the java.net.InetAddress
* class.
*
* @param aArgs The command line arguments; none expected.
*/
public static void main(final String[] aArgs)
{
try
{
System.out.println( "InetAddress: " + InetAddress.getLocalHost() );
}
catch (UnknownHostException unknownHostException) // checked exception
{
System.err.println( "Doh!! Unknown Host ("
+ unknownHostException.getClass().toString()
+ "): " + unknownHostException.getMessage() );
}
}
}


The output from this simplified Java code is shown in the next screen snapshot.



Even with only one call on InetAddress, there were still quite a few more lines of code required to use it. The same functionality is implemented in Groovy as shown in the next code listing.

getLocalHost.groovy


println "InetAddress: " + InetAddress.getLocalHost()


If you blinked while reading the above or started to wander a little, you probably missed the single line of Groovy code. That's the entire script. Assuming that Groovy has been installed correctly and that the system path includes the Groovy installation bin directory, all that is needed to run this script is groovy getLocalHost. The output is shown in the next screen snapshot.



This output shows that the results of running the Java code and the single line Groovy script are the same (not surprising given that Groovy really IS Java). The Groovy code is so short because no imports were required (Groovy does not require any class in a package starting with java to be imported), no checked exception had to be caught (Groovy does not force checking or handling of exceptions), and no class and main method declarations are required in Groovy. These base assumptions in Groovy significantly reduce the overhead associated with running this single statement. Even running the Groovy script happened to be slightly easier in this example because no classpath had to be specified for the Groovy script in this particular case.

If we wanted all the information to be displayed from a Groovy script that was shown in the very first Java code example, the Groovy script remains simple:

useInetAddress.groovy


localhost = InetAddress.getLocalHost()
println "InetAddress: " + localhost
println "\ttoString: " + localhost.toString()
println "\tCanonicalHostName: " + localhost.getCanonicalHostName()
println "\tHost Name: " + localhost.getHostName()
println "\tHost Address: " + localhost.getHostAddress()
println "\tHost Bytes: " + localhost.getAddress()
println "\tHash Code: " + localhost.hashCode()


The output of this Groovy script is the same as for the Java class as demonstrated in the next screen snapshot.



In this example, I included the .groovy extension on the name of the Groovy script file being run to make it a little different than the previous example.


Script Example #2: Readable Java Epoch Time

When working with Date and Calendar and other related contexts, it is common to store and pass around dates as longs representing the number of milliseconds since Java epoch. It can be handy to have scripts that allow for easier use of these long representations of a date/time. For example, it can be helpful to know what long corresponds to the current date/time and to convert a given long to its corresponding date/time in Java. This is especially helpful when reviewing logs or other code output that displays dates in this milliseconds since epoch form.

The next code listing is simple Java code for displaying the current time in terms of milliseconds since Java's epoch time.


package dustin.examples;

public class TimeNowInMillisecondsSinceEpochTime
{
/**
* Provide current time as milliseconds since Java epoch time.
*
* @param arguments Command-line arguments; none expected.
*/
public static void main(final String[] arguments)
{
System.out.println( "Milliseconds Since Java Epoch: "
+ System.currentTimeMillis());
}
}


The output from this sample Java code is shown next.



The Groovy code for the same functionality is even simpler and again fits into a single line:


println "Milliseconds Since Java Epoch: " + System.currentTimeMillis()


The output is the same as for Java (with some milliseconds passed since running that example):



There are numerous times when I need to know what a given long representing milliseconds since Java epoch time is in terms I better understand. A simple Java class that can convert milliseconds to human readable date/time is shown next.


package dustin.examples;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Locale;
import java.util.TimeZone;

/**
* This class converts the provided milliseconds (as sole command-line argument)
* to a Calendar. This class assumes a US/Denver/Mountain time zone and English
* locale.
*/
public class MillisecondsSinceEpochConverter
{
/**
* Main executable for this class. Expects a single command-line argument,
* which is assumed to be a Long that represents a time based on milliseconds
* since Java epoch time.
*
* @param arguments Command-line arguments: one expected, the long that
* represents the number of milliseconds since Java epoch for which the
* more human readable date/time String is desired.
*/
public static void main(final String[] arguments)
{
final Long millisecondsSinceEpoch = Long.valueOf(arguments[0]);
Calendar calendar =
Calendar.getInstance(TimeZone.getTimeZone("America/Denver"), Locale.US);
calendar.setTimeInMillis(millisecondsSinceEpoch);
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println(
millisecondsSinceEpoch + " is "
+ dateFormat.format(calendar.getTime())
+ " (" + calendar.getTimeZone().getDisplayName() + ")");
}
}


Output from running the above Java code is shown next.



The Groovy equivalent to the above is now shown.

getDateTimeRepresentation.groovy


import java.text.SimpleDateFormat

final Long millisecondsSinceEpoch = Long.valueOf(args[0])
calendar = Calendar.getInstance(TimeZone.getTimeZone("America/Denver"), Locale.US)
calendar.setTimeInMillis(millisecondsSinceEpoch)
dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
println millisecondsSinceEpoch + " is " + dateFormat.format(calendar.getTime()) + " (" + calendar.getTimeZone().getDisplayName() + ")"


The output from running the Groovy script is shown next.



In all of the Groovy examples so far, including this last one, I left off the static data typing to show off Groovy's duck typing. I did have to import one Java class in the last example, but I was able to remove the rest of the import statements. I also had to use the name "args" for the command-line arguments in Groovy because there was no explicit specification of how the command-line arguments would be accessed. Instead, Groovy implicitly provides the command-line arguments in an array of Strings called "args."

I also placed the entire last statement that outputs the results to standard output on a single line. If I had left the statement spanning multiple lines as it was in the Java version, I'd see an error message saying something like

Caught: org.codehaus.groovy.runtime.metaclass.MissingMethodExceptionNoStack: No signature of method: java.lang.String.positive() is applicable for argument types: () values: []


This same error is also shown in the next screen snapshot.



However, there is an even better way to output this final String to the standard output. Instead of using the overridden + operator to add Strings, I can take advantage of Groovy's GString support. The revised version of the Groovy script is shown next (only the last statement has changed).


import java.text.SimpleDateFormat

final Long millisecondsSinceEpoch = Long.valueOf(args[0])
calendar = Calendar.getInstance(TimeZone.getTimeZone("America/Denver"), Locale.US)
calendar.setTimeInMillis(millisecondsSinceEpoch)
dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
println "${millisecondsSinceEpoch} is ${dateFormat.format(calendar.getTime())} (${calendar.getTimeZone().getDisplayName()})"


There is one more Groovy feature to demonstrate in this example. The last statement is still on one line. Groovy supports multiline Strings. These are specified by enclosing the multi-line Strings between three double quotes markers and by using backslashes at the end of each code line that should NOT be a newline in the String. The final revision of this long-to-readable Date/Time representation script is shown next.


import java.text.SimpleDateFormat

final Long millisecondsSinceEpoch = Long.valueOf(args[0])
calendar = Calendar.getInstance(TimeZone.getTimeZone("America/Denver"), Locale.US)
calendar.setTimeInMillis(millisecondsSinceEpoch)
dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
println """${millisecondsSinceEpoch} is ${dateFormat.format(calendar.getTime())} \
(${calendar.getTimeZone().getDisplayName()})"""


The output for all three versions of this Groovy script are exactly the same.


Script Example #3: System Properties

I often want to know which Java System properties are defined for my environment. The following Java code will provide this information.


package dustin.examples;

import java.util.Enumeration;
import java.util.Properties;

/**
* Class that accesses the System properties.
*/
public class SystemPropertiesAccessor
{
public static void main(final String[] arguments)
{
Properties systemProperties = System.getProperties();
Enumeration propertyKeys = systemProperties.keys();
while (propertyKeys.hasMoreElements())
{
String key = (String) propertyKeys.nextElement();
String value = (String) systemProperties.get(key);
System.out.println(key + "=" + value);
}
}
}


I will not show the output here, but it consists of name/value pairs for the system properties with an equals sign separating the name and value. The equivalent Groovy code is shown next.

systemProperties.groovy


theSystemProperties = System.getProperties();
propertyKeys = theSystemProperties.keys();
while (propertyKeys.hasMoreElements())
{
key = propertyKeys.nextElement();
value = theSystemProperties.get(key);
println "${key}=${value}"
}


The Groovy version loses the casts to String along with no more need for static data typing and the removal of import statements. The output statement uses the same ${} syntax we looked at in the last Groovy example.

Another interesting observation can be made from this last Groovy example. Because I named the Groovy script file systemProperties.groovy, I was not able to name my variable the same thing (it was named systemProperties in the Java code). The name conflict is evident in the associated error message.




Conclusion

Groovy allows Java developers to write tight, concise scripts that combine the advantages of scripting languages with the advantage of access to the large set of Java classes and libraries. Groovy allows the script writer to adapt a Java class minimally or to move more fully to Groovy-specific syntax as feels appropriate for the given situation.

Sunday, April 26, 2009

Colorado Software Summit 2009 Preliminary Agenda Posted

The Preliminary Agenda for Colorado Software Summit 2009 has been posted. I am excited to announce that I will be speaking for my second time at this fabulous software development conference. My topics are "Applied JRuby" and "RESTful Java."

I'm also excited to preview the abstracts of some of the other presentations that I definitely plan to attend during this conference. These include Scala - The Java Path to Functional Programming, Advanced Relational Persistence, JSR 223 - The Java Scripting Engine, A Cornucopia of JVM Languages on the Google App Engine, con(Currency) in the Java World, at least one of the Cloud Computing presentations, and, of course, the always insightful keynote presentations. It also sounds like more presentations will be added to the agenda in the near future.

It is going to be a lot of work preparing these two presentations and then giving each of the 90-minute presentations three times each during the week, but I am really looking forward to another outstanding week at the Colorado Software Summit in gorgeous Keystone, Colorado.

CSS 2008 Linux Presentations Released

Three Linux-related presentations from Colorado Software Summit 2008 have been made available on the Colorado Software Summit site. Two of the presentations are from Thomas Cameron and are called "Automating Your Linux Infrastructure" and "SELinux for Mere Mortals (or, 'Don't Turn It Off!')." The third Linux-related presentation from CSS 2008 that was just posted is Noel Bergman's "Laptop Linux: Arrive Dependent on MS-Windows, Leave Living with Linux." Noel's other presentation, which is also available now, is called "Business Processes: Big Business' Secret Weapon Is Now Available to Everyone!" and covers WS-BPEL.

The three Linux-related presentations can be downloaded from the 2008 Agenda by Speaker Name.

Saturday, April 25, 2009

The Truth is Out There: Is It At JavaOne and Oracle OpenWorld?

There is no shortage of articles covering the news of Oracle's intent to buy Sun and Sun's agreement to be purchased by Oracle. This level of coverage is justifiable given the potential magnitude of this on development using Java and on many other areas of the information systems and computer science fields. Many of us were not surprised, but now that it has actually happened, there are many questions. The answers to some of these questions may be full of surprises.

It seems that 2009 JavaOne (June 2-5, 2009) and Oracle OpenWorld 2009 (October 11-15, 2009) will likely provide answers to many of our questions and perhaps even prompt a few new questions and even start or strengthen some conspiracy theories. [By the way, I'm especially looking forward to the hallway chat and Q&A session at Colorado Software Summit 2009 (October 25-30, 2009) regarding the latest developments.]

A very recent Java.net poll asked the question, "Which of the technologies highlighted at JavaOne 2009 is of greatest importance for the future of Java?" It is interesting to note that as of this writing (and with this poll question no longer featured on Java.net as the current poll question), there have been only 310 votes so far. I am probably reading more into the responses than I should and the relatively low number of votes could simply imply that the poll question was not significantly interesting or controversial to a large number of developers. Having said that, I wonder if at least part of the low response is due to developers more interested in the overall future of Java than of any one particular aspect of it.

My guess (and that's all it is) is that JavaFX will not reign as the main attraction for a third year running, but that talk of the effects and impact of Oracle buying Sun will dominate JavaOne regardless of the organized presentations and activities. Similarly, but to a lesser degree, the same Oracle/Sun transaction will be a major topic at Oracle OpenWorld. Because Oracle OpenWorld includes many presentations, activities, and attendees with no or very little direct interest in Java, there may be more "other things" to talk about.

Some of the questions that people will be talking about and looking for answers to at these two major conferences are:

* Is 2009 JavaOne the last JavaOne? With Oracle's OpenWorld being a huge event in its own right, will Oracle have interest in maintaining a separate and very large conference? What will JavaOne be like in the future under Oracle if the conference continues?

* Will Oracle support JavaFX with the same passion and resources that Sun did?

* Will Oracle support GlassFish and NetBeans with the same passion and resources that Sun did?

* Will Oracle support MySQL with the same passion and resources that Sun did or is this another conspiracy theory with potential?

* Will Oracle support JRuby and other largely Sun-sponsored community projects with the same passion and resources that Sun did?

* What effect will this have on the Java Community Process (JCP)?

* How will the life of the Java developer change?


Two television series that I have enjoyed remind me of how many of us feel now as we contemplate Oracle's purchase of Sun. Both The X Files (1993-2002) and Lost (2004-present) had/have a way of answering one or two questions now and then while at the same time opening up several times that number of new questions. Although this was/is extremely frustrating at times, I kept/keep watching in a desperate hope to get some answers. In fact, based on my own behavior and the popularity of these series, it seems that we may even like the questions and the speculations that ensue. It will be interesting to see if 2009 JavaOne and Oracle OpenWorld 2009 actually satisfy most of our questions or if, like The X Files and Lost, they answer a few questions while opening up many more. Perhaps we enjoy this ability to speculate in Java-dom as much as we do about our favorite television shows.

Finally, if Oracle is thinking about combining "JavaOne" with "Oracle OpenWorld", a natural blend would be "Oracle JavaWorld", but the "JavaWorld" trademark is already taken. So, if the conferences are combined in the future, what will the new conference's name be?

Effective Java NullPointerException Handling

It doesn't take much Java development experience to learn firsthand what the NullPointerException is about. In fact, one person has highlighted dealing with this as the number one mistake Java developers make. I blogged previously on use of String.value(Object) to reduce unwanted NullPointerExceptions. There are several other simple techniques one can use to reduce or eliminate the occurrences of this common type of RuntimeException that has been with us since JDK 1.0. This blog post collects and summarizes some of the most popular of these techniques.

Check Each Object For Null Before Using

The most sure way to avoid a NullPointerException is to check all object references to ensure that they are not null before accessing one of the object's fields or methods. As the following example indicates, this is a very simple technique.


final String causeStr = "adding String to Deque that is set to null.";
final String elementStr = "Fudd";
Deque<String> deque = null;

try
{
deque.push(elementStr);
log("Successful at " + causeStr, System.out);
}
catch (NullPointerException nullPointer)
{
log(causeStr, nullPointer, System.out);
}

try
{
if (deque == null)
{
deque = new LinkedList<String>();
}
deque.push(elementStr);
log( "Successful at " + causeStr
+ " (by checking first for null and instantiating Deque implementation)",
System.out);
}
catch (NullPointerException nullPointer)
{
log(causeStr, nullPointer, System.out);
}


In the code above, the Deque used is intentionally initialized to null to facilitate the example. The code in the first try block does not check for null before trying to access a Deque method. The code in the second try block does check for null and instantiates an implementation of the Deque (LinkedList) if it is null. The output from both examples looks like this:


ERROR: NullPointerException encountered while trying to adding String to Deque that is set to null.
java.lang.NullPointerException
INFO: Successful at adding String to Deque that is set to null. (by checking first for null and instantiating Deque implementation)


The message following ERROR in the output above indicates that a NullPointerException is thrown when a method call is attempted on the null Deque. The message following INFO in the output above indicates that by checking Deque for null first and then instantiating a new implementation for it when it is null, the exception was avoided altogether.

This approach is often used and, as shown above, can be very useful in avoiding unwanted (unexpected) NullPointerException instances. However, it is not without its costs. Checking for null before using every object can bloat the code, can be tedious to write, and opens more room for problems with development and maintenance of the additional code. For this reason, there has been talk of introducing Java language support for built-in null detection, automatic adding of these checks for null after the initial coding, null-safe types, use of Aspect-Oriented Programming (AOP) to add null checking to byte code, and other null-detection tools.

Groovy already provides a convenient mechanism for dealing with object references that are potentially null. Groovy's safe navigation operator (?.) returns null rather than throwing a NullPointerException when a null object reference is accessed.

Because checking null for every object reference can be tedious and does bloat the code, many developers choose to judiciously select which objects to check for null. This typically leads to checking of null on all objects of potentially unknown origins. The idea here is that objects can be checked at exposed interfaces and then be assumed to be safe after the initial check.

This is a situation where the ternary operator can be particularly useful. Instead of


// retrieved a BigDecimal called someObject
String returnString;
if (someObject != null)
{
returnString = someObject.toEngineeringString();
}
else
{
returnString = "";
}


the ternary operator supports this more concise syntax


// retrieved a BigDecimal called someObject
final String returnString = (someObject != null)
? someObject.toEngineeringString()
: "";
}



Check Method Arguments for Null

The technique just discussed can be used on all objects. As stated in that technique's description, many developers choose to only check objects for null when they come from "untrusted" sources. This often means testing for null first thing in methods exposed to external callers. For example, in a particular class, the developer might choose to check for null on all objects passed to public methods, but not check for null in private methods.

The following code demonstrates this checking for null on method entry. It includes a single method as the demonstrative method that turns around and calls two methods, passing each method a single null argument. One of the methods receiving a null argument checks that argument for null first, but the other just assumes the passed-in parameter is not null.


/**
* Append predefined text String to the provided StringBuilder.
*
* @param builder The StringBuilder that will have text appended to it; should
* be non-null.
* @throws IllegalArgumentException Thrown if the provided StringBuilder is
* null.
*/
private void appendPredefinedTextToProvidedBuilderCheckForNull(
final StringBuilder builder)
{
if (builder == null)
{
throw new IllegalArgumentException(
"The provided StringBuilder was null; non-null value must be provided.");
}
builder.append("Thanks for supplying a StringBuilder.");
}

/**
* Append predefined text String to the provided StringBuilder.
*
* @param builder The StringBuilder that will have text appended to it; should
* be non-null.
*/
private void appendPredefinedTextToProvidedBuilderNoCheckForNull(
final StringBuilder builder)
{
builder.append("Thanks for supplying a StringBuilder.");
}

/**
* Demonstrate effect of checking parameters for null before trying to use
* passed-in parameters that are potentially null.
*/
public void demonstrateCheckingArgumentsForNull()
{
final String causeStr = "provide null to method as argument.";
logHeader("DEMONSTRATING CHECKING METHOD PARAMETERS FOR NULL", System.out);

try
{
appendPredefinedTextToProvidedBuilderNoCheckForNull(null);
}
catch (NullPointerException nullPointer)
{
log(causeStr, nullPointer, System.out);
}

try
{
appendPredefinedTextToProvidedBuilderCheckForNull(null);
}
catch (IllegalArgumentException illegalArgument)
{
log(causeStr, illegalArgument, System.out);
}
}


When the above code is executed, the output appears as shown next.


ERROR: NullPointerException encountered while trying to provide null to method as argument.
java.lang.NullPointerException
ERROR: IllegalArgumentException encountered while trying to provide null to method as argument.
java.lang.IllegalArgumentException: The provided StringBuilder was null; non-null value must be provided.


In both cases, an error message was logged. However, the case in which a null was checked for threw an advertised IllegalArgumentException that included additional context information about when the null was encountered. Alternatively, this null parameter could have been handled in a variety of ways. For the case in which a null parameter was not handled, there were no options for how to handle it. Many people prefer to throw a NullPolinterException with the additional context information when a null is explicitly discovered (see Item #60 in the Second Edition of Effective Java or Item #42 in First Edition), but I have a slight preference for IllegalArgumentException when it is explicitly a method argument that is null because I think the very exception adds context details and it is easy to include "null" in the subject.

The technique of checking method arguments for null is really a subset of the more general technique of checking all objects for null. However, as outlined above, arguments to publicly exposed methods are often the least trusted in an application and so checking them may be more important than checking the average object for null.

Checking method parameters for null is also a subset of the more general practice of checking method parameters for general validity as discussed in Item #38 of the Second Edition of Effective Java (Item 23 in First Edition).


Consider Primitives Rather than Objects

I don't think it is a good idea to select a primitive data type (such as int) over its corresponding object reference type (such as Integer) simply to avoid the possibility of a NullPointerException, but there is no denying that one of the advantages of primitive types is that they do not lead to NullPointerExceptions. However, primitives still must be checked for validity (a month cannot be a negative integer) and so this benefit may be small. On the other hand, primitives cannot be used in Java Collections and there are times one wants the ability to set a value to null.

The most important thing is to be very cautious about the combination of primitives, reference types, and autoboxing. There is a warning in Effective Java (Second Edition, Item #49) regarding the dangers, including throwing of NullPointerException, related to careless mixing of primitive and reference types.


Carefully Consider Chained Method Calls

A NullPointerException can be very easy to find because a line number will state where it occurred. For example, a stack trace might look like that shown next:


java.lang.NullPointerException
at dustin.examples.AvoidingNullPointerExamples.demonstrateNullPointerExceptionStackTrace(AvoidingNullPointerExamples.java:222)
at dustin.examples.AvoidingNullPointerExamples.main(AvoidingNullPointerExamples.java:247)


The stack trace makes it obvious that the NullPointerException was thrown as a result of code executed on line 222 of AvoidingNullPointerExamples.java. Even with the line number provided, it can still be difficult to narrow down which object is null if there are multiple objects with methods or fields accessed on the same line.

For example, a statement like someObject.getObjectA().getObjectB().getObjectC().toString(); has four possible calls that might have thrown the NullPointerException attributed to the same line of code. Using a debugger can help with this, but there may be situations when it is preferable to simply break the above code up so that each call is performed on a separate line. This allows the line number contained in a stack trace to easily indicate which exact call was the problem. Furthermore, it facilitates explicit checking each object for null. However, on the downside, breaking up the code increases the line of code count (to some that's a positive!) and may not always be desirable, especially if one is certain none of the methods in question will ever be null.


Make NullPointerExceptions More Informative

In the above recommendation, the warning was to consider carefully use of method call chaining primarily because it made having the line number in the stack trace for a NullPointerException less helpful than it otherwise might be. However, the line number is only shown in a stack trace when the code was compiled with the debug flag turned on. If it was compiled without debug, the stack trace looks like that shown next:


java.lang.NullPointerException
at dustin.examples.AvoidingNullPointerExamples.demonstrateNullPointerExceptionStackTrace(Unknown Source)
at dustin.examples.AvoidingNullPointerExamples.main(Unknown Source)


As the above output demonstrates, there is a method name, but not no line number for the NullPointerException. This makes it more difficult to immediately identify what in the code led to the exception. One way to address this is to provide context information in any thrown NullPointerException. This idea was demonstrated earlier when a NullPointerException was caught and re-thrown with additional context information as a IllegalArgumentException. However, even if the exception is simply re-thrown as another NullPointerException with context information, it is still helpful. The context information helps the person debugging the code to more quickly identify the true cause of the problem.

The following example demonstrates this principle.


final Calendar nullCalendar = null;

try
{
final Date date = nullCalendar.getTime();
}
catch (NullPointerException nullPointer)
{
log("NullPointerException with useful data", nullPointer, System.out);
}

try
{
if (nullCalendar == null)
{
throw new NullPointerException("Could not extract Date from provided Calendar");
}
final Date date = nullCalendar.getTime();
}
catch (NullPointerException nullPointer)
{
log("NullPointerException with useful data", nullPointer, System.out);
}


The output from running the above code looks as follows.


ERROR: NullPointerException encountered while trying to NullPointerException with useful data
java.lang.NullPointerException
ERROR: NullPointerException encountered while trying to NullPointerException with useful data
java.lang.NullPointerException: Could not extract Date from provided Calendar


The first error does not provide any context information and only conveys that it is a NullPointerException. The second error, however, had explicit context information added to it which would go a long way in helping identify the source of the exception.


Use String.valueOf Rather than toString

As described previously, one of the surest methods for avoiding NullPointerException is to check the object being referenced for null first. The String.valueOf(Object) method is a good example of a case where this check for null can be done implicitly without any additional effort on the developer's part. I blogged on this previously, but include a brief example of its use here.


final String cause = "getting BigDecimal as String representation";
final BigDecimal decimal = null;
try
{
final String decimalStr = decimal.toString();
log("Retrieved " + decimalStr + " by " + cause, System.out);
}
catch (NullPointerException nullPointer)
{
log(cause, nullPointer, System.out);
}

try
{
final String decimalStr = String.valueOf(decimal);
log("Retrieved " + decimalStr + " by " + cause, System.out);
}
catch (NullPointerException nullPointer)
{
log(cause, nullPointer, System.out);
}


The output from this code sample appears as follows.


ERROR: NullPointerException encountered while trying to getting BigDecimal as String representation
java.lang.NullPointerException
INFO: Retrieved null by getting BigDecimal as String representation


This example demonstrates that use of String.valueOf(Object) enables the attempt to get the null BigDecimal's String representation be provided with a "null" string rather than a NullPointerException being thrown. This can be a particularly useful technique for implementing objects' toString() implementations.

One minor downside of use of String.valueOf stems from its behavior that is normally a positive. Although there are many cases where having a null object's String representation be returned as a "null" String is better than having a NullPointerException thrown, this can sometimes be a disadvantage if used indiscriminately. For example, String methods called on the String returned by valueOf(Object) will return a real String with the characters null. This is proven by the following code.


final String nullString = null;
final String nullStringValueOf = String.valueOf(nullString);
log("The length of the nullString is " + nullStringValueOf.length(),
System.out);
if (nullStringValueOf.isEmpty())
{
log("Empty String!", System.out);
}
else
{
log("String is NOT empty.", System.out);
}


The code above leads to these results that prove that there is a String "null" returned by String.valueOf(Object) when it is called upon an object with a null reference.


INFO: The length of the nullString is 4
INFO: String is NOT empty.


As the code and results above show, use String.valueOf(Object) on a null object will actually return a non-empty String (four characters n-u-l-l).


Avoid Returning Nulls

In Item #43 of the Second Edition of Effective Java (Item #27 in the First Edition), Joshua Bloch recommends returning empty arrays or empty collections rather than returning null. He points out that returning null requires client code to make special effort to handle such a contingency. When a client fails to do so, a NullPointerException is almost certainly going to be encountered down the road. The Java Collections class has useful methods for returning empty Collections that make it really easy to follow this advice. I have often found it to be similarly useful to return empty Strings rather than null for methods returning a String to indicate no match or error condition.

While there are problems associated with returning a null to indicate a failure or less than successful status, returning a null to indicate success is even more troubling because it is not normally associated with a positive outcome. In other words, it is typically not a good idea to return null as an indicator of success and a non-null object as an indicator of some type of failure.

The null object pattern is a well-known and slightly sophisticated approach to returning an object to the caller that indicates a null condition. It is more work than returning null, but is safer for the client.


Discourage Passing of Null Parameters

I previously mentioned the importance of checking passed-in parameters for null. There are several steps one can take to reduce the chance of nulls being passed into constructors or methods in the first place. One easy approach is to specify in the Javadoc comments on the method or constructor which arguments must not be null. This is appropriately documented in the @param tags. Similarly, if an exception is thrown when a null parameter is encountered, that exception can be advertised in the Javadoc comment with the @throws tag.

A common situation in which null gets passed as a parameter too often is in constructors accepting large lists of parameters. In Item #2 of the Second Edition of Effective Java, Bloch recommends employing the builder pattern instead of the telescoping constructor pattern. The appeal of this approach is that clients only need specify required parameters in the constructor and optional parameters only need be specified if applicable. This reduces the need for clients to pass null and that will hopefully reduce the likelihood of passing null seeming like a normal thing to do. The chapter that includes this item from Effective Java is available here. This idea is also covered in A Java Builder Pattern, Effective Java Reloaded: This Time It's For Real, and the Java Specialists' Book Review.


Calls String.equals(String) on 'Safe' Non-Null String

Some Java Strings are more likely to be non-null than others. For example, literal Strings are obviously not null. String constants and other Strings with well-known sources are also more trusted to be non-null. When comparing two Strings for equality with the equals method (or the equalsIgnoreCase method), it is typically best to call the equals method on the String that is more likely to NOT be null. This reduces the chances of a NullPointerException.

The following example code compares the two approaches, trying to access equals on a String that is really null and on a non-null String. The results are very different.


final String safeStringOrConstant = "Sally Ann Cavanaugh";
final String nullString = null;

try
{
if (nullString.equals(safeStringOrConstant))
{
log(nullString + " IS equal to " + safeStringOrConstant, System.out);
}
else
{
log(nullString + " is NOT equal to " + safeStringOrConstant, System.out);
}
}
catch (NullPointerException nullPointer)
{
log("call 'equals' on null String", nullPointer, System.out);
}

try
{
if (safeStringOrConstant.equals(nullString))
{
log(nullString + " IS equal to " + safeStringOrConstant, System.out);
}
else
{
log(nullString + " is NOT equal to " + safeStringOrConstant, System.out);
}
}
catch (NullPointerException nullPointer)
{
log("call 'equals' on non-null String", nullPointer, System.out);
}


The results of running the code above are shown next.


ERROR: NullPointerException encountered while trying to call 'equals' on null String
java.lang.NullPointerException
INFO: null is NOT equal to Sally Ann Cavanaugh


When the equals method was invoked on a null, the only text message we were presented with was the name of the exception. By invoking the equals method against a safe, non-null String, we avoid the exception altogether and got a correct result (the null passed to the equals method does not match the String on which the equals method is invoked).


Let Others Do the Heavy Lifting

As mentioned before, one of the safest ways to avoid the NullPointerException is to add code to check each object for null before accessing its methods and attributes. It is really nice when this check can be done without any extra effort. The String.valueOf(Object) method covered earlier does this for calling toString() on potentially null references. There are other libraries that provide similar built-in null-checking support so that you don't need to explicitly check for null. An example is ToStringBuilder, which builds toString() representations of objects and gracefully handles any null references in the object.


The Complete Sample Code Listing


package dustin.examples;

import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.math.BigDecimal;
import java.util.Calendar;
import java.util.Date;
import java.util.Deque;
import java.util.LinkedList;

/**
* Examples demonstrating avoidance, minimization, or more effective use of
* NullPointerExceptions in Java.
*/
public class AvoidingNullPointerExamples
{
private static final String NEW_LINE = System.getProperty("line.separator");

/**
* Demonstrate how the order of a String equality comparison can reduce or
* eliminate NullPointerExceptions.
*/
public void demonstrateOrderOfStringEqualityCheck()
{
logHeader("ORDER IN STRING COMPARISON", System.out);
final String safeStringOrConstant = "Sally Ann Cavanaugh";
final String nullString = null;

try
{
if (nullString.equals(safeStringOrConstant))
{
log(nullString + " IS equal to " + safeStringOrConstant, System.out);
}
else
{
log(nullString + " is NOT equal to " + safeStringOrConstant, System.out);
}
}
catch (NullPointerException nullPointer)
{
log("call 'equals' on null String", nullPointer, System.out);
}

try
{
if (safeStringOrConstant.equals(nullString))
{
log(nullString + " IS equal to " + safeStringOrConstant, System.out);
}
else
{
log(nullString + " is NOT equal to " + safeStringOrConstant, System.out);
}
}
catch (NullPointerException nullPointer)
{
log("call 'equals' on non-null String", nullPointer, System.out);
}
}

/**
* Demonstrate how supplying context information to an
* {@link NullPointerException} can make it more useful for clients and for
* debugging.
*/
public void demonstrateThrowingMoreUsefulNullPointerException()
{
logHeader("CONSTRUCT NULLPOINTEREXCEPTION WITH USEFUL DATA", System.out);
final Calendar nullCalendar = null;

try
{
final Date date = nullCalendar.getTime();
}
catch (NullPointerException nullPointer)
{
log("NullPointerException with useful data", nullPointer, System.out);
}

try
{
if (nullCalendar == null)
{
throw new NullPointerException("Could not extract Date from provided Calendar");
}
final Date date = nullCalendar.getTime();
}
catch (NullPointerException nullPointer)
{
log("NullPointerException with useful data", nullPointer, System.out);
}
}

/**
* Append predefined text {@link String} to the provided {@link StringBuilder}.
*
* @param builder The StringBuilder that will have text appended to it; should
* be non-null.
* @throws IllegalArgumentException Thrown if the provided StringBuilder is
* null.
*/
private void appendPredefinedTextToProvidedBuilderCheckForNull(
final StringBuilder builder)
{
if (builder == null)
{
throw new IllegalArgumentException(
"The provided StringBuilder was null; non-null value must be provided.");
}
builder.append("Thanks for supplying a StringBuilder.");
}

/**
* Append predefined text {@link String} to the provided {@link StringBuilder}.
*
* @param builder The StringBuilder that will have text appended to it; should
* be non-null.
*/
private void appendPredefinedTextToProvidedBuilderNoCheckForNull(
final StringBuilder builder)
{
builder.append("Thanks for supplying a StringBuilder.");
}

/**
* Demonstrate effect of checking parameters for null before trying to use
* passed-in parameters that are potentially null.
*/
public void demonstrateCheckingArgumentsForNull()
{
final String causeStr = "provide null to method as argument.";
logHeader("DEMONSTRATING CHECKING METHOD PARAMETERS FOR NULL", System.out);

try
{
appendPredefinedTextToProvidedBuilderNoCheckForNull(null);
}
catch (NullPointerException nullPointer)
{
log(causeStr, nullPointer, System.out);
}

try
{
appendPredefinedTextToProvidedBuilderCheckForNull(null);
}
catch (IllegalArgumentException illegalArgument)
{
log(causeStr, illegalArgument, System.out);
}
}

/**
* Demonstrate checking for null before trying to access an object's data
* methods or attributes.
*/
public void demonstrateCheckingForNullFirst()
{
logHeader("DEMONSTRATE CHECKING FOR NULL BEFORE ACTING", System.out);
final String causeStr = "adding String to Deque that is set to null.";
final String elementStr = "Fudd";
Deque<String> deque = null;

try
{
deque.push(elementStr);
log("Successful at " + causeStr, System.out);
}
catch (NullPointerException nullPointer)
{
log(causeStr, nullPointer, System.out);
}

try
{
if (deque == null)
{
deque = new LinkedList<String>();
}
deque.push(elementStr);
log(
"Successful at " + causeStr
+ " (by checking first for null and instantiating Deque implementation)",
System.out);
}
catch (NullPointerException nullPointer)
{
log(causeStr, nullPointer, System.out);
}
}

/**
* Demonstrate how use of {@code String.valueOf(Object)} provides functionality
* similar to calling {@code toString()} on an object without the risk of a
* {@code NullPointerException}.
*/
public void demonstrateUsingStringValueOf()
{
logHeader("USING STRING.VALUEOF RATHER THAN TOSTRING", System.out);
final String cause = "getting BigDecimal as String representation";
final BigDecimal decimal = null;
try
{
final String decimalStr = decimal.toString();
log("Retrieved " + decimalStr + " by " + cause, System.out);
}
catch (NullPointerException nullPointer)
{
log(cause, nullPointer, System.out);
}

try
{
final String decimalStr = String.valueOf(decimal);
log("Retrieved " + decimalStr + " by " + cause, System.out);
}
catch (NullPointerException nullPointer)
{
log(cause, nullPointer, System.out);
}
}

/**
* Demonstrates that while String.valueOf(String) does perform like a
* {@code toString()} call without the risk of a {@code NullPointerException},
* it also has the side effects of returning a non-null, non-empty String
* (four characters) for an object that is actually null. This is because
* it returns "null".
*/
public void demonstratingSideEffectsOfStringValueOf()
{
logHeader("SIDE EFFECTS OF STRING.VALUEOF(OBJECT)", System.out);
final String nullString = null;
final String nullStringValueOf = String.valueOf(nullString);
log("The length of the nullString is " + nullStringValueOf.length(),
System.out);
if (nullStringValueOf.isEmpty())
{
log("Empty String!", System.out);
}
else
{
log("String is NOT empty.", System.out);
}
}

/**
* Demonstrate a {@code NullPointerException} stack trace. To see the
* difference between debug and nodebug, compile this class both with debug
* turned on and with debug turned off and run this method with each setting.
* With debug on, line numbers will be included in the stack trace; these line
* numbers will not be included with the nodebug mode
*/
public void demonstrateNullPointerExceptionStackTrace()
{
logHeader("EXAMPLE STACK TRACE FOR NULLPOINTERECEPTION", System.out);
final Object nullObject = null;
try
{
final String objectString = nullObject.toString();
}
catch (NullPointerException nullPointer)
{
final PrintWriter writer = new PrintWriter(System.out);
nullPointer.printStackTrace(writer);
writer.close();
log("END OF NULL POINTER STACK TRACE", System.out);
}
}

/**
* Main executable method for running all of the demonstrations of techniques
* for reducing or eliminating dealing with thrown {@code NullPointerException}s.
*
* @param arguments Command-line arguments: none expected.
*/
public static void main(final String[] arguments)
{
final AvoidingNullPointerExamples demonstrator =
new AvoidingNullPointerExamples();
demonstrator.demonstrateOrderOfStringEqualityCheck();
demonstrator.demonstrateThrowingMoreUsefulNullPointerException();
demonstrator.demonstrateCheckingArgumentsForNull();
demonstrator.demonstrateCheckingForNullFirst();
demonstrator.demonstrateUsingStringValueOf();
demonstrator.demonstratingSideEffectsOfStringValueOf();
demonstrator.demonstrateNullPointerExceptionStackTrace();
}

/**
* Log header information by logging provided message to the provided
* {@link OutputStream}.
*
* @param headerMessage The text portion of the header being logged.
* @param out OutputStream to which complete header is written.
*/
public static void logHeader(final String headerMessage, final OutputStream out)
{
final String headerSeparator =
"====================================================================";
final String loggedString =
NEW_LINE + headerSeparator + NEW_LINE
+ headerMessage + NEW_LINE
+ headerSeparator + NEW_LINE;

try
{
out.write(loggedString.getBytes());
}
catch (IOException ioEx)
{
System.out.print(loggedString);
}
}

/**
* Log provided text message to the provided {@link OutputStream}.
*
* @param messageToLog String to be logged.
* @param out OutputStream to which to write the log.
*/
public static void log(final String messageToLog, final OutputStream out)
{
final String infoStr = "INFO: " + messageToLog;
try
{
out.write((infoStr + NEW_LINE).getBytes());
}
catch (IOException ioEx)
{
System.out.println(infoStr);
}
}

/**
* Log {@code NullPointerException} error condition by logging the provided
* action leading to the {@code NullPointerException} along with the
* {@code NullPointerException} itself to the provided OutputStream.
*
* @param actionCausingNullPointerException Action that led to the throwing
* of the NullPointerException.
* @param exception NullPointerException that was caught.
* @param out OutputStream to which to write log information.
*/
public static void log(
final String actionCausingNullPointerException,
final NullPointerException exception,
final OutputStream out)
{
final String errorStr =
"ERROR: NullPointerException encountered while trying to "
+ actionCausingNullPointerException;
try
{
out.write((errorStr + NEW_LINE).getBytes());
out.write((exception.toString() + NEW_LINE).getBytes());
}
catch (IOException ioEx)
{
System.err.println(errorStr + exception.toString());
}
}

/**
* Log {@link Exception} information by logging the provided action leading
* to the general {@code Exception} along with the general {@code Exception}
* itself to the provided {@link OutputStream}.
*
* @param actionCausingNullPointerException Action that led to the throwing
* of the rException.
* @param exception Exception that was caught.
* @param out OutputStream to which to write log information.
*/
public static void log(
final String actionCausingNullPointerException,
final Exception exception,
final OutputStream out)
{
final String errorStr =
"ERROR: " + exception.getClass().getSimpleName()
+ " encountered while trying to "
+ actionCausingNullPointerException;
try
{
out.write((errorStr + NEW_LINE).getBytes());
out.write((exception.toString() + NEW_LINE).getBytes());
}
catch (IOException ioEx)
{
System.err.println(errorStr + exception.toString());
}
}
}


The complete output when this code is run as shown above is shown next.


====================================================================
ORDER IN STRING COMPARISON
====================================================================
ERROR: NullPointerException encountered while trying to call 'equals' on null String
java.lang.NullPointerException
INFO: null is NOT equal to Sally Ann Cavanaugh

====================================================================
CONSTRUCT NULLPOINTEREXCEPTION WITH USEFUL DATA
====================================================================
ERROR: NullPointerException encountered while trying to NullPointerException with useful data
java.lang.NullPointerException
ERROR: NullPointerException encountered while trying to NullPointerException with useful data
java.lang.NullPointerException: Could not extract Date from provided Calendar

====================================================================
DEMONSTRATING CHECKING METHOD PARAMETERS FOR NULL
====================================================================
ERROR: NullPointerException encountered while trying to provide null to method as argument.
java.lang.NullPointerException
ERROR: IllegalArgumentException encountered while trying to provide null to method as argument.
java.lang.IllegalArgumentException: The provided StringBuilder was null; non-null value must be provided.

====================================================================
DEMONSTRATE CHECKING FOR NULL BEFORE ACTING
====================================================================
ERROR: NullPointerException encountered while trying to adding String to Deque that is set to null.
java.lang.NullPointerException
INFO: Successful at adding String to Deque that is set to null. (by checking first for null and instantiating Deque implementation)

====================================================================
USING STRING.VALUEOF RATHER THAN TOSTRING
====================================================================
ERROR: NullPointerException encountered while trying to getting BigDecimal as String representation
java.lang.NullPointerException
INFO: Retrieved null by getting BigDecimal as String representation

====================================================================
SIDE EFFECTS OF STRING.VALUEOF(OBJECT)
====================================================================
INFO: The length of the nullString is 4
INFO: String is NOT empty.

====================================================================
EXAMPLE STACK TRACE FOR NULLPOINTERECEPTION
====================================================================
java.lang.NullPointerException
at dustin.examples.AvoidingNullPointerExamples.demonstrateNullPointerExceptionStackTrace(AvoidingNullPointerExamples.java:239)
at dustin.examples.AvoidingNullPointerExamples.main(AvoidingNullPointerExamples.java:265)



Conclusion

The NullPointerException can be very helpful in identifying problems in our applications and especially in identifying problems with many assumptions we often make when developing software. However, there are times when we encounter them without any benefit or new information simply because we have not taken proper steps to avoid them. This posting has attempted to cover techniques that are commonly used to reduce NullPointerException exposure, to make valid NullPointerExceptions more meaningful, and to handle NullPointerExceptions more gracefully. Use of these techniques can reduce the number of NullPointerExceptions encountered, increase the quality of those that are encountered, and improve out ability to identify the very problems that that remaining NullPointerExceptions are meant to convey.


Additional References

* How to Avoid '!= null' Statements in Java?

* StackOverflow: What is a NullPointerException?

* NullPointerException

* Java Programming: Preventing NullPointerException

* Basics Uncovered: NullPointerException

* java.lang.NullPointerException

* A Small Tip on String to Avoid NullPointerException

* Null Objects

* Introduce Null Object

* IMHO: Preventing NullPointerException

* Preventing the NullPointerException in Java

* Detecting NullPointerException with Transparent Checks (Added 10 October 2009)