Tuesday, February 28, 2012

Viewing JavaFX 2 Standard Colors

The JavaFX 2 class javafx.scene.paint.Color includes several fields that are static Color members. I have taken advantage of the convenience of these publicly available static fields in many of my JavaFX 2 examples shown in this blog. There is a lengthy list of these predefined Color fields ranging (in alphabetical order) from Color.ALICEBLUE to Color.YELLOWGREEN. I have sometimes thought it would be nice to quickly see what some of the less obvious colors look like and the simple JavaFX 2 application featured in this post provides a sampling of those colors.

The sample JavaFX 2 application shown here uses simple Java reflection to introspect the JavaFX Color class for its public fields that themselves of type Color. The application then iterates over those public fields, providing information about each color such as the color's field name, a sample of the color, and the red/green/blue components of that color.

The final row allows the user to specify red/green/blue values to see how such a color is rendered. This is useful if the user sees a standard color that is close to what he or she wants and the user wants to try adjusting it slightly. To ensure meaningful values for displaying a color based on provided red/green/blue values, the application ensures that entered values are treated as doubles between 0.0 and 1.0 even if they are not numbers or are numbers outside of that range.

The simple JavaFX 2 application showing standard Color fields is shown in the next code listing.

JavaFxColorDemo.java
package dustin.examples;

import static java.lang.System.err;
import java.lang.reflect.Field;
import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Pane;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.scene.shape.RectangleBuilder;
import javafx.stage.Stage;

/**
 * Simple JavaFX 2 application that prints out values of standardly available
 * Color fields.
 * 
 * @author Dustin
 */
public class JavaFxColorDemo extends Application
{
   /** Width of label for colorn name. */
   private final static int COLOR_NAME_WIDTH = 150;
   /** Width of rectangle that displays color. */
   private final static int COLOR_RECT_WIDTH = 50;
   /** Height of rectangle that displays color. */
   private final static int COLOR_RECT_HEIGHT = 25;

   private final TextField redField = TextFieldBuilder.create()
      .text("Red Value").build();
   private final TextField greenField = TextFieldBuilder.create()
      .text("Green Value").build();
   private final TextField blueField = TextFieldBuilder.create()
      .text("Blue Value").build();
   private final Rectangle customColorRectangle = RectangleBuilder.create()
      .width(COLOR_RECT_WIDTH).height(COLOR_RECT_HEIGHT)
      .fill(Color.WHITE).stroke(Color.BLACK).build();

   /**
    * Build a pane containing details about the instance of Color provided.
    * 
    * @param color Instance of Color about which generated Pane should describe.
    * @return Pane representing information on provided Color instance.
    */
   private Pane buildColorBox(final Color color, final String colorName)
   {
      final HBox colorBox = new HBox();
      final Label colorNameLabel = new Label(colorName);
      colorNameLabel.setMinWidth(COLOR_NAME_WIDTH);
      colorBox.getChildren().add(colorNameLabel);
      final Rectangle colorRectangle = new Rectangle(COLOR_RECT_WIDTH, COLOR_RECT_HEIGHT);
      colorRectangle.setFill(color);
      colorRectangle.setStroke(Color.BLACK);
      colorBox.getChildren().add(colorRectangle);
      final String rgbString =
           String.valueOf(color.getRed())
         + " / " + String.valueOf(color.getGreen())
         + " / " + String.valueOf(color.getBlue())
         + " // " + String.valueOf(color.getOpacity());
      final Label rgbLabel = new Label(rgbString);
      rgbLabel.setTooltip(new Tooltip("Red / Green / Blue // Opacity"));
      colorBox.getChildren().add(rgbLabel);
      return colorBox;
   }

   /**
    * Extracts a double between 0.0 and 1.0 inclusive from the provided String.
    * 
    * @param colorString String from which a double is extracted.
    * @return Double between 0.0 and 1.0 inclusive based on provided String;
    *    will be 0.0 if provided String cannot be parsed.
    */
   private double extractValidColor(final String colorString)
   {
      double colorValue = 0.0;
      try
      {
         colorValue = Double.valueOf(colorString);
      }
      catch (Exception exception)
      {
         colorValue = 0.0;
         err.println("Treating '" + colorString + "' as " + colorValue);
      }
      finally
      {
         if (colorValue < 0)
         {
            colorValue = 0.0;
            err.println("Treating '" + colorString + "' as " + colorValue);
         }
         else if (colorValue > 1)
         {
            colorValue = 1.0;
            err.println("Treating '" + colorString + "' as " + colorValue);
         }
      }
      return colorValue;
   }

   /**
    * Build pane with ability to specify own RGB values and see color.
    * 
    * @return Pane with ability to specify colors.
    */
   private Pane buildCustomColorPane()
   {
      final HBox customBox = new HBox();
      final Button button = new Button("Display Color");
      button.setPrefWidth(COLOR_NAME_WIDTH);
      button.setOnMouseClicked(new EventHandler<MouseEvent>()
      {
         @Override
         public void handle(MouseEvent t)
         {
            final Color customColor =
               new Color(extractValidColor(redField.getText()),
                         extractValidColor(greenField.getText()),
                         extractValidColor(blueField.getText()),
                         1.0);
            customColorRectangle.setFill(customColor);
         }
      });
      customBox.getChildren().add(button);
      customBox.getChildren().add(this.customColorRectangle);
      customBox.getChildren().add(this.redField);
      customBox.getChildren().add(this.greenField);
      customBox.getChildren().add(this.blueField);
      return customBox;
   }

   /**
    * Build the main pane indicating JavaFX 2's pre-defined Color instances.
    * 
    * @return Pane containing JavaFX 2's pre-defined Color instances.
    */
   private Pane buildColorsPane()
   {
      final VBox colorsPane = new VBox();
      final Field[] fields = Color.class.getFields(); // only want public
      for (final Field field : fields)
      {
         if (field.getType() == Color.class)
         {
            try
            {
               final Color color = (Color) field.get(null);
               final String colorName = field.getName();
               colorsPane.getChildren().add(buildColorBox(color, colorName));
            }
            catch (IllegalAccessException illegalAccessEx)
            {
               err.println(
                  "Securty Manager does not allow access of field '"
                  + field.getName() + "'.");
            }
         }
      }
      colorsPane.getChildren().add(buildCustomColorPane());
      return colorsPane;
   }

   /**
    * Start method overridden from parent Application class.
    * 
    * @param stage Primary stage.
    * @throws Exception JavaFX application exception.
    */
   @Override
   public void start(final Stage stage) throws Exception
   {
      final Group rootGroup = new Group();
      final Scene scene = new Scene(rootGroup, 700, 725, Color.WHITE);
      final ScrollPane scrollPane = new ScrollPane();
      scrollPane.setPrefWidth(scene.getWidth());
      scrollPane.setPrefHeight(scene.getHeight());
      scrollPane.setContent(buildColorsPane());
      rootGroup.getChildren().add(scrollPane);
      stage.setScene(scene);
      stage.setTitle("JavaFX Standard Colors Demonstration");
      stage.show();
   }

   /**
    * Main function for running JavaFX application.
    * 
    * @param arguments Command-line arguments; none expected.
    */
   public static void main(final String[] arguments)
   {
      Application.launch(arguments);
   }
}

The snapshots shown next demonstrate this simple application. The first snapshot shows the application after loading. The second snapshot shows the application after scrolling down to the bottom and demonstrates use of the Tooltip and of the TextField.setPrompt(String) method. The third image shows the results of providing red/green/blue values and clicking on the button to see the corresponding color.

The simple JavaFX 2 application shown in this post makes it easy to get an idea of what colors are available as standard JavaFX 2 public static Color fields. It also allows one to enter red/green/blue values that might be provided to the Color constructor to obtain an instance of Color.

Monday, February 27, 2012

Late February 2012 Software Development Links of Interest

This post summarizes and provides links to some online resources related to software development that have recently captured my attention. Topics include Linux, DevOps, dynamic typing versus static typing, abstraction versus simplicity, and cloud computing.

Linux

Several posts on Linux have recently captured my interest. The post 10 free Linux e-books provides a list of ten freely available Linux books. Each book is featured with an image of its cover along with a brief description and a link to the electronic version of the book. Titles include Advanced Linux Programming (2001), Java Application Development on Linux (2005), and Linux Network Administrator's Guide, 2nd Edition (2000). One of the free referenced electronic Linux titles is The Linux Command Line: A Complete Introduction, a book that receives rave reviews from Peter N. M. Hansteen in yesterday's post The Linux Command Line Is A Very Appealing Story. The Linux Command Line has tremendous breadth, covering topics ranging from use of vi, to shell scripting to basic Linux commands. Speaking of Linux commands, the post Linux Command Line Tips that Every Linux User Should Know provides an interesting summary of Linux command-line commands.

DevOps

I remain uncommitted to the long-term value of the DevOps movement, but have certainly not made up my mind for good yet and am waiting it out to see if more substance comes from it. For example, even though I've tangentially touched on DevOps before, I still have not made a "Label" for it to mark my blog posts that cover the topic. Edward Capriolo's post DevOps has no chance is not on the fence about the subject. The post concludes with a point that I think's worth considering: "It is a left brain right brain thing. The qualities that make a good dev usually make a terrible ops person and vice versa. The world is ok that way."

Dynamic Typing

As software developers, we cannot seem to help ourselves and must continue the debate about whether static or dynamic typing is best. I've found advantages to both (that most realistic and fair developers will acknowledge), so it truly is a case of what best fits the particular task at hand as well as the task's surrounding development environment. As a general rule of thumb, I prefer dynamic typing for small efforts, especially scripting, but begin favoring static typing as a program gets larger and more people are involved. It sounds bad, but in essence I prefer static typing when I cannot trust "the other person" (which may be myself on a large enough code base). In Why I don’t like Dynamic Typing, John Mount states, "I find the pain of having to type or read through extra declarations is small (especially if you know how to copy-paste or use a modern IDE). And certainly much smaller than the pain of the dynamic language driven anti-patterns of: lurking bugs, harder debugging and more difficult maintenance. ... Initial coding is not the only phase of the software lifecycle." Mount appropriately recognizes that "there is, of course, no prior reason anybody should immediately care if I do or do not like dynamic typing," but offers some valid arguments for static typing (just as Martin Fowler has offered for dynamic typing). The reddit/programming comments/responses are a reminder that if you want a blog post to get attention, write about static typing versus dynamic typing.

Too Much Abstraction

Several experienced colleagues and I have been discussion off and on over recent months the seeming over-abstraction we've seen in certain frameworks and in code bases we've been exposed to. In the post Peak Abstraction, Tom Hammersley hits on this topic. Hammersley has done a nice job of articulating how this is especially likely to happen with a developer who is no longer new, but has not yet learned some hard lessons from more experience: "There is a common pattern. It typically occurs after 3-4 years of professional practice. A programmer is growing in his confidence. He begins to tackle more complex, challenging problems. And, he reflects those problems with complex, challenging data structures. He has not yet learnt the fine art of simplicity." Simplicity is often recognized as a desirable virtue in software development, but it is all too easy to become enamored with excessive abstraction, especially when one sees abstraction replied layer upon layer frequently in so many other aspects of software.

Anticipating Cloud Failures

In my summary of 2012 software development developments, I talked about the continuing prevalence of cloud computing in software development literature and also highlighted cloud failures in 2011 in the "honorable mention" list. The post New Year, New Security Breach; Three Potential Cloud Provider ‘Screw Ups’ to Watch cites 3 big screw-ups you can expect from cloud providers in 2012, which lists three expected cloud provider blunders in 2012: security, migration cost, and performance. The "New Year, New Security Breach" post also provides an interesting "Security Breach Timeline" for 2011.

Conclusion

There is a lot going on in the world of software development and the posts referenced above provide a very small taste of what's going on out there in the blogosphere.

Saturday, February 25, 2012

Book Review: Java Reflection in Action

The book Java Reflection in Action was published in 2004, but remains largely applicable eight years later. In this post, I review this book and cover its strengths and its weaknesses. In general, age is the common theme of most of its weaknesses, but I was surprised at how relevant its information still is. The book was written when JDK 1.4 was the commonly used release of Java and J2SE 5 was well on its way (released late September 2004). Given this relative timing, it's obvious that where this book suffers is in coverage of reflection-related features made available after the release of JDK 1.4.

Java reflection is a topic that most Java developers use on a daily basis, either directly or indirectly via popular frameworks and libraries that make use of reflection. However, it is probably true that many of us could use reflection to good effect in even more ways. For example, I have found reflection to be useful in writing Groovy scripts to manage Java application development.

Java Reflection in Action is written by the father/son team of Ira R. Forman and Nate Forman. It consists of ten chapters and is under 300 pages long. It's a quick read and one can understand the basics of Java reflection after reading only the first three chapters.

Chapter One ("A few basics"), Chapter Two ("Accessing fields reflectively"), and Chapter Three ("Dynamic loading and reflective construction") cover the basics of Java reflection. The contents of these three chapters are what most people probably expect in a book on Java reflection. Reading these three chapters alone provides the Java developer with the basics of Java reflection, including the advantages and some pitfalls of using reflection. These chapters provide detailed coverage of the most important reflection APIs and focus on constructing instances of Java classes and introspecting method and field information.

Early pages of Java Reflection in Action provide nice reflection-oriented definitions. For example, reflection is defined as "the ability of a running program to examine itself and its software environment, and to change what it does depending on what it finds" (p. 3). Introspection is defined as "reflective features that allow a program to examine itself" (p. 7) and metaobjects are defined as "objects that are part of a program's self-representation" (p. 9).

Chapter Four ("Using Java's dynamic proxy") is devoted to coverage of Java's dynamic proxies. This chapter states that java.lang.reflect.Proxy is "Java's only way of approximating method invocation intercession." The chapter defines intercession as "any reflective ability that modifies the behavior of the program by directly taking control of that behavior." This is one of the best treatments of dynamic proxies that I've seen.

Chapter Five ("Call stack introspection") covers use of StackTraceElement to provide introspection capabilities against the call stack (feature available since JDK 1.4). The authors point out that this is an approach for performing introspection on "execution state of the running application" (versus much of the commonly considered reflection that focuses on introspection of structure). The authors demonstrate accessing these stack trace elements via the Throwable.getStackTrace() call. Although this is still the approach for acquiring a stack's elements recommended in the Javadoc documentation for StackTraceElement, I prefer using Thread.getStackTrace() approach (see my blog post The Surprisingly Simple StackTraceElement), which was not made available until J2SE 5.

Chapter Six ("Using the class loader") provides nice coverage of Java class loaders. This is another subject that Java developers frequently run into directly and indirectly. The chapter provides a nice introduction to class loading in Java. Section 6.3 ("Multiple namespaces") provides information on a subject that Java developers definitely need to be aware of even when only using class loaders indirectly. This section explains that "a class object in the virtual machine is actually identified by both its fully qualified name and defining loader" (I added the emphasis).

Chapter Seven ("Reflective code generation") and Chapter Eight ("Design patterns") discuss using reflection capabilities to generate code. Specifically these chapters focus on using reflective capabilities to transform source classes into target classes. Specific design patterns applied to new classes that are implemented via transformation from existing source via reflective capabilities.

The Reflection API Trail of the Java Tutorials warns of "performance overhead" in its list of "reflection drawbacks." Chapter Nine ("Evaluating performance") of Java Reflection in Action addresses real and perceived performance issues related to reflection. Perhaps more importantly, the chapter provides ideas and issues related to the notoriously difficult application of micro-benchmarking. Besides covering micro-benchmarking itself, this chapter also introduces Amdahl's Law and reinforces use of proxies.

The first paragraph of the "Summary" of Chapter 10 made me think again about some of my preconceptions about Java reflection performance. This paragraph states (pp. 223-224):

Runtime performance is often cited as a disadvantage that renders reflection APIs impractical. Don't be taken in by this argument. Reflection is not slow! Over the first 50 years of software engineering, similar arguments were made against the move to high-level languages, against the move to virtual memory, against the move to object-oriented programming, and, most recently, against the move to garbage collection.

Chapter Ten ("Reflecting on the future") is, not surprisingly, the chapter made most obsolescent by the passage of time. Hindsight being 20/20, it is easy to see things missed in the Formans' predictions and speculation for the future of Java reflection. However, when one remembers that the book was published in 2004 before the general release of J2SE 5, this chapter's obsolescence is easily understood. The chapter specifically discusses the impact on reflection of several J2SE features we are now use regularly such as annotations, generics, and JSR 201 language extensions (Enums, for-each loop, static imports, and the cursed [my words] autoboxing). The chapter talks about other languages' likely advancements in reflection capabilities and provides a very brief introduction to aspect-oriented programming.

Java Reflection in Action packs a lot of information into its three appendices. Appendix A is the largest of the three and provides a description of "reflection and metaobject protocols and the relationship between the two." There is a two-page appendix devoted to basic UML (which is applied several times within the book) as well as appendix covering possible compilation problems of one of the book's basic code generation examples on certain operating systems versions.

Java Reflection in Action includes a lengthy list of authoritative references (nearly 100) for additional reading related to the topics covered in the book. It also provides a short glossary of key terms in reflection.

One of the book's most practical positive features is its supplying of a small set of static Java functions for making reflection tasks easier. Provided as part of the often referenced Mopex class (in the mopex package), this code is available for download from the Manning site for the book. The Mopex's class-level documentation describes the class: "This class provides a set of static methods that extend the Java metaobject protocol." The downloaded code samples include many more classes and code definitions used in the book as well.

Conclusion

Java Reflection in Action provides a thorough introduction to Java reflection. It features many positive aspects and its main negative aspect is its age (2004/JDK 1.4). Because versions of Java since JDK 1.4 have supplemented more than replaced reflective features, most of the book's content still applies today. Perhaps the most glaring omission from a book on Java reflection is Java 7's introduction of method handles, but few Java books in print today cover these.

Wednesday, February 22, 2012

A Plethora of Java Developments in February 2012

There are several sites (Java.net, JavaWorld, JavaLobby/DZone, Java reddit, and Java Code Geeks) that I like to browse for the latest Java news. These sites are great and bring the best from around the web from the wider Java community. A nice complement to these sites is Oracle Technology Network's Java page. There are several Java stories available on the OTN Java page that originate from Oracle and its employees that are of interest to Java developers. I briefly summarize and link to a subset of these in this blog post.

New Java Language and Java VM Specifications

Alex Buckley's post JLS7 and JVMS7 online announces the availability of new versions of the Java Language Specification and of the Java Virtual Machine Specification. Besides announcing the availability of these new specifications associated explicitly with Java SE 7, the post also provides some interesting background regarding the history of these two specifications. For example, Buckley states, "Only a major Java SE release can change the Java language and JVM." I also find it interesting that these specifications no longer have names based on their edition (was Third Edition for JLS and Second Edition for JVMS). Instead, these two specifications are now named for the edition of Java SE they are associated with. To me, that's much clearer. You may wonder why this wasn't done in the first place and Buckley explains that, "Historically, the JLS and JVMS pre-date the Java Community Process so there was no Java SE platform to which they could be tied." The specifications are available in HTML or PDF format and it is anticipated that they will be published in printed book format in the future.

Java SE 6 End of Life Extended

Henrik Stahl uses the post Updated Java 6 EOL date to announce that the JDK6 "EOL date has been extended from July 2012 to November 2012, to allow some more time for the transition to JDK 7." He also highlights portions of the updated EOL policy. The Oracle Java SE Support Roadmap (AKA "Java SE EOL Policy") was updated on 15 February 2012 with this new EOL date.

New Java Updates

The Java SE News blog contains posts regarding newly available Java updates. The titles of the posts say it all: Java 7 Update 3 and Java 6 Update 31 have released!, 7u4 Developer Preview is now Available, and 6u32 Developer Preview is now Available.

JSR 354: Money and Currency API

The JCP Program Office blog features a post announcing JSR 354: Money and Currency API. This JSR proposal describes deficiencies with the already available java.util.Currency class that will be addressed by the JSR. The "proposed Specification" section states:

This JSR will provide a money and currency API for Java, targeted at all users of currencies and monetary amounts in Java. The API will provide support for standard ISO-4217 and custom currencies, and a representation of a monetary amount. It will support currency arithmetic, even across different currencies, and will support foreign currency exchange. Additionally, implementation details surrounding serialization and thread safety are to be considered.

It sounds like there is some optimism about this making it into Java SE 8.

JavaFX 2 Developer Community

Nicolas Lorain writes in JavaFX 2 and the developer community that "JavaFX 2 was only released in October 2011, but there's already a thriving developer community kicking the tires of the new kid on the block." He adds, "There's no denying that we've pretty much started from scratch with JavaFX 2." Lorain then provides evidence of the growing JavaFX 2 community that includes increasing number of discussion threads on the JavaFX 2.0 and Later forum, the developer community contributing roughly 20% of the bug reports related to JavaFX, an "increasing number of people interested in JavaFX are following me" (@javafx4you), and number of community blog posts on JavaFX (references JavaFX Links of the Week). Lorain concludes, "pretty much all the [metrics] I've seen show that JavaFX is growing in terms of popularity."

Incidentally, one of the co-authors of Pro JavaFX 2: A Definitive Guide to Rich Clients with Java Technology has provided some details about that book which will soon be in print and is already available in electronic format.

Conclusion

The Java development community seems more lively and more energetic in recent months (especially since JavaOne 2011) than it has been for years. After years of seeming stagnation, Java-related developments appear to be coming at us more quickly again. It is nice to have so many online forums to get information about these developments.

Monday, February 20, 2012

JavaFX 2: Simultaneous Animated Text Strings

I decided to have a simple JavaFX 2 animated sample running as attendees entered the room for my RMOUG Training Days 2012 presentation. The desired result was achieved as attendees asked if how the running application was implemented. More than one person was surprised that it was implemented in "pure Java" without Flash or HTML5. I provide the source code for this simple example along with some screen snapshots in this post. Along the way, the example demonstrates animating multiple instances of Text along a path simultaneously.

I have previously blogged about animating along a predefined path using PathTransition. I have adapted that example into this new example by changing the moving Shape from a Circle to a Text "shape" and by having three of these "shapes" move along the path simultaneously via ParallelTransition.

To add a little extra to the demonstration, I have also made use of JavaFX effects, font sizing and specification, and character coloring in this example. The code listing for the entire simple demonstrative sample is shown next.

RmougTd2012Animation.java
package dustin.examples;

import javafx.animation.ParallelTransition;
import javafx.animation.PathTransition;
import javafx.animation.PathTransition.OrientationType;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.effect.Glow;
import javafx.scene.effect.Reflection;
import javafx.scene.paint.Color;
import javafx.scene.shape.CubicCurveTo;
import javafx.scene.shape.MoveTo;
import javafx.scene.shape.Path;
import javafx.scene.shape.Shape;
import javafx.scene.text.Font;
import javafx.scene.text.Text;
import javafx.scene.text.TextBuilder;
import javafx.stage.Stage;
import javafx.util.Duration;

/**
 * Simple animation of labels related to RMOUG Training Days 2012 using JavaFX.
 * 
 * @author Dustin
 */
public class RmougTd2012Animation extends Application
{
   /**
    * Generate Path upon which animation will occur.
    * 
    * @return Generated path.
    */
   private Path generateCurvyPath()
   {
      final Path path = new Path();
      path.getElements().add(new MoveTo(70,20));
      path.getElements().add(new CubicCurveTo(430, 0, 430, 120, 250, 120));
      path.getElements().add(new CubicCurveTo(50, 120, 50, 240, 430, 240));
      path.setOpacity(0.0);
      return path;
   }

   /**
    * Generate the path transition.
    * 
    * @param shape Shape to travel along path.
    * @param path Path to be traveled upon.
    * @param duration Duration of single animation.
    * @param delay Delay before beginning first animation.
    * @param orientation Orientation of shape during animation.
    * @return PathTransition.
    */
   private PathTransition generatePathTransition(
      final Shape shape, final Path path,
      final Duration duration, final Duration delay,
      final OrientationType orientation)
   {
      final PathTransition pathTransition = new PathTransition();
      pathTransition.setDuration(duration);
      pathTransition.setDelay(delay);
      pathTransition.setPath(path);
      pathTransition.setNode(shape);
      pathTransition.setOrientation(orientation);
      pathTransition.setCycleCount(Timeline.INDEFINITE);
      pathTransition.setAutoReverse(true);
      return pathTransition;
   }

   /**
    * Generate RMOUG text string with appropriate fill, font, and effect.
    * 
    * @return "RMOUG" text string with fill, font, and effect.
    */
   private Text generateRmougText()
   {
      return TextBuilder.create().text("RMOUG").x(20).y(20).fill(Color.DARKGRAY)
                        .font(Font.font(java.awt.Font.SERIF, 75))
                        .effect(new Glow(0.25)).build();
   }

   /**
    * Generate "Training Days 2012" text string with appropriate position, fill,
    * and font.
    * 
    * @return "Training Days 2012" with specified font, fill, and position.
    */
   private Text generateTrainingDaysText()
   {
      return TextBuilder.create().text("Training Days 2012")
                        .x(380).y(240).fill(Color.DARKOLIVEGREEN)
                        .font(Font.font(java.awt.Font.SERIF, 50)).build();
   }

   /**
    * Location String with specifed effect, font, and position.
    * 
    * @return Location String with specified effect, font, and position.
    */
   private Text generateDenverText()
   {
      final Reflection reflection = new Reflection();
      reflection.setFraction(1.0);
      return TextBuilder.create()
                        .text("Denver, Colorado").x(20).y(20)
                        .font(Font.font(java.awt.Font.SANS_SERIF, 25))
                        .effect(reflection)
                        .build();
   }

   /**
    * Apply animation.
    *  
    * @param group Group to which animation is to be applied.
    */
   private void applyAnimation(final Group group)
   {
      final Path path = generateCurvyPath();
      group.getChildren().add(path);
      final Shape rmoug = generateRmougText();
      group.getChildren().add(rmoug);
      final Shape td = generateTrainingDaysText();
      group.getChildren().add(td);
      final Shape denver = generateDenverText();
      group.getChildren().add(denver);
      final PathTransition rmougTransition =
         generatePathTransition(
            rmoug, path, Duration.seconds(8.0), Duration.seconds(0.5),
            OrientationType.NONE);
      final PathTransition tdTransition =
         generatePathTransition(
            td, path, Duration.seconds(5.5), Duration.seconds(0.1),
            OrientationType.NONE);
      final PathTransition denverTransition =
         generatePathTransition(
            denver, path, Duration.seconds(30), Duration.seconds(3),
            OrientationType.ORTHOGONAL_TO_TANGENT);
      final ParallelTransition parallelTransition =
         new ParallelTransition(rmougTransition, tdTransition, denverTransition);
      parallelTransition.play(); 
   }

   /**
    * JavaFX Application starting method.
    * 
    * @param stage Primary stage.
    * @throws Exception Potential JavaFX application exception.
    */
   @Override
   public void start(Stage stage) throws Exception
   {
      final Group rootGroup = new Group();
      final Scene scene = new Scene(rootGroup, 500, 400, Color.GHOSTWHITE);
      stage.setScene(scene);
      stage.setTitle("JavaFX 2 RMOUG Training Days 2012 Animations");
      stage.show();
      applyAnimation(rootGroup);
   }

   /**
    * Main function for running JavaFX animation demo.
    * 
    * @param arguments Command-line arguments; none expected.
    */
   public static void main(final String[] arguments)
   {
      Application.launch(arguments);
   }
}

The next series of screen snapshots attempt to provide an idea of how this appears when it is executed.

This example demonstrates that text can be animated along a path and it also demonstrates the difference between OrientationType types NONE and ORTHOGONAL_TO_TANGENT. The former orientation specification has the text facing upwards from an absolutist point of view while the latter shifts the text's direction according to the twists and turns of the path. The Javadoc for each type provides more precise explanation where NONE is defined as "The targeted node's rotation matrix stays unchange along the geometric path" while ORTHOGONAL_TO_TANGENT is defined as "The targeted node's rotation matrix is set to keep node perpendicular to the path's tangent along the geometric path."

For me, the more interesting part of this example is how easy it is to specify multiple animations be run in parallel. As the applyAnimation method of the sample code shows, three text Strings are associated with three distinct PathTransition instances. Although each of these three instances of PathTransition uses the same Path, the start time and duration time of each transition differs. None of the PathTransition instances have their individual play() methods called. Rather, each is associated with a single ParallelTransition instance and it is that ParallelTransition instance's play() method that is invoked. Because the three instances of PathTransition were associated with the instance of ParallelTransition, invoking play() on it invokes play() on all three individual PathTransition instances in parallel.

Conclusion

JavaFX 2 makes it easy to perform multiple transitions in parallel. One simply sets up each individual transition in a preferred manner and then associates each of these transitions with an instance of ParallelTransition and invokes the play() method on that instance of ParallelTransition. Animation is not limited to shapes, but can be used on text as well.

Saturday, February 18, 2012

Questions at My RMOUG Training Days 2012 Presentation on JavaFX 2

I presented "JavaFX 2.0: Java in the Rich Internet Application Space" at RMOUG Training Days 2012 earlier this week. After many years of presenting at technical conferences, I've decided that one of the best indicators of how well I did in my presentation is the types of questions I get from attendees. If I get no questions, it is more likely that I've confused, lost, or bored people than that I covered all possible questions. If I get really basic questions asking about things I already covered, it means I either messed that part of the presentation up or that I simply forgot to cover that thoroughly. When I get relevant questions that seem to pick up where my presentation left off or that demonstrate the attendee asking a question to apply what I've presented to an individual situation, I know that I've been able to provide what I had hoped to provide. The questions from attendees at my presentation this week fell into that last category. They were excellent questions.

In this post, I repeat (paraphrase) the questions (thanks Bill for recording them!) I was asked and provide answers to those questions. In most cases, I answer here pretty much the same way that I answered at the presentation (but with links here). One exception is my answer to the question about JavaFX 3D support, which has much more information provided in the answer in this post than I could provide at the presentation.

Q: What does JavaFX have for layout managers related to Swing and CSS?

One of the points I made in my presentation is that JavaFX 2 does a nice job of supporting industry standards such as Scalable Vector Graphics (SVG) and Cascading Style Sheets (CSS). An insightful attendee asked the question of whether JavaFX 2 uses Swing-like layout managers for layout or uses CSS for layout. My answer was that I had mostly seen (and had only used) JavaFX 2's layout panes for layout and I described these as akin to Swing's layout managers. I added that I have typically seen CSS used in JavaFX 2 applications for styling elements more than for layout purposes. CSS can be used to style many elements of the scene graph including nodes and even layouts. CSS can affect the layout panes by styling things such as padding and borders.

The document Working With Layouts in JavaFX (PDF) provides a nice introduction to JavaFX 2 layout techniques. JavaFX2.0 Layout: A Class Tour is another nice introduction to layout in JavaFX 2. Skinning JavaFX Applications with CSS (PDF) is a nice introduction to using CSS with JavaFX 2.

Q: What Does JavaFX Provide for Database Access?

With hindsight, I probably should have addressed JavaFX in context of database access at a conference that is heavily oriented to the Oracle Database. I suggested that because JavaFX is now "pure Java," it can easily be used with JDBC, favorite Java ORM tools (including JPA implementations), or other database-access goodies in alternative JVM languages such as Groovy.

I mentioned that the JavaFX community appears to be growing and its ecosystem is growing rapidly. I stated that I had just read this week about DataFX, "a project that intends to make retrieving, massaging, populating, viewing, and editing data in JavaFX UI controls easier." Although I have not used DataFX (currently at version 0.0.5), this may be something of interest for those wanting easier integration of data sources and JavaFX UI controls. The JavaOne 2011 slides for JavaFX Datasources: Getting Real-World Data into JavaFX Controls provide introductory details regarding DataFX.

Q: Will JavaFX become incorporated into ADF?

This question reminded my of a question that I too have had. Although I did not specifically wonder if Oracle would incorporate JavaFX into their Application Developer Framework, I have wondered if Oracle would incorporate JavaFX 2 into their products in general (believe they will) and into NetBeans (and NetBeans Rich Client Platform) in particular (less certain of this). I responded as such and said that I could only speculate, but that I hoped that they would incorporate JavaFX and gradually replace components that are heavily Swing-based with JavaFX. Given the statements at JavaOne 2011 regarding JavaFX essentially replacing Swing as the client-side UI technology, this would seem logical. It will obviously take quite some time to make this happen.

The post Oracle ADF and JavaFX demonstrates running "a JavaFX applet within an ADF application."

Q: Is there any out-of-box support for JavaFX 3D?

I mentioned in my slides that JavaFX 2 provides built-in and customizable 2D shapes. In response to the question related to JavaFX 2's 3D support, I responded that I wasn't aware of any existing JavaFX 2 API support for 3D graphics.

It appears that support for "3D primitives" has been anticipated for JavaFX 2.1. A Richard Bair podcast (Java Spotlight Episode 16) provides more information on the need to have Java 7 for applet (plugin) delivery changes to support Prism and 3D more fully. Under the section titled "New Features Proposed for JavaFX," the JavaFX 2 Roadmap has a sub-section called "3D Graphics Support" that states, "JavaFX will feature support for 3D graphics that can be leveraged for modern forms of data visualization and advanced user experience."

In addition, there are some other common practices for achieving 3D effects in JavaFX 2.0. These include use of Java 3D and using 2D shapes with creative animation to simulate 3D effects. Other good online resources related to JavaFX and 3D support (which JavaFX 1.x had) include 3D with JavaFX, Java 3D™ meets JavaFX™, 3D Capabilities in JavaFX 1.3 Release, JavaFX 2.0 for 3D Website, and Early reports on JavaFX 2 are in.

More JavaFX 2 Recent News

Because this is a JavaFX-oriented post, it seems appropriate to include references to some new online JavaFX content. Jonathan Giles announced that More of the JavaFX Scenegraph open sourced and he references specifically javafx-ui-common in the OpenJFX project.

The Apress page for the forthcoming book Pro JavaFX 2: A Definitive Guide to Rich Clients with Java Technology now states the publication date of this book as 7 March 2012. The Java-Buddy blog is featuring a series of numerous blog posts with simple JavaFX 2.0 examples and demonstrations.

Conclusion

I appreciated the great questions from attendees at my JavaFX 2 presentation at RMOUG Training Days 2012. They were such great questions that I thought it worth writing this post to summarize those questions and my best answers for those questions. I'm looking forward to the imminent release of Pro JavaFX 2 and am happy to see more of JavaFX open sourced and to see more JavaFX code examples online.

Saturday, February 11, 2012

JSF Open Source Throwdown

Optimus Prime's post IceFaces Copies PrimeFaces Line by Line and Brian McKinney's response (New ACE Component Origins) have led to a controversial discussion on the blogosphere regarding legalities and ethics in an open source context. It is interesting to read the perspectives of those associated with PrimeFaces, the perspectives of those associated with ICEfaces, and the community reaction (and here).

Although I tend not to use JavaServer Faces, I have still found the general discussion interesting because the points and counterpoints being made could apply to any open source development projects. Perspectives on what is legal, what is ethical, and what is morale in open source appear to differ greatly among users of these products. Some people think that everything that has been done is legal and ethical. Others believe it is legal but unethical and still others believe there may be copyright infringement even if there are no license issues.

There are numerous good points made in these online discussions that made me think more about the nature of open source. There is no question that there are numerous different perspectives on what's right and wrong in open source, but I'd like to see opinions from well-known open source advocates such as Simon Phipps and Richard Stallman on the matter.

This recent open source controversy is also a reminder of the importance of choosing the appropriate license for one's open source projects. There is always a tenuous balance between wanting to offer a very liberal license to increase adoption and wanting to protect one's work and get appropriate credit/attribution for that work. The Apache Software Foundation license is very friendly to other users, but in this case it seems it may be a little more liberal than the folks at PrimeFaces would have liked.

Monday, February 6, 2012

JavaFX 2 Animation: Path Transitions

One of the flashiest aspects of JavaFX 2 is its animation support. The insightful Creating Transitions and Timeline Animation in JavaFX covers using both Transitions and Timelines in JavaFX 2. In this blog post, I adapt an example provided in that tutorial to specifically demonstrate Path Transitions.

Example 2 ("Path Transition") shown in Creating Transitions and Timeline Animation in JavaFX demonstrates creating a Path with classes from the JavaFX 2 "shapes" package: javafx.scene.shape.Path, javafx.scene.shape.MoveTo, and javafx.scene.shape.CubicCurve. That example then demonstrates instantiation of a javafx.animation.PathTransition and applying an instantiated javafx.scene.shape.Rectangle to move along the created Path.

In my code listing below, I've made some slight changes to Example 2 in Creating Transitions and Timeline Animation in JavaFX. I have specifically changed the moving shape from a rectangle to a Circle, added two "end knobs" to the path as two separate circles, and added the ability to change the opacity of the path along with the animated circle moves. The nice side effect of using a zero opacity is that the path itself does not appear and it instead looks like the circle is moving along freely. I tried to break each major piece of this up into its own private method to make it easier to see the "chunks" of functionality.

JavaFxAnimations.java
package dustin.examples;

import java.util.List;
import javafx.animation.PathTransition;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.paint.Color;
import javafx.scene.shape.*;
import javafx.stage.Stage;
import javafx.util.Duration;

/**
 * Simple example demonstrating JavaFX animations.
 * 
 * Slightly adapted from Example 2 ("Path Transition") which is provided in
 * "Creating Transitions and Timeline Animation in JavaFX"
 * (http://docs.oracle.com/javafx/2.0/animations/jfxpub-animations.htm).
 * 
 * @author Dustin
 */
public class JavaFxAnimations extends Application
{
   /**
    * Generate Path upon which animation will occur.
    * 
    * @param pathOpacity The opacity of the path representation.
    * @return Generated path.
    */
   private Path generateCurvyPath(final double pathOpacity)
   {
      final Path path = new Path();
      path.getElements().add(new MoveTo(20,20));
      path.getElements().add(new CubicCurveTo(380, 0, 380, 120, 200, 120));
      path.getElements().add(new CubicCurveTo(0, 120, 0, 240, 380, 240));
      path.setOpacity(pathOpacity);
      return path;
   }

   /**
    * Generate the path transition.
    * 
    * @param shape Shape to travel along path.
    * @param path Path to be traveled upon.
    * @return PathTransition.
    */
   private PathTransition generatePathTransition(final Shape shape, final Path path)
   {
      final PathTransition pathTransition = new PathTransition();
      pathTransition.setDuration(Duration.seconds(8.0));
      pathTransition.setDelay(Duration.seconds(2.0));
      pathTransition.setPath(path);
      pathTransition.setNode(shape);
      pathTransition.setOrientation(PathTransition.OrientationType.ORTHOGONAL_TO_TANGENT);
      pathTransition.setCycleCount(Timeline.INDEFINITE);
      pathTransition.setAutoReverse(true);
      return pathTransition;
   }

   /**
    * Determine the path's opacity based on command-line argument if supplied
    * or zero by default if no numeric value provided.
    * 
    * @return Opacity to use for path.
    */
   private double determinePathOpacity()
   {
      final Parameters params = getParameters();
      final List<String> parameters = params.getRaw();
      double pathOpacity = 0.0;
      if (!parameters.isEmpty())
      {
         try
         {
            pathOpacity = Double.valueOf(parameters.get(0));
         }
         catch (NumberFormatException nfe)
         {
            pathOpacity = 0.0;
         }
      }
      return pathOpacity;
   }

   /**
    * Apply animation, the subject of this class.
    * 
    * @param group Group to which animation is applied.
    */
   private void applyAnimation(final Group group)
   {
      final Circle circle = new Circle(20, 20, 15);
      circle.setFill(Color.DARKRED);
      final Path path = generateCurvyPath(determinePathOpacity());
      group.getChildren().add(path);
      group.getChildren().add(circle);
      group.getChildren().add(new Circle(20, 20, 5));
      group.getChildren().add(new Circle(380, 240, 5));
      final PathTransition transition = generatePathTransition(circle, path);
      transition.play(); 
   }

   /**
    * Start the JavaFX application
    * 
    * @param stage Primary stage.
    * @throws Exception Exception thrown during application.
    */
   @Override
   public void start(final Stage stage) throws Exception
   {
      final Group rootGroup = new Group();
      final Scene scene = new Scene(rootGroup, 600, 400, Color.GHOSTWHITE);
      stage.setScene(scene);
      stage.setTitle("JavaFX 2 Animations");
      stage.show();
      applyAnimation(rootGroup);
   }

   /**
    * Main function for running JavaFX application.
    * 
    * @param arguments Command-line arguments; optional first argument is the
    *    opacity of the path to be displayed (0 effectively renders path
    *    invisible).
    */
   public static void main(final String[] arguments)
   {
      Application.launch(arguments);
   }
}

The following series of screen snapshots show this simple JavaFX animation example in action. They are listed in order of descending opacity (from 1.0 to 0.0).

Demonstration of Adapted PathTransition Example (Opacity 1.0)
Demonstration of Adapted PathTransition Example (Opacity 0.2)
Demonstration of Adapted PathTransition Example (Opacity 0.05)
Demonstration of Adapted PathTransition Example (Opacity 0.0)

Each of the above screen snapshots was taken after running the application with the specified command-line argument (1, 0.2, 0.05, and 0).

This adapted example has demonstrated using PathTransition to animate a node's movement along the prescribed path (I have blogged on use of Path and some of its alternatives before). Developers can implement their own derivative of Transition and there are other supplied transitions supported as well (such as FadeTransition, ParallelTransition, and SequentialTransition).

It is a straightforward process to quickly begin applying JavaFX 2 animation using the provided Transition classes.