Wednesday, December 31, 2014

Significant Software Development Developments of 2014

One of my favorite posts to write each year is the year-ending summary of some of the developments in the world of software development that I have read about or observed during that year. As with any opinionated posts, these are significant developments from my perspective and may be more or less significant to others than they are to me. I'll undoubtedly completely miss some significant events in the world of software development during 2014 as well.

10. Docker (and Containers in General)

Docker, described as "an open platform for developers and sysadmins to build, ship, and run distributed applications," seems to be gaining significant attention in 2014 after being open sourced in 2013 and version 1.0 being released in 2014. Docker has several major partners now including IBM, VMware, OpenStack, and RedHat. Although Docker has been typically seen as a container for flavors of Linux, Microsoft announced in late 2014 that "developers and organizations that want to create container applications using Docker will be able to use either Windows Server or Linux with the same growing Docker ecosystem of users, applications and tools." Docker has been called the first true DevOps tool and Docker might be seen as the representative of the general class of containers that are becoming very popular.

9. DevOps

I had considered lumping Docker and other containers into this DevOps category, but decided that containers (and Docker in particular) were big enough news in 2014 to leave as a separate item. However, their success in 2014 definitely contributes to the growth of DevOps in 2014. I still find that DevOps means different things to different people, but there is no arguing that the term is frequently discussed in 2014. The sheer number of conferences associated with it attest to its popularity. These conferences include Mountain West DevOps 2014, DevOps track at Agile2014, DevOps Summit 2014, and DevOps Days.

The rise of tools that many consider "DevOps tools" has also been significant in 2014. Tools such as Docker, Chef, and Puppet are widely popular this year.

8. C++14

It was announced in late summer of 2014 that C++14 has been approved. Someone who only read the most popular software development blogs might wonder why a new C++ standard matters, but anyone with a broader view of the software development industry understands that C++ is one of the most widely used programming languages on the planet. A brief summary of the new features of C++14 is available in the post "C++14 is done -- here's what's new."

O'Reilly's publication of Scott Meyer's Effective Modern C++: 42 Specific Ways to Improve Your Use of C++11 and C++14 in November provides more evidence of a big year for C++. If this 300+ page book is any significant fraction as insightful as the classics Effective C++ and More Effective C++, it will be an important book for modern C++ developers.

7. Java 8

Java 8 brought arguably the most significant changes to Java since J2SE 5. Java 8 brought some of the most desirable features of trendier programming languages into one of the most commonly used programming languages.

Java 8 is not the only big news in Java and the JVM. Martijn Verburg has written The Java Ecosystem – My top 5 highlights of 2014.

6. Apple's Swift Programming Language

Until 2014, most of us thought of Objective-C when we thought about native language development for Apple devices. Apple introduced Swift in 2014, which it has described as modern, safe, expressive, and high performing. Perhaps as important as any of these characteristics is that Swift can run alongside Objective-C on Cocoa and Cocoa Touch.

5. AngularJS

AngularJS made my "Honorable Mention" list in last year's version of this post and its popularity increased even more in 2014. It seems to be mentioned as often as jQuery in discussions on web development. It is jQuery that made (and still makes) JavaScript development bearable for many of us and it will be interesting to see if AngularJS has the same type of long-range effect on web development (moving more development to HTML built-in and extension tags and away from JavaScript). There seems to be a lot of potential for this already popular framework with the coming of AngularJS 2.0, Web Components, and ECMAScript 6 (ES6). Google is introducing AtScript with AngularJS 2.0 as a "new superset JavaScript runtime type system."

4. Cloud Computing

Barb Darrow opens Yup, 2014 was a big year in cloud with this statement: "2014 was the year in which both Microsoft and Google got serious about their public cloud options and taking on Amazon Web Services directly with their own Infrastructure as a Service and associated services." Office 365, other Microsoft offerings, and Google offerings are bringing the cloud to an ever increasing number of individuals, organizations, and businesses.

In 2014: The year the cloud killed the datacenter, Jason Perlow writes:

In the last year, competing public and private Cloud providers have tremendously upped the ante in terms of lowering their costs and also improving the feature sets of their services. ... In 2013, for the enterprise, the low hanging fruit for Cloud was all about tackling Development and Test workloads which could take advantage of Self-Service provisioning and also de-provisioning. In 2014 for CxOs it was all about investigating, piloting and actively moving production workloads into the Cloud.

3. Technical Dysfunction and Outages

2014 saw continuation of the technical dysfunction that landed high on my list last year. There were high-profile cloud outages, security incidents (get their own #1 item below), software update problems (such as iOS 8 on iPhones and August 2014 Windows update) and other problems with consumer-focused software (such as inability to submit bar exams and the RepricerExpress/ issue).

2. Open Sourcing of .NET Core and Freely Available Visual Studio Community Edition

In the post .NET Core is Open Source, Immo Landwerth writes, ".NET Core will be open source, including the runtime as well as the framework libraries." He also explains that ".NET Core is a modular development stack that is the foundation of all future .NET platforms" and "the new .NET Core stack will be entirely open sourced on GitHub." Earlier in 2014, it was announced that the C# compiler was being open sourced.

Scott Guthrie's blog post Announcing Open Source of .NET Core Framework, .NET Core Distribution for Linux/OSX, and Free Visual Studio Community Edition talks about the .NET Core open sourcing and also mentions Microsoft's intentions to support it on Linux and OS X. Guthrie also introduces Visual Studio Community 2013 edition and states that it "is a full-featured IDE" that is "completely free" for developers in one of several categories (individual developers, developers contributing to open source, academic, non-enterprise development with team of 5 or fewer developers).

Microsoft is not one of the first companies one thinks of when one thinks "open source" and these announcements have even been called "shocker." Patrick Hynds's Microsoft developers are no longer isolated provides a thorough overview of the market forces that led to this announcement from Microsoft and an explanation of why this policy change could mean "another decade of that language (and maybe even that framework) remaining relevant."

1. Software Security

In my post on last year's most significant software development developments, my top two developments were the categories of "technical dynsfunction" and "security." The high profile cases that made these major factors in 2013 were matched by more high profile cases in 2014. The year 2014 was the year of both Heartbleed and Shellshock. I found the pieces The Internet Is Broken, and Shellshock Is Just the Start of Our Woes and How Heartbleed Broke the Internet — And Why It Can Happen Again to be insightful (and scary) looks at how these respective bugs were introduced and not found earlier. It could easily happen to many other software development teams and projects.

Rick Delgado states, "These recent attacks beg the question as to whether the worst is behind us, or still ahead." His opinion is, "Unfortunately, it seems to be the later."

"Software Security" was already my #1 item for this list and everything in this #1 description above this sentence was already written when news of the Sony hack came to light. The rest of this section is on the Sony hack and only further cements "Software Security" as my #1 development in software development in 2014.

The Sony hack has been expensive in terms of money, reputations, and earning potential. It has also embarrassed many people, become an international incident, and impacted free speech in the United States. In addition, its spawned conspiracy theories, allegations against North Korea, and arguments that it was a Sony insider. It also is likely a sign of what's to come.

In one of the articles I cited earlier on cloud's huge 2014, that article's author pointed out that "data security concerns remain the biggest inhibitor to cloud adoption."

Honorable Mention

I've never been able to squeeze all the significant developments in software development in a given calendar year into ten items. This year is no different and this "Honorable Mention" section allows me to list items that I considered for the top ten, but ultimately, for me, did not bump any of the items in the top ten.

SQL Reminds Us of Its Dominance

Nearly eight years ago, Steve Yegge wrote in his post The Next Big Language that rule #1 for making sure a new programming language "stands a chance" is to create it with a "C-like syntax." A similar post on creating the next big database might say the same thing for a SQL-like syntax being rule #1. In my professional career, I've obviously worked with relational databases, but I have also worked with object-oriented and XML databases. In all cases (not just relational), SQL or a SQL-like syntax was introduced to the products I used in an attempt to gain marketshare that the relational databases enjoyed.

We're seeing the same thing with the NoSQL databases today, making the name "NoSQL" even more imprecise. One of the things that appealed to me about Cassandra when I first started using it was it's SQL-like Cassandra Query Language (CQL) (and cqlsh environment). CouchBase has announced N1QL (pronounced "nickel") as its "next generation query language" and the N1QL Language Reference describes it relative to SQL: "N1QL builds on the SQL language and includes many of SQL's features in addition to features associated with document-oriented databases."

Although relational databases in particular and database of all sorts in general have adopted SQL, the Structured Query Language has impacted software development outside of databases as well. XQuery brings SQL-like semantics to XML, JMS selectors are often described SQL-like, JMS expression syntax "is based on a subset of the SQL92 conditional expression syntax" (Java EE 6 Tutorial on JMS Message Selectors), and introductions to Java SE 8 streams and aggregate operations often use SQL as part of their explanations.

Legal Changes Regarding Software Patents

At least in the United States, there is some evidence that software patents may be increasingly difficult to obtain and defend. Timothy B. Lee writes in "The patent office is rejecting a lot more software patents" that a recent Supreme Court decision (PDF) is "causing the patent office to reject a lot more patents on 'business methods,' a category of software patent that is notorious for its high litigation rate."

Reactive Manifesto 2.0

We seem to like to use common phrases in software development. For example, "xxxxxxx considered harmful" has become very popular for a variety of allegedly harmful software development practices since Edsger Dijkstra's 1968 letter Go To Statement Considered Harmful.

In a similar vein, manifestos have become popular in software development. The manifesto has been used outside of software development well before there was such a thing as software development. Karl Marx (who is unrelated to me as far as I know) is well-known for his contributions to the Communist Manifesto.

The Agile Manifesto has popularized the manifesto approach in software development. Other software development related manifestos include Manifesto for Async Software Development, Manifesto for Software Craftsmanship, the funny (but somewhat true) Manifesto for Half-Arsed Agile Software Development and Manifesto for Realistic Software Development, proposed DevOps Manifesto, Rugged Manifesto, Software Design Manifesto, The Gobbledygook Manifesto, Manifesto for Minimalist Software Engineers (Minifesto), Software Architecture Manifesto, SOA Manifesto, GNU Manifesto, and even the Anti Agile Manifesto.

The Reactive Manifesto asserts that "reactive systems" are "more flexible, loosely-coupled and scalable" and therefore are "easier to develop and amenable to change." The Reactive Manifesto also states that reactive systems are responsive, resilient, elastic, and message driven. Version 2 of the Reactive Manifesto was published in September 2014. Differences in version 2 are discussed in Martin Thompson Discusses the Reactive Manifesto 2.0 and Reactive Manifesto 2.0. Other interesting posts on the Reactive Manifesto include Thoughts on The Reactive Manifesto, The reactive manifesto is 'not even wrong', and A Response to the Reactive Manifesto.

Chrome Dropping NPAPI Plugins

It was announced in a September 2013 blog post Saying Goodbye to Our Old Friend NPAPI (Netscape Plugin Application Programming Interface) that the Chrome web browser would "block webpage-instantiated NPAPI plug-ins by default on the Stable channel" starting in January 2014. The November 2014 blog post The Final Countdown for NPAPI announced that the whitelist allowing the most commonly used NPAPI-based plugins (Silverlight, Google Talk, Java, Facebook, Unity, Google Earth) to still work would be removed in January 2015. A "NPAPI deprecation: developer guide" with additional information regarding Chrome's deprecation of NPAPI has been provided.

The post "Soon-to-be-banned Chrome browser plug-ins get reprieve" explains that plugins making use of NPAPI are encouraged to move to Google's own Pepper Plugin API (part of Native Client). There are some implementations available already, such as Flash.

There are very mixed reactions to this news. Some focus on the positive aspects, including the argument that dropping NPAPI moves things towards being safer and "more mobile friendly." Others argue that they don't need Google being Big Brother and making it impossible to use plugins even at the consumer's own risk. Another argument is that the alternatives to NPAPI are not mature enough or sufficient to justify complete abandonment of NPAPI and that Google's Pepper Plugin API is insufficient for using popular plugins that are said to work with it. It does seem to make things more difficult for the web developer who needs characteristics that have made plugins more attractive than HTML5 if that developer needs to write his or her application differently for each browser because they cannot agree on their native client technology.

Internet of Things

The Internet of Things was on my list last year and remains a major concept in the software development community that has spread to the general populace as consumers have purchased connected devices.


HTML5 continues to gain market share thanks to the ubiquity of the web and of mobile devices.

OpenStack Moving to the Enterprise

The reasons why OpenStack is more appealing for use in the enterprise are covered in OpenStack is becoming more cohesive.

systemd (Linux)

The introduction of systemd in Red Hat's Linux distribution has been the source of major controversy. The titles of articles and blog posts on the subject communicate the strength of feeling involved here: Systemd: Harbinger of the Linux apocalypse, Meet systemd, the controversial project taking over a Linux distro near you, Broken by design: systemd, and The Biggest Myths of systemd. Nice summaries of systemd and why it's so controversial are presented in Understanding and Using Systemd and Linus Torvalds and others on Linux's systemd. The stated purpose of uselessd is "to reduce systemd to a base initd, process supervisor and transactional dependency system, while minimizing intrusiveness and isolationism."


Geertjan Wielenga covers NetBeans-related 2014 highlights in the post NetBeans Top 5 Highlights of 2014. One of the highlights is "Release of NetBeans IDE 8.0, 8.0.1, and 8.0.2." NetBeans supports JDK 8.


Eclipse Luna was Eclipse's annual release in 2014, supporting JDK 8.

IntelliJ IDEA

IntelliJ IDEA saw major new versions in 2014 (Release 13.1 and Release 14) and now supports JDK 8.

Material Design

Google's Material Design concept was all over the blogosphere in 2014. It's defined as a "visual language for our users that synthesizes the classic principles of good design with the innovation and possibility of technology and science." Coverage of Material Design includes What Google's Material Design is Really About and Google Developers Blog's This is material design.


2014 was another year with many developments in software development. I have not had as much time as I like this year to put into this post, so I may add to it over the coming days. If I add any new items, I will note the added items in Feedback comments.

Previous Years' Editions

Saturday, December 27, 2014

Three Common Methods Generated in Three Java IDEs

In this post, I look at the differences in three "common" methods [equals(Object), hashCode(), and toString()] as generated by NetBeans 8.0.2, IntelliJ IDEA 14.0.2, and Eclipse Luna 4.4.1. The objective is not to determine which is best, but to show different approaches one can use for implementing these common methods. Along the way, some interesting insights can be picked up regarding creating of these common methods based on what the IDEs assume and prompt the developer to set.

NetBeans 8.0.2

NetBeans 8.0.2 allows the Project Properties to be configured to support the JDK 8 platform and to expect JDK 8 source formatting as shown in the next two screen snapshots.

Code is generated in NetBeans 8.0.2 by clicking on Source | Insert Code (or keystrokes Alt+Insert).

When generating the methods equals(Object), hashCode(), and toString(), NetBeans 8.0.2 asks for the attributes to be used in each of these generated methods as depicted in the next two screen snapshots.

The NetBeans-generated methods take advantage of the JDK 7-introduced Objects class.

NetBeans-Generated hashCode() Method for Class
public int hashCode()
   int hash = 5;
   hash = 29 * hash + Objects.hashCode(this.someString);
   hash = 29 * hash + Objects.hashCode(this.timeUnit);
   hash = 29 * hash + this.integer;
   hash = 29 * hash + Objects.hashCode(this.longValue);
   return hash;
NetBeans-Generated equals(Object) Method for Class
public boolean equals(Object obj)
   if (obj == null)
      return false;
   if (getClass() != obj.getClass())
      return false;
   final NetBeans802GeneratedCommonMethods other = (NetBeans802GeneratedCommonMethods) obj;
   if (!Objects.equals(this.someString, other.someString))
      return false;
   if (this.timeUnit != other.timeUnit)
      return false;
   if (this.integer != other.integer)
      return false;
   if (!Objects.equals(this.longValue, other.longValue))
      return false;
   return true;
NetBeans-Generated toString() Method for Class
public String toString()
   return "NetBeans802GeneratedCommonMethods{" + "someString=" + someString + ", timeUnit=" + timeUnit + ", integer=" + integer + ", longValue=" + longValue + '}';

Some observations can be made regarding the NetBeans-generated common methods:

  • All generated code is automatic and does not support customization with the exception of the fields used in the methods which the operator selects.
  • All of these common methods that extend counterparts in the Object class automatically have the @Override annotation provided.
  • No Javadoc documentation is included for generated methods.
  • The methods make use of the Objects class to make the generated code more concise with less need for null checks.
  • Only one format is supported for the String generated by toString() and that output format is a single comma-delimited line.
  • I did not show it in the above example, but NetBeans 8.0.2's methods generation does treat arrays differently than references, enums, and primitives in some cases:
    • The generated toString() method treats array attributes of the instance like it treats other instance attributes: it relies on the array's toString(), which leads to often undesirable and typically useless results (the array's system identity hash code). It'd generally be preferable to have the string contents of array attributes provided by Arrays.toString(Object[]) or equivalent overloaded version or Arrays.deepToString(Object[]).
    • The generated hashCode() method uses Arrays.deepHashCode(Object[]) for handling arrays' hash codes.
    • The generated equals(Object) method uses Arrays.deepEquals(Object[], Object[]) for handling arrays' equality checks.
    • It is worth highlighting here that NetBeans uses the "deep" versions of the Arrays methods for comparing arrays for equality and computing arrays' hash codes while IntelliJ IDEA and Eclipse use the regular (not deep) versions of Arrays methods for comparing arrays for equality and computing arrays' hash codes.


IntelliJ IDEA 14.0.2

For these examples, I'm using IntelliJ IDEA 14.0.2 Community Edition.

IntelliJ IDEA 14.0.2 provides the ability to configure the Project Structure to expect a "Language Level" of JDK 8.

To generate code in IntelliJ IDEA 14.0.2, one uses the Code | Generate options (or keystrokes Alt+Insert like NetBeans).

IntelliJ IDEA 14.0.2 prompts the operator for which attributes should be included in the generated methods. It also asks which fields are non-null, meaning which fields are assumed to never be null. In the snapshot shown here, they are checked, which would lead to methods not checking those attributes for null before trying to access them. In the code that I generate with IntelliJ IDEA for this post, however, I won't have those checked, meaning that IntelliJ IDEA will check for null before accessing them in the generated methods.

IntelliJ IDEA 14.0.2's toString() generation provides a lengthy list of formats (templates) for the generated toString() method.

IntelliJ IDEA 14.0.2 also allows the operator to select the attributes to be included in the generated toString() method (selected when highlighted background is blue).

IDEA-Generated equals(Object) Method for Class
public boolean equals(Object o)
   if (this == o) return true;
   if (o == null || getClass() != o.getClass()) return false;

   Idea1402GeneratedCommonMethods that = (Idea1402GeneratedCommonMethods) o;

   if (integer != that.integer) return false;
   if (longValue != null ? !longValue.equals(that.longValue) : that.longValue != null) return false;
   if (someString != null ? !someString.equals(that.someString) : that.someString != null) return false;
   if (timeUnit != that.timeUnit) return false;

   return true;
IDEA-Generated hashCode() Method for Class
public int hashCode()
   int result = someString != null ? someString.hashCode() : 0;
   result = 31 * result + (timeUnit != null ? timeUnit.hashCode() : 0);
   result = 31 * result + integer;
   result = 31 * result + (longValue != null ? longValue.hashCode() : 0);
   return result;
IDEA-Generated toString() Method for Class
public String toString()
   return "Idea1402GeneratedCommonMethods{" +
      "someString='" + someString + '\'' +
      ", timeUnit=" + timeUnit +
      ", integer=" + integer +
      ", longValue=" + longValue +

Some observations can be made regarding the IntelliJ IDEA-generated common methods:

  • Most generated code is automatic with minor available customization including the fields used in the methods which the operator selects, specification of which fields are expected to be non-null (so that null checks are not needed in generated code), and the ability to select one of eight built-in toString() formats.
  • All of these common methods that extend counterparts in the Object class automatically have the @Override annotation provided.
  • No Javadoc documentation is included for generated methods.
  • The generated methods do not make use of the Objects class and so require explicit checks for null for all references that could be null.
  • It's not shown in the above example, but IntelliJ IDEA 14.0.2 does treat arrays differently in the generation of these three common methods:


Eclipse Luna 4.4.1

Eclipse Luna 4.4.1 allows the Java Compiler in Project Properties to be set to JDK 8.

In Eclipse Luna, the developer uses the "Source" drop-down to select the specific type of source code generation to be performed.

Eclipse Luna allows the operator to select the attributes to be included in the common methods. It also allows the operator to specify a few characteristics of the generated methods. For example, the operator can choose to have the elements of an array printed individually in the generated toString() method rather than an often meaningless class name and system identity hash code presented.

Eclipse-Generated hashCode() Method for Class
/* (non-Javadoc)
 * @see java.lang.Object#hashCode()
public int hashCode()
   final int prime = 31;
   int result = 1;
   result = prime * result + this.integer;
   result = prime * result
         + ((this.longValue == null) ? 0 : this.longValue.hashCode());
   result = prime * result
         + ((this.someString == null) ? 0 : this.someString.hashCode());
   result = prime * result
         + ((this.timeUnit == null) ? 0 : this.timeUnit.hashCode());    return result;
Eclipse-Generated equals(Object) Method for Class
/* (non-Javadoc)
 * @see java.lang.Object#equals(java.lang.Object)
public boolean equals(Object obj)
   if (this == obj)
      return true;
   if (obj == null)
      return false;
   if (getClass() != obj.getClass())
      return false;
   Eclipse441GeneratedCommonMethods other = (Eclipse441GeneratedCommonMethods) obj;
   if (this.integer != other.integer)
      return false;
   if (this.longValue == null)
      if (other.longValue != null)
         return false;
   } else if (!this.longValue.equals(other.longValue))
     return false;
   if (this.someString == null)
      if (other.someString != null)
         return false;
   } else if (!this.someString.equals(other.someString))
      return false;
   if (this.timeUnit != other.timeUnit)
      return false;
   return true;
Eclipse-Generated toString() Method for Class
/* (non-Javadoc)
 * @see java.lang.Object#toString()
public String toString()
   return "Eclipse441GeneratedCommonMethods [someString=" + this.someString
         + ", timeUnit=" + this.timeUnit + ", integer=" + this.integer
         + ", longValue=" + this.longValue + "]";

Some observations can be made regarding the Eclipse-generated common methods:

  • Eclipse provides the most points in the generation process in which the generated output can be configured. Here are some of the configurable options:
    • Location in class (before or after existing methods of class) can be explicitly specified.
    • All of these common methods that extend counterparts in the Object class automatically have the @Override annotation provided.
    • "Method comments" can be generated, but they are not Javadoc style comments (use /* instead of /** and explicitly state they are not Javadoc comments as part of the generated comment).
    • Option to "list contents of arrays instead of using native toString()" allows developer to have Arrays.toString(Array) be used (same as IntelliJ IDEA's approach and occurs if checked) or have the system identify hash code be used (same as NetBeans's approach and occurs if not checked).
    • Support for four toString() styles plus ability to specify custom style.
    • Ability to limit the number of entries of an array, collection, or map that is printed in toString().
    • Ability to use instance of in generated equals(Object) implementation.
  • All of these common methods that extend counterparts in the Object class automatically have the @Override annotation provided.
  • The generated methods do not make use of the Objects class and so require explicit checks for null for all references that could be null.
  • Eclipse Luna 4.4.1 does treat arrays differently when generating the three common methods highlighted in this post:
    • Generated toString() optionally uses Arrays.toString(Object[]) or overloaded version for accessing contents of array.
    • Generated equals(Object) uses Arrays.equals(Object[], Object[]) or overloaded version for comparing arrays for equality.
    • Generated hashCode() uses Arrays.hashCode(Object[]) or overloaded version for computing hash code of array.

All three IDEs covered in this post (NetBeans, IntelliJ IDEA, and Eclipse) generate sound implementations of the common methods equals(Object), hashCode(), and toString(), but there are differences between the customizability of these generated methods across the three IDEs. The different customizations that are available and the different implementations that are generated can provide lessons for developers new to Java to learn about and consider when implementing these methods. While the most obvious and significant advantage of these IDEs' ability to generate these methods is the time savings associated with this automatic generation, other advantages of IDE generation of these methods include the ability to learn about implementing these methods and the greater likelihood of successful implementations without typos or other errors.

Wednesday, December 24, 2014

Book Review: Puppet Essentials

This blog post is my review of Felix Frank's Puppet Essentials (Packt Publishing, 2014). The subtitle of this book is, "Get up and running quickly using the power of Puppet to manage your IT infrastructure," and it consists of 8 chapters spanning just over 200 substantive pages.


The Preface of a Packt book tends to be a good first place to look when trying to decide whether the books suits the potential reader. As with other Packt books I've reviewed, Puppet Essentials's Preface provides short summaries of its eight chapters and explains what's needed to run the examples ("two or more virtual machine instances" with the "virtualization guests [having] a connection to the Internet and with each other"). The first chapter also tells us that all examples in the book use "the 3.6.2 release from Puppet Labs' repository."

The "Who this book is for" section of Packt Prefaces us perhaps the most important to a potential reader. This one states:

This book assumes that you have no prior Puppet knowledge. You should have a sound technical background. Experience with the GNU/Linux command line is required. Existing programming skills are recommended. This book is also suitable for beginners or intermediate Puppet users who wish to expand their knowledge about the software.
Chapter 1: Writing Your First Manifests

The initial chapter of Puppet Essentials provides some brief historical facts about Puppet and then explains how to download and install Puppet. The chapter then explains that Puppet manifests are "the equivalent of scripts or programs" and are "written in Puppet's domain-specific language (DSL)."

Chapter 1 differentiates parameters and properties in Puppet and then explains and demonstrates use of the -e option (pass in-lined manifest via shell command) and use of the --noop option ("dry run" what command would do without actually causing that effect or change).

This first chapter provides an introduction to Puppet syntax including conditional statements (if/elsif/else, case, and selectors [ternary]), using variables (which are immutable) and variable types (strings, arrays, and hashes). The first chapter also has a nice explanation of how Puppet manifests are declarative rather than imperative (or procedural). The author writes that "manifests should always describe what you expect to be the end result. The specifics of what actions need to be taken to get there are decided by Puppet."

Because Puppet manifest files are declarative, it is important to explicitly specify order of the results prescribed in the manifest file. The first chapter demonstrates use of -> syntax (order chaining arrow) to establish these explicit dependencies. It also explains and demonstrates application of the before and require metaparameters for explicitly specifying dependencies.

I liked that, in the section on avoiding circular dependencies, the author shows the error that will be printed to the console indicating a circular dependency error and discusses how to see the cyclic path using the --graph option. Use of -graph generates .dot files that can be viewed as graphics with OmniGraffle, Graphwiz, or dotty.

Chapter 1's introduction to Puppet also covers communication between resources via events/signals. I like how the use of notify and subscribe are shown to be analogous to use of before and require. This section also introduces the notification chaining arrow (~>).

The first chapter wraps up with a discussion on "examining the most notable resource types" and specifically looks at the file, package, service, user, group, exec (with a warning to beware abusing this), cron, and mount. The chapter's summary provides some useful reminders including that Puppet manifests "resemble scripts," but "they should not be considered as such" because "they consist of resources instead of commands" and these "resources are generally not evaluated in the order in which they have been written."

Chapter 2: The Master and Its Agents

The second chapter of Puppet Essentials moves the focus from simple Puppet manifests used on single hosts to master/agent use. This chapter introduces puppet-master and explains how to specify agent-specific configuration in node designations in the site manifest on the master.

I liked that Chapter 2 mentions use of --configprint to print out configuration settings Puppet is using. The chapter also covers setting up the agents and getting them to communicate properly with certificates. The discussion covers creating a certificate, revoking a certificate, and renewing a certificate. Another part of the chapter discusses using cron to manage agent lifecycle.

Chapter 2 includes a warning about not using Puppet's built-in WEBrick in a production environment. It then describes in detail how to configure Ruby-based Phusion Passenger with Apache server and with Nginx.

The second chapter discusses tuning Puppet by monitoring and configuring the Passenger Pool Size when using Phusion Passenger instead of WEBrick. There is also a section in this chapter on troubleshooting SSL issues.

Chapter 3: A Peek Under the Hood – Facts, Types, and Providers

Puppet Essentials's third chapter begins with an explanation for why Facter is a valuable "secondary system" in Puppet. The author describes Facter as being "a layer of abstraction over the characteristics of both hardware and software." This feature especially intrigued me as Facter supplies "facts" about each agent that are essentially characteristics of each particular host identified by well-known names. Some of the built-in "facts" that are referenced include processorcount, ipaddress, operatingsystem, operatingsystemrelease, osfamily, and macaddress. The chapter then moves onto developing custom facts with Ruby code and discusses approaches for specifying when facts only apply to certain operating systems or hardware. I also appreciate the author addressing external facts that can be written without Ruby as static (YAML or JSON format) files or even scripts.

Chapter 3 also provides more in-depth discussion of types and providers in Puppet.

Chapter 4: Modularizing Manifests with Classes and Defined Types

Chapter 4 of Puppet Essentials introduces Puppet classes and Puppet defined types and then compares and contrasts them and describes the situations in which each is preferred. Nesting classes is also explained and demonstrated as an approach for composite classes.

Sections in Chapter 4 explain how to use defined types as resource wrappers, as resource multiplexers, as macros, and to process array values. This very detailed chapter also discusses limitations of Puppet classes and some work-arounds for those limitations.

Chapter 5: Extending Your Puppet Infrastructure with Modules

Chapter 5 of Puppet Essentials is about Puppet modules, which the PuppetForge website describes as "reusable, sharable units of Puppet code." The chapter describes the types of things that can be part of a module and explains that modules are in root directories with names matching the module's name. Manifests are stored under that module-named root directory in the manifests subdirectory. The author explains that manifests/init.pp "can be thought of as a default manifest location, because it is looked up for any definition from the module in question." The author also uses text explanation and indented text hierarchical representation of the module's directory/file structure to illustrate structuring of a module in the file system. This chapter also explains how to configure various environments for Puppet.

Another section of Chapter 5 covers downloading and installing modules created by others. This section references PuppetForge as one source of modules and introduces the command puppet module install to download and install a Puppet module. The author recommends that "the stdlib module should be considered mandatory" because "it adds a large number of useful functions to the Puppet language."

The "Modules' Best Practices" section of Chapter 5 "provides details on how to organize your manifests" and "advises some design practices and strategies in order to test changes to modules." Along the way, the author references Puppet taking advantage of an infrastructure as code paradigm. This chapter also explains how to create one's own module without publishing it to PuppetForge. An interesting example working with Cacti illustrates various points being made, including that there are times when it's best to write a wrapper script when a series of complex commands needs to be run and call that wrapper script from Puppet.

A relatively lengthy section of the fifth chapter discusses "enhancing the agent through plugins" such as custom facts, parser functions, types, and providers. The portion of custom facts states that "native Ruby facts ... are more portable than external facts." The chapter concludes with a brief overview of how to find modules matching one's needs on PuppetForge.

Chapter 6: Leveraging the Full Toolset of the Language

Puppet Essentials's sixth chapter covers "some techniques that you are not going to need every day" that "can make difficult scenarios much easier." In the section on templating configuration files, the author points out that Puppet uses ERB as its template language and that this is similar to PHP or JSP, but with Ruby code inside the tags. This section on templating introduces basic ERB syntax, describes how to apply templates, and describes how to mitigate performance issues with templates.

The section of Chapter 6 on creating virtual resources with the @ prefix provides concrete discussion on how these virtual resources make it much easier to use common resources across Puppet modules. This section uses text and code listings to explain realizing virtual resources with the realize function and with a collector.

Chapter 6 also introduces exported resources and demonstrates use of @@ prefix to declare these. It also provides an example of collecting exported resources.

The brief "Exporting SSH host keys" section of Chapter 6 introduces Puppet's sshkey service. The chapter also includes two other brief sections on "managing hosts files locally" and "automating custom configuration items." There are much more detailed sections on overriding resource parameters, Puppet class inheritance, and using resource defaults. Chapter 6 concludes with warnings about using the defined function or stdlib's ensure_resource and a discussion about why these should be avoided.

Chapter 7: Separating Data from Code Using Hiera

Chapter 7 of Puppet Essentials talks about the maintenance issues associated with Puppet manifests that mix data and logic and introduces use of Hiera to support an "external database that holds all individual and shared values." The chapter describes Hiera built into Puppet and demonstrates how to configure Hiera via the hiera.yaml file. The chapter briefly compares and contrasts the three back-ends for Hiera (YAML, JSON, and Puppet Manifest Files), mentions that custom Ruby back-ends can be written, and then focuses on YAML files. It provides detailed explanations and examples of using Hiera and briefly discusses considerations when "choosing between manifest and Hiera designs."

A particularly useful section of Chapter 7 is the section "Debugging Hiera lookups" which introduces the command-line tool hiera that can be used to help "determine where the respective [data] values are retrieved from for any given agent node."

Chapter 8: Configuring Your Cloud Application with Puppet

The final chapter of Puppet Essentials talks about using Puppet in the cloud. Before discussing Puppet and the cloud, however, the chapter first looks at some of Puppet's most common deployment environments (Debian and Red Hat Linux and with Vagrant). This eighth chapter also describes Craig Dunn's Roles and Profiles pattern.

The discussion on "Taking Puppet to the cloud" approaches this subject based on the "Infrastructure as a Service (IaaS) paradigm," but later provides an explanation of how to implement a Platform as a Service (PaaS) implementation on top of the IaaS implementation. Sections in this chapter cover "initializing agents in the cloud," "using Puppet's cloud-provisioner module," "building Manifests for the cloud," "composing arbitrary configuration files," and "handling instance deletions."

A major section in this final chapter is on "preparing for autoscaling" so commonly associated with deployments to the cloud. Several items are discussed in this section, including the need to test manifests regularly.

The final chapter's Summary summarizes the chapter and includes a couple of paragraphs that provide an overall book conclusion.

General Observations
  • Puppet Essentials serves as both an introductory text on use of Puppet and as a reference on more intermediate and advanced uses of Puppet.
  • I like that Puppet Essentials talks about things that have changed in Puppet or are likely to change in the future. It's difficult for a technical book to avoid being overcome by events or becoming obsolete, but these references to changes help.
  • Puppet Essentials is written as though expecting an audience familiar with Ruby or Perl for most of their scripting tasks. This assumption is manifest (no pun intended) by many references to those languages when introducing Puppet concepts and syntax.
  • Puppet Essentials references things that are outside the scope of the book such as Puppet 4, Stages, scaling a master with load balancing, using "openssl command-line tool ... for analyzing the certificates and related files", generating HTML documentation with puppet-doc (which apparently has been used to create much of the impressive Puppet online documentation), writing Ruby back-ends for Hiera, publishing modules, and "exploiting PuppetDB."
  • The "Summary" sections of each chapter did a nice job of thoroughly and relatively concisely reviewing the highlights covered earlier in each chapter.
  • The numerous code listings in this book are black font on white background with no color syntax and no line numbers. There are some instances where portions of code most relevant to the discussion are highlighted in bold.
  • Although the text of Puppet Essentials is generally highly readable, there are some typos. For example, there are at least a couple references to "boxen" instead of "boxes."
  • Other reviews of Puppet Essentials might help provide a more complete picture of the book:

I recommend Puppet Essentials for developers or operations personnel (or "DevOps" personnel) who want a good introductory text on Puppet that also provides enough in-depth information and observations to be useful as a reference. As the author states in the book, the online Puppet documentation seems well maintained and highly approachable, but it's nice to have a book to tie it altogether and to provide some in-depth asides.

Monday, December 22, 2014

Book Review: Mastering JavaServer Faces 2.2

Anghel Leonard's Mastering JavaServer Faces 2.2 (Packt Publishing, 2014) has the subtitle, "Master the art of implementing user interfaces with JSF 2.2." The book features twelve chapters and a short appendix spanning approximately 530 substantive pages. This blog post is my review of the PDF version of the book.


The Preface of Mastering JavaServer Faces 2.2 provides 2 to 3 sentences summarizing each of the book's chapters. It also recommends NetBeans 8+, GlassFish 4, and Mojarra JavaServer Faces 2.2.6 for running the book's sample applications. The "Who this book is for" section of the Preface clearly articulates that Mastering JavaServer Faces 2.2 is intended for readers who are already familiar with JavaServer Faces. This section states:

This book is a perfect symbiosis between JSF 2.0 and 2.2. It is dedicated to JSF developers who have previous experience and want to upgrade their knowledge to the new JSF 2.2. By fortifying your knowledge on JSF 2.0 and adding the power of JSF 2.2, you will soon become a JSF expert.

I re-emphasize this point here: Mastering JavaServer Faces 2.2 assumes JavaServer Faces experience. The book dives right into newer (JSF 2.2) JavaServer Features without the traditional background and introductory text one would expect from a book that introduces a language or framework. In other words, this book would be best suited for a developer with JSF experience who wants to learn about JSF 2 and JSF 2.2 new features or who has an older book on earlier versions of JSF and wants to use this book as a companion to that older book.

Chapter 1: Dynamic Access to JSF Application Data through Expression Language (EL 3.0)

The initial chapter of Mastering JavaServer Faces 2.2 begins fast with an introduction to Expression Language (EL). The chapter looks at EL 3.0 (JSR 341) syntax (operators, reserved words, immediate evaluation with ${}, deferred evaluation with #{}, referencing both CDI managed beans and JSF managed beans, referencing managed beans' properties and nested properties and methods, referencing Java enumerated types, accessing collections from JSF, and implicit objects).

I liked the Chapter 1 section on "writing a custom EL resolver" because I was not previously aware that one could write one's own custom implicit variables in JSF expression language. This section introduces EL Resolvers, demonstrates how to writ a custom EL Resolver, and describes how to differentiate between a VariableResolver and a PropertyResolver.

The "EL 3.0 overview" section of the first chapter introduces EL 3.0 (part of Java EE 7), lists some of its features, and describes how to use it with JSF. One of the more interesting portions of this section for me was the coverage of EL lambda expressions and streams.

Chapter 2: Communication in JSF

The second chapter of Mastering JavaServer Faces 2.2 opens with the statement, "Communication is the core of a JSF application, and is one of the main aspects that dictate the architecture of such an application." It adds, "JSF provides many solutions for ensuring a powerful and flexible communication layer between JSF components and also between JSF and XHTML pages, the JavaScript code, and other third-party components." With this introduction, the chapter moves onto covering a lengthy list of miscellaneous approaches to communicating between components of a JSF application.

The topics covered in Chapter 2 include context parameters, <f:param ...> tag and >c:set<, view parameters (UIViewParameter/<f:viewParam>), GET request view actions (<f:viewAction>), <f:attribute> tag (demonstrated with an example that modifies supported behavior of a PrimeFaces component), action listeners (<f:setPropertyActionListener>), JSF Flash scope, cookies, hidden fields (<h:inputHidden>), accepting passwords (<h:inputSecret>), accessing JSF user interface components from JSF Java code, EL method expressions, JSF data binding, injecting one managed bean into another managed bean (@ManagedProperty), and communication between managed beans.

Chapter 3: JSF Scopes – Lifespan and Use in Managed Beans Communication

Chapter 3 of Mastering JavaServer Faces 2.2 is all about scopes in JavaServer Faces. The chapter contrasts JSF managed beans and CDI beans and recommends "[using] CDI beans whenever possible," but does discuss situations in which JSF managed beans are preferable. This section includes a useful figure that makes it easy to see the JSF core scope annotations (javax.faces.bean) alongside the CDI scope annotations (javax.enterprise.context). The section describes each level of scope in a JSF application (request, session, view, application, conversation, flow, dependent pseudo-scope, none, custom) and whether JSF managed beans and/or CDI beans support each scope. This coverage of scopes includes code listings for each type of bean to which that scope applies. The sections on flow scope and custom scopoe are longer than the others and particularly useful in understanding these relatively more complicated scopes.

The third chapter concludes with brief sections on easy and lazy managed bean instantiation, allowable scopes for injected and injecting managed beans, and when to use @ManagedProperty versus @Inject. There are several useful figures in this chapter that use shapes and colors to illustrate points being made.

Chapter 4: JSF Configurations Using XML Files and Annotations – Part 1

Mastering JavaServer Faces 2.2's fourth chapter looks at how JSF 2.2 allows annotations to be used to configure many characteristics of a JSF application that formerly had to be configured in a faces-config.xml file. A table that is present early in this chapter maps old ("Before JSF 2.2") namespaces to new ("JSF 2.2") namespaces. The chapter also looks at specifying certain JSF characteristics both with XML and programmatically. The chapter has sections explaining how to use and order multiple configuration files and how to support internationalization by configuring locales and resource bundles.

Chapter 4 has a lengthy section on "configuring validators and converters." I like the author's discussion in this section regarding the state of injecting dependencies into validators and whether it's supported in JSF 2.2 or 2.3. Configuring JSF application navigation in another large topic in the fourth chapter that covers implicit navigation, conditional navigation, preemptive navigation (AKA predetermined navigation), and programmatic navigation.

Chapter 4's focus on configuration moves onto configuring action listeners, system event listeners, phase listeners, @ListenerFor and @ListenersFor.

Chapter 5: JSF Configurations Using XML Files and Annotations – Part 2

The fifth chapter of Mastering JavaServer Faces 2.2 continues the general theme of JSF configuration that the preceding chapter also addressed. The chapter begins with a relatively in-depth look at various approaches for configuring resource handlers (default configuration via placement in JSF 2.0 conventional locations, custom resource handler, and javax.faces.WEBAPP_RESOURCES_DIRECTORY JSF 2.0 context parameter in web.xml file). The section in Chapter 5 on configuring view handlers discusses and demonstrates writing custom view handlers to "convert absolute URLs into relative URLs" and to handle encountered ViewExpiredExceptions.

Chapter 5's section on overriding JSF renderers uses code listings and explanations to demonstrate overriding the HTML output by JSF components when rendered. I particularly liked the "little bit tricky" example of extending ResponseWriterWrapper to change the behavior of writeText to write escaped strings and making some other changes to support that PrimeFaces-like functionality in standard JSF. Another section in the chapter looks at extending ClientBehaviorBase and the other steps necessary to "define specific client-side behavior to a component in a reusable approach."

A considerable portion of Chapter 5 is devoted to JSF factories. Examples include configuring the global exception handler by extending ExceptionHandlerFactory and ExceptionHandlerWrapper, configuring the RenderKitFactory, configuring PartialViewContext, configuring VisitContext, configuring ExternalContext, and configuring Flash by extending FlashFactory and FlashWrapper. Each of these is explained by spelling out the steps needed to perform the configuration and then demonstrating those steps implemented with code listings.

Chapter 5 concludes with coverage of enabling and disabling the ClientWindow API, configuring the JSF lifecycle by extending LifecycleFactory and LifecycleWrapper, configuring an application by extending ApplicationFactory and ApplicationWrapper, and configuring View Declaration Language (VDL), and using more than one configured factory in conjunction with each other to write "a Java Servlet capable of converting a non-JSF request into a JSF view."

Chapter 6: Working with Tabular Data

Chapter 6 is devoted to coverage of applying <h:dataTable> to represent tabular data in JSF. Specific examples covered include rendering of tabular data from JSF-hosted POJOs, displaying a collection of objects with CollectionDataModel, presenting sorted data, an introduction to DataModel, deleting a row from a table, modifying a row in a table, adding a new row, supporting selection of a single row and multiple rows, nesting tables, paginating tables, filtering tables, and styling tables.

The sixth chapter also demonstrates how to generate a JSF table programatically with JSF API classes such as HtmlDataTable, HtmlColumn, and HtmlOutputText.

Chapter 7: JSF and AJAX

The seventh chapter of Mastering JavaServer Faces 2.2 covers use of JavaServer Faces with Ajax. The chapter introduces <f:ajax> and the JSF/Ajax lifecycle. It then provides detailed explanations of the main attributes of <f:ajax>: execute, render, listener, event, onevent, onerror.

Mastering JavaServer Faces 2.2's Chapter 7 covers more examples of using JSF with Ajax such as grouping multiple components within a single <f:ajax> tag, "updating input fields with Ajax after validation error" using resetValues, implementing Cancel and Clear buttons, mixing Ajax and Flow scope, determining if a request is an Ajax request (PartialViewContext.isAjaxRequest or headers Faces-Request and X-Requested-With), using <f:param> with <f:ajax>, controlling client-side Ajax queuing with <f:ajax>'s delay attribute, explicitly loading and customizing the JavaScript file that contains JSF's Ajax support (jsf.js).

Chapter 8: JSF 2.2 – HTML5 and Upload

Chapter 8 is introduced as being primarily composed of two sections: "The first part will present the JSF 2.2 support for HTML5, while the second part discusses the new upload component of JSF 2.2." The chapter's section on using HTML5 with JSF 2.2 discusses pass-through attributes and pass-through elements (TagDecorator). It also discusses application of Bean Validation 1.1 with HTML5 and JSF 2.2.

The section of Chapter 8 on JSF Upload introduces <h:inputFile> and some of its "most important" attributes before discussing use of multiple upload tags, identify characteristics of a file to be uploaded, writing uploaded data to disk, building a file upload validator, using upload with Ajax, uploading multiple files, upload with both indeterminate and determinate progress bars, and an especially lengthy discussion on providing previews of images to be uploaded.

Chapter 9: JSF State Management

The ninth chapter of Mastering JavaServer Faces 2.2 states early in the chapter that "JSF saves and restores the view state between requests using the ViewHandler/StateManager API. ... JSF uses this technique because it needs to preserve the views state over the HTTP protocol, which is a stateless protocol." The chapter goes on to explain how JSF 2.0 and 2.2 have improved JSF application performance with changes in how JSF state is managed. It provides a very detailed example of persisting state in JSF Mojarra to a MongoDB database.

One of the more interesting discussions in the ninth chapter for me was the discussion on JSF 2.2 support for stateless views via the transient attribute on the <f:view> element. Another interesting discussion covers security in JSF (CSRF, XSS, and SQL injection).

Chapter 10: JSF Custom Components

The opening statement of Chapter 10 is, "JSF is a component-based framework, and JSF custom components are the major proof that sustain JSF flexibility and extensibility." The chapter differentiates between custom components and composite components. I like the author's recommendation to look for already existing components as the first step when deciding to implement and then implement a custom component. This idea and a few other ideas are presented as possibly more appropriate approaches than implementing a custom component in many situations.

Chapter 10 explains and demonstrates "building noncomposite custom components" in JSF 2.2 with a single Java class annotated with @FacesComponent. The explanation and demonstration of writing noncomposite custom components dives into deeper details about implementing more complex custom components with Java classes and tag handlers.

Chapter 10's coverage of "building composite components" describes JSF 2 custom components as "practically custom components written in XHTML pages using markup tags" and is a longer and more detailed section than the section on noncomposite custom components. The author makes a good point here that use of XHTML "means that JSF page authors can start writing their components without having the same level of knowledge and skills as dedicated JSF component authors." This section demonstrates implementation of an example of a composite component that makes it easy to compare to the same example application implemented earlier in the chapter with a noncomposite custom component. Chapter 10 also provides explanations and illustrations of transforming the jQuery UI range slider component into a JSF composite component and transforming the HTML5 DatePicker into a JSF composite component.

There are several aspects of developing composite components in JSF covered in Chapter 10. These include working with composite facets, validating and converting input information within a composite component, distributing a composite component as a JAR, and instantiating composite components programatically.

Chapter 11: JSF 2.2 Resource Library Contracts – Themes

The second-to-last chapter of Mastering JavaServer Faces 2.2 starts with the sentence, "Starting with version 2.0, JSF developers exploit Facelets as the default View Declaration Language (VDL)." The early part of this chapter also describes a Facelet template as "a mix of XHTML and other resources such as CSS, JS, and images" that "acts as a base (or a model) for the application pages," providing "reusable code that serves as a consistent and standard look and feel." The chapter begins coverage of Resource Library Contracts by discussing the contracts folder. The chapter explains and illustrates applying style to tables and JSF components with contracts. The chapter also covers writing of contracts for composite components, writing custom themes, using XML to configure contracts, and packaging contracts in JARs under META-INF/contracts.

Chapter 12: Facelets Templating

Mastering JavaServer Faces 2.2 introduced and referenced Facelets in earlier chapters, but this final chapter focuses on Facelets (specifically templating with Facelets). After a brief history of how Facelets supplanted JavaServer Pages as the default View Definition Language for JavaServer Faces, the chapter provides a bullet list of Facelet tags with brief descriptions of each tag in each bullet.

After listing major Facelets tags with brief descriptions, Chapter 12 provides more in-depth discussion and examples of applying Facelets tags such as <ui:param>, <ui:decorate>, <ui:fragment>, <ui:repeat>, <ui:include>, <ui:debug>, and <ui:remove>.

Until reading Mastering JavaServer Faces 2.2, I was not aware of jsfc, but that is covered in the final chapter. The chapter also discusses "Facelets programmatic aspects" such as FaceletFactory, FaceletCache, ResourceHandler, including Facelets programatically, implementing a TagHandler class and implementing Facelets taglib functions.

The section of Chapter 12 titled "Facelets pitfalls" opens with something I've definitely observed: "It is a well-known fact that JSF pitfalls are not easy to understand and fix." This section then focuses on "three common Facelets pitfalls." Chapter 12's Summary is for that chapter only; there is no overall book summary.

Appendix: The JSF Life Cycle

This appendix is barely more than a single page, but has valuable information on the JSF lifecycle depicted in a flow diagram.

General Observations
  • There are numerous code listings in Mastering JavaServer Faces 2.2. These are black text on white background with no line numbers or syntax highlighting. Code is also available online, which is probably preferable because it can be presented in the reader's favorite IDE or text editor with color syntax highlighting and line numbers.
  • Mastering JavaServer Faces 2.2 provides graphics and figures to illustrate points being made. Many of these are in color in the PDF version I reviewed.
  • In multiple cases, the author mentioned a feature that was supposed to be part of JSF 2.x, but that was not working for him at time of writing of the book. I appreciated this being called out as it appears that some of these features may still not be supported in a standard way.
  • The author differentiates between standard JSF features and functionality and features and functionality provided by alternative JSF implementations.
  • NetBeans is referenced a few times in Mastering JavaServer Faces 2.2. In all of these cases, even a person who has not used NetBeans would likely understand the principle being stated.
  • Mastering JavaServer Faces 2.2 is not intended for the developer who is completely new to JavaServer Faces (the author stated this in the Preface: "It is dedicated to JSF developers who have previous experience and want to upgrade their knowledge to the new JSF 2.2."). Rather, this book is focused on providing in-depth details of new features of JSF 2.0 and 2.2 for developers who already have some basic familiarity with JSF. Alternative resources to consider for those entirely new to JSF in preparation for reading Mastering JavaServer Faces 2.2 include the following (some of which I've linked to earlier in this post):

Mastering JavaServer Faces 2.2 provides wide coverage of JavaServer Faces 2.0 and 2.2 additions that have made the framework more powerful and easier to apply. Mastering JavaServer Faces 2.2 assumes that the reader has previous JavaServer Faces experience and does not spend time bringing the reader up to speed on JSF basics before diving into the relatively detailed coverage of features new to JSF with 2.0 and 2.2. The book is best suited for developers who have mostly developed with JSF 1.x and want to start taking advantage of JSF 2 and JSF 2.2 features. This book is not appropriate for someone brand-new to JSF with no previous JSF experience.