Tuesday, April 29, 2014

Book Review: NetBeans Platform for Beginners

The recent Leanpub publication NetBeans Platform for Beginners: Modular Application Development for the Java Desktop by Jason Wexbridge and Walter Nyland provides an introduction to and coverage of the NetBeans Platform. I review the PDF version of NetBeans Platform for Beginners that was last updated on 26 March 2014 in this post.

NetBeans Platform for Beginners features over 350 pages of content divided into ten chapters and three major parts. Although the authors address NetBeans 7.4 specifically, the material in this book should be appropriate for several future versions of NetBeans as well. No prior NetBeans experience is assumed, but familiarity with Java is assumed. Although I've used Java and NetBeans IDE for years, my experience with NetBeans Platform has been minimal, making a book focused on NetBeans Platform for Beginners attractive to me.

Part 1: Core

Part 1 of NetBeans Platform for Beginners consists of four chapters focusing on "the mandatory core features of the NetBeans Platform." The initial chapter provides an overview of NetBeans Platform and demonstrates wizard-based creation and modification of simple NetBeans Platform-based applications. Although I don't have any significant experience with NetBeans Platform, this chapter was an easy-to-understand introduction, especially because much of what is covered consists of variations of approaches very familiar to anyone who has used NetBeans IDE extensively. This first chapter also outlines many advantages and features of NetBeans Platform.

The second, third, and fourth chapters of NetBeans Platform for Beginners respectively cover the Module System, File System, and Lookup features of the NetBeans Platform (three of Geertjan Wielenga's top four NetBeans Platform APIs).

The second chapter's coverage of the NetBeans Platform Module System describes benefits and trade-offs of modularity in general and discusses several details related to NetBeans Platform Module System such as use of manifest files, NBM files, and how to split an application into modules. The third chapter's coverage of the NetBeans Platform File System includes System FileSystem (see also related slides), module layers, FileObjects, FileObject attributes and DataObjects.

The fourth chapter (and final chapter in Part 1) begins with an introduction of why high cohesion and low coupling are architecturally desirable and states that "Lookup is a generic mechanism for loose coupling" in NetBeans Platform. The authors discuss the general JDK ServiceLoader mechanism as a foundation for understanding the NetBeans Lookup mechanism. They then compare the two approaches and list advantages of using NetBeans Lookup with applications based on NetBeans Platform. There are quite a few pages in this chapter devoted to introducing and demonstrating use of various approaches one can use to leverage the Lookup mechanism and the @ServiceProvider annotation.

Part 2: GUIs

Part 2 of NetBeans Platform for Beginners contains three chapters focusing on GUI components of the NetBeans Platform. Chapter 5 covers the Action System, Chapter 6 covers the Window System, and Chapter 7 covers Nodes and Explorers.

Chapter 5 introduces the NetBeans Platform Action System and introduces the ActionListener annotations @ActionID, @ActionRegistration, and @ActionReference. The chapter covers presenters such as menus, toolbars, keyboard shortcuts, and mnemonics.

The sixth chapter of NetBeans Platform for Beginners is focused on the NetBeans Platform Window System. There is quite a bit of content packed into this chapter including coverage of the benefits of the Window System as well as coverage of specific conceptual details such as describing components, registering components, component lifecycle, docking components, undoing changes within components, and lookup. The advanced section of this chapter's concept coverage was useful in understanding some of the material prior to the advanced section. For example, I understood Modes better after reading the advanced section on Modes than I did after reading the earlier section that briefly described Modes. One particularly interesting aspect of this chapter is highlighting of the internally (to NetBeans) developed Simple Validation API.

NetBeans Platform's Nodes and Explorer Views are the subject of Chapter 7 of NetBeans Platform for Beginners. The authors emphasize that "Nodes are a layer of indirection between a data model" before delving into coverage of specific types of Node classes. For example, the authors explain how a BeanNode is an adapter that wraps an underlying data-centric JavaBean/POJO with properties for presentation purposes. Other types of covered Node classes include DataNode (wraps file access), FilterNode (decorates another node in memory), and AbstractNode (suitable for extending for most custom Node implementations).

The authors also discuss explorer views in Chapter 7: "The Explorer & Property Sheet API consists of a set of GUI components, known as explorer views or explorers, that render Nodes."

Part 3: Extras

The first two parts of NetBeans Platform for Beginners ("Core" and "GUI") covered commonly used features of the NetBeans Platform. Part 3 focuses on NetBeans Platform features that are less commonly used.

Chapter 8 begins with an introduction of NetBeans Visual Library and NetBeans Platform Component Palette. Its initial paragraph on NetBeans Visual Library is essentially that provided on the library's main page:

The NetBeans Visual Library provides a set of reusable, predefined, and extensible Java components, called "widgets". Each widget has, built into it, various features, such as actions, layouts, and borders. When you compose widgets together, you can quickly and easily visualize data to the user. Combined with other NetBeans APIs, the NetBeans Visual Library lets you create interactive UIs, with drag-and-drop features commonly found in designer software.

The NetBeans Platform Palette and NetBeans Platform Widgets are covered in Chapter 8.

The ninth chapter of NetBeans Platform for Beginners introduces the NetBeans Platform "project type" and defines it as "a group of folders and files that should be treated as a single unit." There is significant detail in this chapter on using various APIs available on a NetBeans Platform project.

Chapter 10 is a "Miscellaneous" chapter that begins with a table of NetBeans APIs listed in alphabetical order. Text detailing each of these APIs follows the table. Most of the chapters prior to this one covered concepts first (basic and then advanced) before covering application of those concepts in the "Getting Started" section of each chapter. Chapter 10 is different in that the concepts and application are largely covered (briefly) together.

Other Observations
  • NetBeans Platform for Beginners makes use of numerous color (in the PDF version) screen snapshots. This makes visualizing what is being described more pleasant and makes reading and understanding the material easier.
  • I appreciate the color coded syntax applied to the code listings in PDF version of NetBeans Platform for Beginners. Using editors and IDEs that provide color coded syntax for years has spoiled me and I find it much easier to read code in a book when it has syntax coloring. Code samples in books are still not as readable as in IDEs but color syntax is far easier to read than syntax with no color highlighting. Some of the code listings don't seem completed color coded (some keywords are color coded in some listings but not others), but I appreciate the effort to get most of them color coded.
  • The PDF version of NetBeans Platform for Beginners that I reviewed has embedded links in text that references other parts of the book. This is very convenient and much easier to use to navigate throughout the text than trying to find a referenced subtitle or page number. Hyperlinks are a big part of the reason for the ubiquity of the web and I'm a bit surprised that more electronic books don't apply the concept as it is a major advantage over printed books.
  • I like that NetBeans Platform for Beginners often provides keyboard shortcuts for various actions in addition to explaining how to specify actions with mouse clicks.
  • There aren't many typos or spelling errors in the version (March 2014) of NetBeans Platform for Beginners that I reviewed. One exception to this is in Section 7.1.6.1.2 ("JPA"), which defines the JPA acronym as "Java Persistence Annotation specification" rather than as the "Java Persistence API specification." None of the typos I saw affected the accuracy of the information in a meaningful way as far as I could tell.
  • Although the "for Beginners" portion of its title suggests its introductory nature, NetBeans Platform for Beginners has enough detail in it to be useful as a reference as well. In fact, I think there are portions of the book that I'd better appreciate once I had more familiarity and practical experience with NetBeans Platform. Geertjan Wielenga, who is very familiar with the NetBeans Platform and has read multiple books on the NetBeans Platform, has written about NetBeans Platform for Beginners: "I think 'NetBeans Platform for Beginners' is a fantastic resource for NetBeans Platform developers, all the more so in combination with Leanpub.com, which is a simply wonderful authoring/publishing platform."
  • Most chapters in NetBeans Platform for Beginners covered concepts first and then illustrated those concepts with realistic code examples. In some cases, I found this enhanced my learning and in other cases I found I needed the code examples to clear up my interpretation of the descriptions of the concepts.
Conclusion

NetBeans Platform for Beginners provides a comprehensive introduction to the NetBeans Platform (version 7.4 specifically, though most of its content will apply to versions before and after that). It begins with "core" information that is easily learned by someone new to NetBeans Platform and the other two parts add increasingly deep information regarding the NetBeans Platform.

Saturday, April 26, 2014

Book Review: Web Development with Jade

Packt Publishing recently published Web Development with Jade by Sean Lang. The subtitle of this book is "Utilize the advanced features of Jade to create dynamic web pages and significantly decrease development time."

Web Development with Jade is a relatively short book coming in at under 60 pages of main content divided into eight chapters and a one-page appendix. As is the case with most Packt Publishing books, the Preface contains useful information for people trying to decide whether to purchase the book. The Preface describes Jade as "a templating engine for Node.js" that is a "new, simplified language that compiles into HTML and is extremely useful for web developers." About Web Development with Jade, the Preface states, "This book is an introduction to Jade, and it will provide readers a with faster and cleaner way to write HTML that is more maintainable and automates redundant markup."

The Preface of Web Development with Jade states that the book is designed for "web developers with at least a basic understanding of HTML and JavaScript" and that readers of the book should have access to Node.js and a text editor.

Chapter 1: What is Jade?

The initial chapter of Web Development with Jade introduces Jade as "a templating language and a shorter, more elegant way to write HTML." The chapter discusses preprocessors in general before describing use Jade preprocessing specifically. The early part of this chapter also compares Jade to potential alternates HAML, PHP, Jinja2, and Mustache.

The first chapter moves to discussion of installing Jade by downloading Node.js and using the Node.js Package Manager (npm) to install Jade from the command line. With Jade installed, the chapter concludes with examples of compiling Jade template code into JavaScript and HTML.

Chapter 2: Basic Syntax

The second chapter of Web Development with Jade begins coverage of Jade syntax by explaining that indentation is used in Jade rather than opening and closing tags and braces like some other languages and templating tools use. This chapter does a nice job of presenting the basics of Jade syntax in an approachable manner. Seeing is believing and it's this chapter filled with simple examples that really "sells" one on the expressiveness of Jade better than any amount of descriptive text could.

Chapter 3: Feeding Data into Templates

Web Development with Jade's third chapter begins by demonstrating that JavaScript code can be executed within Jade templates by prefixing the JavaScript code with a hyphen and a space. The chapter describes and illustrates with examples how to use interpolation and escaping in Jade. The chapter also discusses and demonstrates providing data to a Jade template being compiled via compiler argument using --obj and via programmatic application of client-side Jade utilities in runtime.js.

Chapter 4: Logic in Templates

Chapter 4 of Web Development with Jade begins by introducing JavaScript-based logic (if/else, for, etc.) added to Jade templates. The chapter then moves to coverage of built-in Jade logical operators (if/else/else if, unless, cases, each, while) that read cleaner than embedded JavaScript.

Chapter 5: Filters

The fifth chapter of Web Development with Jade discusses use of other preprocessed languages within Jade by taking advantage of Jade filters and the underlying transformers library. The chapter provides a lengthy list of supported template engines along with lists of supported stylesheet languages, minifiers, and a miscellaneous category of supported preprocessor languages. The author then demonstrates embedding a subset of these (Markdown, CoffeeScript, and Stylus) into Java via code examples.

Chapter 6: Mixins

Web Development with Jade's sixth chapter covers Jade mixins and describes mixins as "small, encapsulated pieces of code that are reusable throughout the template" that "allow you to reduce redundancy" and to "make code easier to understand by providing good names." The chapter introduces mixin syntax, demonstrates passing of values and blocks of code to a mixin via arguments, and warns again regarding use of interpolation with mixins.

Chapter 7: Template Inheritance

Chapter 7 of Web Development with Jade covers insertion of "interchangeable blocks into templates" to "prevent you from needing to repeat [a base page layout] in every single file." The chapter describes and illustrates using the block keyword to designate Jade blocks. The chapter includes concise descriptions and short, clear example of how to extend, replace, append and prepend template blocks.

The seventh chapter also describes and provides examples of using Jade's support for includes, which it describes as the "simplest way" to "insert content from another file," but which is "the least dynamic because you cannot change/generate the name of the file you want to include." Static assets, filters, and including external Jade files are demonstrated and discussed as types of includes.

Chapter 8: Organizing Jade Projects

The eighth chapter of Web Development with Jade covers applying "conventions and best practices" when developing with Jade. After pointing out that most HTML conventions and best practices apply to Jade as well, the author discusses "more Jade-specific" practices.

The use of JSON to separate business logic from presentation is covered and the author recommends using JSON Schema. The section of this chapter on inlining explains the advantages of not inlining source code, but inlining compiled code. This section references Yahoo! Developer Network's Best Practices for Speeding Up Your Web Site and the assetgraph optimization framework (the latter of which is also recommended for minification).

Other practices discussed in Chapter 8 include use of mixins to remove redundant style specifications, "dividing templates into separated mixins and blocks," selecting between client-side rendering and server-side rendering, and build systems (Grunt, roots, and make).

Other Observations
  • Web Development with Jade is, at times, an opinionated book. Examples of this include the author calling angle brackets used in HTML/XML "lame and ugly" and stating that "PHP's already awful design" combined with ability to easily mix presentation and business logic "makes for some pretty horrific code." I don't mind this kind of opinionated writing (even if I don't always fully agree with it), but some readers might be put off by it.
  • The code examples in the PDF version of Web Development with Jade feature color coded syntax, making the code easier to read.
  • There are a few basic graphics in Web Development with Jade. Although all of these are pretty basic in terms of aesthetics (they look like simple diagrams drawn in PowerPoint), they do a great job of communicating the message they are intended to communicate.
  • Although I had never seen Jade before reviewing this book, I quickly became comfortable with Jade's syntax and prime uses after the quick read of the relatively short Web Development with Jade. Although Jade is not particularly complex and seems easy to pick up, there does appear to me to be a dearth of introductory Jade resources. LearnJade.com has some good introductory Jade material. The Jade Language Reference provides some nice code examples minimal explanations, but the Jade Tutorial is still lacking quite a bit of content. Web Development with Jade combines tutorial information, basic language reference information, and additional usage explanations in a single easy-to-read and convenient location.
  • The examples are simple and only a rudimentary knowledge of HTML, CSS, and JavaScript is needed to understand the discussion and examples.
Conclusion

Web Development with Jade is an excellent introduction to Jade. Web Development with Jade concisely and clearly outlines the basics of Jade and provides some thoughts on how Jade might be applied in web development. Jade seems to be a templating language that is easy to learn and Web Development with Jade appears to me to be the most efficient available approach for quickly learning this templating language.

Monday, April 21, 2014

Coverity Scan 2013 Open Source Report

The Heartbleed Bug has received significant attention lately and has reignited discussions regarding open source security issues and open source quality issues. The article Heartbleed: Open source's worst hour goes so far as to open with the sentiment that Heartbleed is "open source software's biggest failure to date." In the midst of this discussion, the Coverity ScanTM 2013 Open Source Report has been released and provides another interesting source of input for the discussion.

Coverity Scan'sTM main page states that it uses static analysis to "find and fix defects in your C/C++ or Java open source project for free." Coverity, which was recently acquired by Synopsys, originally teamed up with the Department of Homeland Security to develop the Coverity ScanTM as part of the "Open Source Code Hardening Project." Last year's edition, the Coverity Scan: 2012 Open Source Report, found that "Code quality for open source software continues to mirror that of proprietary software–and both continue to surpass the accepted industry standard for good software quality." The just-released 2013 Coverity ScanTM Open Source Report reports a change this year, "Open source code quality surpasses proprietary code quality in C/C++ projects."

Although the Coverity ScanTM Open Source Report has mainly focused on the "state of open source software quality" in terms of C/C++ projects and Linux in the past, the 2013 report also adds Java-based open source projects Apache Cassandra, Apache CloudStack, Apache Hadoop, and Apache HBase. The report acknowledges that "we are still in the early days of working with Java projects" and looks at some possible explanations for the Java code that was analyzed having higher defect rates than the C/C++ code that was analyzed. These reasons include Java source code being new to the analysis (and thus not benefiting from being able to address previous results) and the use of FindBugs ("Many of the FindBugs checkers generate large quantities of results, in particular in the areas of dodgy code, performance and bad practices").

One of the other "key differences" analyzed in the 2013 Coverity Scan ReportTM is a lower percentage of "resource leaks" being fixed in analyzed Java code than in analyzed C/C++ code. The report's authors postulate that this might be explained by Java developers relying more on "some of the built-in protections in the language, such as the garbage collection." The authors point out potential fallacies of those types of reliance.

The 2013 Coverity Scan ReportTM includes an interesting assessment, "Quality concerns are no longer a barrier to open source adoption in the enterprise. In fact, the quality of the open source code for Coverity Scan participants can be higher than the proprietary code included in an enterprise product." Although not all open source is created equal and although product A is not necessarily superior to product B simply because the former is open source and the latter is proprietary, it is interesting to see more empirically driven studies demonstrating advantages of open source rather than relying on opinion, wishful thinking, and anecdotal evidence.

Thursday, April 17, 2014

Handy New Map Default Methods in JDK 8

The Map interface provides some handy new methods in JDK 8. Because the Map methods I cover in this post are implemented as default methods, all existing implementations of the Map interface enjoy the default behaviors defined in the default methods without any new code. The JDK 8 introduced Map methods covered in this post are getOrDefault(Object, V), putIfAbsent(K, V), remove(Object, Object), remove(Object, Object), replace(K, V), and replace(K, V, V).

Example Map for Demonstrations

I will be using the Map declared and initialized as shown in the following code throughout the examples in this blog post. The statesAndCapitals field is a class-level static field. I intentionally have only included a small subset of the fifty states in the United States for reading clarity and to allow easier demonstration of some of the new JDK 8 Map default methods.

   private final static Map statesAndCapitals;

   static
   {
      statesAndCapitals = new HashMap<>();
      statesAndCapitals.put("Alaska", "Anchorage");
      statesAndCapitals.put("California", "Sacramento");
      statesAndCapitals.put("Colorado", "Denver");
      statesAndCapitals.put("Florida", "Tallahassee");
      statesAndCapitals.put("Nevada", "Las Vegas");
      statesAndCapitals.put("New Mexico", "Sante Fe");
      statesAndCapitals.put("Utah", "Salt Lake City");
      statesAndCapitals.put("Wyoming", "Cheyenne");
   }
Map.getOrDefault(Object, V)

Map's new method getOrDefault(Object, V) allows the caller to specify in a single statement to get the value of the map that corresponds to the provided key or else return a provided "default value" if no match is found for the provided key.

The next code listing compares how checking for a value matching a provided key in a map or else using a default if no match is found was implemented before JDK 8 and how it can now be implemented with JDK 8.

/*
 * Demonstrate Map.getOrDefault and compare to pre-JDK 8 approach. The JDK 8
 * addition of Map.getOrDefault requires fewer lines of code than the
 * traditional approach and allows the returned value to be assigned to a
 * "final" variable.
 */

// pre-JDK 8 approach
String capitalGeorgia = statesAndCapitals.get("Georgia");
if (capitalGeorgia == null)
{
   capitalGeorgia = "Unknown";
}

// JDK 8 approach
final String capitalWisconsin = statesAndCapitals.getOrDefault("Wisconsin", "Unknown");

The Apache Commons class DefaultedMap provides functionality similar to the new Map.getOrDefault(Object, V) method. The Groovy GDK includes a similar method for Groovy, Map.get(Object, Object), but that one's behavior is a bit different because it not only returns the provided default if the "key" is not found, but also adds the key with the default value to the underlying map.

Map.putIfAbsent(K, V)

Map's new method putIfAbsent(K, V) has Javadoc advertising its default implementation equivalent:

The default implementation is equivalent to, for this map:
 
 V v = map.get(key);
 if (v == null)
     v = map.put(key, value);

 return v;

This is illustrated with another code sample that compares the pre-JDK 8 approach to the JDK 8 approach.

/*
 * Demonstrate Map.putIfAbsent and compare to pre-JDK 8 approach. The JDK 8
 * addition of Map.putIfAbsent requires fewer lines of code than the
 * traditional approach and allows the returned value to be assigned to a
 * "final" variable.
 */

// pre-JDK 8 approach
String capitalMississippi = statesAndCapitals.get("Mississippi");
if (capitalMississippi == null)
{
   capitalMississippi = statesAndCapitals.put("Mississippi", "Jackson");
}

// JDK 8 approach
final String capitalNewYork = statesAndCapitals.putIfAbsent("New York", "Albany");

Alternate solutions in the Java space before the addition of this putIfAbsent method are discussed in the StackOverflow thread Java map.get(key) - automatically do put(key) and return if key doesn't exist?. It's worth noting that before JDK 8, the ConcurrentMap interface (extends Map) already provided a putIfAbsent(K, V) method.

Map.remove(Object, Object)

Map's new remove(Object, Object) method goes beyond the long-available Map.remove(Object) method to remove a map entry only if both the provided key and provided value match an entry in the map (the previously available version only looked for a "key" match to remove).

The Javadoc comment for this method explains the how the default method's implementation works in terms of equivalent pre-JDK 8 Java code:

The default implementation is equivalent to, for this map:
if (map.containsKey(key) && Objects.equals(map.get(key), value)) {
     map.remove(key);
     return true;
 } else
     return false;

A concrete comparison of the new approach to the pre-JDK 8 approach is shown in the next code listing.

/*
 * Demonstrate Map.remove(Object, Object) and compare to pre-JDK 8 approach.
 * The JDK 8 addition of Map.remove(Object, Object) requires fewer lines of
 * code than the traditional approach and allows the returned value to be
 * assigned to a "final" variable.
 */

// pre-JDK 8 approach
boolean removed = false;
if (   statesAndCapitals.containsKey("New Mexico")
    && Objects.equals(statesAndCapitals.get("New Mexico"), "Sante Fe"))
{
   statesAndCapitals.remove("New Mexico", "Sante Fe");
   removed = true;
}

// JDK 8 approach
final boolean removedJdk8 = statesAndCapitals.remove("California", "Sacramento");
Map.replace(K, V)

The first of the two new Map "replace" methods sets the specified value to be mapped to the specified key only if the specified key already exists with some mapped value. The Javadoc comment explains the Java equivalent of this default method implementation:

The default implementation is equivalent to, for this map:
 if (map.containsKey(key)) {
     return map.put(key, value);
 } else
     return null;

The comparison of this new approach to the pre-JDK 8 approach is shown next.

/*
 * Demonstrate Map.replace(K, V) and compare to pre-JDK 8 approach. The JDK 8
 * addition of replace(K, V) requires fewer lines of code than the traditional
 * approach and allows the returned value to be assigned to a "final" 
 * variable.
 */

// pre-JDK 8 approach
String replacedCapitalCity;
if (statesAndCapitals.containsKey("Alaska"))
{
   replacedCapitalCity = statesAndCapitals.put("Alaska", "Juneau");
}

// JDK 8 approach
final String replacedJdk8City = statesAndCapitals.replace("Alaska", "Juneau");
Map.replace(K, V, V)

The second newly added Map "replace" method is more narrow in its interpretation of which existing values are replaced. While the method just covered replaces any value in a value available for the specified key in the mapping, this "replace" method that accepts an additional (third) argument will only replace the value of a mapped entry that has both a matching key and a matching value. The Javadoc comment shows the default method's implementation:

The default implementation is equivalent to, for this map:
 
 if (map.containsKey(key) && Objects.equals(map.get(key), value)) {
     map.put(key, newValue);
     return true;
 } else
     return false;

My comparison of this approach to the pre-JDK 8 approach is shown in the next code listing.

/*
 * Demonstrate Map.replace(K, V, V) and compare to pre-JDK 8 approach. The
 * JDK 8 addition of replace(K, V, V) requires fewer lines of code than the
 * traditional approach and allows the returned value to be assigned to a
 * "final" variable.
 */

// pre-JDK 8 approach
boolean replaced = false;
if (   statesAndCapitals.containsKey("Nevada")
    && Objects.equals(statesAndCapitals.get("Nevada"), "Las Vegas"))
{
   statesAndCapitals.put("Nevada", "Carson City");
   replaced = true;
}

// JDK 8 approach
final boolean replacedJdk8 = statesAndCapitals.replace("Nevada", "Las Vegas", "Carson City");
Observations and Conclusion

There are several observations to make from this post.

  • The Javadoc methods for these new JDK 8 Map methods are very useful, especially in terms of describing how the new methods behave in terms of pre-JDK 8 code. I discussed these methods' Javadoc in a more general discussion on JDK 8 Javadoc-based API documentation.
  • As the equivalent Java code in these methods' Javadoc comments indicates, these new methods do not generally check for null before accessing map keys and values. Therefore, one can expect the same issues with nulls using these methods as one would find when using "equivalent" code as shown in the Javadoc comments. In fact, the Javadoc comments generally warn about the potential for NullPointerException and issues related to some Map implementations allowing null and some not for keys and values.
  • The new Map methods discussed in this post are "default methods," meaning that implementations of Map "inherit" these implementations automatically.
  • The new Map methods discussed in this post allow for cleaner and more concise code. In most of my examples, they allowed the client code to be converted from multiple state-impacting statements to a single statement that can set a local variable once and for all.

The new Map methods covered in this post are not ground-breaking or earth-shattering, but they are conveniences that many Java developers previously implemented more verbose code for, wrote their own similar methods for, or used a third-party library for. JDK 8 brings these standardized methods to the Java masses without need for custom implementation or third-party frameworks. Because default methods are the implementation mechanism, even Map implementations that have been around for quite a while suddenly and automatically have access to these new methods without any code changes to the implementations.

Tuesday, April 15, 2014

Programmatic Access to Sizes of Java Primitive Types

One of the first things many developers new to Java learn about is Java's basic primitive data types, their fixed (platform independent) sizes (measured in bits or bytes in terms of two's complement), and their ranges (all numeric types in Java are signed). There are many good online resources that list these characteristics and some of these resources are the Java Tutorial lesson on Primitive Data Types, The Eight Data Types of Java, Java's Primitive Data Types, and Java Basic Data Types.

Java allows one to programmatically access these characteristics of the basic Java primitive data types. Most of the primitive data types' maximum values and minimum values have been available for some time in Java via the corresponding reference types' MAX_VALUE and MIN_VALUE fields. J2SE 5 introduced a SIZE field for most of the types that provides each type's size in bits (two's complement). JDK 8 has now provided most of these classes with a new field called BYTES that presents the type's size in bytes (two's complement).

DataTypeSizes.java
package dustin.examples.jdk8;

import static java.lang.System.out;
import java.lang.reflect.Field;

/**
 * Demonstrate JDK 8's easy programmatic access to size of basic Java datatypes.
 * 
 * @author Dustin
 */
public class DataTypeSizes
{
   /**
    * Print values of certain fields (assumed to be constant) for provided class.
    * The fields that are printed are SIZE, BYTES, MIN_VALUE, and MAX_VALUE.
    * 
    * @param clazz Class which may have static fields SIZE, BYTES, MIN_VALUE,
    *    and/or MAX_VALUE whose values will be written to standard output.
    */
   private static void printDataTypeDetails(final Class clazz)
   {
      out.println("\nDatatype (Class): " + clazz.getCanonicalName() + ":");
      final Field[] fields = clazz.getDeclaredFields();
      for (final Field field : fields)
      {
         final String fieldName = field.getName();
         try  
         {
            switch (fieldName)
            {
               case "SIZE" :  // generally introduced with 1.5 (twos complement)
                  out.println("\tSize (in bits):  " + field.get(null));
                  break;
               case "BYTES" : // generally introduced with 1.8 (twos complement)
                  out.println("\tSize (in bytes): " + field.get(null));
                  break;
               case "MIN_VALUE" :
                  out.println("\tMinimum Value:   " + field.get(null));
                  break;
               case "MAX_VALUE" :
                  out.println("\tMaximum Value:   " + field.get(null));
                  break;
               default :
                  break;
            }
         }
         catch (IllegalAccessException illegalAccess)
         {
            out.println("ERROR: Unable to reflect on field " + fieldName);
         }
      }
   }

   /**
    * Demonstrate JDK 8's ability to easily programmatically access the size of
    * basic Java data types.
    * 
    * @param arguments Command-line arguments: none expected.
    */
   public static void main(final String[] arguments)
   {
      printDataTypeDetails(Byte.class);
      printDataTypeDetails(Short.class);
      printDataTypeDetails(Integer.class);
      printDataTypeDetails(Long.class);
      printDataTypeDetails(Float.class);
      printDataTypeDetails(Double.class);
      printDataTypeDetails(Character.class);
      printDataTypeDetails(Boolean.class);
   }
}

When executed, the code above writes the following results to standard output.

The Output

Datatype (Class): java.lang.Byte:
 Minimum Value:   -128
 Maximum Value:   127
 Size (in bits):  8
 Size (in bytes): 1

Datatype (Class): java.lang.Short:
 Minimum Value:   -32768
 Maximum Value:   32767
 Size (in bits):  16
 Size (in bytes): 2

Datatype (Class): java.lang.Integer:
 Minimum Value:   -2147483648
 Maximum Value:   2147483647
 Size (in bits):  32
 Size (in bytes): 4

Datatype (Class): java.lang.Long:
 Minimum Value:   -9223372036854775808
 Maximum Value:   9223372036854775807
 Size (in bits):  64
 Size (in bytes): 8

Datatype (Class): java.lang.Float:
 Maximum Value:   3.4028235E38
 Minimum Value:   1.4E-45
 Size (in bits):  32
 Size (in bytes): 4

Datatype (Class): java.lang.Double:
 Maximum Value:   1.7976931348623157E308
 Minimum Value:   4.9E-324
 Size (in bits):  64
 Size (in bytes): 8

Datatype (Class): java.lang.Character:
 Minimum Value:   

UPDATE: Note that, as Attila-Mihaly Balazs has pointed out in the comment below, the MIN_VALUE values showed for java.lang.Float and java.lang.Double above are not negative numbers even though these constant values are negative for Byte, Short, Int, and Long. For the floating-point types of Float and Double, the MIN_VALUE constant represents the minimum absolute value that can stored in those types.

Although the characteristics of the Java primitive data types are readily available online, it's nice to be able to programmatically access those details easily when so desired. I like to think about the types' sizes in terms of bytes and JDK 8 now provides the ability to see those sizes directly measured in bytes.

Monday, April 14, 2014

New BigInteger Methods in Java 8

Attention to new features in JDK 8 has rightfully been largely focused on new language features and syntax. However, there are some nice additions to the libraries and APIs and in this post I cover four new methods added to the BigInteger class: longValueExact(), intValueExact(), shortValueExact(), and byteValueExact().

All four of the newly introduced "xxxxxExact()" methods throw an ArithmeticException if the number contained in the BigInteger instance cannot be provided in the specified form (specified in the method's name) without loss of information. BigInteger already had methods intValue() and longValue() as well as inherited (from Number) methods shortValue() and byteValue(). These methods do not throw exceptions if the BigInteger value loses information in the presentation as one of these types. Although at first glance this may seem like an advantage, it means that code that uses the results of these methods uses values that are not accurate without any ability to know that information was lost. The new "xxxxxExact" methods throw an ArithmenticException rather than pretending to provide a result that has lost significant information.

The following simple code listing demonstrates the "legacy" methods that present wrong data in types byte, short, int, and long rather than throwing an exception. The same code also demonstrates use of the new "xxxxxExact" methods that throw an exception when information is lost rather than presenting a bad representation. The output of running this code follows the code and demonstrates how the methods behave differently when the BigInteger contains a value with more information than the returned byte, short, int, or long can represent.

BigIntegerDem.java
package dustin.examples.jdk8;

import static java.lang.System.out;
import java.math.BigInteger;

/**
 * Demonstrate the four new methods of BigInteger introduced with JDK 8.
 * 
 * @author Dustin
 */
public class BigIntegerDemo
{
   /**
    * Demonstrate BigInteger.byteValueExact().
    */
   private static void demonstrateBigIntegerByteValueExact()
   {
      final BigInteger byteMax = new BigInteger(String.valueOf(Byte.MAX_VALUE));
      out.println("Byte Max: " + byteMax.byteValue());
      out.println("Byte Max: " + byteMax.byteValueExact());
      final BigInteger bytePlus = byteMax.add(BigInteger.ONE);
      out.println("Byte Max + 1: " + bytePlus.byteValue());
      out.println("Byte Max + 1: " + bytePlus.byteValueExact());
   }

   /**
    * Demonstrate BigInteger.shortValueExact().
    */
   private static void demonstrateBigIntegerShortValueExact()
   {
      final BigInteger shortMax = new BigInteger(String.valueOf(Short.MAX_VALUE));
      out.println("Short Max: " + shortMax.shortValue());
      out.println("Short Max: " + shortMax.shortValueExact());
      final BigInteger shortPlus = shortMax.add(BigInteger.ONE);
      out.println("Short Max + 1: " + shortPlus.shortValue());
      out.println("Short Max + 1: " + shortPlus.shortValueExact());
   }

   /**
    * Demonstrate BigInteger.intValueExact().
    */
   private static void demonstrateBigIntegerIntValueExact()
   {
      final BigInteger intMax = new BigInteger(String.valueOf(Integer.MAX_VALUE));
      out.println("Int Max: " + intMax.intValue());
      out.println("Int Max: " + intMax.intValueExact());
      final BigInteger intPlus = intMax.add(BigInteger.ONE);
      out.println("Int Max + 1: " + intPlus.intValue());
      out.println("Int Max + 1: " + intPlus.intValueExact());
   }

   /**
    * Demonstrate BigInteger.longValueExact().
    */
   private static void demonstrateBigIntegerLongValueExact()
   {
      final BigInteger longMax = new BigInteger(String.valueOf(Long.MAX_VALUE));
      out.println("Long Max: " + longMax.longValue());
      out.println("Long Max: " + longMax.longValueExact());
      final BigInteger longPlus = longMax.add(BigInteger.ONE);
      out.println("Long Max + 1: " + longPlus.longValue());
      out.println("Long Max + 1: " + longPlus.longValueExact());
   }

   /**
    * Demonstrate BigInteger's four new methods added with JDK 8.
    * 
    * @param arguments Command line arguments.
    */
   public static void main(final String[] arguments)
   {
      System.setErr(out); // exception stack traces to go to standard output
      try
      {
         demonstrateBigIntegerByteValueExact();
      }
      catch (Exception exception)
      {
         exception.printStackTrace();
      }

      try
      {
         demonstrateBigIntegerShortValueExact();
      }
      catch (Exception exception)
      {
         exception.printStackTrace();
      }

      try
      {
         demonstrateBigIntegerIntValueExact();
      }
      catch (Exception exception)
      {
         exception.printStackTrace();
      }

      try
      {
         demonstrateBigIntegerLongValueExact();
      }
      catch (Exception exception)
      {
         exception.printStackTrace();
      }
   }
}
The Output
Byte Max: 127
Byte Max: 127
Byte Max + 1: -128
java.lang.ArithmeticException: BigInteger out of byte range
 at java.math.BigInteger.byteValueExact(BigInteger.java:4428)
 at dustin.examples.jdk8.BigIntegerDemo.demonstrateBigIntegerByteValueExact(BigIntegerDemo.java:23)
 at dustin.examples.jdk8.BigIntegerDemo.main(BigIntegerDemo.java:75)
Short Max: 32767
Short Max: 32767
Short Max + 1: -32768
java.lang.ArithmeticException: BigInteger out of short range
 at java.math.BigInteger.shortValueExact(BigInteger.java:4407)
 at dustin.examples.jdk8.BigIntegerDemo.demonstrateBigIntegerShortValueExact(BigIntegerDemo.java:36)
 at dustin.examples.jdk8.BigIntegerDemo.main(BigIntegerDemo.java:84)
Int Max: 2147483647
Int Max: 2147483647
Int Max + 1: -2147483648
java.lang.ArithmeticException: BigInteger out of int range
 at java.math.BigInteger.intValueExact(BigInteger.java:4386)
 at dustin.examples.jdk8.BigIntegerDemo.demonstrateBigIntegerIntValueExact(BigIntegerDemo.java:49)
 at dustin.examples.jdk8.BigIntegerDemo.main(BigIntegerDemo.java:93)
Long Max: 9223372036854775807
Long Max: 9223372036854775807
Long Max + 1: -9223372036854775808
java.lang.ArithmeticException: BigInteger out of long range
 at java.math.BigInteger.longValueExact(BigInteger.java:4367)
 at dustin.examples.jdk8.BigIntegerDemo.demonstrateBigIntegerLongValueExact(BigIntegerDemo.java:62)
 at dustin.examples.jdk8.BigIntegerDemo.main(BigIntegerDemo.java:102)

As the above output demonstrates, the new BigInteger methods with "xxxxxExact" in their name will not present inaccurate representations when the returned type cannot hold the information in BigInteger instance. Although exceptions are generally not one of our favorite things, they are almost always going to be better than getting and using wrong data and not even realizing it is wrong.

Wednesday, April 9, 2014

Dubious Aspects of Features of JDK 8

Most of us who develop with Java are generally enthusiastic for the features and improvements that come with JDK 8. However, there have been several recent posts that have pointed out some features that can be misused and abused and might lead to some additional issues in the future. These features, which remind me of the introduction of autoboxing in J2SE 5, have their useful situations, but can also lead to issues when not correctly understood and applied. In this post, I use references to other peoples' posts written about these dubious features. Note that this post is not about the "normal" known issues that are associated with any release.

Lambda expressions seem to be the biggest new feature of JDK 8, but Tal Weiss has written a post called The Dark Side Of Lambda Expressions in Java 8. In that post, Weiss writes about a "dark side" to lambda expressions and the Nashorn JavaScript engine (which he argues is the second biggest feature of JDK 8). He talks about the "distance between your code and the runtime" and points out that "we’re paying the price for shorter, more concise code with more complex debugging, and longer synthetic call stacks."

In Love and hate for Java 8, Andrew C. Oliver and Michael Brush provide a nice introduction to some of the main new features of JDK 8. They are argue that default methods on interfaces "allow a form of multiple inheritance" and will "probably [be] the detail that will concern most people in Java 8." He concludes the article with the assessment, "The feature that is going to be dangerous is functional interfaces. If they are not used properly, they could cause a lot of headaches."

Peter Verhas has written a detailed analysis of the potential issues with default methods on interfaces in the posts Java 8 default methods: what can and can not do? and How not to use Java 8 default methods. In one post, he states, "Adding a default method to an interface may render some class unusable." In the other post, he adds, "The default method is a technological mistake" and references the fact that default methods were added to Java interfaces to support backward compatibility of existing implementations with methods that need to be added to interfaces to support new JDK 8 features.

Lukas Eder's The Dark Side of Java 8 post expresses different concerns about default methods: the inability to make a default method final or synchronized and introduction of the "default" keyword. Another interesting "caveat" pointed out in this post is the effect lambda expressions have on overloading.

Another Tal Weiss post, New Parallelism APIs in Java 8: Behind The Glitz and Glamour, looks at some issues Weiss observed when measuring performance of the "new Java 8 parallel operation APIs" under load. Weiss observes, "adding threads in what already is a multi-threaded environment doesn’t help you" and reminds us, "While these are very strong and easy-to-use APIs, they’re not a silver bullet. We still need to apply judgment as to when to employ them."

Lukas Krecan warns Think twice before using Java 8 parallel streams and writes, "The problem is that all parallel streams use common fork-join thread pool and if you submit a long-running task, you effectively block all threads in the pool." To deal with this, Krecan advises either "[ensuring] that all tasks submitted to the common fork-join pool will not get stuck and will finish in a reasonable time" or "not use parallel streams and wait until Oracle allows us to specify the thread pool to be used for parallel streams."

Edwin Dalorzo's post Why There’s Interface Pollution in Java 8 looks at how type erasure, checked exceptions, and lack of value types (JEP 169) led to design decisions in JDK 8 that have "polluted" Java interfaces. The post mixes quotes from Brian Goetz regarding JDK 8 design decisions with the author's own commentary to make the point that "there are good explanations for the dark side to exist."

There are, of course, issues between newly released JDK 8 and tools built on Java. For example, in the post Hello Java 8 (and how it makes GlassFish speechless...), Cay Horstmann documents GlassFish 4 not writing any stack trace whatsoever when he had "[compiled] the WAR with the wrong version of Java."

Although the referenced posts point out legitimate issues of concern related to some of JDK 8's most anticipated features such as lambda expressions, streams, interface default methods, and the Nashorn JavaScript engine, I am still excited about the brave new world of Java development with JDK 8. The posts highlighted in this post are reminders to use these new features carefully and judiciously so that we enjoy the advantages they bring while mitigating as much as possible the new dangers and costs they present when used less wisely.

Tuesday, April 8, 2014

Responses to Contributions of Individual Programming Languages to Software Development

My recent post Contributions of Individual Programming Languages to Software Development has received numerous useful and informative responses that I highlight here. Because select posts to this blog are syndicated to JavaWorld, DZone/JavaLobby, and Java Code Geeks, the responses to my blog posts sometimes appear on those various sites (all of which, by the way, are highly useful sites for Java developers). I am using this post as a centralized location for these educational responses.

When I originally published Contributions of Individual Programming Languages to Software Development, I forgot to include my text on Java, other JVM languages, PHP, and Ada, but those are now covered in the original post and are reflected as well in the DZone and Java Code Geeks syndicated versions.

Clay Shannon highlighted (and Hans Salvisberg emphasized) the influence of Delphi on software development in a comment on the DZone syndicated version of my post. Clay wrote that C# "really drew most of its inspiration from Delphi; Anders Hejlsberg, the C# architect, was poached/seduced away from Borland by the Redmondians. Hejlsberg was the main cat behind Delphi, and forsooth, many Delphiesque thingamajigs reappeared rebranded in his other brainchild, C#."

Luciano Quadraccia wrote on the DZone version of my post about ALGOL and provided a historical anecdote to back up the premise of the significant influence of that language. He concluded, "So, ALGOL was the preferred vehicle for code sharing (at least in the scientific community), and was probably the first general purpose mainstream language with recursion."

In a response to the Java Code Geeks version of my post, Howard Fear mentioned the influences of languages such as Tcl ("really took the concept of DSLs to another level") and Eiffel (one I wish I had mentioned in my original post because I agree with Howard's assessment that it "had a big impact on the development of object oriented programming languages").

There were a few programming languages mentioned that I knew nothing or next to nothing about. These include Forth (mentioned on DZone by Curtis Esac). Howard Fear also mentioned Snobol in a response to the Java Code Geeks version of my post and stated that without Snobol "there would be no shell, awk, perl, or the myriad of other scripting languages."

In a response to my original post, Boffin wrote of the influence of frameworks/computing platforms CUDA and Hadoop.

Monday, April 7, 2014

Constructor/Method Parameters Metadata Available Via Reflection in JDK 8

One of the lesser advertised new features of JDK 8 is the optional ability to include parameter metadata in compiled Java classes [JDK Enhancement Proposal (JEP) 118]. This feature allows Java applications to access this parameter metadata information at runtime via reflection.

The Java Tutorials' Reflection API trail includes a lesson called Obtaining Names of Method Parameters that discusses and demonstrates how to apply this new feature in Java 8. The lesson includes an example Java class MethodParameterSpy that can be run against a provided Java class to indicate characteristics of method and constructor parameters. This lesson also emphasizes that this is an optional feature because storing additional parameter metadata in .class files increases the size of those files. The lesson also points out that there may be some cases where parameter names have sensitive information that the developer does not want available in the compiled .class files.

The additional parameter metadata can be included in .class files compiled in Java 8 by passing the -parameters option to the javac compiler. This -parameters option is also shown when one types javac -help as shown in the next screen snapshot.

The Oracle TechNotes page on javac indicates how this additional method/constructor parameter data can be accessed at runtime: "Stores formal parameter names of constructors and methods in the generated class file so that the method java.lang.reflect.Executable.getParameters from the Reflection API can retrieve them." The following code snippet (class called ParameterDisplayer) demonstrates this (emphasis is on the displayParametersMetadata(String[]) method).

ParameterDisplayer.java
package dustin.examples.jdk8;

import static java.lang.System.out;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Parameter;

/**
 * Uses JDK 8 Parameter class to demonstrate metadata related to the parameters
 * of the methods and constructors of the provided class (includes private,
 * protected, and public methods, but does not include methods inherited from
 * parent classes; those classes should be individually submitted).
 * 
 * @author Dustin
 */
public class ParameterDisplayer
{
   private static void displayParametersMetadata(final String[] classesNames)
   {
      for (final String className : classesNames)
      {
         try
         {
            final Class clazz = Class.forName(className);

            // Get all class's declared methods (does not get inherited methods)
            final Method[] declaredMethods = clazz.getDeclaredMethods();
            for (final Method method : declaredMethods)
            {
               writeHeader(
                    "Method " + method.toGenericString()
                  + " has " + method.getParameterCount() + " Parameters:");
               int parameterCount = 0;
               final Parameter[] parameters = method.getParameters();
               for (final Parameter parameter : parameters)
               {
                  out.println(
                       "\targ" + parameterCount++ + ": "
                     + (parameter.isNamePresent() ? parameter.getName() : "Parameter Name not provided,")
                     + (isParameterFinal(parameter) ? " IS " : " is NOT ")
                     + "final, type " + parameter.getType().getCanonicalName()
                     + ", and parameterized type of " + parameter.getParameterizedType()
                     + " and " + (parameter.isVarArgs() ? "IS " : "is NOT ")
                     + "variable." );
               }
            }
         }
         catch (ClassNotFoundException cnfEx)
         {
            out.println("Unable to find class " + className);
         }
      }
   }

   private static void writeHeader(final String headerText)
   {
      out.println("\n==========================================================");
      out.println("= " + headerText);
      out.println("==========================================================");
   }

   /**
    * Indicate whether provided Parameter is final.
    * 
    * @param parameter Parameter to be tested for 'final' modifier.
    * @return {@code true} if provided Parameter is 'final'.
    */
   private static boolean isParameterFinal(final Parameter parameter)
   {
      return Modifier.isFinal(parameter.getModifiers());
   }

   public static void main(final String[] arguments)
   {
      if (arguments.length < 1)
      {
         out.println("You must provide the fully qualified name of at least one class.");
         System.exit(-1);
      }

      displayParametersMetadata(arguments);
   }
}

I had initially thought about running this class against a well-known class of the JDK, but realized that would not be too helpful because those classes are not likely to have been built with the -parameters option. Therefore, I have created a simple example class to aid with the demonstration. It is called ManyMethods and is shown next.

ManyMethods.java
package dustin.examples.jdk8;

import java.util.List;

/**
 * Class with numerous methods intended to be used in demonstrating JDK 8's new
 * Parameter class.
 * 
 * @author Dustin
 */
public class ManyMethods
{
   public ManyMethods() {}

   private void addArrayOfStrings(String[] strings) {}

   private void addManyStrings(final String ... strings) {}

   private void addListOfStrings(final List<String> strings) {}

   @Override
   public String toString()
   {
      return "ManyMethods";
   }
}

The next two screen snapshots demonstrate running ParameterDisplayer against instances of ManyMethods compiled without and with the -parameters option. The most notable differences are that the parameter names are not provided when compiled without the -parameters option. Also, there is no trusted information on whether the parameter is final when compiled without the -parameters option. The Parameter.getModifiers() method does not include final when compiled without -parameters whether or not the parameter is actually final.

The ParameterDisplayer class uses Parameter.isNamePresent() to programmatically identify that the parameter name is not present (when not compiled with the -parameters option). Had that check not been made, the parameter name returned by Parameter.getName() would have been "arg" plus the number of the parameter (arg0 for the first parameter, arg1 for the second parameter, and so on).

Two of the three methods in ManyMethods class that had a parameter had the final modifier on that parameter. These cases were correctly identified by reflection using Parameter.getModifiers() only when the class was compiled with the -parameters option.

Slightly Related Side Note: Sun/Oracle tools documentation has always consisted of a "windows" page and a "solaris" page, with the latter typically being used to describe how the particular tool works on all flavors on Linux and Unix. I noted that this has changed with the Java 8 documentation. This documentation still has a "windows" version, but the Unix/Linux version now has "unix" in its URL. To illustrate this, here are the URLs for Java SE 7 and Java SE 8 javac tool pages:

Returning to the new (with Java 8) Parameter class, it's worth noting that there is an increase in compiled .class files that store this additional parameter metadata. For my ManyMethods class shown above, the .class file was enlarged from 909 bytes to 961 bytes.

Constructor, like Method, extends Executable, and so the Constructor class enjoys the same getParameters method as Method. Java 8 provides more detail on method and constructor parameters when the code is explicitly compiled with that extra information.

Tuesday, April 1, 2014

Compiling and Running Java Without an IDE

A recent Java subreddit thread called "Compiling Java Packages without IDE" posed the question, "is [there] a command that compiles a group of java files that are inside a package into a separate folder (let's just call it bin), and how would I go about running the new class files?" The post's author, kylolink, explains that "When I started out using Java I relied on Eclipse to do all the compiling for me and just worried about writing code." I have seen this issue many times and, in fact, it's what prompted my (now 4 years old) blog post GPS Systems and IDEs: Helpful or Harmful? I love the powerful modern Java IDEs and they make my life easier on a daily basis, but there are advantages to knowing how to build and run simple Java examples without them. This post focuses on how to do just that.

In my blog post Learning Java via Simple Tests, I wrote about how I sometimes like to use a simple text editor and command-line tools to write, build, and run simple applications. I have a pretty good idea now how my much "overhead" my favorite Java IDEs require and make an early decision whether the benefits achieved from using the IDE are sufficient to warrant the "overhead." In most real applications, there's no question the IDE "overhead" is well worth it. However, for the simplest of example applications, this is not always the case. The rest of this post shows how to build and run Java code without an IDE for these situations.

The Java Code to be Built and Executed

To make this post's discussion more concrete, I will use some very simple Java classes that are related to each other via composition or inheritance and are in the same named package (not in the unnamed package) called dustin.examples. Two of the classes do not have main functions and the third class, Main.java does have a main function to allow demonstration of running the class without an IDE. The code listings for the three classes are shown next.

Parent.java
package dustin.examples;

public class Parent
{
   @Override
   public String toString()
   {
      return "I'm the Parent.";
   }
}
Child.java
package dustin.examples;

public class Child extends Parent
{
   @Override
   public String toString()
   {
      return "I'm the Child.";
   }
}
Main.java
package dustin.examples;

import static java.lang.System.out;

public class Main
{
   private final Parent parent = new Parent();
   private final Child child = new Child();

   public static void main(final String[] arguments)
   {
      final Main instance = new Main();
      out.println(instance.parent);
      out.println(instance.child);
   }
}

The next screen snapshot shows the directory structure with these class .java source files in place. The screen snapshot shows that the source files are in a directory hierarchy representing the package name (dustin/examples because of package dustin.examples) and that this package-reflecting directory hierarchy is under a subdirectory called src. I have also created classes subdirectory (which is currently empty) to place the compiled .class files because javac will not create that directory when it doesn't exist.

Building with javac and Running with java

No matter which approach one uses to build Java code (Ant, Maven, Gradle, or IDE) normally, I believe it is prudent to at least understand how to build Java code with javac. The Oracle/Sun-provided javac command-line tool's standard options can be seen by running javac -help and additional extension options can be viewed by running javac -help -X. More details on how to apply these options can be found in the tools documentation for javac for Windows or Unix/Linux.

As the javac documentation states, the -sourcepath option can be use to express the directory in which the source files exist. In my directory structure shown in the screen snapshot above, this would mean that, assuming I'm running the javac command from the C:\java\examples\javacAndJava\ directory, I'd need to have something like this in my command: javac -sourcepath src src\dustin\examples\*.java. The next screen snapshot shows the results of this.

Because we did not specify a destination directory for the .class files, they were placed by default in the same directory as the source .java files from which they were compiled. We can use the -d option to rectify this situation. Our command could be run now, for example, as javac -sourcepath src -d classes src\dustin\examples\*.java. As stated earlier, the specified destination directory (classes) must already exist. When it does, the command will place the .class files in the designated directory as shown in the next screen snapshot.

With the Java source files compiled into the appropriate .class files in the specified directory, we can now run the application using the Java application launcher command line tool java. This is simply done by following the instructions shown by java -help or by the java tools page and specifying the location of the .class files with the -classpath (or -cp) option. Using both approaches to specify that the classes directory is where to look for the .class files is demonstrated in the next screen snapshot. The last argument is the fully qualified (entire Java package) name of the class who has a main function to be executed. The commands demonstrated in the next screen snapshot is java -cp classes dustin.examples.Main and java -classpath classes dustin.examples.Main.

Building and Running with Ant

For the simplest Java applications, it is pretty straightforward to use javac and java to build and execute the application respectively as just demonstrated. As the applications get a bit more involved (such as code existing in more than one package/directory or more complex classpath dependencies on third-party libraries and frameworks), this approach can become unwieldy. Apache Ant is the oldest of the "big three" of Java build tools and has been used in thousands of applications and deployments. As I discussed in a previous blog post, a very basic Ant build file is easy to create, especially if one starts with a template like I outlined in that post.

The next code listing is for an Ant build.xml file that can be use to compile the .java files into .class files and then run the dustin.examples.Main class just like was done above with javac and java.

build.xml
<?xml version="1.0" encoding="UTF-8"?>
<project name="BuildingSansIDE" default="run" basedir=".">
   <description>Building Simple Java Applications Without An IDE</description>

   <target name="compile"
           description="Compile the Java code.">
      <javac srcdir="src"
             destdir="classes"
             debug="true"
      includeantruntime="false" />
   </target>

   <target name="run" depends="compile"
           description="Run the Java application.">
      <java classname="dustin.examples.Main" fork="true">
         <classpath>
           <pathelement path="classes"/>
         </classpath>
      </java>
   </target>
</project>

I have not used Ant properties and not included common targets I typically include (such as "clean" and "javadoc") to keep this example as simple as possible and to keep it close to the previous example using javac and java. Note also that I've included "debug" set to "true" for the javac Ant task because it's not true in Ant's default but is true with javac's default. Not surprisingly, Ant's javac task and java task closely resemble the command tools javac and java.

Because I used the default name Ant expects for a build file when it's not explicitly specified (build.xml) and because I provided the "run" target as the "default" for that build file and because I included "compile" as a dependency to run the "run" target and because Ant was on my environment's path, all I need to do on the command line to get Ant to compile and run the example is type "ant" in the directory with the build.xml file. This is demonstrated in the next screen snapshot.

Although I demonstrated compiling AND running the simple Java application with Ant, I typically only compile with Ant and run with java (or a script that invokes java if the classpath is heinous).

Building and Running with Maven

Although Ant was the first mainstream Java build tool, Apache Maven eventually gained its own prominence thanks in large part to its adoption of configuration by convention and support for common repositories of libraries. Maven is easiest to use when the code and generated objects conform to its standard directory layout. Unfortunately, my example doesn't follow this directory structure, but Maven does allow us to override the expected default directory structure. The next code listing is for a Maven POM file that overrides the source and target directories and provides other minimally required elements for a Maven build using Maven 3.2.1.

pom.xml
<project>
   <modelVersion>4.0.0</modelVersion>
   <groupId>dustin.examples</groupId>
   <artifactId>CompilingAndRunningWithoutIDE</artifactId>
   <version>1</version>
  
   <build>
      <defaultGoal>compile</defaultGoal>
      <sourceDirectory>src</sourceDirectory>
      <outputDirectory>classes</outputDirectory>
      <finalName>${project.artifactId}-${project.version}</finalName>
   </build>
</project>

Because the above pom.xml file specifies a "defaultGoal" of "compile" and because pom.xml is the default custom POM file that the Maven executable (mvn) looks for and because the Maven installation's bin directory is on my path, I only needed to run "mvn" to compile the .class files as indicated in the next screen snapshot.

I can also run the compiled application with Maven using the command mvn exec:java -Dexec.mainClass=dustin.examples.Main, which is demonstrated in the next screen snapshot.

As is the case with Ant, I would typically not use Maven to run my simple Java application, but would instead use java on the compiled code (or use a script that invokes java directly for long classpaths).

Building and Running with Gradle

Gradle is the youngest, trendiest, and hippest of the three major Java build tools. I am sometimes skeptical of the substance of something that is trendy, but I have found many things to like about Gradle (written in Groovy instead of XML, built-in Ant support, built-in Ivy support, configuration by convention that is easily overridden, Maven repository support, etc.). The next example shows a Gradle build file that can be used to compile and run the simple application that is the primary example code for this post. It is adapted from the example I presented in the blog post Simple Gradle Java Plugin Customization.

build.gradle
apply plugin: 'java'
apply plugin: 'application'

// Redefine where Gradle should expect Java source files (*.java)
sourceSets {
    main {
        java {
            srcDirs 'src'
        }
    }
}

// Redefine where .class files are written
sourceSets.main.output.classesDir = file("classes")

// Specify main class to be executed
mainClassName = "dustin.examples.Main"

defaultTasks 'compileJava', 'run'

The first two lines of the build.gradle file specify application of the Java plugin and the Application plugin, bringing a bunch of functionality automatically to this build. The definition of "sourceSets" and "sourceSets.main.output.classesDir" allows overriding of Gradle's Java plugin's default directories for Java source code and compiled binary classes respectively. The "mainClassName" allows explicit specification of which class should be run as part of the Application plugin. The "defaultTasks" line specifies the tasks to be run by simply typing "gradle" at the command line: 'compileJava' is a standard task provided by the Java plugin and 'run' is a standard task provided by the Application plugin. Because I named the build file build.gradle and because I specified the default tasks of 'compileJava' and 'run' and because I have the Gradle installation bin directory on my path, all I needed to do to build and run the examples was to type "gradle" and this is demonstrated in the next screen snapshot.

Even the biggest skeptic has to admit that Gradle build is pretty slick for this simple example. It combines brevity from relying on certain conventions and assumptions with a very easy mechanism for overriding select defaults as needed. The fact that it's in Groovy rather than XML is also very appealing!

As is the case with Ant and Maven, I tend to only build with these tools and typically run the compiled .class files directly with java or a script that invokes java. By the way, I typically also archive these .class into a JAR for running, but that's outside the scope of this post.

Conclusion

An IDE is often not necessary for building simple applications and examples and can even be more overhead than it's worth for the simplest examples. In such a case, it's fairly easy to apply javac and java directly to build and run the examples. As the examples become more involved, a build tool such as Ant, Maven, or Gradle becomes more appealing. The fact that many IDEs support these build tools means that a developer could transition to the IDE using the build tool created earlier in the process if it was determined that IDE support was needed as the simple application grew into a full-fledged project.