Thursday, February 20, 2014

Video Review: HTML5 Game Development

Packt Publishing recently invited me to review the recently released video HTML5 Game Development by Makzan (http://makzan.net/). I hesitated initially to accept this offer because I've typically preferred reading text (books, blogs, and articles) over watching videos and podcasts for learning new technical concepts. However, after viewing the HTML5 Game Development video, I'm glad that I accepted that offer.

The HTML5 Game Development video, once downloaded, can be viewed in a web browser via the Packt Video player. The next screen snapshot demonstrates this for the first section of the video.

The HTML5 Game Development video is a series of short video clips ranging from a little shorter than 2 minutes to a little longer than 4 minutes each. These videos are categorized by "section" (sections are referenced as "chapters" in navigation buttons) and the next screen snapshot shows the first, second, and last (eighth) sections. The one in the middle (Section 1 in this case) is the Section whose video snippets would be viewed when the "Browse Videos" button is clicked.

When a Section (or Chapter) is selected, multiple short videos are made available. An example of this is shown in the next screen snapshot. Click on "Watch Video" allows one to start watching the specific video.

I have taken the time in this post to depict this presentation of the short video snippets because there are some advantages to the HTML5 Game Development video being available in this format. The short videos allow easily digestible amounts of information to be seen in just a few minutes. Objectives for each video snippet are outlined before the video snippet and then are addressed in the video snippet. With such short video snippets available and with clear objectives outlined before each video, it is easy to pick and choose which portions to watch more than once. An effective way of viewing this overall video might be to first watch the video snippets once through and then return to those of most interest are those that need to be seen again.

The overall video length is advertised as just under 2 hours. This is divided into eight chapters/sections ranging from 12+ minutes each to 17+ minutes each. With each chapter/section having 5 videos, these videos range from 1 minute to 4 minutes each. The Packt HTML5 Game Development Video Table of Contents outlines the eight chapters/sections, the five videos per chapter/section, and the total duration of each chapter/section. The O'Reilly page for this video breaks down each of the five videos in each of the eight chapters/sections by their individual durations (to minutes granularity).

Through the course of the 40 video snippets, HTML5 Game Development uses audio and video presentation to demonstrate creation of two simple HTML5-based game applications that work in web browsers on desktops and laptops and work on mobile devices. Along the way, the presentation covers HTML, CSS, JavaScript, and the EaselJS/CreateJS libraries. Seeing the code being edited in the Sublime text editor while the action being taken is narrated makes it easy to quickly see and learn how this all works together. I also liked that the video introduced many specific syntax features of HTML5 (such as local storage), JavaScript built-in functionality (such as use of JSON.stringify and JSON.parse), and CSS styling techniques.

HTML5 Game Development depicts application of several interesting products. Its use of Sublime Text makes it easy to read the code thanks to color coded syntax on a dark background, line numbers, code completion, and keyword matching capabilities. The video also uses Sloppy and the iOS Simulator to help demonstrate adjusting the developed games to run on mobile devices. The video also demonstrates using free tools available online to secure fonts and make them presentable on the web. Another example is the video's demonstration of using Zoƫ to covert Flash animation to sprite sheets (.png and .json files) and then applying those with EaselJS Sprite Sheet Animations.

The Packt page describing HTML5 Game Development includes a section with the header "Who this video course is for" that succinctly (and correctly in my opinion) summarizes the audience for this series of video snippets: "HTML5 Game Development is ideal for anyone who wants to get started with the fundamentals of game development in HTML5. Some basic knowledge of HTML, JavaScript, and CSS would be useful." The narration in the videos includes several nice references to best practices and reasons why certain things are coded the way they are and having basic familiarity with HTML, CSS, and JavaScript made it much easier to appreciate these points.

The videos demonstrate quite a bit in the two hours. The narration is quick and the code editing in Sublime Text is quick thanks to significant copying-and-pasting that occurs in synchronization with the narration. I enjoyed the relatively fast pace because I didn't have a chance to lose interest or get bored. However, I was glad that I had used HTML5 technologies previously because a lot of content was covered so rapidly. For viewers with less experience with these technologies, the short videos provide the opportunity to easily re-watch parts that need more than one viewing and possibly mix viewing of those parts with reading other more introductory resources.

One of the things I most enjoyed about the HTML5 Game Development video snippets was the real-time development and refactoring that was demonstrated. Other than the JavaScript libraries being used, both simple games were built from nothing in front of the viewer. Although this often meant copying and pasting of code obviously written earlier, it was done as if it was being typed in (but thankfully pasting is much quicker than most peoples' typing). The narration describes what is happening in each case and Sublime Text features are used to highlight portions being discussed. The best presentations at conferences or in videos are those in which significant upfront time has been invested in writing and generating the presentation. It is clear to me that this investment was made in preparing HTML5 Game Development. The coordination of audio and video is generally very good and is very conducive to quick learning.

I learned several things specific to game development from this video. For example, it was interesting to see discussion and implementation of the Sliding Door Effect. It was also interesting to see how common JavaScript functions and calculations could be used to model the game dynamics.

There are a few things to note to get the most out of "HTML5 Game Development." Although video 6.2 is called "Applying Gravity to the Hero", it actually talks about running hero and moving camera instead of falling hero. On the other hand, video 6.3 is called "Making the Hero Run" but talks about making the hero stop falling on the platform rather than falling through it. These videos, at least in my download, were switched in order.

To see full screen (which is particularly important with the code editing video), click on the square to the right of the video progress bar and volume control when mouse cursor is over video in the Packt Video Player.

The audio in HTML5 Game Development is clear and the woman narrating the video speaks in a clear manner and enunciates well (and I liked the accent).

HTML5 Game Development is a great resource for anyone with basic familiarity with HTML, JavaScript, and CSS to expand that knowledge into learning key principles that can be applied to generate HTML5 games and other interactive applications. For developers in that position, I highly recommend the HTML5 Game Development video.

Monday, February 17, 2014

Book Review: Backbone.js Patterns and Best Practices

The sub-title of Swarnendu De's Backbone.js Patterns and Best Practices (Packt Publishing, 2014) is "A one-stop guide to best practices and design patterns when building applications using Backbone.js." The Backbone.js site describes Backbone.js as follows:

Backbone.js gives structure to web applications by providing models with key-value binding and custom events, collections with a rich API of enumerable functions, views with declarative event handling, and connects it all to your existing API over a RESTful JSON interface.
Preface

The Preface states that most of the book's examples can be followed with simple text editor and web browser, but some examples require a web server and Node.js. The Preface points out that Backbone.js Patterns and Best Practices "is not a general introduction to Backbone.js or JavaScript design patterns," but is instead intended " for any developers who ha[ve] a basic knowledge of Backbone.js and is looking for solutions to common Backbone.js problems, looking to enforce reusability in their code by removing boilerplate and developing custom plugins and extensions, and hoping to use the most effective patterns to develop large-scale web application architecture."

The Preface further reinforces the point that this book is not for beginners when talking about the book's objective: "Whether you are an intermediate- or advanced-level Backbone.js developer, this book will guide you through the best practices and patterns to handle different issues with each Backbone component."

Chapter 1: Reducing Boilerplate with Plugin Development

The initial chapter of Backbone.js Patterns and Best Practices introduces the basics of Backbone.js and provides short descriptions of Backbone.Model, Backbone.View, Backbone.Collection, Backbone.Router, and Backbone.Events. The first chapter introduces the Underscore.js utility and mentions that "Backbone.js has a hard dependency on Underscore.js." The author also mentions Lo-Dash as an Underscore.js alternative. The core coverage of this initial chapter is on reusing code by extending (with and without a base class) and using mixins.

Chapter 2: Working with Views

Chapter 2 of Backbone.js Patterns and Best Practices begins with the sentence, "Backbone view works as the presentation layer of an application." The chapter is dedicated to coverage of Backbone Views and covers the el property, listening to view events, working with nested views, working with templates, organizing templates, precompiling templates, and more. Along the way, the chapter mentions the JavaScript Memory Profiling, Backbone-Debugger, Require.js, Handlebars.js, backbone.stickit, rivets.js, and Backbone.ModelBinder.

The second chapter also introduces Marionette.js, which it describes as "a composite application library for Backbone.js." The focus is on Marionette's ItemView, CollectionView, and CompositeView.

Chapter 2 moves finishes with coverage of backbone.layoutmanager as an alternative to Marionette RegionManager.

Chapter 3: Working with Models

Backbone.js Patterns and Best Practices's third chapter discusses working with Backbone models. The chapter begins by outlining the basics of Backbone models and how to use Backbone models with an emphasis on CRUD (create/read/update/delete) operations. Model validation is covered next with examples of using direct Backbone model validation as well as using Backbone.Validation. Chapter 2 covers serialization of Backbone models and using Backbone-relational.js for relational data work with Backbone.

Chapter 4: Working with Collections

Chapter 4 of Backbone.js Patterns and Best Practices defines a Backbone collection as "an ordered set of models" that includes "functionality to add, remove, sort, and filter models, and save to or fetch data from the server." The chapter includes a brief overview of Backbone collections before moving onto describing how to perform database-related operations on a Backbone collection. Sorting and filtering of Backbone collections are also covered in the fourth chapter.

Chapter 5: Routing Best Practices and Subrouting

The fifth chapter in Backbone.js Patterns and Best Practices describes a Backbone router as a mechanism that matches a "URL fragment" to an invoked method. The chapter provides an overview of Backbone routers and routing before moving onto coverage of "best practices for working with routers." In the course of this discussion, the author references Marionette.AppRouter and Marionette.Controller. Sub-routing is described in Chapter 5 and the extension backbone.subroute is specifically referenced.

Chapter 6: Working with Events, Sync, and Storage

Chapter 6 of Backbone.js Patterns and Best Practies covers "custom events, Backbone.sync() method and Backbone.LocalStorage." The portion of the chapter on events begins with a definition of events from the Backbone.Events API page. This section demonstrates how easy it is to create custom events in Backbone, contrasts use of Events to use of Callbacks, and provides a case study describing use of events. The section of Chapter 6 on Backbone.LocalStorage discusses and demonstrates use of Backbone.localStorage Adapter before mention an alternative called Backbone.dualStorage.

Chapter 7: Organizing Backbone Applications – Structure, Optimize, and Deploy

As its title suggests, Chapter 7 of Backbone.js Patterns and Best Practices discusses issues related to application structure, optimization, and deployment of Backbone-based applications. The author proposes an application directory structure which "is not something that will work universally for every application," but "lots of developers use it for their projects without any issues."

One of Chapter 7's main themes is Asynchronous Model Definition and using Require.js to add AMD support to a Backbone application.

Chapter 8: Unit Test, Stub, Spy, and Mock Your App

The final chapter (not including appendices) of Backbone.js Patterns and Best Practices begins with the opinionated statement, "Majority of developers believe that testing is essential, but in reality only a few of them actually go for test-driven development." The author lists multiple tools/frameworks for testing JavaScript code, but the chapter's focus is on use of QUnit (unit testing framework) and SinonJS (test doubles support).

Appendix A: Books, Tutorials, and References

Appendix A includes the author's recommendations for three books on Backbone.js along with recommended online tutorials and blog posts on Backbone.js. This appendix also includes references to additional resources on testing Backbone-based applications with QUnit and SinonJS as well as references to more Backbone plugins and tutorials.

Appendix B: Precompiling Templates on the Server Side

Appendix B is short and uses a Node.js-based example to illustrate how to precompile JavaScript templates.

Appendix C: Organizing Templates with AMD and Require.js

Although two chapters earlier in Backbone.js Patterns and Best Practices discuss AMD and Require.js briefly, both chapters reference Appendix C for additional details. The example in this appendix is built on top of requirejs-tpl.

General Observations
  • My most important observation is that the implication of Backbone.js Patterns and Best Practices's title and the explicit statements in its Preface that the book is targeted at intermediate Backbone developers should not be taken lightly. Although the book does provide some brief introductory material on most of the subjects it covers, at least some familiarity with the basics of a Backbone.js-based application would be extremely beneficial in realizing the full value of reading this book.
  • There are not many images or screen snapshots in this book, but these are not particularly important to the content.
  • Even in the PDF version of Backbone.js Patterns and Best Practices that I reviewed, the code listings are black text on white background with no color syntax. Most of the code listings are short enough to mitigate the issue, but color-coded syntax would be easier to read.
  • Backbone.js Patterns and Best Practices is written with the intent to discuss issues that the author believes developers frequently run into when developing Backbone-based applications.
Conclusion and Recommendation

Backbone.js Patterns and Best Practices (Packt, 2014, 174 pages) is explicitly intended for intermediate to advanced level Backbone.js developers. For more introductory text to Backbone.js, other books that might be more appropriate (none of which I have read) include Beginning Backbone.js (Apress, 2013, 304 pages), Developing Backbone.js Applications: Building Better JavaScript Applications (O'Reilly, 2013, 374 pages, free open source reading), Backbone.js Cookbook (Packt, 2013, 282 pages), or Instant Backbone.js Application Development (Packt, 2013, 64 pages). There are also numerous online resources with introductory Backbone.js content. Because I have not reviewed these other Backbone.js books, I cannot definitively state that Backbone.js Patterns and Best Practices picks up where they leave off. However, my best guess is that there is some overlap between these seemingly more introductory Backbone.js books, but that Backbone.js Patterns and Best Practices likely covers some more advanced topics (patterns and best practices) not covered in those books.

Saturday, February 15, 2014

Book Review: Test-Driven Development with Mockito

Test-Driven Development with Mockito provides a general introduction to test-driven development (TDD) before looking at application of Mockito to implement test doubles as part of test-driven development. Test-Driven Development with Mockito is written by Sujoy Acharya, is published by Packt Publishing with a publication date of November 2013, and has about 150 substantive pages of substantive content divided into 9 chapters and 2 appendices. The subtitle of Test-Driven Development with Mockito is "Learn how to apply Test-Driven Development and the Mockito framework in real life projects, using realistic, hands-on examples."

Preface

Test-Driven Development with Mockito's Preface opens with a very brief description of test-driven development and how Mockito plays a role in test-driven development. The preface summarizes each chapter and appendix before recommending what a reader of that book should use while reading the book: J2SE 5, the Eclipse IDE (Kepler 4.3 recommended), and Mockito.

One of the most important parts of a Packt Publishing Preface is the section on "Who this book is for." In this case, the paragraph in this section states:

This book is for developers who want to develop software according to Test Driven Development using Mockito and to leverage various Mockito features. Developers don't need prior knowledge of TDD, Mockito, or JUnit. It is ideal for developers who have some experience in Java application development as well as some basic knowledge of unit testing, but it covers the basic fundamentals of TDD and JUnit testing to get you acquainted with these concepts before you use them.

Chapter 1: Getting Familiar with TDD

As the Preface stated, Test-Driven Development with Mockito does cover "basic fundamentals of TDD" and begins this in the first chapter. This chapter starts out at a very basic level, defining a test in Java development and listing some "available code-driven unit-testing frameworks for Java." In this chapter, we learn that JUnit 4.0 will be used in examples in the book. An example is then presented using Eclipse and JUnit in which the test class is written before the production class. This transitions into more details on the historical background of TDD and lists benefits of TDD.

Chapter 1 continues by looking into how TDD fits into overall software development and how refactoring plays a role in test-driven development. In many ways this first chapter is what you'd expect from a book on test-driven development. The code-based examples of test-driven development do a nice job of illustrating basic techniques and advantages associated with test-driven development. However, there seemed to be some things that seemed a bit out of place in this chapter. In particular, the chapter's extremely brief coverage of "Object-function programming languages such as Scala and Groovy" seemed irrelevant to the rest of the chapter and added little value. As with most books on TDD, this chapter of this book had a paragraph that seemed a bit preachy.

Chapter 2: Refactoring – Roll the Dice

The second chapter of Test-Driven Development with Mockito, as its name implies, focuses on refactoring. The chapter begins by reviewing benefits of refactoring and then discusses "trigger points for refactoring" and when not to refactor. Some relatively lengthy code listings are provided to show some code in desperate need of refactoring with text explaining issues with the code and possible ways to refactor that code. This section of the book also introduces the Eclipse plugin CodePro Analytix.

The second chapter moves onto coverage of code smells. Duplicate code with switch statements is shown as a code smell and there is discussion and more code listings on how to refactor this using the strategy pattern and polymorphic behavior. Other code smells that are covered in this chapter along with potential remedies include duplicate code, comments, long methods, long method parameter lists, large classes, dead code, and overengineering.

This second chapter is a reasonable introduction to code smells and how to use refactoring and other techniques to deal with them. This chapter mentions common object-oriented and software development principles such as YAGNI, DRY, open-closed principle, and strategy pattern. A single chapter of a book cannot compete with an entire seminal treatment of a subject, but this chapter does provide a good illustration of how refactoring fits into TDD.

Chapter 3: Applying TDD

The third chapter of Test-Driven Development with Mockito begins with a bold statement, "Test-Driven Development (TDD) is the new way of programming." The chapter then outlines the simple steps that are taken to implement TDD and is the first chapter in the book to really dive into TDD. The chapter concludes with a lengthy example including code listings and Eclipse screen snapshots to demonstrate JUnit and TDD in practice.

Chapter 4: Understanding the Difference between Inside-out and Outside-in

Chapter 4 of Test-Driven Development with Mockito compares and contrasts TDD's two "common" styles: Outside-In and Inside-Out. The chapter provides details regarding the outside-in approach before listing advantages and disadvantages of that outside-in approach. The same is then done for inside-out, though the coverage is much shorter than for outside-in.

Chapter 5: Test Doubles

Test-Driven Development with Mockito's fifth chapter covers test doubles. The chapter very briefly discusses why test doubles are useful (I don't think this part is particularly strong) before categorizing the types of test doubles (dummy, stub, mock, and fake). The coverage of these types of test doubles is much better than the general introduction to test doubles and provides nice code examples and discussion on each and how they are different.

Chapter 6: Mockito Magic

Chapter 6 of Test-Driven Development with Mockito is the book's first significant look at Mockito (although Mockito was mentioned in Chapter 5 for the example of the mock category of test double). The chapter begins with an overview of Mockito and explains Mockito's primary roles in test-driven development: "Mockito plays a key role to mock out external dependencies" and helps achieve the desired "qualities of unit testing."

Chapter 6 continues by demonstrating adding Mockito to Eclipse. There are numerous screen snapshots of Mockito being used within Eclipse (these are in color in the electronic edition of the book). The chapter introduces key annotations and functionality provided by Mockito and demonstrates using Mockito to address things commonly tested using mocks. A reader of this book who's primary interest in the book is learning Mockito would find this to be one of his or her favorite chapters of the book.

Chapter 7: Leveraging the Mockito Framework in TDD

Test-Driven Development with Mockito's seventh chapter begins with a brief discussion of classical TDD versus mockist TDD. The chapter is then introduced with the statement that it will "use Mockist TDD style to mock external dependencies and explore Test-Driven Development." The entire chapter is then devoted to a fairly realistic example of building an "online portal for the aspiring game developers" with test-driven development techniques and using Mockito to mock out the external interfaces.

Chapter 8: World of Patterns

Chapter 8 of Test-Driven Development with Mockito opens with reference to Robert Martin's "three important characteristics of a bad design": rigidity, fragility, and immobility. The chapter then covers "higher level design guidelines" of modularity, high cohesion, and low coupling and "lower level design principles" of Open/Closed Principle, Dependency Inversion Principle, Integration Segregation Principle, Single Responsibility Principle, Liskov Substitution Principle, and the Law of Demeter.

The next section of Chapter 8 discusses design patterns. The section provides an overview of what design patterns are, how they are categorized, and provides a couple of examples of applying design patterns.

Chapter 9: TDD, Legacy Code, and Mockito

The ninth chapter of Test-Driven Development with Mockito discusses what constitutes legacy code and then emphasizes: "Any code with no unit test is legacy code." Chapter 9 looks at some common less-than-testable features of legacy code and how to refactor that code for greater testability. The chapter then moves onto how Mockito can make it easier to refactor code to be more testable.

Appendix A: TDD Tools and Frameworks

Appendix A covers Eclipse IDE and JUnit 4 unit testing framework. It discusses using keyboard shortcuts in Eclipse (including "The mother of all shortcuts is Ctrl + Shift + L" to see all shortcuts) and emphasizes those shortcuts useful in refactoring and TDD. There are some nice color screen snapshots showing shortcuts applied in this section. Appendix A's coverage of JUnit begins with the statement, "Inheritance in Java is not a smart thing to implement" to explain advantages of JUnit 4.x (which supports annotations) over earlier versions which required inheritance. Appendix A's coverage of JUnit covers fundamentals of JUnit and demonstrates using Eclipse shortcuts in JUnit unit test development.

Appendix B: Agile Practices

Appendix B discusses continuous integration (CI) in general before covering Jenkins as a particular continuous integration tool. The author begins continuous integration coverage with the statement, "In a good software development team, we'd find TDD as well as CI." There are numerous color screen snapshots depicting configuration of Jenkins. Appendix B also discusses the "Agile development methodologies Scrum and Kanban." After briefly discussing Agile in general and providing a reference to the Agile Manifesto, Appendix B focuses on Scrum and Kanban specifically.

General Observations
  • Test-Driven Development with Mockito attempts to cover numerous topics within its roughly 150 pages.
  • Test-Driven Development with Mockito has several nice images. I especially like the screen snapshots that depict Eclise refactoring keyboard shortcuts and the screen snapshots that depict Jenkins configuration. An advantage of my reviewing the PDF provided by Packt Publishing is that these images are in full color.
  • The code listings are useful in illustrating the points being made, but the lack of color syntax (even in the electronic PDF version) make it more difficult to read the code quickly and easily. I have become spoiled by my IDE (and even my vim!) and online code listings featuring color syntax. Reading code without color syntax reminds me of the "old days," but the nostalgia is not worth the extra effort required to read the code.
  • Test-Driven Development with Mockito has some typos in it and also has some awkward and incomplete sentences. However, none of these were significant enough to prevent me from picking up the concept being covered.
  • Although the flow of topics covered in Test-Driven Development with Mockito generally made sense, there were some aspects of the arrangement of the various concepts that were a bit awkward. In particular, there were a couple concepts that were presented in almost a "side note" manner at first and were not very clearly explained, but then were much more clearly explained in the later sections that focused on that topic.
  • As is the case with just about every TDD-related book I have read, Test-Driven Development with Mockito is a highly opinionated book. Although I generally agreed with most of the opinions, I felt some of the stated opinions were backed up better than others and some I don't feel quite as strongly about or think are quite as certain as the author does. That being stated, I do like to see opinions expressed and I generally agreed with them in principle. The more focused books I mentioned in an earlier bullet would be useful for the reader of Test-Driven Development with Mockito who wanted to better understand the "why" behind some of the opinions expressed in this book.
Conclusion and Recommendation

Test-Driven Development with Mockito will be most beneficial to readers who have little to no familiarity with the numerous concepts introduced in the book (test-driven development, refactoring, object design, JUnit, Mockito, etc.). The book provides an overview of each of these and how they are used together. Developers who have read other books on these subjects may not find the introductory information in Test-Driven Development with Mockito as useful or as new to them. Developers wanting in-depth coverage of a topic might prefer a book focused on that particular topic. The book is most useful for those using the Eclipse IDE, but many of the sections are useful for developers who don't use Eclipse.

Monday, February 10, 2014

Serializing Java Objects with Non-Serializable Attributes

There are multiple reasons one might want to use custom serialization instead of relying on Java's default serialization. One of the most common reasons is for performance improvements, but another reason for writing custom serialization is when the default serialization mechanism is unsupported. Specifically, as will be demonstrated in this post, custom serialization can be used to allow a larger object to be serialized even when attributes of that object are not themselves directly serializable.

The next code listing shows a simple class for serializing a given class to a file of the provided name and for deserializing an object from that same file. I will be using it in this post to demonstrate serialization.

SerializationDemonstrator.java
package dustin.examples.serialization;

import static java.lang.System.out;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

/**
 * Simple serialization/deserialization demonstrator.
 * 
 * @author Dustin
 */
public class SerializationDemonstrator
{
   /**
    * Serialize the provided object to the file of the provided name.
    * @param objectToSerialize Object that is to be serialized to file; it is
    *     best that this object have an individually overridden toString()
    *     implementation as that is used by this method for writing our status.
    * @param fileName Name of file to which object is to be serialized.
    * @throws IllegalArgumentException Thrown if either provided parameter is null.
    */
   public static <T> void serialize(final T objectToSerialize, final String fileName)
   {
      if (fileName == null)
      {
         throw new IllegalArgumentException(
            "Name of file to which to serialize object to cannot be null.");
      }
      if (objectToSerialize == null)
      {
         throw new IllegalArgumentException("Object to be serialized cannot be null.");
      }
      try (FileOutputStream fos = new FileOutputStream(fileName);
           ObjectOutputStream oos = new ObjectOutputStream(fos))
      {
         oos.writeObject(objectToSerialize);
         out.println("Serialization of Object " + objectToSerialize + " completed.");
      }
      catch (IOException ioException)
      {
         ioException.printStackTrace();
      }
   }

   /**
    * Provides an object deserialized from the file indicated by the provided
    * file name.
    * 
    * @param <T> Type of object to be deserialized.
    * @param fileToDeserialize Name of file from which object is to be deserialized.
    * @param classBeingDeserialized Class definition of object to be deserialized
    *    from the file of the provided name/path; it is recommended that this
    *    class define its own toString() implementation as that will be used in
    *    this method's status output.
    * @return Object deserialized from provided filename as an instance of the
    *    provided class; may be null if something goes wrong with deserialization.
    * @throws IllegalArgumentException Thrown if either provided parameter is null.
    */
   public static <T> T deserialize(final String fileToDeserialize, final Class<T> classBeingDeserialized)
   {
      if (fileToDeserialize == null)
      {
         throw new IllegalArgumentException("Cannot deserialize from a null filename.");
      }
      if (classBeingDeserialized == null)
      {
         throw new IllegalArgumentException("Type of class to be deserialized cannot be null.");
      }
      T objectOut = null;
      try (FileInputStream fis = new FileInputStream(fileToDeserialize);
           ObjectInputStream ois = new ObjectInputStream(fis))
      {
         objectOut = (T) ois.readObject();
         out.println("Deserialization of Object " + objectOut + " is completed.");
      }
      catch (IOException | ClassNotFoundException exception)
      {
         exception.printStackTrace();
      }
      return objectOut;
   }
}

The next code listing illustrates use of the SerializationDemonstrator class to serialize and deserialize a standard Java string (which is Serializable). A screen snapshot follows the code listing and shows the output (in NetBeans) of running that String through the serialize and deserialize methods of the SerializationDemonstrator class.

Running SerializationDemonstrator Methods on String
SerializationDemonstrator.serialize("Inspired by Actual Events", "string.dat");
final String stringOut = SerializationDemonstrator.deserialize("string.dat", String.class);

The next two code listings are for the class Person.java and a class that it has as an attribute type (CityState.java). Although Person implements Serializable, the CityAndState class does not.

Person.java
package dustin.examples.serialization;

import java.io.Serializable;

/**
 * Person class.
 * 
 * @author Dustin
 */
public class Person implements Serializable
{
   private String lastName;
   private String firstName;
   private CityState cityAndState;

   public Person(
      final String newLastName, final String newFirstName,
      final CityState newCityAndState)
   {
      this.lastName = newLastName;
      this.firstName = newFirstName;
      this.cityAndState = newCityAndState;
   }

   public String getFirstName()
   {
      return this.firstName;
   }

   public String getLastName()
   {
      return this.lastName;
   }

   @Override
   public String toString()
   {
      return this.firstName + " " + this.lastName + " of " + this.cityAndState;
   }
}
CityAndState.java
package dustin.examples.serialization;

/**
 * Simple class storing city and state names that is NOT Serializable.
 * 
 * @author Dustin
 */
public class CityState
{
   private final String cityName;
   private final String stateName;

   public CityState(final String newCityName, final String newStateName)
   {
      this.cityName = newCityName;
      this.stateName = newStateName;
   }

   public String getCityName()
   {
      return this.cityName;
   }

   public String getStateName()
   {
      return this.stateName;
   }

   @Override
   public String toString()
   {
      return this.cityName + ", " + this.stateName;
   }
}

The next code listing demonstrates running SerializationDemonstrator on the serializable Person class with a non-serializable CityState. The code listing is followed by a screen snapshot of the output in NetBeans.

Running SerializationDemonstrator Methods on Serializable Person with Non-Serializable CityState
final Person personIn = new Person("Flintstone", "Fred", new CityState("Bedrock", "Cobblestone"));
SerializationDemonstrator.serialize(personIn, "person.dat");

final Person personOut = SerializationDemonstrator.deserialize("person.dat", Person.class);

In this case, the CityState class is my own class and I could make it Serializable. However, supposing that this class was part of a third-party framework or library and I was not able to change the class itself, I can change Person to use custom serialization and deserialization and work with CityState properly. This is shown in the next code listing for the class SerializablePerson that is adapted from Person.

SerializablePerson.java
package dustin.examples.serialization;

import java.io.IOException;
import java.io.InvalidObjectException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.ObjectStreamException;
import java.io.Serializable;

/**
 * Person class.
 * 
 * @author Dustin
 */
public class SerializablePerson implements Serializable
{
   private String lastName;
   private String firstName;
   private CityState cityAndState;

   public SerializablePerson(
      final String newLastName, final String newFirstName,
      final CityState newCityAndState)
   {
      this.lastName = newLastName;
      this.firstName = newFirstName;
      this.cityAndState = newCityAndState;
   }

   public String getFirstName()
   {
      return this.firstName;
   }

   public String getLastName()
   {
      return this.lastName;
   }

   @Override
   public String toString()
   {
      return this.firstName + " " + this.lastName + " of " + this.cityAndState;
   }

   /**
    * Serialize this instance.
    * 
    * @param out Target to which this instance is written.
    * @throws IOException Thrown if exception occurs during serialization.
    */
   private void writeObject(final ObjectOutputStream out) throws IOException
   {
      out.writeUTF(this.lastName);
      out.writeUTF(this.firstName);
      out.writeUTF(this.cityAndState.getCityName());
      out.writeUTF(this.cityAndState.getStateName());
   }
 
   /**
    * Deserialize this instance from input stream.
    * 
    * @param in Input Stream from which this instance is to be deserialized.
    * @throws IOException Thrown if error occurs in deserialization.
    * @throws ClassNotFoundException Thrown if expected class is not found.
    */
   private void readObject(final ObjectInputStream in) throws IOException, ClassNotFoundException
   {
      this.lastName = in.readUTF();
      this.firstName = in.readUTF();
      this.cityAndState = new CityState(in.readUTF(), in.readUTF());
   }

   private void readObjectNoData() throws ObjectStreamException
   {
      throw new InvalidObjectException("Stream data required");
   }
}

The above code listing shows that SerializablePerson has custom writeObject and readObject methods to support custom serialization/deserialization that handle its attribute of unserializable type CityState appropriately. A snippet of code for running this class through the SerializationDemonstrator and the successful output of doing so are shown next.

Running SerializationDemonstrator on SerializablePerson
final SerializablePerson personIn = new SerializablePerson("Flintstone", "Fred", new CityState("Bedrock", "Cobblestone"));
SerializationDemonstrator.serialize(personIn, "person1.dat");

final SerializablePerson personOut = SerializationDemonstrator.deserialize("person1.dat", SerializablePerson.class);

The approach depicted above will allow non-serializable types to be used as attributes of serializable classes without the need to make those fields transient. However, if the CityState instance shown earlier needs to be used in multiple serializable classes, it might be better to decorate the CityState class with a serializable decorator and then used that serialized decorator class in classes needing to be serialized. The next code listing shows SerializableCityState which decorates CityState with a serialized version.

SerializableCityState
package dustin.examples.serialization;

import java.io.IOException;
import java.io.InvalidObjectException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.ObjectStreamException;
import java.io.Serializable;

/**
 * Simple class storing city and state names that IS Serializable. This class
 * decorates the non-Serializable CityState class and adds Serializability.
 * 
 * @author Dustin
 */
public class SerializableCityState implements Serializable
{
   private CityState cityState;

   public SerializableCityState(final String newCityName, final String newStateName)
   {
      this.cityState = new CityState(newCityName, newStateName);
   }

   public String getCityName()
   {
      return this.cityState.getCityName();
   }

   public String getStateName()
   {
      return this.cityState.getStateName();
   }

   @Override
   public String toString()
   {
      return this.cityState.toString();
   }

   /**
    * Serialize this instance.
    * 
    * @param out Target to which this instance is written.
    * @throws IOException Thrown if exception occurs during serialization.
    */
   private void writeObject(final ObjectOutputStream out) throws IOException
   {
      out.writeUTF(this.cityState.getCityName());
      out.writeUTF(this.cityState.getStateName());
   }
 
   /**
    * Deserialize this instance from input stream.
    * 
    * @param in Input Stream from which this instance is to be deserialized.
    * @throws IOException Thrown if error occurs in deserialization.
    * @throws ClassNotFoundException Thrown if expected class is not found.
    */
   private void readObject(final ObjectInputStream in) throws IOException, ClassNotFoundException
   {
      this.cityState = new CityState(in.readUTF(), in.readUTF());
   }

   private void readObjectNoData() throws ObjectStreamException
   {
      throw new InvalidObjectException("Stream data required");
   }
}

This serializable decorator can be used in the Person class directly and that enclosing Person can use default serialization because its fields are all serializable. This is shown in the next code listing for Person2 adapted from Person.

Person2.java
package dustin.examples.serialization;

import java.io.Serializable;

/**
 * Person class.
 * 
 * @author Dustin
 */
public class Person2 implements Serializable
{
   private final String lastName;
   private final String firstName;
   private final SerializableCityState cityAndState;

   public Person2(
      final String newLastName, final String newFirstName,
      final SerializableCityState newCityAndState)
   {
      this.lastName = newLastName;
      this.firstName = newFirstName;
      this.cityAndState = newCityAndState;
   }

   public String getFirstName()
   {
      return this.firstName;
   }

   public String getLastName()
   {
      return this.lastName;
   }

   @Override
   public String toString()
   {
      return this.firstName + " " + this.lastName + " of " + this.cityAndState;
   }
}

This code can be executed as shown in the next code listing, which is followed by its output as seen in the NetBeans output window.

Running SerializationDemonstrator Against Person2/SerializableCityState
final Person2 personIn = new Person2("Flintstone", "Fred", new SerializableCityState("Bedrock", "Cobblestone"));
SerializationDemonstrator.serialize(personIn, "person2.dat");

final Person2 personOut = SerializationDemonstrator.deserialize("person2.dat", Person2.class);

Custom serialization can be used to allow a class with attributes of nonserializable types to be serialized without making those attributes of nonserializable type transient. This is a useful technique when serializable classes need to use attributes of types that are not serializable and that cannot be changed.

Monday, February 3, 2014

ObjectStreamClass: Peeking at a Java Object's Serialization

ObjectStreamClass can be a useful class to analyze the serialization characteristics of a serialized class loaded in the JVM. This post looks at some of the information this class provides about a loaded serialized class.

ObjectStreamClass provides two static methods for lookup of a class: lookup(class) and lookupAny(Class). The first, lookup(Class), will only return an instance of ObjectStreamClass when the provided class is serializable and returns null if the provided class is not serializable. The second, lookupAny(Class) returns an instance of ObjectStreamClass for the provided class regardless of whether it's serializable or not.

Once an instance of ObjectStreamClass is provided via the static "lookup" methods, that instance can be queried for class name, for serial version UID, and for serializable fields.

To demonstrate use of ObjectStreamClass, I first list the code listings for two simple classes that will be part of the demonstration. One class, Person, is Serializable, but has a transient field. The other class, UnserializablePerson, is nearly identical, but it is not Serializable.

Person.java
package dustin.examples.serialization;

import java.io.Serializable;

/**
 * Person class intended for demonstration of ObjectStreamClass.
 * 
 * @author Dustin
 */
public class Person implements Serializable
{
   private final String lastName;
   private final String firstName;
   transient private final String fullName;

   public Person(final String newLastName, final String newFirstName)
   {
      this.lastName = newLastName;
      this.firstName = newFirstName;
      this.fullName = this.firstName + " " + this.lastName;
   }

   public String getFirstName()
   {
      return this.firstName;
   }

   public String getLastName()
   {
      return this.lastName;
   }

   public String getFullName()
   {
      return this.fullName;
   }

   @Override
   public String toString()
   {
      return this.fullName;
   }
}
UnserializablePerson.java
package dustin.examples.serialization;

/**
 * Person class intended for demonstration of ObjectStreamClass.
 * 
 * @author Dustin
 */
public class UnserializablePerson
{
   private final String lastName;
   private final String firstName;
   private final String fullName;

   public UnserializablePerson(final String newLastName, final String newFirstName)
   {
      this.lastName = newLastName;
      this.firstName = newFirstName;
      this.fullName = this.firstName + " " + this.lastName;
   }

   public String getFirstName()
   {
      return this.firstName;
   }

   public String getLastName()
   {
      return this.lastName;
   }

   public String getFullName()
   {
      return this.fullName;
   }

   @Override
   public String toString()
   {
      return this.fullName;
   }
}

With two classes in place to run use in conjunction with ObjectStreamClass, it's now time to look at a simple demonstration application that shows use of ObjectStreamClass.

ObjectStreamClassDemo.java
package dustin.examples.serialization;

import static java.lang.System.out;

import java.io.ObjectStreamClass;
import java.io.ObjectStreamField;

/**
 * Demonstrates use of ObjectStreamDemo.
 * 
 * @author Dustin
 */
public class ObjectStreamClassDemo
{
   /**
    * Displays class name, serial version UID, and serializable fields as
    * indicated by the provided instance of ObjectStreamClass.
    * 
    * @param serializedClass 
    */
   public static void displaySerializedClassInformation(
      final ObjectStreamClass serializedClass)
   {
      final String serializedClassName = serializedClass.getName();
      out.println("Class Name: " + serializedClassName);
      final long serializedVersionUid = serializedClass.getSerialVersionUID();
      out.println("serialversionuid: " + serializedVersionUid);
      final ObjectStreamField[] fields = serializedClass.getFields();
      out.println("Serialized Fields:");
      for (final ObjectStreamField field : fields)
      {
         out.println("\t" + field.getTypeString() + " " + field.getName());
      }
   }

   /**
    * Main function that demonstrates use of ObjectStreamDemo.
    * 
    * @param arguments Command line arguments; none expected.
    */
   public static void main(String[] arguments)
   {
      // Example 1: ObjectStreamClass.lookup(Class) on a Serializable class
      out.println("\n=== ObjectStreamClass.lookup(Serializable) ===");
      final ObjectStreamClass serializedClass = ObjectStreamClass.lookup(Person.class);
      displaySerializedClassInformation(serializedClass);

      // Example 2: ObjectStreamClass.lookup(Class) on a class that is not
      //            Serializable (which will result in a NullPointerException
      //            when trying to access null returned from 'lookup'
      out.println("\n=== ObjectStreamClass.lookup(Unserializable) ===");
      try
      {
         final ObjectStreamClass unserializedClass =
            ObjectStreamClass.lookup(UnserializablePerson.class);
         displaySerializedClassInformation(unserializedClass);
      }
      catch (NullPointerException npe)
      {
         out.println("NullPointerException: Unable to lookup unserializable class with ObjectStreamClass.lookup.");
      }

      // Example 3: ObjectStreamClass.lookupAny(Class) works without the
      //            NullPointerException, but only provides name of the class as
      //            Serial Version UID and serialized fields do not apply in the
      //            case of a class that is not serializable.
      out.println("\n=== ObjectStreamClass.lookupAny(Unserializable) ===");
      final ObjectStreamClass unserializedClass =
          ObjectStreamClass.lookupAny(UnserializablePerson.class);
      displaySerializedClassInformation(unserializedClass);
   }
}

The comments in the source code above indicate what is being demonstrated. The output from running this class is shown in the next screen snapshot.

When the output shown above is correlated with the code before it, we can make several observations related to ObjectStreamClass. These include the fact that the transient field of a serializable class is not returned as one of the serializable fields. We also see that ObjectStreamClass.lookup(Class) method returns null if the class provided to it is not serializable. ObjectStreamClass.lookupAny(Class) returns an instance of ObjectStreamClass for classes that are not serializable, but only the class's name is available in that case.

The code above showed a Serial Version UID for Person.java of 1940442894442614965. When serialver is run on the command line, the same Serial Version UID is generated and displayed.

What's nice about the ability to programatically calculate the same Serial Version UID as would be calculated by the serialver tool that comes with the Oracle JDK is that one could explicitly add the same Serial Version UID to generated code as would be implicitly added anyway. Any JVM-friendly script or tool (such as one written in Groovy) that needs to know the implicit Serial Version UID of a class could use ObjectStreamClass to obtain that Serial Version UID.