Monday, January 31, 2011

Groovy, JMX, and the Attach API

One of the exciting new features of the (then Sun) HotSpot Java SE 6 release was support for the Attach API. The Attach API is "a Sun Microsystems extension that provides a mechanism to attach to a Java virtual machine." Tools such as JConsole and VisualVM "use the Attach API to attach to a target virtual machine and load its tool agent into that virtual machine." Custom Java and Groovy clients can likewise use the Attach API to monitor and manage JVMs.

There are several online resources that demonstrate Java client code that uses the Attach API. These include Daniel Fuchs's code listing for a JVMRuntimeClient, the "Setting up Monitoring and Management Programmatically" section of "Monitoring and Management Using JMX Technology," the Core Java Technology Tech Tip called "The Attach API," and the Javadoc API documentation for the class com.sun.tools.attach.VirtualMachine. These examples generally demonstrate using VirtualMachine.attach(String) to attach to the virtual machine based on its process ID in String form. This is generally followed by loading the appropriate agent with VirtualMachine.loadAgent(String), where the String parameter represents the path to the JAR file containing the agent. The VirtualMachine.detach() method can be called to detach from the previously attached JVM.

All of the previously mentioned examples demonstrate use of the Attach API from Java clients. In this post, I demonstrate use of the Attach API via Groovy. The three code listings that follow present three pieces of Groovy code but all work together as a single script. The main script is embodied in the Groovy file getJvmThreadInfo.groovy and is a simple script file that calls the other two Groovy script files (attachToVirtualMachine.groovy and displayMxBeanDerivedInfo.groovy) to attach to the virtual machine and to display details regarding that virtual machine via its MXBeans.

getJvmDetails.groovy
#!/usr/bin/env groovy
// getJvmDetails.groovy
//
// Main script for extracting JVM details via Attach API and JMX.
// Accepts single parameter which is the process ID (pid) of the Java application
// whose JVM is to be connected to.
//
import static attachToVirtualMachine.retrieveConnector
import static displayMxBeanDerivedInfo.*

def serverConnection = attachToVirtualMachine.retrieveServerConnection(args[0])

displayMxBeanDerivedInfo.displayThreadInfo(serverConnection)
displayMxBeanDerivedInfo.displayOperatingSystemInfo(serverConnection)
displayMxBeanDerivedInfo.displayRuntimeInfo(serverConnection)
displayMxBeanDerivedInfo.displayMemoryInfo(serverConnection)

attachToVirtualMachine.groovy
// attachToVirtualMachine.groovy
//
// Provide an MBeanServerConnection acquired via the Attach API.

import javax.management.MBeanServerConnection
import javax.management.remote.JMXConnector
import javax.management.remote.JMXConnectorFactory
import javax.management.remote.JMXServiceURL

import com.sun.tools.attach.VirtualMachine


/**
 * Provide an MBeanServerConnection based on the provided process ID (pid).
 *
 * @param pid Process ID of Java process for which MBeanServerConnection is
 *    desired.
 * @return MBeanServerConnection connecting to Java process identified by pid.
 */
def static MBeanServerConnection retrieveServerConnection(String pid)
{
   println "Get JMX Connector for pid ${pid}!"
   def connectorAddressStr = "com.sun.management.jmxremote.localConnectorAddress"
   def jmxUrl = retrieveUrlForPid(pid, connectorAddressStr)
   def jmxConnector = JMXConnectorFactory.connect(jmxUrl)
   return jmxConnector.getMBeanServerConnection()
}


/**
 * Provide JMX URL for attaching to the provided process ID (pid).
 *
 * @param @pid Process ID for which JMX URL is needed to connect.
 * @param @connectorAddressStr String for connecting.
 * @return JMX URL to communicating with Java process identified by pid.
 */
def static JMXServiceURL retrieveUrlForPid(String pid, String connectorAddressStr)
{
   // Attach to the target application's virtual machine
   def vm = VirtualMachine.attach(pid)

   // Obtain Connector Address
   def connectorAddress =
      vm.getAgentProperties().getProperty(connectorAddressStr)

   // Load Agent if no connector address is available
   if (connectorAddress == null)
   {
      def agent = vm.getSystemProperties().getProperty("java.home") +
          File.separator + "lib" + File.separator + "management-agent.jar"
      vm.loadAgent(agent)

      // agent is started, get the connector address
      connectorAddress =
         vm.getAgentProperties().getProperty(connectorAddressStr)
   }

   return new JMXServiceURL(connectorAddress);
}

displayMxBeanDerivedInfo.groovy
// displayMxBeanDerivedInfo.groovy
//
// Display details regarding attached virtual machine and associated MXBeans.

import java.lang.management.ManagementFactory
import java.lang.management.MemoryMXBean
import java.lang.management.OperatingSystemMXBean
import java.lang.management.RuntimeMXBean
import java.lang.management.ThreadMXBean
import javax.management.MBeanServerConnection

/**
 * Display thread information based on ThreadMXBean associated with the provided
 * MBeanServerConnection.
 *
 * @param server MBeanServerConnection to use for obtaining thread information
 *    via the ThreadMXBean.
 */
def static void displayThreadInfo(MBeanServerConnection server)
{
   def remoteThreadBean = ManagementFactory.newPlatformMXBeanProxy(
                             server,
                             ManagementFactory.THREAD_MXBEAN_NAME,
                             ThreadMXBean.class);

   println "Deadlocked Threads: ${remoteThreadBean.findDeadlockedThreads()}"
   println "Monitor Deadlocked Threads: ${remoteThreadBean.findMonitorDeadlockedThreads()}"
   println "Thread IDs: ${Arrays.toString(remoteThreadBean.getAllThreadIds())}"
   def threads = remoteThreadBean.dumpAllThreads(true, true);
   threads.each
   {
      println "\t${it.getThreadName()} (${it.getThreadId()}): ${it.getThreadState()}"
   }
}


/**
 * Display operating system information based on OperatingSystemMXBean associated
 * with the provided MBeanServerConnection.
 *
 * @param server MBeanServerConnection to use for obtaining operating system
 *    information via the OperatingSystemMXBean.
 */
def static void displayOperatingSystemInfo(MBeanServerConnection server)
{
   def osMxBean = ManagementFactory.newPlatformMXBeanProxy(
                     server,
                     ManagementFactory.OPERATING_SYSTEM_MXBEAN_NAME,
                     OperatingSystemMXBean.class)
   println "Architecture: ${osMxBean.getArch()}"
   println "Number of Processors: ${osMxBean.getAvailableProcessors()}"
   println "Name: ${osMxBean.getName()}"
   println "Version: ${osMxBean.getVersion()}"
   println "System Load Average: ${osMxBean.getSystemLoadAverage()}"
}


/**
 * Display operating system information based on RuntimeMXBean associated with
 * the provided MBeanServerConnection.
 *
 * @param server MBeanServerConnection to use for obtaining runtime information
 *    via the RuntimeMXBean.
 */
def static void displayRuntimeInfo(MBeanServerConnection server)
{
   def remoteRuntime = ManagementFactory.newPlatformMXBeanProxy(
                          server,
                          ManagementFactory.RUNTIME_MXBEAN_NAME,
                          RuntimeMXBean.class);

   println "Target Virtual Machine: ${remoteRuntime.getName()}"
   println "Uptime: ${remoteRuntime.getUptime()}"
   println "Classpath: ${remoteRuntime.getClassPath()}"
   println "Arguments: ${remoteRuntime.getInputArguments()}"
}


/**
 * Display operating system information based on MemoryMXBean associated with
 * the provided MBeanServerConnection.
 *
 * @param server MBeanServerConnection to use for obtaining memory information
 *    via the MemoryMXBean.
 */
def static void displayMemoryInfo(MBeanServerConnection server)
{
   def memoryMxBean = ManagementFactory.newPlatformMXBeanProxy(
                         server,
                         ManagementFactory.MEMORY_MXBEAN_NAME,
                         MemoryMXBean.class);
   println "HEAP Memory: ${memoryMxBean.getHeapMemoryUsage()}"
   println "Non-HEAP Memory: ${memoryMxBean.getNonHeapMemoryUsage()}"
}

The three Groovy code listings above together form a script that will use the Attach API to contact to an executing JVM without host or port specified and solely based on the provided process ID. The examples demonstrate use of several of the available MXBeans built into the virtual machine. Because it's Groovy, the code is somewhat more concise than its Java equivalent, especially because no checked exceptions must be explicitly handled and there is no need for explicit classes.

Much more could be done with the information provided via the Attach API and the MXBeans. For example, the Groovy script could be adjusted to persist some of the gathered details to build reports, Java mail could be used to alert individuals when memory constraints or other issues requiring notice occurred, and nearly anything else that can be done in Java could be added to these client scripts to make it easier to monitor and manage Java applications.

Running with the Attach API

The main implementation class of the Attach API, VirtualMachine, is located in the ${JAVA_HOME}\lib\tools.jar or %JAVA_HOME\lib\tools.jar JAR file included with the HotSpot SDK distribution. This file typically needs to be explicitly placed on the classpath of the Java client that uses the Attach API unless it is otherwise placed in a directory that is part of that inherent classpath. This is typically not required when using Groovy because it's normally already in Groovy's classpath. I briefly demonstrated this in the post Viewing Groovy Application's Classpath.

Conclusion

The Attach API makes it easier for the Java (or Groovy) developer to write clients that can communicate with, manage, and monitor Java processes. The Attach API provides the same benefits to the developer of custom JMX clients that JConsole and VisualVM leverage.

Saturday, January 29, 2011

Having the Last Word with Java and Groovy

For the past several months, I have been somewhat of a Groovy evangelist and have been touting the virtues of Groovy to Java developer colleagues. Recently, a colleague asked if Groovy has a slick way for extracting the last word from a sentence. My immediate answer was to use Java's String.split(String), split on a single space string (" "), and take the last element of the array returned from String.split(String). However, a quick perusal through the Groovy GDK documentation reminded me of the many alternatives available to the Groovy developer. In this post, I cover some of these different options.

The following Groovy script, lastWord.groovy demonstrates multiple ways of getting the final word in a String of words where the words are separated by spaces. Although this script contains multiple approaches, I certainly don't claim that it covers all available approaches via Java or Groovy.

lastWord.groovy
#!/usr/bin/env groovy
if (args.length < 1)
{
   println "Please provide a String as a parameter."
   System.exit(-1)
}
def stringWithWords = args[0]
println "Parsing the final word from provided string '${stringWithWords}' ..."

//
// Get last word with Java String's substring method.
//
def javaSubStringWords = stringWithWords.substring(stringWithWords.lastIndexOf(" ")+1);
println "[Java] String.substring(String.lastIndexOf): ${javaSubStringWords}"

//
// Get last word with Java String's split(regex) where regex is any whitespace
// character (not limited to space).
//
def javaWhiteSpaceSplitWords = stringWithWords.split("\\s+")
println "[Java] String.split(white space): ${javaWhiteSpaceSplitWords[javaWhiteSpaceSplitWords.length-1]}"

//
// Get the last word with Java String's split(" ") method and accessing last
// element in array returned by the split method.
//
def javaWords = stringWithWords.split(" ")
def javaSplitLastWord = javaWords[javaWords.length-1]
println "[Java] String.split(\" \"): ${javaSplitLastWord}"

//
// Get the last word with Groovy's (GDK) String.split()
//
def groovyWords = stringWithWords.split()
def splitLastWord = groovyWords[groovyWords.length-1]
println "[Groovy] String.split(): ${splitLastWord}"

//
// Get the last word with Groovy's (GDK) String.tokenize() and List.last() 
//
println "[Groovy] String.tokenize()/List.last(): ${stringWithWords.tokenize().last()}"

//
// Get last word with Groovy's GDK String.find(String) method using regular
// expression that includes end of line character.
//
println "[Groovy] String.find(String regex): ${stringWithWords.find('\\w+$')}"

//
// Get last word with "crazy" approach of using Groovy's GDK String reverse()
// method (twice) in conjunction with the find(String regex) method. This is
// not intended to be an example of how this should be done; rather it is an
// example of what Groovy can do (even if it shouldn't be done).
//
print "[Groovy] String.reverse().find(regex).reverse(): "
println stringWithWords.reverse().find('\\w+').reverse()

The output from running the above code is shown in the next screen snapshot.


All approaches used in the above Groovy code provide the "events" string as expected when passed the longer string "When, in the course of human events". If the larger string is passed in with a comma at the end of it ("When, in the course of human events,"), the output is a little different as demonstrated in the next screen snapshot.


As the two above screen snapshots indicate, the approaches used in the Groovy script can lead to different results depending on whether or not a String to be parsed for the last work end with punctuation. The next screen snapshot indicates the behavior of the respective approaches if the provided String ends with one or more space characters.


The approaches covered in the example Groovy script are summarized next. Note that although all examples are demonstrated in a Groovy script as shown above, the first three are general Java approaches that can be used directly in Java. The last four listed approaches employ one or more Groovy-specific features.
  • Java's String.substring and Java's String.lastIndexOf(" ") provide the last word by finding the last space in the String and bounding the returned String from the next character after the space (the +1) to the end of the String. This example is also referenced in Java: Fastest Way to Get Last Word in a String. This approach includes the comma as part of the final word in the String when it's included and returns spaces when the String ends with spaces (so calling String.trim() before invoking this would be a good idea).
  • Java String.split(String) on regular expression with one or more whitespace characters provides "events" for the nominal case (when "events" really is the last characters in the provided String) and for the case where the String ends with spaces (String.trim() not needed) and returns "events," for the case with a comma at the end of the provided String. Because String.split(String) returns an array, the last element of the array is accessed with array syntax whether in Java or in Groovy. This approach is also mentioned in Java: Fastest Way to Get Last Word in a String.
  • The Java example that uses String.split(String) on a more limited basis (supplying " " to the method rather than \s+ works the same way but splits on only single space (" ") rather than on any whitespace character.
  • Groovy's GDK String class provides a convenience String.split() method that does not take any parameters because it assumes white space as the delimiting character. It is the same as previous two Java approaches using Java's String.split(String), but does not require the developer to explicitly specify that whitespace is the delimiter. Like the two Java approaches, this approach returns "events" when the provided String ends with "events" or ends with "events" and some spaces and returns "events," when the provided String literally ends with that String.
  • The Groovy GDK String class provides a String.tokenize() method that works similarly to Groovy's String.split() method, but which returns a List rather than an array. Because it works similarly, it is not surprising that it returns "events", "events", and "events," as do those approaches. Note also that the GDK String class also provides overloaded versions of the tokenize method that accept a String or a single Character as the delimiter.
  • Groovy provides GDK String methods with the name "find" that allow for substring expressions to be "found" in a provided String. In the Groovy script above, this method is invoked with a String representation of the regular expression pattern '\\w+$'. Because this depends on the end of line character being preceded by one or more word characters, it returns null in the cases of the provided String ending with spaces or with comma. It returns "events" as expected when that is the last series of characters. Groovy's GDK String.find is overloaded several times, including once that accepts a Pattern. The behavior is the same and will be demonstrated later in this post.
  • Groovy's GDK String.reverse() method can be used to reverse the order of characters in a given String. With this, another approach is to reverse the provided String, extract the first word, and then re-reverse the String to get the extracted String back in the correct order. If performance is an issue, pulling a double reverse (not the American football type) is probably not the best idea. However, one major advantage of this approach is that concisely (in terms of code space) returns "events" without any other characters for all three test cases. Indeed, it's the only one of the demonstrated approaches that does this. Of course, the other approaches could be tweaked to do this as well. For example, passing changing the regular expression passed to the Groovy GDK String.find method (either overloaded version accepting String or Pattern) can be adjusted for different results.

I mentioned previously that Groovy's GDK String provides a find method that accepts an instance of Pattern rather than a String. Groovy's regular expression niceties really shine in this case. A code snippet that demonstrates Groovy's regular expression slashy syntax, ~ for Pattern, and String.find(Pattern) is shown next.

//
// Get last word with Groovy's GDK String.find(Pattern) method using regular
// expression that includes end of line character.
//
def regExPattern = ~/\w+$/
println "[Groovy] String.find(Pattern): ${stringWithWords.find(regExPattern)}"

Many of the approaches discussed above assume that at least one "word" is contained in the provided String and exceptions such as ArrayIndexOutOfBoundsException will be encountered if this is not a valid assumption. For a production script, these types of conditions should either be prevented by checking provided String or handled by catching the exception.


Conclusion

When I was a young boy, I found satisfaction in tormenting my younger brother by insisting on having the "last word" when we were supposed to be going to sleep. I'd say a word just loud enough so that he'd hear it and know I had the last word. As an adult, getting the last word can still be satisfying and Groovy makes doing just that particularly easy to do.

Wednesday, January 26, 2011

The State of HTML5

I will be presenting the thirty minute presentation "A First Look at HTML5" at Rocky Mountain Oracle Users Group (RMOUG) Training Days 2011 three weeks from today. Because I only have thirty minutes, I will necessarily only be able to cover high level concepts of HTML5 features and perhaps show some of the HTML5 demonstrations I have used in previous blog posts. However, one item I do intend to focus on because I think it will be the question on the minds of many in the audience is, "What is the state of HTML5 today?" In this post, I briefly look at what I plan my answer to be.

HTML5 and associated modern web technologies and standards hold much promise. Some features are better supported across the major browsers than others. Unfortunately, most web developers using HTML5 features today would need to ensure that their applications detect absence of HTML5 features and provide fallback mechanisms when necessary. Some HTML5 features suffer such lack of comprehensive support currently that including them at all may not seem worth the cost.

A World Wide Web Consortium (W3C) official (Philippe Le Hegaret) has stated (October 2010) that "it’s a little too early to deploy" HTML5 due to "interoperability issues." Le Hegaret specifically cites lack of video codec and, according to the Paul Krill article (W3C: Hold off on deploying HTML5 in websites), "does not expect to have one in the upcoming specification."

This seems to be born out by Google's dropping of H.264 from Chrome. The five major browsers are currently split 3-2 in terms of which video codecs they support in their <video> tags. The impasse is not limited to <video> only: Scott Schiller lays out the issues and caveats surrounding the current state of the HTML5 <audio> tag in "Probably, Maybe, No": The State of HTML5 Audio (December 2010).

Perhaps the most telling review of the current state of HTML5 is provided by Ido Yehieli in the post Why I'm Moving from HTML5 to Flash. Yehieli lists three main reasons (including well-known spotty feature support across browsers as well as performance issues) for switching from HTML5 (used for prototyping) to Flash for the game Cardinal Quest. What makes news of this switch compelling is that it comes from people who really wanted HTML5 to work and who invested time and energy into building something real with HTML5. Practicality, however, seems to have forced their hand. Yehieli ends his post with statements that I think reflect many web developers' feelings regarding HTML5 and its current state:
Is html5 the future? I sure hope so! Unfortunately, it isn't the present.

My recommendation is that HTML5 features should be considered on an individual basis and some might be applied earlier than others. Considerations that factor into this include how well a particular feature is supported across browsers, how difficult it is to provide fallback mechanisms, and the ability of browsers to degrade gracefully.

Joe Stagner's post 10 things you should think about with HTML 5 summarizes some other promising and concerning issues surrounding HTML5 as currently constituted. He too recognizes the ability to take advantage of HTML5 features incrementally.

An increasing number of HTML5 features should be more generally supported as time rolls on. Firefox 4 supports many HTML5 features not previously supported in Firefox and there is hope that it will be out of beta soon. Similarly, Internet Explorer 9 is also expected to be much more supportive of HTML5 features. With Internet Explorer and Firefox still holding the majority of web browser market share, the release of more compliant versions is important to the future of HTML5. Of course, there will be people who don't upgrade to more HTML5-compliant browsers for years to come.

I find HTML5 to be promising, but there are portions of it that still have a long way to go. Fortunately, there are some features that are or soon will be well supported by all major browsers and can likely be adopted currently or in the very near future. The WHATWG decision to change HTML5 to HTML reflects an increasingly popular perspective that the future of HTML mirrors its past: inconsistent support across browsers gradually evolving to more standardized approaches as the cowpaths are paved.

Sunday, January 23, 2011

HTML5 Canvas

One of the exciting features of HTML5 is the promise of universally supported animation and graphics via the new canvas element/tag. In this post, I look at how easy it is to use this tag with a simple example. I also demonstrate how well it is supported in five major web browsers.

The following HTML/JavaScript example illustrate <canvas>'s ease of use.

<html lang="en">
<head>
  <meta charset="utf-8" />
  <title>HTML5 Canvas Demonstrated</title>
  <script language="javascript">
  var context;
  function initializeCanvas()
  {
     var canvas = document.getElementById("canvas1");
     context = canvas.getContext("2d");
     canvas.width = canvas.width;  // reset
  }

  function drawRectangle()
  {
     context.fillStyle = "black";
     context.fillRect(70, 25, 150, 50);
  }

  function addText()
  {
    context.fillText("RMOUG", 250, 40);
    context.fillText("Dustin", 125, 100);
  }

  function addGradient()
  {
     var gradient = context.createLinearGradient(125, 115, 250, 225);
     gradient.addColorStop(0, "red");
     gradient.addColorStop(1, "blue");
     context.fillStyle = gradient;
     context.fillRect(125, 115, 250, 225);
  }

  function addDrawnLinePath()
  {
     context.moveTo(10, 250);
     context.lineTo(10, 400);
     context.lineTo(30, 250);
     context.lineTo(30, 400);
     context.lineTo(50, 250);
     context.lineTo(50, 400);
     context.lineTo(75, 225);
     context.lineTo(10, 250);
     context.strokeStyle = "#000000";
     context.stroke();  // draw on path
  }

  function addDrawnCirclePath(fillIn)
  {
     context.beginPath();
     context.arc(150, 400, 25, 0, Math.PI * 2, false);
     context.closePath();
     context.strokeStyle = "green";
     context.stroke();
     if (fillIn)
     {
        context.fillStyle = "yellow";
        context.fill();
     }
  }
  </script>
</head>
<body onload="initializeCanvas()">
  <header>
    <h1>HTML5 Canvas Demonstrated</h1>
  </header>
  <canvas id="canvas1" width="400" height="500">
  </canvas>
  <form name="canvasForm">
     <input type="button" value="Draw Rectangle" onmousedown="drawRectangle()">
     <input type="button" value="Add Text" onmousedown="addText()">
     <input type="button" value="Add Gradient" onmousedown="addGradient()">
     <input type="button" value="Add Line Path" onmousedown="addDrawnLinePath()">
     <input type="button" value="Add Circle Path" onmousedown="addDrawnCirclePath(false)">
     <input type="button" value="Add Full Circle" onmousedown="addDrawnCirclePath(true)">
  </form>
</body>
</html>

The above example allows the user to click on a button at a time to see each different item drawn to the canvas. Rather than show each step here, I show the final result of pressing all buttons as rendered in Chrome 8, Firefox 3.6, Opera 11, and Safari 5. Internet Explorer 8 is covered separately later in the post.

Chrome 8


Firefox 3.6


Opera 11


Safari 5


Internet Explorer 8

Unfortunately, as the next image shows, Internet Explorer 8 does not render the above example as well as the others.


The What About IE? section of Dive Into HTML5's (free online version of book HTML5: Up and Running) chapter called Let's Call It A Draw(ing Surface) describes how to get around this in Internet Explorer 8. The suggestion there is to use explorercanvas, a project hosted on Google Code with the slogan "HTML5 Canvas for Internet Explorer." It's description states about explorercanvas:
Modern browsers like Firefox, Safari, Chrome and Opera support the HTML5 canvas tag to allow 2D command-based drawing. ExplorerCanvas brings the same functionality to Internet Explorer. To use, web developers only need to include a single script tag in their existing web pages.

The license for explorercanvas is Apache License 2.0, its downloaded ZIP file is less than 100 KB in size, and the Instructions wiki page demonstrates how easy it is to use.

The beauty of explorercanvas is that only one line needs to be added to the example above to allow Internet Explorer to support the <canvas> APIs similarly to the other browser. Here is that line (which is placed between the <head> and </head> tags), assuming that the downloaded excanvas.jar is in the same relative directory:

<!--[if IE]><script src="excanvas.js"></script><![endif]-->

When I add this to the HTML shown at the beginning of this post and reload the page in Internet Explorer 8, it (mostly) works! The newly rendered page taking advantage of explorercanvas is shown next.


The canvas text does not seem to work (no "RMOUG" or "Dustin" strings), but everything else appears to behave in Internet Explorer 8 thanks to explorercanvas.


Conclusion

The HTML5 <canvas> is one of the more consistently supported HTML5 features across the major browsers. Thanks to explorercanvas, even Internet Explorer 8 can largely support it. Besides being standard and consistent, the <canvas> functionality is easy to apply.

Saturday, January 22, 2011

HTML5 Form Field Validation

With HTML forms submissions today, web developers typically must use JavaScript to ensure values are provided when required and are within appropriate ranges and types. HTML5 offers form field validation support built into the HTML form input tags that should greatly reduce the need for JavaScript validation code. In this post, I look at some examples of this. As will be demonstrated in this post, Opera 11 provides the most sophisticated field validation of the measure non-beta browsers and thus is the best browser to use to demonstrate what we might one day enjoy across all major browsers.

<html lang="en">
<head>
  <meta charset="utf-8" />
  <title>E-mail / URL Input Fields Demonstrated</title>
</head>
<body>
<header>
  <h1>E-mail / URL Input Fields Demonstrated</h1>
</header>
<form>
   <p><strong>E-mail Address</strong></p>
   <input name="email" type="email">

   <p><strong>Web URL</strong></p>
   <input name="url" type="url">

   <p><input name="Submit" type="submit"></p>
</form>
</body>
</html>

In the HTML above, the input element is used with respective type attributes of email and url. This type can be used by HTML5-compliant browsers to prevent the field from being submitted if the text entered in the respective input fields does not match the format expected for the specified type. Of the major web browsers (not including beta versions), Opera 11 is the only one that enforces these typings. Screen snapshots from Opera 11 are shown next.



The dialogs indicating bad formatting of the e-mail address and URL fields do not appear until the user clicks the button to submit the form. Opera 11 does not allow the form to be submitted and instead shows the errors as indicated. Other browsers do not currently indicate the error, though some of them do prohibit a form from being submitted when the format is incorrect.

Some of the major web browsers do take advantage of the "email" and "url" types of input fields to identify text previously input for that type of field. For example, a list of e-mail addresses or previous URLs might be provided for an input element with the appropriate type.

HTML5 form field validation also works with numeric input types and with the "required" specification. Suppose we enhanced the above HTML to add an input field with "required" and another input field of type "number" with "min" and "max" specifications. That enhanced example is shown next.

<html lang="en">
<head>
  <meta charset="utf-8" />
  <title>E-mail / URL Input Fields Demonstrated</title>
</head>
<body>
<header>
  <h1>E-mail / URL Input Fields Demonstrated</h1>
</header>
<form>
   <p><strong>E-mail Address</strong></p>
   <input name="email" type="email">

   <p><strong>Web URL</strong></p>
   <input name="url" type="url">

   <p><strong>Required Field</strong></p>
   <input name="required" type="text" required>

   <p><strong>Out of Range Numeric</strong></p>
   <input name="outofrange" type="number" min="0" max="10">

   <p><input name="Submit" type="submit"></p>
</form>
</body>
</html>

Screen snapshots of Opera 11's enforcement of "required" and of Opera 11's enforcement of a numeric input being within the provided range are shown next.




Custom format field validation is also supported via the pattern attribute on the input element. See HTML5 Recipes: Form Validation for an example of this.


Conclusion

As the screen snapshots in this post have shown, Opera 11 does a nice job of enforcing HTML5 form field validation for types of input ("email"/"url"), for presence of "required" fields, and for ranges of numeric inputs. I look forward to the day when all major browsers will fully support forms field validation in non-beta versions so that we can reduce the amount of JavaScript required for form validation. Because these are HTML tags, it doesn't matter whether the user has JavaScript enabled and it means simpler, more readable code.

HTML5 Logo and WHATWG HTML Naming

I recently blogged on Recent HTML5 Links of Interest and discussed Chrome's announcement of their intention to drop support for the video codec H.264 in the <video> tag (see also the comments section of that post), Modernizr's coverage of undetectable HTML5 features, the People of HTML5 series, and HTML5 templates. Although that post was published less than two weeks ago, there have been more significant developments in HTML5 news since then and I cover some of those stories here.

HTML5 Logo

The World Wide Web Consortium (W3C) released an HTML5 logo in different styles and formats, but the with the same general presentation theme. Ian Jacob's interview of Michael Nieling and the HTML5 Logo FAQ provide additional background information regarding this logo, ideas behind its creation, and motivations for its creation. There has been significant enthusiasm in the blogosphere regarding the HTML5 logo, but there have been skeptics as well. Ian Jacobs addresses some of the concerns in The HTML5 Logo Conversation.

The main HTML5 logo page provides for downloading the various logo representations (black/white, orange/white, with or without "HTML", SVG, PNG, various resolutions, etc.). A few of the logos as provided by the W3C are shown next.






The W3C not only provides the HTML5 logo itself in different formats, but it also provides icons representing various technology classes. The HTML5 Logo page has a section on which each of these eight icons can be clicked on to see a brief description of what the icon represents. The idea is that these icons can be appended to the HTML5 log either vertically or horizontally to represent which "HTML5" features a particular site supports. Here are those icons with descriptions that are even more brief than those on the HTML5 Logo page.

Semantics / Structure


Offline and Storage Class


Device Access including Geolocation


Connectivity


Audio / Video / Multimedia


Graphics / Effects / 3D


Performance and Integration (including XMLHttpRequest 2)


CSS3 and Web Open Font Format (WOFF)


The license requires attribution and, as stated above, the HTML5 logos shown in this post are attributed to the World Wide Web Consortium.


WHATWG: HTML is the New HTML5

There was already some confusion surrounding the HTML5 logo as described in Gavin Clarke's articles W3C tackles HTML5 confusion with, um, more confusion and W3C apologizes for HTML5 brand confusion. It probably won't help matters that in the same week that an HTML5 logo was unveiled with the "5" as its central defining feature, the Web Hypertext Application Technology Working Group (WHATWG) announced that they are dropping the "5" in the blog post HTML is the New HTML5. In that post, Ian Hickson references a December 2009 message in which he stated:
I just checked in a change which moves the WHATWG from working on
versioned specifications ("HTML5") to just working on technology without
trying to version it ("HTML").

WHATWG now maintains an HTML living standard. So how is W3C's HTML5 specification related to WHATWG's living HTML standard? The best answer may be provided by the WHATWG HTML specification's "Introduction" section which addresses the question Is This HTML5? (I have added the emphasis):
In short: Yes.

In more length: "HTML5" has at various times been used to refer to a wide variety of technologies, some of which originated in this document, and some of which have only ever been tangentially related.

This specification actually now defines the next generation of HTML after HTML5. HTML5 reached Last Call at the WHATWG in October 2009, and shortly after we started working on some experimental new features that are not as stable as the rest of the specification.

The relationship between WC3 and WHATWG and their respective relationships to HTML can be a source of confusion. A good summary of these two groups and their relationship to each other and to HTML and other web technologies can be found in Dive into HTML5: How Did We Get Here? which describes the convoluted relationships between HTML5, WC3, and WHATWG. The post Reinventing HTML describes the decision in late 2006 to have the W3C and the WHATWG collaborate on "HTML5" (Web Applications 1.0).

Another interesting post for reading about what constitutes "HTML5" is the concise post HTML5 Brief: in a couple paragraphs. The post HTML5 - what is it and what’s in it for me? summarizes the observations and conclusions drawn by "just another software engineer" regarding what HTML5 is.


The "Little Things" of HTML5

The post Falling for HTML5: Finding Love in the Little Things is a summary of the "little things" in HTML5 that Felicity Evans believes "will make the world of difference to the way I code day-in, day-out." She covers HTML5 advancements such as block-level <a> element, form placeholders, and the <section> element.


Conclusion

Just as some enterprise Java developers gloat in their "superiority" when they know it is Java EE rather than J2EE, it seems that this is an opportunity for the same type of personalities to gloat when they know that it's now just HTML rather than HTML5. Of course, then there's the logo with the prominent "5" that's just getting started. Its main page's URL doesn't include a "5" (http://www.w3.org/html/logo/), but the logo does.

The logo with the "5", the specification without versioning, and Google Chrome's dropping of support for H.264 in its <video> element all mean that the web development environment will remain for the foreseeable future as it has always been: inconsistent support across multiple browsers will require developers to use feature detection, graceful degradation, and other now common web development tactics as they adopt HTML5 features.

Wednesday, January 19, 2011

RMOUG Training Days 2011 Four Weeks Away

I will be presenting "Groovier Java Scripting" and "A First Look at HTML5" at Rocky Mountain Oracle User Group's (RMOUG's) Training Days 2011 four weeks from today. I've blogged quite a bit on HTML5 and Groovy and many of those posts were based on examples I was preparing for my RMOUG Training Days 2011 presentations. I'm looking forward to giving these two presentations.

I expect to see several more blog posts on RMOUG Training Days 2011 between now and the end of the actual conference. There are already several interesting posts related to this conference. Cary Millsap has posted New Paper 'Mastering Performance with Extended SQL Trace' in which he includes a link to download this paper which he refers to as "a 15-page update to chapter 5 of Optimizing Oracle Performance."

In Back on the speaking circuit - RMOUG Training Days 2011, James F. Koopmann states that it has been nearly five years since his last presentation, but he will be presenting "The Diagnostic World Has Changed; Using Oracle's Automatic Diagnostic Repository Command Interface to Effectively View and Manage Diagnostic Information" at RMOUG Training Days 2011.

TUSC is associated with eight presentations at Training Days 2011. Their page with information about the conference and the titles and summaries of their presentations also states that Training Days is "the largest regional user group conference in the US" and "is the place to network with local Oracle professionals and talk with internationally renowned Oracle experts." I'll also be there.

RMOUG Training Days 2011 is being held 15-17 February 2011 at the Colorado Convention Center in Denver, Colorado.

O'Reilly Best of Ebook Deal of the Day: Top 25 of 2010

For one day only (today), O'Reilly is offering 60% off their Top 25 Ebooks of 2010. These are obviously popular titles that are DRM free and many of which cost less than $10 US. The deal is offered at the deal page and there is also a link from the main page.

I'm thinking about taking advantage of this offer to purchase JavaScript: The Good Parts. I've been trying to find things to like about JavaScript and it is recommended in Why Java Developers Hate JavaScript.

Tuesday, January 18, 2011

HTML5 Color Picker

As I stated in my post HTML5 Date Picker, Opera 11 is ahead of some of the other non-beta web browsers in implementing some of the expected HTML5 tags. In this post, I look at Opera's implementation of the HTML5 "color picker" as an illustration of what is possible when the other browsers begin adding their own implementations.

I use the following simple HTML code to demonstrate Opera 11's color picker.

ColorPicker.html
<html lang="en">
<head>
  <meta charset="utf-8" />
  <title>HTML5 Color Picker Demonstrated</title>
  <script language="javascript">
  function newBackgroundColor(color)
  {
     document.bgColor = color;
     document.colorForm.selectedcolor.value = color;
  }
  </script>
</head>
<body bgcolor="white">
<header>
  <h1>HTML 5 Color Picker Demonstrated</h1>
</header>
<form name="colorForm">
   <p>Select Background Color
   <input name="colorpicker" type="color" onchange="newBackgroundColor(colorpicker.value);">
   </p>
   <p>
   Selected Color
   <input name="selectedcolor" type="text">
   </p>
</form>
</body>
</html>

There's not much in the code above for a color picker (just <input type="color"> with a "name" attribute and an "onchange" event to make things a little more interesting). Before demonstrating this code in action on the five major browsers, I'll point out that the code works on all the browsers. What differentiates Opera's treatment from the other browsers is that Opera provides an elegant control to allow the user to select a color or type in a color's code. The other browsers (non-beta versions) do not provide a nice control at this point, but the code still works in them if the user types in a recognized color string.


Opera 11's Color Picker

The next set of screen snapshots demonstrates Opera's treatment of the color picker. The images show that a small set of colors is presented first to choose from and that the user can choose from a larger set of colors or even specify a custom color. Simple JavaScript code is invoked when a color is selected and the color of the background is changed accordingly.






Firefox 3.6's "Color Picker"

Firefox 3.6 does not support the color picker as well as Opera 11. Indeed, it is presented as a simple text field. The good news is that if the user types a String that can be interpreted as a valid color code, the functionality still works appropriately. This is demonstrated in the next set of screen snapshots.





Chrome 8's "Color Picker"

Chrome 8's "color picker support" is very similar to Firefox 3.6's as is illustrated in the next three images.





Safari 5's "Color Picker"

Safari 5 provides the same level of support for color picker as Chrome 8 and Firefox 3.6.





Internet Explorer 8's "Color Picker"

Internet Explorer 8 support is similar to that of all the previously covered browsers other than Opera 11.





Conclusion

As with the date/time pickers, Opera 11 leads the pack of non-beta web browsers in maturity of color picker implementation and therefore provides the best illustration of what this tag can become. As with the date picker, I look forward to the day when we have an elegant color picker that works across all major browsers and is employed via simple HTML markup. Today, to get this, we need to use something outside of standard HTML such as Flex or a color picker provided by a third-party JavaScript library.

Monday, January 17, 2011

HTML5 Date Picker

I recently posted that I had decided to use Opera in my HTML5 demonstrations for RMOUG Training Days 2011. As I stated in that post, a big reason for adding the Opera web browser to the set being demonstrated is that it supports some of the HTML5 features better than the other browsers. This post will illustrate one of these cases: the HTML5 Date Pickers.

One of the small but nice things about using Flex or a JavaScript library such as JQuery is the availability of built-in mechanisms for user-friendly input controls. In particular, a good date picker is always appreciated.

HTML5 is currently slated to offer a standard date picker widget that can be used with HTML tags. In this post, I look at the state of the HTML5 date pickers in recent non-beta versions of five popular web browsers (Chrome 8, Safari 5, Firefox 3.6, Internet Explorer 8, and Opera 11).

HTML supports various input fields via the input tag. The different types of input fields are specified via the input element's type attribute. HTML5 dramatically increases the number of available types that can be specified. Several of the new values for the type attribute include those related to date/time: date, datetime, datetime-local, month, week, and time. Each of these is illustrated in the following HTML code snippet.

<html lang="en">
<head>
  <meta charset="utf-8" />
  <title>HTML5 Date Pickers Demonstrated</title>
</head>
<body>
<header>
  <h1>HTML 5 Date Pickers Demonstrated</h1>
</header>
<form>

   <table>

   <tr>
   <th>Input Type</th>
   <th>Input Field</th>
   </tr>

   <tr>
   <td>date</td>
   <td><input type="date"></td>
   </tr>

   <tr>
   <td>datetime</td>
   <td><input type="datetime"></td>
   </tr>

   <tr>
   <td>datetime-local</td>
   <td><input type="datetime-local"></td>
   </tr>

   <tr>
   <td>month</td>
   <td><input type="month"></td>
   </tr>

   <tr>
   <td>week</td>
   <td><input type="week"></td>
   </tr>

   <tr>
   <td>time</td>
   <td><input type="time"></td>
   </tr>
   </table>
</form>
</body>
</html>

Of the five web browsers I previously listed, Opera provides by far the most sophisticated implementation of the date/time types of the input tag. Beginning with the positive, the first several screen snapshots show how this simple HTML renders in Opera 11.

Opera 11 Initial Rendering of Page


Opera 11 Input Tag "date" Attribute


Opera 11 Input Tag "datetime" Attribute


Opera 11 Input Tag "datetime-local" Attribute


Opera 11 Input Tag "month" Attribute

Opera's implementation highlights the entire month that will be selected.


Opera 11 Input Tag "week" Attribute

Opera highlights the week that will be selected.


Opera 11 Input Tag "time" Attribute


Opera 11 - All Input Fields Selected


Opera's implementation of the date/time input fields is impressive. I wish the same could be said for the other non-beta browsers. Sadly, the other browsers don't provide support for these field types anywhere close to this elegant. In fact, I don't think it's even worth including all their screen snapshots here. Instead, I simply show a screen snapshot of each after filling out all the fields. In most cases, the browsers simply treated these fields as simple "text" type fields.

Firefox 3.6 Date Pickers: They're Just Text


Internet Explorer 8 Date Pickers: They're Just Text


Safari 5 Date Pickers: They're Just Text with Focus Highlighting


Chrome 8 Date Pickers: Not Quite There

Although not as elegant as Opera's treatment of date/time fields, the Chrome browser treats these fields as more than text and limits what can be entered into the fields. Unfortunately, there are no nice date/time selection popups like Opera provides. Still, it the focused field highlighting is nice and the fact that selected data is somewhat date/time like in format helps.



Conclusion

I look forward to the day when the major browsers consistently support standardized date/time controls so that simple HTML "input" tags with the appropriate attributes will render elegant and stylistic date/time selectors on any browser. Opera 11 currently leads the pack and provides the best illustration of what could be.