Tuesday, May 27, 2014

Connecting to Cassandra from Java

In my post Hello Cassandra, I looked at downloading the Cassandra NoSQL database and using cqlsh to connect to a Cassandra database. In this post, I look at the basics of connecting to a Cassandra database from a Java client.

Although there are several frameworks available for accessing the Cassandra database from Java, I will use the DataStax Java Client JAR in this post. The DataStax Java Driver for Apache Cassandra is available on GitHub. The datastax/java-driver GitHub project page states that it is a "Java client driver for Apache Cassandra" that "works exclusively with the Cassandra Query Language version 3 (CQL3)" and is "licensed under the Apache License, Version 2.0."

The Java Driver 2.0 for Apache Cassandra page provides a high-level overview and architectural details about the driver. Its Writing Your First Client section provides code listings and explanations regarding connecting to Cassandra with the Java driver and executing CQL statements from Java code. The code listings in this post are adaptations of those examples applied to my example cases.

The Cassandra Java Driver has several dependencies. The Java Driver 2.0 for Apache Cassandra documentation includes a page called Setting up your Java development environment that outlines the Java Driver 2.0's dependencies: cassandra-driver-core-2.0.1.jar (datastax/java-driver 2.0), netty-3.9.0-Final.jar (netty direct), guava-16.0.1.jar (Guava 16 direct), metrics-core-3.0.2.jar (Metrics Core), and slf4j-api-1.7.5.jar (slf4j direct). I also found that I needed to place LZ4Factory.java and snappy-java on the classpath.

The next code listing is of a simple class called CassandraConnector.

CassandraConnector.java
package com.marxmart.persistence;

import com.datastax.driver.core.Cluster;
import com.datastax.driver.core.Host;
import com.datastax.driver.core.Metadata;
import com.datastax.driver.core.Session;

import static java.lang.System.out;

/**
 * Class used for connecting to Cassandra database.
 */
public class CassandraConnector
{
   /** Cassandra Cluster. */
   private Cluster cluster;

   /** Cassandra Session. */
   private Session session;

   /**
    * Connect to Cassandra Cluster specified by provided node IP
    * address and port number.
    *
    * @param node Cluster node IP address.
    * @param port Port of cluster host.
    */
   public void connect(final String node, final int port)
   {
      this.cluster = Cluster.builder().addContactPoint(node).withPort(port).build();
      final Metadata metadata = cluster.getMetadata();
      out.printf("Connected to cluster: %s\n", metadata.getClusterName());
      for (final Host host : metadata.getAllHosts())
      {
         out.printf("Datacenter: %s; Host: %s; Rack: %s\n",
            host.getDatacenter(), host.getAddress(), host.getRack());
      }
      session = cluster.connect();
   }

   /**
    * Provide my Session.
    *
    * @return My session.
    */
   public Session getSession()
   {
      return this.session;
   }

   /** Close cluster. */
   public void close()
   {
      cluster.close();
   }
}

The above connecting class could be invoked as shown in the next code listing.

Code Using CassandraConnector
/**
 * Main function for demonstrating connecting to Cassandra with host and port.
 *
 * @param args Command-line arguments; first argument, if provided, is the
 *    host and second argument, if provided, is the port.
 */
public static void main(final String[] args)
{
   final CassandraConnector client = new CassandraConnector();
   final String ipAddress = args.length > 0 ? args[0] : "localhost";
   final int port = args.length > 1 ? Integer.parseInt(args[1]) : 9042;
   out.println("Connecting to IP Address " + ipAddress + ":" + port + "...");
   client.connect(ipAddress, port);
   client.close();
}

The example code in that last code listing specified default node and port of localhost and port 9042. This port number is specified in the cassandra.yaml file located in the apache-cassandra/conf directory. The Cassandra 1.2 documentation has a page on The cassandra.yaml configuration file which describes the cassandra.yaml file as "the main configuration file for Cassandra." Incidentally, another important configuration file in that same directory is cassandra-env.sh, which defines numerous JVM options for the Java-based Cassandra database.

For the examples in this post, I will be using a MOVIES table created with the following Cassandra Query Language (CQL):

createMovie.cql
CREATE TABLE movies
(
   title varchar,
   year int,
   description varchar,
   mmpa_rating varchar,
   dustin_rating varchar,
   PRIMARY KEY (title, year)
);

The above file can be executed within cqlsh with the command source 'C:\cassandra\cql\examples\createMovie.cql' (assuming that the file is placed in the specified directory, of course) and this is demonstrated in the next screen snapshot.

One thing worth highlighting here is that the columns that were created as varchar datatypes are described as text datatypes by the cqlsh describe command. Although I created this table directly via cqlsh, I also could have created the table in Java as shown in the next code listing and associated screen snapshot that follows the code listing.

Creating Cassandra Table with Java Driver
final String createMovieCql =
     "CREATE TABLE movies_keyspace.movies (title varchar, year int, description varchar, "
   + "mmpa_rating varchar, dustin_rating varchar, PRIMARY KEY (title, year))";
client.getSession().execute(createMovieCql);

The above code accesses an instance variable client. The class with this instance variable that it might exist in is shown next.

Shell of MoviePersistence.java
package dustin.examples.cassandra;

import com.datastax.driver.core.ResultSet;
import com.datastax.driver.core.Row;

import java.util.Optional;

import static java.lang.System.out;

/**
 * Handles movie persistence access.
 */
public class MoviePersistence
{
   private final CassandraConnector client = new CassandraConnector();

   public MoviePersistence(final String newHost, final int newPort)
   {
      out.println("Connecting to IP Address " + newHost + ":" + newPort + "...");
      client.connect(newHost, newPort);
   }

   /**
    * Close my underlying Cassandra connection.
    */
   private void close()
   {
      client.close();
   }
}

With the MOVIES table created as shown above (either by cqlsh or with Java client code), the next steps are to manipulate data related to this table. The next code listing shows a method that could be used to write new rows to the MOVIES table.

/**
 * Persist provided movie information.
 *
 * @param title Title of movie to be persisted.
 * @param year Year of movie to be persisted.
 * @param description Description of movie to be persisted.
 * @param mmpaRating MMPA rating.
 * @param dustinRating Dustin's rating.
 */
public void persistMovie(
   final String title, final int year, final String description,
   final String mmpaRating, final String dustinRating)
{
   client.getSession().execute(
      "INSERT INTO movies_keyspace.movies (title, year, description, mmpa_rating, dustin_rating) VALUES (?, ?, ?, ?, ?)",
      title, year, description, mmpaRating, dustinRating);
}

With the data inserted into the MOVIES table, we need to be able to query it. The next code listing shows one potential implementation for querying a movie by title and year.

Querying with Cassandra Java Driver
/**
 * Returns movie matching provided title and year.
 *
 * @param title Title of desired movie.
 * @param year Year of desired movie.
 * @return Desired movie if match is found; Optional.empty() if no match is found.
 */
public Optional<Movie> queryMovieByTitleAndYear(final String title, final int year)
{
   final ResultSet movieResults = client.getSession().execute(
      "SELECT * from movies_keyspace.movies WHERE title = ? AND year = ?", title, year);
   final Row movieRow = movieResults.one();
   final Optional<Movie> movie =
        movieRow != null
      ? Optional.of(new Movie(
           movieRow.getString("title"),
           movieRow.getInt("year"),
           movieRow.getString("description"),
           movieRow.getString("mmpa_rating"),
           movieRow.getString("dustin_rating")))
      : Optional.empty();
   return movie;
}

If we need to delete data already stored in the Cassandra database, this is easily accomplished as shown in the next code listing.

Deleting with Cassandra Java Driver
/**
 * Deletes the movie with the provided title and release year.
 *
 * @param title Title of movie to be deleted.
 * @param year Year of release of movie to be deleted.
 */
public void deleteMovieWithTitleAndYear(final String title, final int year)
{
   final String deleteString = "DELETE FROM movies_keyspace.movies WHERE title = ? and year = ?";
   client.getSession().execute(deleteString, title, year);
}

As the examples in this blog post have shown, it's easy to access Cassandra from Java applications using the Java Driver. It is worth noting that Cassandra is written in Java. The advantage of this for Java developers is that many of Cassandra's configuration values are JVM options that Java developers are already familiar with. The cassandra-env.sh file in the Cassandra conf directory allows one to specify standard JVM options used by Cassandra (such as heap sizing parameters -Xms, -Xmx, and -Xmn),HotSpot-specific JVM options (such as -XX:-HeapDumpOnOutOfMemoryError, -XX:HeapDumpPath, garbage collection tuning options, and garbage collection logging options), enabling assertions (-ea), and exposing Cassandra for remote JMX management.

Speaking of Cassandra and JMX, Cassandra can be monitored via JMX as discussed in the "Monitoring using JConsole" section of Monitoring a Cassandra cluster. The book excerpt The Basics of Monitoring Cassandra also discusses using JMX to monitor Cassandra. Because Java developers are more likely to be familiar with JMX clients such as JConsole and VisualVM, this is an intuitive approach to monitoring Cassandra for Java developers.

Another advantage of Cassandra's Java roots is that Java classes used by Cassandra can be extended and Cassandra can be customized via Java. For example, custom data types can be implemented by extending the AbstractType class.

Conclusion

The Cassandra Java Driver makes it easy to access Cassandra from Java applications. Cassandra also features significant Java-based configuration and monitoring and can even be customized with Java.

Monday, May 19, 2014

Hello Cassandra

A colleague recently told me about several benefits of Cassandra and I decided to try it out. Apache Cassandra is described in A Quick Introduction to Apache Cassandra as "one of today’s most popular NoSQL-databases." The main page for Apache Cassandra states that the "Apache Cassandra database is the right choice when you need scalability and high availability without compromising performance." Cassandra is being used by companies such as eBay, Netflix, Adobe, Reddit, Instagram, and Twitter. This post is a summary of steps for getting started with Cassandra.

Apache Cassandra can be downloaded from the main Apache Cassandra web page. The Download page states that "the latest stable release of Apache Cassandra is 2.0.7 (released on 2014-04-18)" and this is the version I will discuss and use in this post.

For this post, I downloaded and installed the DataStax Community Edition from Planet Cassandra Downloads. The DataStax Community 2.0.7 edition includes "The Most Stable and Recommended Version of Apache Cassandra for Production (2.0.7)." There are DataStax Community Edition downloads available for Mac OS X, Microsoft Windows, and several flavors of Linux.

The next screen snapshot shows the directory listing for the "bin" directory of the Apache Cassandra included with the DataStax Community Edition installation.

From that "bin" directory, the Cassandra server can be started simply by running the appropriate executable. In the case of this single Windows machine, that command is cassandra.bat and this step is illustrated in the next screen snapshot.

The interactive command-line tool cqlsh is also located in the Apache Cassandra "bin" subdirectory. This tool is similar to SQL*Plus for Oracle databases, mysql for MySQL databases, and psql for PostgreSQL. It allows one to enter various CQL (Cassandra Query Language) statements such as inserting new data and querying data. Starting cqlsh from the command line on a Windows machine is shown in the next screen snapshot.

There are several useful observations that can be made from the previous image. As the output of from starting cqlsh shows, this version of Apache Cassandra is 2.0.7, this version of cqlsh is 4.1.1, and the relevant CQL specification is 3.1.1. The immediately previous screen snapshot also demonstrates help provided by running the "HELP" command. We can see that there are several "documented shell commands" as well as even more "CQL help topics."

The previous screen snapshot demonstrated that the "help" command in cqlsh lists individual topics on which the help command can be specifically run. For example, the next screen snapshot demonstrates the output from running "help types" in cqlsh.

In this screen snapshot, we see CQL data types that are supported in cqlsh such as ascii, text/varchar, decimal, int, double, timestamp, list, set, and map.

Keyspaces in Cassandra

Keyspaces are significant in Cassandra. Although this post covers Cassandra 2.0, the Cassandra 1.0 documentation nicely explains keyspaces in Cassandra: "In Cassandra, the keyspace is the container for your application data, similar to a schema in a relational database. Keyspaces are used to group column families together. Typically, a cluster has one keyspace per application." This documentation goes on to explain that keyspaces are typically used to group column families by replication strategy. The next screenshot demonstrates creation of a keyspace in cqlsh and listing the available keyspaces.

The last screen snapshot included an example of using the command SELECT * FROM system.schema_keyspaces; to see the available keyspaces. When one just wants a list of the names of the available keyspaces without all of the other details, it is easy to use desc keyspaces as shown in the next screens snapshot.

Creating a Column Family ("Table")

With a keyspace created, a column family (or table) can be created. The next screen snapshot demonstrates using the newly created movies_keyspace with the use movies_keyspace; statement and then shows using the cqlsh command SOURCE (similar to using @ in SQL*Plus) to run an external file to create a table (column family). The screen snapshot demonstrates listing available tables with the desc tables command and listing specific details of a given table (MOVIES in this case) with the desc table movies command.

The above screen snapshot demonstrated running an external file called createMovie.cql using the SOURCE command. The code listing for the createMovie.cql file is shown next.

CREATE TABLE movies
(
   title varchar,
   year int,
   description varchar,
   PRIMARY KEY (title, year)
);
Inserting Data into and Querying from the Column Family

The next screen snapshot demonstrates how to insert data into the newly created column family/table [insert into movies_keyspace.movies (title, year, description) values ('Raiders of the Lost Ark', 1981, 'First of Indiana Jones movies.');]. The image also shows how to query the column family/table to see its contents [select * from movies].

Cassandra is NOT a Relational Database

Looking at the Cassandra Query Language (CQL) statements just shown might lead someone to believe that Cassandra is a relational database. However, CQL is a relational-like feature added to Cassandra 2.0 intended to help people with SQL expertise more readily adopt Cassandra. Similarly, triggers are being added in 2.0/2.1. Despite the presence of these Cassandra features intended to make it easier for relational database users to adopt Cassandra, there are significant differences between Cassandra and a relational database.

The Cassandra Data Model is a page in the Apache Cassandra 1.0 Documentation that describes some key differences between Cassandra and relational databases. These include:

  • "Cassandra does not enforce relationships between column families the way that relational databases do between tables"
    • There are no foreign keys in Cassandra and there is no "joining" in Cassandra.
    • Denormalization is not a shameful thing in Cassandra and is actually welcomed to a certain degree.
  • Cassandra "table" (column family) modeling should be done based on expected queries to be used.
Conclusion

I've just begun to get my feet wet with Cassandra but look forward to learning more about it. This post has focused on some basics of acquiring and starting to use Cassandra. There is much to learn about Cassandra and some "deeper" topics that really need to be understood to truly appreciate Cassandra include Cassandra architecture (and here), Cassandra Data Modeling (and here), and Cassandra's strengths and weaknesses.

Thursday, May 8, 2014

Video Review: Building an Application with CoffeeScript

Darko Bozhinovski's video course Building an Application with CoffeeScript was published last month by Packt Publishing. In this post, I review this video course on CoffeeScript (described on its main web page as "a little language that compiles into JavaScript" that is "an attempt to expose the good parts of JavaScript in a simple way").

Building an Application with CoffeeScript runs in the same web browser-based Packt Video Player used by other video courses from Packt Publishing that I've previously reviewed: HTML5 Game Development, jQuery UI Development, and JBoss EAP Configuration, Deployment, and Administration. The player runs completely in a web browser and features short video segments (ranging from 1 minute to 9 minutes each) divided into eight sections (chapters) with between 2 and 3 videos per section.

Section 1: CoffeeScript 101

The first section of Building an Application with CoffeeScript includes three videos and the initial video is the longest of the entire video course with a duration of almost 9 minutes. This initial video's summary includes three bullets and provides a link to additional references for more details. The video introduces CoffeeScript via the CoffeeScript site. In describing how CoffeeScript allows the best parts of JavaScript to be used, the video author also references Douglas Crockford's JavaScript site. Much of this first video uses examples on the CoffeeScript site to compare and contrast CoffeeScript with JavaScript. The site shows CoffeeScript and equivalent JavaScript code side-by-side and the video author shows these same CoffeeScript-to-JavaScript comparisons in the web-based JavaScript-to-CoffeeScript compiler js2coffee. As he narrates, he shows how subtle changes to the CoffeeScript or the JavaScript impact the other language in the js2coffee tool. One slightly distracting issue with the first video is the presence of "Topic 3" text at the end of a bullet on the first slide; I suspect this was template text that should have been removed when the bullet was added.

The second video demonstrates how to download and install the CoffeeScript compiler via download of Node.js. The video demonstrates using the command-line compiler to compile a "Hello, World" example written in CoffeeScript to JavaScript and then shows that JavaScript rendered in a web browser.

Section 1's third video introduces cake, described in the CoffeeScript site as, "a (very) simple build system similar to Make and Rake." Bozhinovski demonstrates writing a Cake task that compiles all CoffeeScript files in a given directory to their CoffeeScript equivalents and then demonstrates running that Cake task.

Section 2: Head-first Application Development

Section 2 features three video snippets that cover concepts such as object-oriented programming, inheritance, classes, and MVC. The first video of Section 2 is the one that really started to pique my interest in CoffeeScript. Although I liked some of the conciseness that CoffeeScript offers over JavaScript as shown in earlier video snippets, it was the support for class-based object-oriented programming in CoffeeScript that really caught my attention. The narrator demonstrates using js2coffee that classes in CoffeeScript are functions in JavaScript and one cannot help but notice how much more readable the CoffeeScript classes are than the JavaScript functions. The author also uses this first video of Section 2 to introduce his project with code examples that are used in the course.

The second video snippet of Section 2 focuses on Model-View-Controller and begins this focus with a reference to the Wikipedia page on MVC. Bozhinovski returns to his Github project coffeescript-course again and makes a short detour to advertise benefits of Github and how to start with Github. He then shows that the files in his project are empty and explains that he will populate them as part of the video course. At that point, he creates base model, controller, and view classes.

The third video of Section 2 begins with a focus on class-based inheritance in CoffeeScript. This coverage includes referencing the CoffeeScript site and demonstrating extending the base classes written in the previous video. A significant portion of this video highlights more resources available to viewers interested in CoffeeScript at the CoffeeScript site, via JavaScript frameworks, and at the http://todomvc.com/ site.

Section 3: The Storage Layer – Models and Data Persistence

There are only two video snippets in Section 3, but the section's overall duration is among the highest of the video course. The first video in this section discusses Web/DOM storage and which browser versions support this feature. The author points out advantage of local (web) storage such as its better support among common web browsers as compared to alternatives such as IndexDB and Web SQL Database.

Section 3's first video demonstrates use of localStorage by opening a web brower's console and running JavaScript-based examples using localStorage in that console (brief discussion on how to open this console in different browsers is included). The examples are then shown in js2coffee so that use of localStorage can be seen both directly in JavaScript and in CoffeeScript.

The second video in Section 3 is "the fun part" and begins with a demonstration of writing a class in CoffeeScript that encapsulates persisting and retrieving data values to localStorage. The example highlights the ability to specify static methods on a CoffeeScript class with the @ symbol and demonstrates how these static methods would be called by clients. Section 3's second video also demonstrates completing and persisting the model classes. JSON.parse and JSON.stringify are demonstrated within CoffeeScript as well.

Section 4: Routing and Views

Section 4 is composed of three video snippets. The first video in this section reviews the roles of controller, view, and model and then introduces the concept of routing. The video demonstrates building a routing class for the example application, but the narrator explains the basic theory behind routers and points out third-party routing micro frameworks that are already available for use. The author's examples are relatively simple, associating routes with controllers' methods, but the author points out that more elaborate routing is possible.

The second video of Section 4 builds on the section's first video to cover routers and controllers in more detail. The author demonstrates writing new controller methods and demonstrates more concretely the association between controllers and routers.

Section 4's final video is the longest of the section and introduces views. Along the way, this video demonstrates some more CoffeeScript features such as its constructor method, its multi-line string support, and its for-of loop. The example application at this point has HTML tags added to its rendering portion of its view classes and jQuery is used here as well.

Section 5: Interactions and Event Handling – Using JQuery with CoffeeScript

Using jQuery was mentioned very briefly a couple times in earlier sections, but the two-video Section 5 makes the use of jQuery with CoffeeScript a central theme. The first of the section's two videos demonstrates how to prevent a hypertext action in the example application from going to a newly served page and instead be routed via the router built in Section 4. This is key to implementing a single-page application. This video also demonstrates additional CoffeeScript/jQuery binding concepts and demonstrates CoffeeScript's switch/when statement.

Section's final second and final video starts by revisiting the hash change support in modern browsers. The author also mentions the pushState API. Demonstration of writing a global Event Emitter based on Backbone.js's Backbone.Events class is also demonstrated and it is explained that this approach allows for less tight coupling than using direct calls between views and controllers.

Section 6: Extending Our Application – Manipulating Stored Data

There are three video snippets in Section 6 and all three use creation and enhancement of the example applications category and document concepts to illustrate organization of data and of additional CoffeeScript code in practice. These are code-heavy videos that illustrate practical implementation of new features for the example application.

Section 7: Extending Our Application – Add an External Library

The first video of Section 7 introduces the idea of using Summernote in the example application to support rich text editing. The second video demonstrates integrating Summernote with the example application, including saving the rich text.

The second video also introduces jsPDF and the third video of Section 7 demonstrates integrating jsPDF with the example application so that the example application can export PDF from HTML.

Section 8: Publishing and Real-world Usage for Our Documents

The final section has three videos. The first of these three demonstrates using the Blob API to allow the example application to export documents in text and HTML formats. The second video demonstrates how to allow a user of the example application to publish the document to a WordPress blog. The third and final video of this section (and final video of the course) talks about ways that viewers could customize and enhance the example application built during the course. The author outlines other possible applications that could be built from it and talks about other ways to change it.

General Observations
  • The title "Building an Application with CoffeeScript" articulates well what this video course is. Although the video course is often introductory in nature, it is organized around demonstration of building an application using CoffeeScript and incidentally providing introductory information along the way. This is different than being organized as an introduction to CoffeeScript that happens to build an example application along the way. Instead of providing lengthy lists of features and syntax examples (which is what a course focused on introduction over application building might do), this video course provides just enough introductory coverage of required features and syntax to allow the work of building an example application to take place.
  • Numerous online references are shown and discussed in this video course, making it easier for the viewer to identify sources of additional details and background information. These online resources help the narrator to explain the topic and showing them to the viewer allows the viewer to directly access them after being introduced to them. The video course makes it even easier to find these resources by listing the URLs for most of them in the summary area of each section.
  • There are several occurrences in the video course when the author references the associated GitHub project ("coffeescript-course") for additional or deeper details than covered in the video. This allows the video presentation to avoid getting too deep in details while at the same time allowing viewers to learn more details as desired after finishing the video.
  • Viewers of Building an Application with CoffeeScript will be best served if they have basic familiarity with JavaScript. This is because many of the examples teach CoffeeScript via comparison to JavaScript and because basic familiarity with JavaScript allows the viewer to more quickly appreciate what CoffeeScript offers in its place.
  • I liked that several popular JavaScript frameworks were used in the example application built in this video course. Specific examples of frameworks used in the example application include jQuery, BackBone, and Bootstrap-based Summernote.
  • I liked that several features of modern web browsers were used in the example application built in this video course.
Conclusion

Building an Application with CoffeeScript delivers on what its title promises: demonstration and explanation of building a simple application with CoffeeScript. This video is most likely going to appeal most strongly to developers who have basic JavaScript familiarity and want to get a quick overview of what CoffeeScript offers and how it can ease some of the burdens of JavaScript development.

Friday, May 2, 2014

Book Review: Java EE 7 with GlassFish 4 Application Server

David R. Heffelfinger's Java EE 7 with GlassFish 4 Application Server has been published by Packt Publishing. The subtitle of this book is "A practical guide to install and configure the GlassFish 4 application server and develop Java EE 7 applications to be deployed to this server."

The Preface of Java EE 7 with GlassFish 4 Application Server states that JDK 7 (or newer), GlassFish 4.0, and Maven are needed to build and run the examples in this book. The Preface also expects that readers are expected to have "familiarity with the Java language" and that the book is intended for Java developers wanting to learn Java EE or current Java EE developers wanting to learn about the newest specification.

Chapter 1: Getting Started with GlassFish

The first chapter of Java EE 7 with GlassFish 4 Application Server begins by briefly describing GlassFish and by providing a high-level overview of the new features of Java EE 7. The new Java EE 7 specifications covered at this high level are JavaServer Faces (JSF) 2.2, Java Persistence API (JPA) 2.1, Java API for RESTful Web Services (JAX-RS) 2.0, Java Message Service (JMS) 2.0, Java API for JSON Processing (JSON-P) 1.0, and Java API for WebSocket 1.0.

Chapter 1 lists two of the primary advantages of using GlassFish as a Java EE application server: it being the reference implementation and, as such, it providing implementations of the latest and newest Java EE features. There is no mention of what I perceive to be GlassFish 4's biggest disadvantage: Oracle has declined to provide commercial support for GlassFish 4.

The initial chapter demonstrates how to download GlassFish 4 and mentions that it is also available bundled with NetBeans IDE ("Java EE" or "All" bundles) since version 7.4. The chapter shows the basics of installing the downloaded GlassFish and assumes that JDK 1.7 or later (note there have been rumors of GlassFish 4 not working well on JDK 8 yet) has been installed and that the Java application launcher is available from the environment's path.

Starting GlassFish from the command-line using the well-known (to previous users of GlassFish) asadmin start-domain command is demonstrated in Chapter 1. The chapter shows bringing up a web browser with the URL http://localhost:8080 to verify that GlassFish is running and then demonstrates using the web-based administrative console at URL http://localhost:4848 to deploy a WAR (simpleapp.war) provided on the book's Packt Publishing site. This chapter also demonstrates using the web-based Administrative Console to undeploy the web application as well before demonstrating two ways to deploy the WAR from the command line (by copying the WAR into the autodeploy directory and by using the asadmin deploy command).

Chapter 1 introduces GlassFish domains as a concept and then explains how to work with them using appropriate asadmin domain commands create-domain, delete-domain, and stop-domain.

This meaty first chapter concludes with a demonstration of how to configure GlassFish to use a JDBC driver for working with a relational database. The example specifically demonstrates configuration of a MySQL database driver and datasource, but the author points out that the examples in the rest of the book that work with relational databases use the Apache Derby-based JavaDB that comes bundled with GlassFish.

Nothing in this first chapter on downloading, installing, deploying to, and configuring a data source for GlassFish seems different to me from previous versions of GlassFish. I believe that experienced GlassFish users who are reading Java EE 7 with GlassFish 4 Application Server to learn the new Java EE 7 features and new GlassFish 4 features could skip most of the introductory chapter with the exception of the section providing concisely worded high-level overviews of the new Java EE 7 features. For readers entirely new to GlassFish, this chapter provides a nice starting point for everything you need to do to get GlassFish up and running for use with examples later in the book.

Chapter 2: JavaServer Faces

The second chapter of Java EE 7 with GlassFish 4 Application Server focuses on JavaServer Faces (JSF), which it describes as "the standard component framework of the Java EE platform." This chapter's coverage includes discussion of Facelets as now (as of Java EE 6/JSF 2.0) JSF's "preferred view technology." The chapter describes how adhering to JSF's expected conventions can lead to minimal required configuration.

Chapter 2 continues its JSF coverage with an example XHTML-based Facelet that is described in detailed text. Along the way, the author explains how to use JSF 2.0 project stages and explains how to specify a project stage to GlassFish as a JNDI resource.

JSF's "built-in input validation capabilities" are covered next. A table of standard JSF validators is provided and there is minor discussion on using Bean Validation with JSF. The chapter also includes discussion on creation of custom validators. The example illustrating custom validators uses Apache Commons Validator. When the chapter includes an example of implementing custom validation methods on Named Beans, it makes use of Apache Commons StringUtils.

After Chapter 2 covers customization of message styles and text, it moves onto a section called "Ajax-enabling JSF applications." This section points out that "JSF 2.0 standardized Ajax support by introducing the <f:ajax> tag" and then provides an example of using that new tag. There is thorough coverage of the Ajax tag, how it works, and what its other options are.

The parts of JSF 2.2 that interest me most and which I looked forward most to reading about in this book are JSF 2.2's HTML5 support and JSF 2.2's Faces Flows. Both subjects are covered well in this chapter with examples and descriptions of those examples.

Chapter 3: Object Relational Mapping with JPA

Chapter 3 is dedicated to Java Persistence API and most of the chapter covers basics of JPA that have been in place well before Java EE 7. The chapter describes JPA as "the standard Java EE Object Relational Mapping (ORM) tool" and provides examples and discussion on using JPA with one-to-one relationships, one-to-many relationships, many-to-many relationships, and composite primary keys. The chapter also introduces Java Persistence Query Language (JPQL).

The third chapter discusses how the Criteria API limitations of JPQL. It also introduces JPA 2.1 (Java EE 7) enhancements to the Criteria API that allow "for updating database data via the CriteriaUpdate interface" because Criteria API could only be used for reading data previously.

Chapter 4: Enterprise JavaBeans

The fourth chapter's focus is Enterprise JavaBeans (EJB), which are introduced as "server side components that encapsulate business logic of an application" and "simplify application development by automatically managing transaction management and security." Two types of EJBs (session beans and message-driven beans) are discussed. Although not necessary anymore, it was interesting (or a walk down memory lane) to read the historical information about how session and entity beans have changed since the days of J2EE.

The examples and discussions regarding Session Enterprise JavaBeans include invocation of these deployed beans from a standalone client using appclient and from a web client using JSF and CDI. The examples also involve JPA, making them very inclusive of the significant Java EE specifications.

This fourth chapter covers several other EJB topics include security, the Timer Service, transactions, and the EJB lifecycle. None of these concepts are new to Java EE 7, but EJBs are of course a significant part of many Java EE applications.

Chapter 5: Contexts and Dependency Injection

Contexts and Dependency Injection (CDI), introduced with Java EE 6, is the subject of Chapter 5. The coverage includes named beans, dependency injection, CDI Qualifiers, and CDI named bean scopes (with particular emphasis on conversation scope).

Chapter 6: JSON Processing with JSON-P

Chapter 6 of Java EE 7 with GlassFish 4 Application Server is about Java API for JSON Processing (JSON-P, JSR 353), a specification new to Java EE 7. The chapter begins by introducing JavaScript Object Notation (JSON) as "a human-readable data interchange format ... derived from JavaScript."

The sixth chapter states that "JSON-P includes two APIs for processing JSON - the Model API and the Streaming API" and covers generating JSON and parsing JSON with each of these two APIs. The examples include code and text descriptions as well as brief descriptions of the advantages and disadvantages of JSON Model API versus JSON Streaming API.

Chapter 7: WebSockets

Like Chapter 6, Chapter 7 covers a specification and feature new to Java EE 7 with its coverage of Java API for WebSocket (JSR 356). The chapter covers development of WebSocket endpoints, development of JavaScript-based WebSocket clients, and development of Java-based WebSocket clients. Significant details regarding JSON-P are covered in this chapter and the author refers the read to the Tyrus User Guide for additional details (Tyrus is the "open source JSR 356 reference implementation").

Chapter 8: The Java Message Service

Chapter 8 of Java EE 7 with GlassFish 4 Application Server continues the streak of chapters covering new Java EE 7 specifications by covering Java Message Service (JMS) 2.0.

This is one of the chapters of Java EE 7 with GlassFish 4 Application Server that includes GlassFish-specific coverage within the topic of a general Java EE 7 specification. In this case, the chapter indicates how to configure GlassFish to use JMS by setting up "a JMS Connection Factory, a message queue, and a message topic." Like Chapter 4 on EJBs, this chapter on JMS also demonstrates using the GlassFish-specific applclient.

Chapter 8 coverage of JMS includes sending and receiving messages to/from queues and topics. It also includes an examples of browsing message queues and creating durable subscribers.

Chapter 9: Securing Java EE Applications

The ninth chapter of Java EE 7 with GlassFish 4 Application Server is on securing Java EE applications with Java Authentication and Authorization Service (JAAS) API and GlassFish. The chapter describes using security realms and covers both preconfigured realms (file, admin-realm, and certificate) and "defining additional realms" (with examples including an LDAP realm, a JDBC realm, and custom realms).

Chapter 10: Web Services with JAX-WS

The final two chapters of Java EE 7 with GlassFish 4 Application Server are on using web services with Java EE and Chapter 10 specifically covers working with SOAP-based web services using Java API for XML Web Services (JAX-WS). Chapter 10 defines web services as "application programming interfaces that can be invoked remotely" and that "can be invoked from clients written in any programming language."

Chapter 10 describes using JAX-WS to develop web services, to develop clients of web services, to add attachments to web services calls, to expose EJBs as web services, and to secure web services. The chapter looks at WSDLs and generating Java from WSDLs using GlassFish's wsimport.

Chapter 11: Developing RESTful Web Services with JAX-RS

The final chapter of Java EE 7 with GlassFish 4 Application Server covers REST-based web services support in Java EE as provided by Java API for RESTful Web Services (JAX-RS). Although this was originally added to enterprise Java with Java EE 6, Java EE 7 introduces JAX-RS 2.0.

Chapter 11 introduces REST and covers basic support for REST-based web services that was added with Java EE 6. This discussion covers basic JAX-RS annotations, using GlassFish logs to analyze working functionality, using curl as a client, and using JAXB for Java/XML binding. The chapter then moves onto discussion of Java EE 7's introduction of "a standard client-side API that we can use to easily develop RESTful web service clients." The chapter concludes with a discussion on query parameters and path parameters (@QueryParam and @PathParam).

Other Observations
  • Java EE 7 with GlassFish 4 Application Server liberally uses full color (in the PDF version I reviewed) screen snapshots that have sufficient resolution to be easy on the eyes and to nicely illustrate the concepts. This was particularly the case in the first chapter on installing and configuring GlassFish 4 and in other chapters dealing with the GlassFish web admin console.
  • I like that Java EE 7 with GlassFish 4 Application Server includes code examples that not only illustrate the points being made, but also include common and useful third-party libraries.
  • Heffelfinger has written other Packt Publishing books on J2EE/Java EE topics and portions of those books are the same across the books. For example, portions of Java EE 7 with GlassFish 4 Application Server are also available in Enterprise JavaBeans, Java EE 5 Development using GlassFish Application Server, and Java EE 6 with GlassFish 3 Application Server. Indeed, Java EE 7 with GlassFish 4 Application Server can be viewed as the third edition of the latter two of those books (it says as much by stating that it was "first published" in October 2007, had a "Second Edition" in July 2010, and the "Third Edition" in March 2014). Much of the Java EE and GlassFish content is the same with this edition adding in Java EE 7 new features and GlassFish 4 coverage. As a third edition, this book is as polished as one expects third editions to be.
  • Although Java EE 7 with GlassFish 4 Application Server explicitly covers GlassFish 4, there is not much that I can see in Java EE 7 with GlassFish 4 Application Server that is unique to GlassFish 4 other than its support for the newly added Java EE 7 specifications. The book is really more focused on Java EE in general and Java EE 7 in particular with GlassFish as the Java EE implementation used to demonstrate the examples. This is a great book for someone wanting to learn new Java EE 7 features and for someone wanting to learn how to use basic GlassFish features in Java EE development. The majority of GlassFish 4's new features are implementations of the new Java EE 7 specifications, so it's not surprising that the differences in this edition are more about Java EE 7 than about GlassFish 4.
  • Java EE 7 with GlassFish 4 Application Server's coverage of Java EE 7 covers it cumulatively rather than covering only features new to Java EE with Java EE 7.
Conclusion

Java EE 7 with GlassFish 4 Application Server provides a polished presentation of Java EE as it stands today with its recently included Java EE 7 specifications. GlassFish 4 is the application server used to demonstrate these Java EE concepts.