Monday, July 25, 2011

JavaOne 2011 Content Catalog is Available

The JavaOne 2011 Content Catalog is now available. Currently, the catalog indicates that there are 434 sessions. I will likely focus on some of the abstracts that interest me most in future posts, but here is a short list of titles that look interesting to me. A couple of notes are in order. First, this is only a subset of the titles and abstracts that are appealing. Second, I don't list the JavaFX presentations because the search in the catalog for "JavaFX" returns 60 matching sessions.


Core Java


JVM Languages Other than Java


Java EE


Performance
  • (The Art of ) (Java) Benchmarking (21682)
  • Are Your Garbage Collection Logs Speaking to You? (24466)
  • Coroutines for HotSpot (24321)
  • Diagnosing Performance Issues in Cloud-Based Java Applications (25006)
  • Java Unleashed "2": More JVM Tuning from the Pros (23828)
  • The Essence of Caching (24241)
  • Troubleshooting Slow or Hung Java Applications (18246)


Serialization and Persistence
  • Cloud-Enabled Java Persistence (24445)
  • Best Practices for XML/Schema Data Binding with JAXB (25364)
  • Java Persistence API 2.1: What's New and What's Coming (24981)
  • Java API for JSON (24742)
  • Serialization: Tips, Traps, and Techniques (24606)


REST
  • JAX-RS 2.0: What's in JSR 339? (22800)
  • REST and Hypermedia as the Engine of Application State with Standard Java APIs (24609)
  • RESTing Hard: Enterprise-Strength REST for Java (22320)
  • Test-Driven Development of RESTful Web Services with the Jersey Test Framework (25180)
  • What's New in Jersey? Production-Ready RESTful Framework That Implements JAX-RS (24607)
  • Writing REST Applications with RestSimple (25663)
  • Developing RESTful Automated Clients with JAX-RS 2.0 (24568)


HTML5
  • HTML5 and Java: The Facts and the Myths (24821)
  • HTML5 with Java Now: A Pragmatic Review of Java's Current Support for HTML5 (24181)


Teaching Java
  • Teaching Java by Using Alice (24625)
  • Teaching Java with Scratch and Greenfoot (24633)

Wednesday, July 20, 2011

Book Review: Java: The Good Parts

I recently had the misfortune of waiting at the airport for roughly six hours as my flight was repeatedly delayed 30 minutes at a time until it was ultimately canceled. The one silver lining in this cloud was that I was able to read almost all of Jim Waldo's Java: The Good Parts while I waited (the book comes in at under 200 pages). In this post, I talk about what I like best about this book and who I believe its best audience is.

In Java: The Good Parts, Waldo writes about parts of Java that he has used and that he has found to be the best parts of Java. His specific focus is portions of Java make it most suitable for certain situations. These situations tend to be large and complex applications that need to run on multiple platforms and will be used and maintained for a long time. In short, Waldo states that "in this book, I talk about the good parts of Java" which he defines as parts of Java that he has used "that aid in writing programs (or parts of programs) in which Java itself is the appropriate choice of programming language and environment."

Looking at the table of contents for Java: The Good Parts not only provides a quick overview of the main topics of the book, but also provides a list of what Waldo considers the "good parts" of Java. There is essentially a chapter devoted to each of the "good parts" and the chapters are on the type system, exceptions, packages, garbage collection, the JVM, Javadoc, Collections, RMI and object serialization, concurrency, and the Java development tools.

For the most part, I agree with Waldo's assessment and generally agree that the items he covers as "good parts" of Java are indeed good parts. The fact that I already felt this way about these items and the fact that I already embrace many of Waldo's recommendations in my Java development may explain why I feel like I didn't learn much about Java or how to use Java. That being stated, I wasn't sorry for reading this book and explain that more in this post.

I think that Java: The Good Parts is probably best suited either for someone with basic familiarity with Java who wants to improve his or her ability to write maintainable Java code. It is probably best to have at least passing experience with Java because the author assumes that. For a developer who has worked on very large systems using Java, many of Waldo's observations are easy to agree with and articulate the experienced Java developers' own experiences. I have read (never all at once) Effective Java and other resources on writing better Java regularly and did not find many new observations in this book, but I think it could be highly valuable to a Java developer who has not invested as much time in reading about improving his or her Java skills.

Although I already was aware of most of what I read in Java: The Good Parts and, more importantly, already generally try to apply many of these principles in my own Java development, I still enjoyed reading this book while waiting at the airport. The main reasons I enjoyed it, which I will discuss a little further, are the historical context it provides and the opinionated writing style of the author.

One of my favorite aspects of Java: The Good Parts was the author's willingness to take a stand and unequivocally make his points. Although he did occasionally acknowledge that there are times when even his strongly held judgment had to bow to other practical concerns, Waldo generally made it clear what he believes are the correct and wrong things one can do with the portions of Java discussed in his book.

Here are some of the funniest of these quotations that did not mince words:

  • Classloaders are the source of many of the most painful parts of using Java, so I like these Waldo quotes on classloaders:
    • Classloaders Quote #1: "But God have mercy on your soul if you ever have a program or system where you cross classloader boundaries."
    • Classloaders Quote #2: "But this book is supposed to be about the good parts of Java, so I'm going to avoid talking about classloaders whenever possible."
  • Regarding people who complain about Java's exception handling: they "either don't understand it, don't realize what it can do, or are simply lazy twits who don't care about writing reliable code."
  • Mixing error-handling code with main code is the "mistake of a puppy programmer."
  • The developer who develops an API with runtime/unchecked exceptions only is a "corrupter of others."
  • Regarding swallowing exceptions by not doing anything the the catch clause: "I’ve not seen this, because I work with adults."
  • Unnamed packages are only used by "confused, obstinate, or lazy programmers."
  • Regarding developers not documenting better: "All programmers also know that it is important to floss, to bathe regularly, to wear seatbelts and not talk on cellphones in the car, and to dress for success. And like all of these other things that we ought to do, when the pressure is on and deadlines loom, we tend to “forget” to do those things. After all, they don’t directly lead to getting the code working. And they can be added later."

Although I don't agree with some of the assertions (at least to the extreme degree), the descriptions are still humorous and make their point.

I think that my favorite aspect of Java: The Good Parts is the historical accounts that Waldo has woven into the text and into notes. These include references to some interesting online reads, but also include accounts of what went into decisions at Sun regarding the good, the bad, and the ugly of Java. Waldo was involved in many of these discussions firsthand and the insight he provides into what went into these decisions is fascinating. It's a reminder that even the developers of the Java programming language run into the same design decisions and their consequences, both good and bad, in the long-term. Software developer, whether of a language or of an application, seems to always involve this. More than once, I was almost relieved to read why some seemingly ridiculous Java things now are perfectly explainable in their origins based on the motivations of the time.

Although I already attempt to practice much of what Waldo preaches in Java: The Good Parts, I liked how he articulated some of the same observations I have made, but not articulated as well. For example, he states (in a parenthetical) about design: "most design dictates boil down to personal taste, which doesn’t make them any less correct, but that’s the subject of a different book."

Perhaps my least favorite aspect of Java: The Good Parts is the numerous typos and similar errors. That being stated, there is currently a dearth of confirmed errata on the book's web page, but there are entries on the unconfirmed errata page.

Most of Waldo's assertions and observations are highly similar to my own and, I think, to many Java developers. The one chapter that is likely to be controversial is the chapter on exceptions. I will likely devote a separate blog post to Waldo's coverage and opinions on exceptions, but the essence of it is that he presents exceptions in Java as of the checked exception variety with the unchecked exceptions being a necessary evil meant only for carefully controlled situations. The basis of this assertion is the idea that checked exceptions force the thrown exception to be part of a method's contract and this is supported by the assertion that a thrown exception is really an alternative form of a return from that method. Although I'm not ready to throw checked exceptions out completely like many are, I also do not feel that runtime exceptions are as evil as Waldo asserts. Indeed, my issue remains that it is often much easier to talk about, than to actually write, an effective and useful exception handling mechanism other than logging the state at the time.

Java: The Good Parts does not intend to be and is not advertised as an introduction to Java. These days, it's far too short to be that. I like to find Java books that are not introductory, but that are approachable and provide something more than "here's how to do so-and-so in Java." This books fits that bill. For an experienced Java developer who has observed his or her own lessons learned and learned from others, much of this book will provide a reaffirmation of what he or she already knows. For the newer Java developer who wants to become a better Java developer, this book will help see some important ways to do just that. Effective Java is still by far my favorite book on how to write better Java, but this book provides a different approach that may be useful to a newer Java developer. What Java: The Good Parts has to offer above just about any recent Java-oriented book I can think of is a historical perspective on why things are the way they are in the world of Java.

I almost never read a technical book cover-to-cover. Indeed, I read very few of my technical books all the way through at all. Thanks to the airport fiasco, I had the opportunity to read Java: The Good Parts from cover-to-cover and I was happy to have that opportunity. Many of the practices I embrace were reaffirmed, but I was even more interested in the historical perspective I gained about what has motivated Java to be what it is today.

Monday, July 18, 2011

Groovy, Java, and the Unix Epoch Time

The link What Every Programmer Should Know about Time was recently posted on DZone and was a highly popular link. It references the original Emil Mikulic post Time and What Programmers Should Know About It. This post and its popularity was reminder to me of how often I find myself dealing with dates and times in software development and especially when writing scripts. I like many of Mikulic's recommendations because I feel that conventions and standards can keep the intricacies of working with time zones, Daylight Saving Time, and leap seconds/leap years somewhat manageable.

I have several times appreciated the fact that Java (and by extension, Groovy) base time against the same epoch as Unix. Java and Unix both use midnight, January 1, 1970 UTC/GMT as their epoch time. The Javadoc documentation for both of Java's standard "Date" classes (java.sql.Date and java.util.Date) talk about the significance of that date. The java.sql.Date documentation states, "A milliseconds value represents the number of milliseconds that have passed since January 1, 1970 00:00:00.000 GMT" while java.util.Date documentation on the constructor accepting a long states, "Allocates a Date object and initializes it to represent the specified number of milliseconds since the standard base time known as "the epoch", namely January 1, 1970, 00:00:00 GMT." The java.util.Date documentation also goes into a discussion of the subtle differences between GMT/UTC/UT.

Because Java (and Groovy) base their date/time APIs (Date, Date, and Calendar) off of the same epoch starting time as Unix, it is easier to deal with dates and times when writing Groovy scripts in a Linux environment. The most important thing to keep in mind when converting between the two is that Unix APIs tend to use seconds since the epoch time while Java's APIs tend to use milliseconds since that same epoch time. In short, the typical conversion is to multiply Unix's seconds since epoch by 1000 to get Java's milliseconds since epoch or divide Java's milliseconds since epoch by 1000 to get Unix's seconds since epoch.

I now show a couple of simple examples. It is easy to get a Unix example. The next screen snapshot shows the number of seconds since Unix epoch time for that last time that page was updated.


As the image above indicates, the integer 1310724379 represents "2011-07-15 10:06:19Z." This is also shown with the online Epoch Converter as shown in the next screen snapshot.


It's really easy to calculate the same time in Groovy from that integer. This is shown in the next screen snapshot.


The code for the above was so simple that I was able to invoke it simply via the command line Groovy launcher with the -e option. The inline Groovy code was fairly simple and is shown again here:

println new Date((1310724379 as long)*1000)

There were some minor things that needed to be done to convert the number used for Unix seconds since epoch to Java/Groovy's milliseconds since epoch. First, there was the obvious need to multiply the Unix number by 1000 to get from seconds to milliseconds. The Groovy coercion to a long is also necessary so that the numeral is not treated as an int, leading to the wrong time. The effect of this is shown in the next screen snapshot where the numeral by itself is shown leading to the wrong time and using the more traditional Java approach of coercing the numeral to a long with the "L designation. As the image indicates, coercion to a long is vital to perform the conversion correctly.




The Groovy example shows MST time rather than GMT. There are ways to address this in Java such as using DateFormat.setTimeZone(TimeZone) or Calendar.setTimeZone(TimeZone). One can use one of these approaches to get a UTC/GMT representation of the time.

In Java or Groovy development, it is easy to save dates and times in the database as such, but it can also be effective to simply store the integer representing the time since epoch in the database. When this approach is used, my preference is to always store UTC/GMT times. This avoids the need to store an offset to have the correct time unless the offset is desired to display the time in a local timezone. Understanding the Unix Epoch (in Java), Time Zones and UTC is a good post on Java's handling of dates/times in UTC format. That post references the post Current time and System.currentTimeMillis() as a good source of information on how date/time storage works in Java. Making Sense of Java's Dates is another good source of information on Java and dates.

It is easy to determine what Java and Groovy use as their epoch time without going to the documentation. The following Groovy script does just that.

displayZeroEpochTime.groovy
#!/usr/bin/env groovy
def zeroEpoch = Calendar.getInstance(TimeZone.getTimeZone('GMT'))
zeroEpoch.setTimeInMillis(0)
println zeroEpoch.format("dd-MMM-yyyy HH:mm:ss zzz")

The output of it is shown in the next screen snapshot and verifies that 0 milliseconds since the epoch time means January 1, 1970, 00:00:00 GMT.


If Java/Groovy and Unix had different epoch times, one could calculate the difference between their starting points and continually apply that difference in conversions between the two systems. However, by using the same epoch time as Unix, Java's original creators have made it easier for those of us writing Groovy scripts that deal with time to integrate with the Unix time handling functions. That definitely makes scripting in a Linux environment easier.

Tuesday, July 12, 2011

Use == (or !=) to Compare Java Enums

Most new Java developers quickly learn that they should generally compare Java Strings using String.equals(Object) rather than using ==. This is emphasized and reinforced to new developers repeatedly because they almost always mean to compare String content (the actual characters forming the String) rather than the String's identity (its address in memory). I contend that we should reinforce the notion that == can be used instead of Enum.equals(Object). I provide my reasoning for this assertion in the remainder of this post.

There are four reasons that I believe using == to compare Java enums is almost always preferable to using the "equals" method:
  1. The == on enums provides the same expected comparison (content) as equals
  2. The == on enums is arguably more readable (less verbose) than equals
  3. The == on enums is more null-safe than equals
  4. The == on enums provides compile-time (static) checking rather than runtime checking

The second reason listed above ("arguably more readable") is obviously a matter of opinion, but that part about "less verbose" can be agreed upon. The first reason I generally prefer == when comparing enums is a consequence of how the Java Language Specification describes enums. Section 8.9 ("Enums") states:
It is a compile-time error to attempt to explicitly instantiate an enum type. The final clone method in Enum ensures that enum constants can never be cloned, and the special treatment by the serialization mechanism ensures that duplicate instances are never created as a result of deserialization. Reflective instantiation of enum types is prohibited. Together, these four things ensure that no instances of an enum type exist beyond those defined by the enum constants.

Because there is only one instance of each enum constant, it is permissible to use the == operator in place of the equals method when comparing two object references if it is known that at least one of them refers to an enum constant. (The equals method in Enum is a final method that merely invokes super.equals on its argument and returns the result, thus performing an identity comparison.)

The excerpt from the specification shown above implies and then explicitly states that it is safe to use the == operator to compare two enums because there is no way that there can be more than one instance of the same enum constant.

The fourth advantage to == over .equals when comparing enums has to do with compile-time safety. The use of == forces a stricter compile time check than that for .equals because Object.equals(Object) must, by contract, take an arbitrary Object. When using a statically typed language such as Java, I believe in taking advantage of the advantages of this static typing as much as possible. Otherwise, I'd use a dynamically typed language. I believe that one of the recurring themes of Effective Java is just that: prefer static type checking whenever possible.

For example, suppose I had a custom enum called Fruit and I tried to compare it to the class java.awt.Color. Using the == operator allows me to get a compile-time error (including advance notice in my favorite Java IDE) of the problem. Here is a code listing that tries to compare a custom enum to a JDK class using the == operator:

/**
    * Indicate if provided Color is a watermelon.
    *
    * This method's implementation is commented out to avoid a compiler error
    * that legitimately disallows == to compare two objects that are not and
    * cannot be the same thing ever.
    *
    * @param candidateColor Color that will never be a watermelon.
    * @return Should never be true.
    */
   public boolean isColorWatermelon(java.awt.Color candidateColor)
   {
      // This comparison of Fruit to Color will lead to compiler error:
      //    error: incomparable types: Fruit and Color
      return Fruit.WATERMELON == candidateColor;
   }

The compiler error is shown in the screen snapshot that comes next.


Although I'm no fan of errors, I prefer them to be caught statically at compile time rather than depending on runtime coverage. Had I used the equals method for this comparison, the code would have compiled fine, but the method would always return false false because there is no way a dustin.examples.Fruit enum will be equal to a java.awt.Color class. I don't recommend it, but here is the comparison method using .equals:

/**
    * Indicate whether provided Color is a Raspberry. This is utter nonsense
    * because a Color can never be equal to a Fruit, but the compiler allows this
    * check and only a runtime determination can indicate that they are not
    * equal even though they can never be equal. This is how NOT to do things.
    *
    * @param candidateColor Color that will never be a raspberry.
    * @return {@code false}. Always.
    */
   public boolean isColorRaspberry(java.awt.Color candidateColor)
   {
      //
      // DON'T DO THIS: Waste of effort and misleading code!!!!!!!!
      //
      return Fruit.RASPBERRY.equals(candidateColor);
   }

The "nice" thing about the above is the lack of compile-time errors. It compiles beautifully. Unfortunately, this is paid for with a potentially high price.

The final advantage I listed of using == rather than Enum.equals when comparing enums is the avoidance of the dreaded NullPointerException. As I stated in Effective Java NullPointerException Handling, I generally like to avoid unexpected NullPointerExceptions. There is a limited set of situations in which I truly want the existence of a null to be treated as an exceptional case, but often I prefer a more graceful reporting of a problem. An advantage of comparing enums with == is that a null can be compared to a non-null enum without encountering a NullPointerException (NPE). The result of this comparison, obviously, is false.

One way to avoid the NPE when using .equals(Object) is to invoke the equals method against an enum constant or a known non-null enum and then pass the potential enum of questionable character (possibly null) as a parameter to the equals method. This has often been done for years in Java with Strings to avoid the NPE. However, with the == operator, order of comparison does not matter. I like that.

I've made my arguments and now I move onto some code examples. The next listing is a realization of the hypothetical Fruit enum mentioned earlier.

Fruit.java
package dustin.examples;

public enum Fruit
{
   APPLE,
   BANANA,
   BLACKBERRY,
   BLUEBERRY,
   CHERRY,
   GRAPE,
   KIWI,
   MANGO,
   ORANGE,
   RASPBERRY,
   STRAWBERRY,
   TOMATO,
   WATERMELON
}

The next code listing is a simple Java class that provides methods for detecting if a particular enum or object is a certain fruit. I'd normally put checks like these in the enum itself, but they work better in a separate class here for my illustrative and demonstrative purposes. This class includes the two methods shown earlier for comparing Fruit to Color with both == and equals. Of course, the method using == to compare an enum to a class had to have that part commented out to compile properly.

EnumComparisonMain.java
package dustin.examples;

public class EnumComparisonMain
{
   /**
    * Indicate whether provided fruit is a watermelon ({@code true} or not
    * ({@code false}).
    * 
    * @param candidateFruit Fruit that may or may not be a watermelon; null is
    *    perfectly acceptable (bring it on!).
    * @return {@code true} if provided fruit is watermelon; {@code false} if
    *    provided fruit is NOT a watermelon.
    */
   public boolean isFruitWatermelon(Fruit candidateFruit)
   {
      return candidateFruit == Fruit.WATERMELON;
   }

   /**
    * Indicate whether provided object is a Fruit.WATERMELON ({@code true}) or
    * not ({@code false}).
    *
    * @param candidateObject Object that may or may not be a watermelon and may
    *    not even be a Fruit!
    * @return {@code true} if provided object is a Fruit.WATERMELON;
    *    {@code false} if provided object is not Fruit.WATERMELON.
    */
   public boolean isObjectWatermelon(Object candidateObject)
   {
      return candidateObject == Fruit.WATERMELON;
   }

   /**
    * Indicate if provided Color is a watermelon.
    *
    * This method's implementation is commented out to avoid a compiler error
    * that legitimately disallows == to compare two objects that are not and
    * cannot be the same thing ever.
    *
    * @param candidateColor Color that will never be a watermelon.
    * @return Should never be true.
    */
   public boolean isColorWatermelon(java.awt.Color candidateColor)
   {
      // Had to comment out comparison of Fruit to Color to avoid compiler error:
      //    error: incomparable types: Fruit and Color
      return /*Fruit.WATERMELON == candidateColor*/ false;
   }

   /**
    * Indicate whether provided fruit is a strawberry ({@code true}) or not
    * ({@code false}).
    *
    * @param candidateFruit Fruit that may or may not be a strawberry; null is
    *    perfectly acceptable (bring it on!).
    * @return {@code true} if provided fruit is strawberry; {@code false} if
    *    provided fruit is NOT strawberry.
    */
   public boolean isFruitStrawberry(Fruit candidateFruit)
   {
      return Fruit.STRAWBERRY == candidateFruit;
   }

   /**
    * Indicate whether provided fruit is a raspberry ({@code true}) or not
    * ({@code false}).
    *
    * @param candidateFruit Fruit that may or may not be a raspberry; null is
    *    completely and entirely unacceptable; please don't pass null, please,
    *    please, please.
    * @return {@code true} if provided fruit is raspberry; {@code false} if
    *    provided fruit is NOT raspberry.
    */
   public boolean isFruitRaspberry(Fruit candidateFruit)
   {
      return candidateFruit.equals(Fruit.RASPBERRY);
   }

   /**
    * Indicate whether provided Object is a Fruit.RASPBERRY ({@code true}) or
    * not ({@code false}).
    *
    * @param candidateObject Object that may or may not be a Raspberry and may
    *    or may not even be a Fruit!
    * @return {@code true} if provided Object is a Fruit.RASPBERRY; {@code false}
    *    if it is not a Fruit or not a raspberry.
    */
   public boolean isObjectRaspberry(Object candidateObject)
   {
      return candidateObject.equals(Fruit.RASPBERRY);
   }

   /**
    * Indicate whether provided Color is a Raspberry. This is utter nonsense
    * because a Color can never be equal to a Fruit, but the compiler allows this
    * check and only a runtime determination can indicate that they are not
    * equal even though they can never be equal. This is how NOT to do things.
    *
    * @param candidateColor Color that will never be a raspberry.
    * @return {@code false}. Always.
    */
   public boolean isColorRaspberry(java.awt.Color candidateColor)
   {
      //
      // DON'T DO THIS: Waste of effort and misleading code!!!!!!!!
      //
      return Fruit.RASPBERRY.equals(candidateColor);
   }

   /**
    * Indicate whether provided fruit is a grape ({@code true}) or not
    * ({@code false}).
    *
    * @param candidateFruit Fruit that may or may not be a grape; null is
    *    perfectly acceptable (bring it on!).
    * @return {@code true} if provided fruit is a grape; {@code false} if
    *    provided fruit is NOT a grape.
    */
   public boolean isFruitGrape(Fruit candidateFruit)
   {
      return Fruit.GRAPE.equals(candidateFruit);
   }
}

I decided to approach demonstration of the ideas captured in the above methods via unit tests. In particular, I make use of Groovy's GroovyTestCase. That class for using Groovy-powered unit testing is in the next code listing.

EnumComparisonTest.groovy
package dustin.examples

class EnumComparisonTest extends GroovyTestCase
{
   private EnumComparisonMain instance

   void setUp() {instance = new EnumComparisonMain()}

   /**
    * Demonstrate that while null is not watermelon, this check does not lead to
    * NPE because watermelon check uses {@code ==} rather than {@code .equals}.
    */
   void testIsWatermelonIsNotNull()
   {
      assertEquals("Null cannot be watermelon", false, instance.isFruitWatermelon(null))
   }

   /**
    * Demonstrate that a passed-in Object that is really a disguised Fruit can
    * be compared to the enum and found to be equal.
    */
   void testIsWatermelonDisguisedAsObjectStillWatermelon()
   {
      assertEquals("Object should have been watermelon",
                   true, instance.isObjectWatermelon(Fruit.WATERMELON))
   }

   /**
    * Demonstrate that a passed-in Object that is really a disguised Fruit can
    * be compared to the enum and found to be not equal.
    */
   void testIsOtherFruitDisguisedAsObjectNotWatermelon()
   {
      assertEquals("Fruit disguised as Object should NOT be watermelon",
                   false, instance.isObjectWatermelon(Fruit.ORANGE))
   }

   /**
    * Demonstrate that a passed-in Object that is really a null can be compared
    * without NPE to the enum and that they will be considered not equal.
    */
   void testIsNullObjectNotEqualToWatermelonWithoutNPE()
   {
      assertEquals("Null, even as Object, is not equal to Watermelon",
                   false, instance.isObjectWatermelon(null))
   }

   /** Demonstrate that test works when provided fruit is indeed watermelon. */
   void testIsWatermelonAWatermelon()
   {
      assertEquals("Watermelon expected for fruit", true, instance.isFruitWatermelon(Fruit.WATERMELON))
   }

   /** Demonstrate that fruit other than watermelon is not a watermelon. */
   void testIsWatermelonBanana()
   {
      assertEquals("A banana is not a watermelon", false, instance.isFruitWatermelon(Fruit.BANANA))
   }

   /**
    * Demonstrate that while null is not strawberry, this check does not lead to
    * NPE because strawberry check uses {@code ==} rather than {@code .equals}.
    */
   void testIsStrawberryIsNotNull()
   {
      assertEquals("Null cannot be strawberry", false, instance.isFruitStrawberry(null))
   }

   /**
    * Demonstrate that raspberry case throws NPE because of attempt to invoke
    * {@code .equals} method on null.
    */
   void testIsFruitRaspberryThrowsNpeForNull()
   {
      shouldFail(NullPointerException)
      {
         instance.isFruitRaspberry(null)
      }
   }

   /**
    * Demonstrate that raspberry case throws NPE even for Object because of
    * attempt to invoke {@code .equals} method on null.
    */
   void testIsObjectRaspberryThrowsNpeForNull()
   {
      shouldFail(NullPointerException)
      {
         instance.isObjectRaspberry(null)
      }
   }

   /**
    * Demonstrate that {@code .equals} approach works for comparing enums even if
    * {@code .equals} is invoked on passed-in object.
    */
   void testIsRaspberryDisguisedAsObjectRaspberry()
   {
      assertEquals("Expected object to be raspberry",
                   true, instance.isObjectRaspberry(Fruit.RASPBERRY))
   }

   /**
    * Demonstrate that while null is not grape, this check does not lead to NPE
    * because grape check invokes {@code .equals} method on the enum constant
    * being compared rather than on the provided {@code null}.
    */
   void testIsGrapeIsNotNull()
   {
      assertEquals("Null cannot be grape", false, instance.isFruitGrape(null))
   }
}

I don't describe what the various tests demonstrate much here because the comments on the tested class's methods and on the test methods cover most of that. In short, the variety of tests demonstrate that == is null-safe, and that equals is not null safe unless invoked on an enum constant or known non-null enum. There are a few other tests to ensure that the comparisons work as we'd expect them to work. The output from running the unit tests is shown next.


The GroovyTestCase method shouldFail reported that an NPE was indeed thrown when code attempted to call equals on an advertised enum that was really null. Because I used the overloaded version of this method that accepted the excepted exception as a parameter, I was able to ensure that it was an NPE that was thrown. The next screen snapshot shows what I would have seen if I had told the unit test that an IllegalArgumentException was expected rather than a NullPointerException.


I'm not the only one who thinks that == is preferable to equals when comparing enums. After I started writing this (because I saw what I deem to be a misuse of equals for comparing two enums again today for the umpteeth time), I discovered other posts making the same argument. The post == or equals with Java enum highlights the compile-time advantage of explicitly comparing two distinct types with ==: "Using == the compiler screams and tells us that we are comparing apples with oranges." Ashutosh's post Comparing Java Enums concludes that "using == over .equals() is more advantageous in two ways" (avoiding the NPE and getting the static compile-time check). The latter post also pointed me to the excellent reference Comparing Java enum members: == or equals()?.


The Dissenting View

All three references just mentioned had dissenting opinions either in the thread (the last reference) or as comments to the blog post (the first two references). The primary arguments for comparing enums with equals rather than == is consistency with comparing of other reference types (non-primitives). There is also an argument that equals is in a way more readable because a less experienced Java developer won't think it is wrong and he or she might think == is a bad idea. My argument to that is that it is good to know the difference and could provide a valuable teaching experience. Another argument against == is that equals gets compiled into the == form anyway. I don't see that so much as an argument against using ==. In fact, it really is a moot point in my mind if they are the same thing in byte code anyway. Furthermore, it doesn't take away from the advantages of == in terms of null safety and static type checking.


Don't Forget !=

All of the above arguments apply to the question of != versus !Enum.equals(Object), of course. The Java Tutorials section Getting and Setting Fields with Enum Types demonstrates comparing the same enum types and their example makes use of !=.


Conclusion

There is very little in software development that can be stated unequivocally and without controversy. The use of equals versus == for comparing enums is no exception to this. However, I have no problem comparing primitives in Java (as long as I ensure they are true primitives and not unboxed references) with == and likewise have no problem comparing enums with == either. The specification explicitly spells out that this is permissible as does the Java Tutorials (which uses != rather than !Enum.equals). I actually go further than that and state that it is preferable. If I can avoid NullPointerExceptions and still get the response I want (two compared things are not equal) and can move my error checking up to compile time all without extra effort, I'll take that deal just about every time.

The JavaOne 2011 Announcements Are Coming

There was a flurry of Tweets yesterday afternoon and evening from rightfully excited folks who received acceptances for their JavaOne 2011 presentation or BOF abstracts. That flurry continues this morning. Although the "official handle of JavaOne" is @JavaOneConf, the best place to find these tweets from individuals' who have had abstracts accepted is #Javaone.

The many Tweets give us a preview of the diverse topics being covered at JavaOne 2011. These topics include Clojure, Grails, Groovy, JBoss, CDI, Spring Batch, Java Persistence API, Java EE, Java tuning, and many more.

Tweets are easier and quicker to write, so it's not surprising that we're seeing mostly Tweets at this point. However, there are blog posts already out as well. These include a summary of some of the earliest Tweets in JavaOne 2011 notifications are in!, Reza Rahman's Java Blog: Speaking at JavaOne 2011!, and Metawidget @ JavaOne 2011.

I'm looking forward to hearing about additional accepted JavaOne abstracts today and during the week. The more I hear about the accepted sessions, the more excited I am to attend JavaOne again this year.

Monday, July 11, 2011

Summer 2011 Edition of RMOUG Newsletter

I received a copy of the Summer 2011 edition of the Rocky Mountain Oracle Users Group (RMOUG) newsletter SQL>Update last week. In this post, I highlight a few items that stood out to me from this edition. In a sign of the times, this may be the issue with the most articles available online that I have ever seen. Although RMOUG does not make the newsletter's articles available online, many of the articles' authors have done so in this case.


RMOUG Training Days 2012

The back cover of the newsletter features a full-page advertisement for RMOUG Training Days 2012. The annual conference is scheduled for February 14-16, 2012, at the Colorado Convention Center in Denver, Colorado. The advertisement states that "early registration begins in November" and that "more information is coming soon."


Expanding Focus at RMOUG

In his "From the President" column, RMOUG President Tim Gorman writes:
"RMOUG needs to reach new audiences, spread our continuing education message through newer mediums, explore the effectiveness of social networking technology, and strive more to reach young and upcoming colleagues around us. Also, as the scope of Oracle Corporation has expanded to new databases, into hardware, new applications, and broader technologies, clearly RMOUG needs to expand beyond our core competencies as well."

I joined RMOUG in 2000 in conjunction with attending RMOUG Training Days 2000, the first edition of this conference that I attended. I also attended RMOUG Training Days 2001 and then have presented in some capacity at each RMOUG Training Days edition since then. Although it's certainly true that RMOUG and its Training Days conference are dominated by DBAs and developers largely tied to Oracle-specific products, it is also true that RMOUG has not entirely limited itself to these areas. There's no better evidence than this than the fact that they've accepted my abstracts for RMOUG Training Days presentations for a wide variety of topics including Java, Enterprise Java, Ruby on Rails, Apache POI, XQuery, Flex, HTML 5, REST, Groovy, XSL-FO, SVG, and Ajax.

Various forces (struggling economy, reduced IT funding, overlapping technologies, etc.) have led many of us to take on tasks from a variety of disciplines. Many developers must learn basic database administration and scripting skills and many DBAs must learn basic development and scripting skills. I agree with Gorman's assertion that the best way for RMOUG to continue to appeal to a younger generation and to a wider audience is to embrace some new approaches and new topics. I think RMOUG's tried to do this for some time and expect that this will continue into the future, perhaps a little more aggressively.


Passwords are Case Sensitive in Oracle Database 11g

Dan Hotka's single-page article "A Change for Oracle 11: Case Sensitive Passwords!" discusses the change in Oracle Database 11g to support case sensitive passwords. Hotka shows how to determine in SQL*Plus (or SQL Developer) if the case sensitive password option is turned on using the SHOW PARAMETER command on SEC_CASE_SENSITIVE_LOGON. He also provides a query DBAs can run to see the PASSWORD_VERSIONS for each user.

Hotka points out that some administrators in certain situations may not want case sensitive passwords. He shows how to run orapwd from the operating system command line followed by use of ALTER SYSTEM to set the SEC_CASE_SENSITIVE_LOGON parameter to FALSE. These steps disable case sensitive passwords, returning behavior to that which existed before Oracle Database 11g.

Hotka's blog, Dan Hotka Blog, features the post Oracle 11g Case Sensitive Passwords: A Change for Oracle 11, which is essentially the same content as the RMOUG SQL>Update article. This is obviously good news for those who don't have access to the printed newsletter, but it's even nice for those of us with the printed newsletter because it means it is available online to us when we don't have the newsletter with us.


Migrating the SQL Management Base

Jed Walker's article "Making Plans with Oracle 11g And Not Leaving Them Behind" discusses the Oracle Database 11g component called SQL Management Base (SMB). Walker discusses using SMB to achieve optimal query performance and then focuses on migrating these stored plans when necessary. Here is text from his introduction:
Starting with Oracle 11g the database now has a component called the SQL Management Base (SMB). The SQL Management Base contains SQL Plan baselines. SQL Plan Baselines are a known plan for a given SQL statement. Oracle stores these plans and then uses them to ensure optimal query performance. SQL Plan Baselines often significantly improve query performance without making any changes to your schema or database configuration. Once you’ve got these performance improving plans stored in the SMB you don’t want to leave them behind. The purpose of this paper is to point out some situations when you would want to migrate your SMB and how to do it.
It appears that this article is available in its entirety in PDF format on Walker's blog in the Papers section.


Oracle Database Write Consistency

Ruslan Dautkhanov begins his article "Oracle's Write Consistency: Side Effects for Applications" with this introduction:
Write consistency is barely covered in official Oracle documentation, though it can have serious impacts to applications. Understanding what issues might be lurking, and some rather puzzling behavior to those not acquainted with write consistency behavior, might provide some insight when architecting a system.
After briefly reviewing read consistency, Dautkhanov focuses the remainder of the article on write consistency in the Oracle Database. Toward the end of the article, he lists the effects Oracle's write consistency approach might have on applications.

Dautkhanov has made a PDF copy of this article available online in his blog post Oracle's Write Consistency. Dautkhanov has also provided links to source code that accompanies the article and references the Ask Tom post on write consistency.


Cloud Integration Checklist

Jordan Braunstein has written two articles in this edition of the RMOUG newsletter. The first is called "The Essential Cloud Integration Checklist." This article approaches Cloud Computing from a very high level and "explores the more critical characteristics of integrating to and from the cloud, and how to ensure your solution is stable, scalable, and interoperable." Braunstein focuses on several aspects of cloud integration such as security, interoperability, presentation, federated search, functionality/usability, and standards before listing some "leading practices." Braunstein has made this article available on his "SOA Today" blog as post The Essential Cloud Integration Checklist.


IT Isn't Dead

Jordan Braunstein begins his second article in this edition of the RMOUG newsletter (called "IT Isn't Dead: 100% Guaranteed Approach to Keep Your CEO Happy") with the statement, "If there is one constant with IT, it is the guarantee of change." As part of this one-page article, Braunstein lists "IT trends that every company should be considering in order to keep their company strategically aligned for high value gains." Braunstein has made this article available online as a blog post: IT Isn't Dead. 100% Guaranteed Approach to Keep your CEO Happy.

By the way, if you're a software architect or like to make fun of software architects, then you should check out Braunstein's post Software Architect Proverbs.


IT Value

Bill Wimsatt's article "IT Investment Management: Get the Value from IT Projects" includes an abstract that starts with a definition of investment: "Investment is about applying resources to return higher value than the initial resource outlay." One of the sentences from this article that I found most interesting is: "I would posit that many projects are failures in the eyes of the investors regardless of whether the project was on time or on budget." He also writes, "The investment must be for business purpose that is used to increase company revenue, market share and profit (via reduced expenses)." This article is available online.


People of RMOUG

This edition of the RMOUG newsletter also featured Lisa Collett in the "RMOUG Member Focus" and Ron Bich in the "RMOUG Board Focus." There are brief biographies also provided for new RMOUG Board Members John Jeunnette and Kellyn Pot'vin.

Saturday, July 9, 2011

O'Reilly's OSCON Chairman: "Java deserves another look"

I frequently wholeheartedly agree with opinions expressed by Java.net editor Kevin Farnham in his Editor's Blog. Nevertheless, I was still surprised to discover that his most recent post (Is Java Becoming an 'Emerging Technology'? Ask O'Reilly) seemed to capture and even better articulate my own recent thoughts after reading the same three O'Reilly posts (all by Edd Dumbill) he references: Seven reasons you should use Java again, Seven Java projects that changed the world, and A rough guide to JVM languages. Each of the three Dumbill/O'Reilly posts is well worth reading on its own merits, but what really struck me is the overall observation I made as I read these posts: this might be O'Reilly's way of saying "Java is back!"

Kevin Farnham emphasizes that these three posts are part of O'Reilly Radar, which describes itself as (I have added the emphasis) "Insight, analysis, and research about emerging technologies." Kevin also cites other evidence of renewed interest from O'Reilly in Java with references to O'Reilly Radar's Clojure: Lisp meets Java, with a side of Erlang post, O'Reilly hosting OSCON-Java, the related post Why OSCON Java?, and O'Reilly's Mike Hendrickson's intriguing 2010 State of the Computer Book Market - The Languages post.

The last cited reference is fascinating because it covers all major computer book sellers (not just O'Reilly), but states the following quote (Kevin also quoted a portion of this due to its obvious interest to Java developers):
In 2008, we reported that C# surpassed Java as the number one language. But hold on, Java proved to be resilient in 2009 and experienced a resurgence in 2010 and is now the number one language from a book sales perspective. As you can see in the 2010 Top 20 languages chart below, Java has a significant lead in the language race with Objective-C moving into third place closely behind C#.

I agree with Kevin's assessment of value of the book sales numbers: "And book sales, I think, are indeed a good indicator, since that's a 'vote' that is registered using financial currency." I think it's also important to note that other JVM languages such as Groovy, Scala, JRuby, and Clojure are NOT included in those Java book sales numbers. For example, Groovy books (2452 books) and Scala books (2531 books) are considered mid-minors (number of books sold in year was between 1682 and 2999) while Java books were the largest (almost 200,000 books sold) of the "large" category (50,000 to 200,000 books sold) in 2010.

I had started to wonder if O'Reilly was no longer interested in selling Java-related books as it seemed in recent years that competing publishers such as Manning had really taken the lead in terms of numbers of available books on Java-related technologies such as the Groovy language. For example, the top three books returned from a current Amazon.com search for "groovy" are the three Groovy books I have previously recommended. None of these three is from O'Reilly and I don't think there are any books on Groovy directly published by O'Reilly. However, it is worth noting that O'Reilly is the distributor of paperback copies to retail stores of two of my top three Groovy books: the Pragmatic Programmers books Groovy Recipes and Programming Groovy. I found it interesting that the O'Reilly/Groovy situation sames to match that for O'Reilly and Ruby.

Kevin points out that "it can't be claimed that O'Reilly ever stopped covering Java." It just seemed to me that perhaps O'Reilly lost some interest and reduced coverage of Java and the Java ecosystem. Evidence that O'Reilly remained somewhat involved in Java includes their direct support for Java.net which lasted from its creation until the Oracle acquisition. About this Kevin stated, "Java.net itself was the joint creation of O'Reilly and Sun. ... java.net is no longer formally associated with O'Reilly, but, without O'Reilly, I doubt there ever would have been a java.net."

O'Reilly has continued to feature Java-related books. RESTful Java with JAX-RS (2009), for example, is one of my favorite "recent" (last few years) Java-related books and includes a chapter that I have cited as one of the Ten Best Chapters of Software Development Books. As they do with the Groovy books previously mentioned, O'Reilly distributes the paperback versions of Using JRuby (published this year) to retail stores on behalf of the Pragmatic Programmers. Two Java-related titles published (not simply distributed) by O'Reilly in 2011 are Building and Testing with Gradle and Clojure Programming: Rough Cuts Version. O'Reilly seems more interested in Android development in recent years.

There was a time when O'Reilly was to go-to publisher for Java books with famous titles like Java in a Nutshell, Enterprise Java in a Nutshell, Enterprise JavaBeans, Java Cookbook, Head First Java, and Java Power Tools. It appears to me that there has been some loss of interest in Java books in the last couple of years and that Manning has shown more interest in Java-related books. I like several books particularly well from both publishers and hope that both (and other publishers) will continue to publish Java/JVM-related books. The competition is good for consumers and the different styles provide nice alternatives. I hope that the impressive numbers of Java books sold again in 2010 motivates these publishers to continue Java/JVM publications.

I definitely agree with Kevin's assessment that "the folks at O'Reilly" have "historically done a pretty good job of sensing where technology is heading." Because of this, I wondered if they knew something I didn't when they seemed disinterested in publishing new Java-related books. It is comforting to think that perhaps they were waiting to see how things turned out and, based on recent trends and announcements, now think it's time to again invest in books about Java and the JVM.

In many ways, I think O'Reilly's recent upsurge in public enthusiasm for Java may be reflective of a wider trend among the general software development community. The prolonged wait from Java SE 6 to Java SE 7, combined with the uncertainty surrounding the Oracle acquisition of Sun, seemed to put a damper on many peoples' expectations regarding the future of Java. I knew many developers who felt that there was little "new" stuff in the world of Java for a few years there to justify purchasing any new books. With this in mind, it may be no surprise if O'Reilly did decide to reduce the number of new Java-related titles it published in recent years.

The rise of the JVM languages, the rise of Android, and a new version of Java (7) with plans for even further new versions of the language, seem to have started bringing back enthusiasm for Java and the JVM. O'Reilly's Radar may turn out to once again be a particularly adept gauge of the language's popularity.

In Seven reasons you should use Java again (one of the posts that Kevin and I linked to), Edd Dumbill starts the post with, "Java's back, baby." He does immediately follow that with acknowledgement that "lots of us never stopped using Java in the first place." It makes me wonder if this, even unintentionally and obviously unofficially, represents a general sentiment around O'Reilly. It certainly could be argued that it reflects a general developer sentiment. He lists seven reasons to "take another look at Java" and I particularly like the final one: "You'll end up using it anyway." He cites the recent Twitter architecture announcement as an example of that last reason.

I'm excited about OSCON Java this year. Although Java has had its own track at OSCON before, this feels bigger and better to have its "own conference" this year held in conjunction with OSCON proper. Personal commitments prevent me from attending, but it looks to be an interesting conference.

Java dominated the Tiobe Index again in 2010 and outsold all other languages in terms of books sold in 2010. That's not bad for a dead language. It's also a reminder that the opinions touted on the blogosphere are rarely reflective of the general spectrum and breakdown of opinions of the software development community.

Friday, July 8, 2011

Automatic Deletion of Temporary Work Files in Java 7/Groovy

I have touched on several subjects in individual posts prior to this one that now come together in this single post. These subjects include use of File.deleteOnExit() in Groovy, creation of temporary files in Java, and use of the Java System property java.io.tmpdir to locate the temporary directory for a particular JVM instance. In this post, I look at different ways to ensure that files created "temporarily" as "work files" get deleted automatically.

There are many times in both application development and script development that I have need of temporary files that are not intended to be used outside of that script's or application's current execution. It is typically best to have the application or script using these temporary files both create them when needed and delete them when no longer needed. Files created for temporary tasks that are not intended to outlive the Java process that creates them are referred to in the Java documentation as "work files." Although these "work files" might be placed in any directory the application or script chooses as long as it ensures they get removed, a convenient location entirely intended for such a person is the temporary directory defined by the Java system property java.io.tmpdir.

For purposes of this post, I will be creating all files in the temporary directory defined by java.io.tmpdir and will use the new Java 7 class Files with its createTempFile methods to create those temporary files. That is all for setup. The real intent of this post is then to demonstrate different options for ensuring that these temporary files are truly temporary. In other words, this post covers multiple ways to establish automatic deletion of files intended to be temporary.

The Javadoc documentation for the methods Files.createTempFile talks about three ways to ensure that a temporarily created file is deleted as part of the "temporary file facility":
As with the File.createTempFile methods, this method is only part of a temporary-file facility. Where used as a work files, the resulting file may be opened using the DELETE_ON_CLOSE option so that the file is deleted when the appropriate close method is invoked. Alternatively, a shutdown-hook, or the File.deleteOnExit() mechanism may be used to delete the file automatically.
These are the three approaches to automatic cleanup of temporary files that I cover in this post and they are all demonstrated in the next code listing.

demoAutoTempFileDeletion.groovy
#!/usr/bin/env groovy
/**
 * demoAutoTempFileDeletion.groovy
 *
 * This script creates three temporary files and then demonstrates ways to
 * ensure that these temporary files are automatically removed by the time the
 * script's JVM ends. The three approaches for automatic file deletion
 * demonstrated in this script are use of StandardOpenOption.DELETE_ON_CLOSE,
 * File.deleteOnExit(), and Runtime.addShutdownHook(Thread).
 */

import java.nio.file.Files
import java.nio.file.Paths
import static java.nio.file.StandardOpenOption.*

@groovy.transform.Field def tempDir = System.getProperty('java.io.tmpdir')

println "\nTemporary directory is ${tempDir}"

/*
 * Demonstrate automatic file cleanup via StandardOpenOption.DELETE_ON_CLOSE
 */
def tempPath1 = Files.createTempFile("dustin1-", "-one")
def os = Files.newOutputStream(tempPath1, CREATE, APPEND, DELETE_ON_CLOSE)
os.write('This is file content.'.bytes)
listFiles(tempPath1)

/*
 * Demonstrate automatic file cleanup via File.deleteOnExit() 
 */
def tempPath2 = Files.createTempFile("dustin2-", "-two")
Files.write(tempPath2, 'This is also file content.'.bytes)
tempPath2.toFile().deleteOnExit()
listFiles(tempPath2)

/*
 * Demonstrate automatic file cleanup via shutdown-hook
 */
def tempPath3 = Files.createTempFile("dustin3-", "-three")
Files.write(tempPath3, 'This is even another file.'.bytes)
Runtime.getRuntime().addShutdownHook(new Thread()
{
   public void run()
   {
      Files.delete(tempPath3)
   }
});
listFiles(tempPath3)



/**
 * List files in temporary directory that meet naming convention for files
 * written by this script.
 *
 * @param progress String indicating progress.
 */
def void listFiles(progress)
{
   println "\n== After ${progress}\n"
   def currentDirectory = Paths.get(tempDir)
   currentDirectory.toFile().eachFile
   {
      def pathName = it.canonicalPath
      if (pathName.contains('dustin'))
      {
         println "\t${pathName}"
      }
   }
}

When the above script is executed, output similar to that in the next screen snapshot is generated.


The output shows that all three files are created by the script, but that by the time a directory listing is done on the temp defined by java.io.tmpdir, they have already been removed automatically. Each of the three temporarily created files was deleted automatically via a different mechanism.

The first file's automatic cleanup is achieved by providing of the Java 7 StandardOpenOption.DELETE_ON_CLOSE enum value to the Files.newOutputStream method. When the script exits, this file gets automatically deleted.

The second file's automatic cleanup is achieved by the more traditional File.deleteOnExit() method that I have previously discussed in the blog post Java's File.deleteOnExit() in Groovy.

The third file's automatic cleanup is achieved through the use of Runtime.addShutdownHook(Thread). In this case, the body of the thread is very simple, using a single statement taking advantage of Java 7's Files.delete(Path) method.


Conclusion

Scripts commonly need to create files for temporary use and Java now provides several easy approaches for ensuring automatic deletion of files meant to be temporary in nature and to be removed when the particular script or application is finished. In this post, I have demonstrated the three main approaches for automatic file deletion recommended by the Javadoc documentation for the Files.createTempFile method to be used in conjunction with the temporary file facility.

Thursday, July 7, 2011

Walking the File Tree with Java 7's Files and FileVisitor

In the previous post Java SE 7 Brings Better File Handling than Ever to Groovy, I discussed the ability to use Java 7's NIO.2 implementation to discover a wide set of attributes, characteristics, and metadata regarding files and file systems. I followed that up with coverage of various operations that can be performed on directories and files using Java 7's NIO.2 support in the post File and Directory Operations with Java 7's Files Class. In this post, I focus on the ridiculously useful new overloaded Files.walkFileTree methods that provide an easy way for Java, Groovy, or other JVM language developers to easily traverse a file/directory tree and process files and directories along the way. I just touch the surface of this powerful technique in this post with a single simple example.

Both overloaded versions of Files.walkFileTree accept a starting point for the "walk" as an instance of the newly introduced Path class. Both of these methods also expect to be passed an instance of an implementation of the FileVisitor interface (SimpleFileVisitor in this case) of parameterized type Path. My example in this post uses the simpler (and less flexible) of the two. It does not allow options such as following symbolic links to be specified. However, it works sufficiently for my example, demonstrates the technique nicely, and it is still easy enough to use the other version of the method with the options for a more flexible example.

My simple example is a script written in Groovy that renames files. For simplicity's sake, I have hard-coded the root directory that will serve as the starting point of the walk, but this could have been easily retrieved as a command-line parameter to the script. This script renames files if they have spaces in their name and changes any uppercase letters to lowercase. The specific details of how files are renamed is documented as comments in the script itself. Here is that simple script.

renameFiles.groovy
#!/usr/bin/env groovy
/**
 * renameFiles.groovy.
 *
 * For simplicity, this script assumes all files to be renamed are in the
 * directory C:\workarea. This script renames all files for which renaming is
 * allowed in the C:\workarea directory that meet certain characteristics.
 * This script replaces spaces in file names with underscores, trims spaces off
 * altogether (no underscore) that are the first or last characters of the file
 * name, and changes all letters in the file name to lowercase.
 */

import java.nio.file.attribute.BasicFileAttributes
import java.nio.file.Files
import java.nio.file.Path
import java.nio.file.Paths
import java.nio.file.FileVisitResult
import java.nio.file.SimpleFileVisitor

Path start = Paths.get("C:\\workarea")
Files.walkFileTree(start, new SimpleFileVisitor()
{
   @Override
   public FileVisitResult visitFile(Path filePath, BasicFileAttributes attrs)
      throws IOException
   {
      def fileName = filePath.fileName
      def dirPath = filePath.parent
      def newFileName = fileName.toString().trim().toLowerCase().replace(" ","_")
      def newFilePath = Paths.get(dirPath.toString(), newFileName)
      Files.move(filePath, newFilePath)
      println "Renamed ${fileName} to ${newFileName}."
      return FileVisitResult.CONTINUE;
   }
});

That's all there is to it! The output is captured in the screen snapshot that comes next. The snapshot shows a directory listing with the original files' names followed by a directory listing after this script has been run. The snapshot also includes the terminal in which this script was run.


As the example above indicates, I can override the method FileVisitor.visitFile to prescribe exactly what actions should be taken on each file that is encountered during my traversal of the files (walking the file tree) underneath the starting directory using Files.walkFileTree. The FileVisitor interface also advertises other hooks that I can implement to control other aspects of walking the file tree: visitFileFailed, preVisitDirectory, and postVisitDirectory.

There are other examples of walking the file tree with Java 7 available online. The Javadoc documentation for FileVisitor includes a "Usage Example" section that provides two more complicated examples than I've shown here. The first example shows deleting the contents of a directory first before deleting the directory itself and implements visitFile and postVisitDirectory (delete the directory AFTER the contained files) in the process. The second example contained in that Javadoc implements preVisitDirectory to first create a directory and then implements visitFile to copy files to that target directory. The second example also shows off using of the other overloaded version of Files.walkFileTree that accepts the option to follow symbolic links.

The Java Tutorials now contain a section focusing exclusively on walking the file tree. Another interesting example online that is also an idea for another application of Java 7 NIO.2 features is in the post The ZIP filesystem provider in JDK7.

Finally, this is a big week for Java 7. Today is Oracle's Java 7 party. I'm looking forward to hearing what they have to say about Java 7 (includes coverage of file I/O). In addition, other recent posts of interest related to Java 7 include Using JDK 7's Fork/Join Framework and the announcement that build 147 is the first release candidate of Java 7.

Conclusion

This is a big week for Java 7. In this post, I've provided a quick taste of the power of the newly available file tree walking mechanism provided by Java 7's NIO.2 support.

Wednesday, July 6, 2011

Groovy One-Liner for Viewing Available Charsets

I've stated several times on this blog that I particularly like Groovy as a scripting language in a Java development environment. Groovy is often the easiest approach to learning more about the available Java libraries and the Java execution environment (JRE). I have posted several examples of this in posts such as Groovy: JVM-based Scripting with Less Ceremony, Ten Groovy One Liners to Impress Your Friends, and Ten More Groovy One-Liners. In this post, I look at another one-liner for determining available character set support.

There are actually two ways to find "every charset for which support is available in the current Java virtual machine" (quote source) using a single line of Groovy script. One single-line approach uses a Groovy-specific class while the other single-line approach uses a standard Java class. I'll demonstrate both examples.

The Java Approach

One approach to determining a JVM's supported character sets with a single line of Groovy is to use the Java NIO class provided for that purpose. The following line of Groovy code uses Charset.availableCharsets() to list all character sets supported on the current JVM. The entire Groovy code looks like this:

java.nio.charset.Charset.availableCharsets().each{println it}

As is the case with most one-liners, this one is short enough that I can easily try it out without an explicit script file by simply passing this command to the groovy launcher with the -e option. This is demonstrated in the next screen snapshot.



The Groovy Approach

Groovy provides a class called CharsetToolkit that can also be used in a single line of Groovy to extract the supported character sets on the current JVM. Here is the code using that class and its getAvailableCharsets() method.

CharsetToolkit.availableCharsets.each{println it}

I again show this as used with the groovy launcher and its -e option.


Although both of the above approaches do the job of displaying the JVM's supported character sets, I slightly prefer the Groovier approach because it uses Groovy's property support on the method named getAvailableCharsets and does not require an explicit import or scoping. These advantages make it slightly more concise with no loss of readability.


Determining the JVM's Default Charset

Both the Java class Charset and the Groovy class CharsetToolkit also make it easy in a single line of Groovy script to determine the default character set for the given JVM. This is done via Charset.defaultCharset() or CharsetToolkit.getDefaultSystemCharset(). The "full" script for each is shown in the next two single-line code listings.

println java.nio.charset.Charset.defaultCharset()

println CharsetToolkit.defaultSystemCharset

The Groovy approach is again shorter, but not by much. The output of running both of these via the groovy launcher and its -e option are shown in the next single screen snapshot.


Conclusion

Acquiring the available character sets supported by a particular JVM as well as determining the default character set supported by a particular JVM are easily accomplished with a single line of Groovy script using either the Java Charset class or the Groovy CharsetToolkit class. This is another example of how Groovy is an ideal scripting language for a Java development environment and working with the JVM.

File and Directory Operations with Java 7's Files Class

In the blog post Java SE 7 Brings Better File Handling than Ever to Groovy, I discussed how the addition of NIO.2 features in JDK 7 means better file handling for Groovy scripts. My particular focus in that post was on the characteristics of files and directories provided by the new NIO.2 classes and interfaces. In this post, I focus on the file operations supported by Java 7's NIO.2 Files class.

I quoted the Javadoc documentation for the Files class in my earlier post and I repeat those two quoted sentences here:
This class consists exclusively of static methods that operate on files, directories, or other types of files.

In most cases, the methods defined here will delegate to the associated file system provider to perform the file operations.

The methods on the Files class have descriptive names. For example, it is obvious what methods like Files.copy, Files.createDirectory, Files.createSymbolicLink, Files.delete, and Files.move are intended to do.

The Files class makes heavy use of an interface new to Java 7 via NIO.2: the Path interface. As can be seen when viewing the Files class API via Javadoc, via running javac -XPrint java.nio.file.Files, or via running javap java.nio.files.Files, the Path interface is expected by many of the methods on the Files class. I introduced some of the useful methods Path provides in my previous post.

Once one has access to an instantiation of Path, that Path's parent can be retrieved as another instance of Path. Similarly root paths, absolute paths, real paths, sibling paths, relative paths, and even sub-paths can be easily accessed from a starting Path instance. Perhaps the most difficult (and it's not really very difficult) part of starting to use the new Files class is knowing how to get an initial instance of Path.

The easiest way to acquire a Path instance if you already have a java.io.File handle is to call File's new toPath() method. Other approaches for acquiring instances of Path include passing parts of a desired path to FileSystem.getPath(String, String...) [usually use the instance of FileSystem provided by FileSystems.getDefault()], passing a single or multiple Strings representing parts of a path to the new Paths class and its Paths.get(String,String...) method, or passing a URI instance to the Paths.get(URI) method.

Although the names of the methods on the Files class are self-describing and the Javadoc comments do a good job of filling in any minor details and covering nuances of these methods, I show some examples here to quickly illustrate some of the features of the new File operations provided by the Files class. The next simple Groovy script (demoFilesOperations.groovy) does just this, demonstrating some key file/directory operations methods on the JDK 7 Files class.

demoFilesOperations.groovy
#!/usr/bin/env groovy
/**
 * demoFilesOperations.groovy
 *
 * Demonstrate some of the operations on files and directories provided by Java
 * SE 7 and its NIO.2 implementation. Specific focus is applied to the methods
 * of the java.nio.file.Files class and the java.nio.file.Path interface.
 */

import java.nio.file.Files
import java.nio.file.Paths

// 1. Acquire 'working directory' name to use as current directory.
def currentDirectoryName = System.getProperty("user.dir")

// 2. Convert 'working directory' name plus a subdirectory named 'playarea' into
//    an instance of Path
def playAreaPath = Paths.get(currentDirectoryName, "playarea")
def playAreaStr = playAreaPath.toString()

// 3. Create new subdirectory with name 'playarea'
def playAreaDirPath = Files.createDirectory(playAreaPath)

// 4. Create a temporary directory with prefix "dustin_"
def tempDirPath = Files.createTempDirectory("dustin_")

// 5. Create temporary files, one in the temporary directory just created and
//    one in the "root" temporary directory. Create them with slightly different
//    prefixes, but the same '.tmp' suffix.
def tempFileInTempDirPath = Files.createTempFile(tempDirPath, "Dustin1-", ".tmp")
def tempFilePath = Files.createTempFile("Dustin2-", ".tmp")

// 6. Create a regular file.
def regularFilePath = Files.createFile(Paths.get(playAreaStr, "Dustin.txt"))

// 7. Write text to newly created File.
import java.nio.charset.Charset
import java.nio.file.StandardOpenOption
Files.write(regularFilePath,
            ["To Be or Not to Be", "That is the Question"],
            Charset.defaultCharset(),
            StandardOpenOption.APPEND, StandardOpenOption.WRITE)

// 8. Make a copy of the file using the overloaded version of Files.copy
//    that expects two Paths.
def copiedFilePath =
   Files.copy(regularFilePath, Paths.get(playAreaStr, "DustinCopied.txt"))

// 9. Move (rename) the copied file.
import java.nio.file.StandardCopyOption
def renamedFilePath = Files.move(copiedFilePath,
                                 Paths.get(playAreaStr, "DustinMoved.txt"),
                                 StandardCopyOption.REPLACE_EXISTING)

// 10. Create symbolic link in 'current directory' to file in 'playarea'
def symbolicLinkPath = Files.createSymbolicLink(Paths.get("SomeoneMoved.txt"), renamedFilePath)

// 11. Create (hard) link in 'current directory' to file in 'playarea'
def linkPath = Files.createLink(Paths.get("TheFile.txt"), regularFilePath)

// 12. Clean up after myself: cannot delete 'playarea' directory until its
//     contents have first been deleted.
Files.delete(symbolicLinkPath)
Files.delete(linkPath)
Files.delete(regularFilePath)
Files.delete(renamedFilePath)
Files.delete(playAreaDirPath)

The above example is self-contained and cleans up after itself. Note that on many file systems the above script should be executed with administrator privileges for the creation of links to work properly. The NIO.2 additions to Java 7 include several new enums and interfaces that these enums implement for capturing options related to these various file/directory operations. I tried to use some of these in the Groovy script above for demonstration. I also added a lot of comments to make it clear what the script is doing. The script is another reminder of the prevalence of Path instances when using the new file I/O API.


Java 7's Files Relationship to File Class

The Javadoc for the Java 7 version of the old timer java.io.File class describes the relationship of that older class with Java 7's new java.nio.file.Files class:
The java.nio.file package defines interfaces and classes for the Java virtual machine to access files, file attributes, and file systems. This API may be used to overcome many of the limitations of the java.io.File class. The toPath method may be used to obtain a Path that uses the abstract path represented by a File object to locate a file. The resulting Path may be used with the Files class to provide more efficient and extensive access to additional file operations, file attributes, and I/O exceptions to help diagnose errors when an operation on a file fails.


Conclusion

Although the example in this post was written in Groovy, the new NIO.2 file APIs are standard Java and can, of course, be used in Java code or by applications and scripts written in other JVM-based languages. The new Java 7 Files class provides convenient and consistent one-stop shopping for the most common operations of files and directories. This post has attempted to demonstrate how easy it is to apply the new Files class and its static methods. However, even with two posts now talking about the Files class, I have still not covered all it has to offer. I expect the Files class and the rest of the Java 7 NIO.2 file APIs to be of particular value in writing Groovy scripts that process files and directories.