Thứ Hai, 24 tháng 10, 2011

Guava's Bidirectional Maps

Google Guava has much to offer the Java developer working with J2SE 5, Java SE 6, or Java SE 7. The older the version of these being used, the more useful Guava can be. Although Java SE 7 brings select Guava-provided functionality to the Java programming language as a standard part of the language (such as the new Objects class), there are still numerous features of Guava that are not available even in JDK 7. In this post, I focus on Guava's support of bidirectional maps.

Guava's heritage is in the "ancient and unmaintained" Google Collections project and Guava's bidirectional map support comes from that Google Collections heritage. The API documentation for Guava's com.google.common.collect.BiMap interface provides a nice concise definition of a bidirectional map:

A bimap (or "bidirectional map") is a map that preserves the uniqueness of its values as well as that of its keys. This constraint enables bimaps to support an "inverse view", which is another bimap containing the same entries as this bimap but with reversed keys and values.

I have run into several situations during my career where bidirectional map support is helpful in making clearer and more readable code. I have even built custom implementations of bidirectional maps, but no longer do that thanks to the availability of Guava (and previously of Google Collections and Apache Commons's BidiMap). The next code listing shows a simple situation where a bidirectional map is useful. This example maps nations to their capital cities. The beauty of the bidirectional map is that I can look up a capital city by its nation's name or I can look up a nation's name by the name of the capital city. An important characteristic of the bidirectional map is that the "value" side of the bidirectional map requires unique values in addition to the more typical "key" side of the bidirectional map requiring unique values.

TwoMonoDirectionalMaps

package dustin.examples;

import static java.lang.System.out;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

/**
* Demonstrate simplistic implementation of functionality equivalent to that
* provided by bidirectional map via two monodirectional maps. This class has
* some intentional problems to illustrate the maintenance disadvantages of this
* approach. For example, there is a mismatch between the two single-direction
* maps for "London" (UK in one case and England in the other case) and the
* mapping for France/Paris was left off one of the single-direction maps.
*
* @author Dustin
*/
public class TwoMonoDirectionalMaps
{
private final static Map<String, String> nationsToCapitals;
private final static Map<String, String> capitalsToNations;

static
{
final Map<String, String> tempNationsToCapitals = new HashMap<String, String>();
tempNationsToCapitals.put("Canada", "Ottawa");
tempNationsToCapitals.put("England", "London");
tempNationsToCapitals.put("France", "Paris");
tempNationsToCapitals.put("Mexico", "Mexico City");
tempNationsToCapitals.put("Portugal", "Lisbon");
tempNationsToCapitals.put("Spain", "Madrid");
tempNationsToCapitals.put("United States", "Washington");
nationsToCapitals = Collections.unmodifiableMap(tempNationsToCapitals);

final Map<String, String> tempCapitalsToNations = new HashMap<String, String>();
tempCapitalsToNations.put("Lisbon", "Portugal");
tempCapitalsToNations.put("London", "United Kingdom");
tempCapitalsToNations.put("Madrid", "Spain");
tempCapitalsToNations.put("Mexico City", "Mexico");
tempCapitalsToNations.put("Ottawa", "Canada");
tempCapitalsToNations.put("Washington", "United States");
capitalsToNations = Collections.unmodifiableMap(tempCapitalsToNations);
}

/**
* Print the capital city of the nation whose name is provided.
*
* @param nationName Name of nation for which capital is decided.
*/
public void printCapitalOfNation(final String nationName)
{
out.println(
"The capital of " + nationName + " is "
+ (nationsToCapitals.containsKey(nationName) ? nationsToCapitals.get(nationName) : "unknown" )
+ ".");
}

/**
* Print the name of the nation whose capital name is provided.
*
* @param capitalName Name of capital city for which nation is desired.
*/
public void printNationOfCapital(final String capitalName)
{
out.println(
capitalName + " is the the capital of "
+ (capitalsToNations.containsKey(capitalName) ? capitalsToNations.get(capitalName) : "unknown" )
+ ".");
}

/**
* Main function demonstrating this use of two mono-directional maps.
*
* @param arguments Command-line arguments; none expected.
*/
public static void main(final String[] arguments)
{
final TwoMonoDirectionalMaps me = new TwoMonoDirectionalMaps();
me.printCapitalOfNation("United States");
me.printCapitalOfNation("England");
me.printCapitalOfNation("France");
me.printNationOfCapital("Washington");
me.printNationOfCapital("London");
me.printNationOfCapital("Paris");
}
}

When the above is run, the output looks like that shown in the next screen snapshot. The names for capital cities and nations that are provided in the example are intended to illustrate one of the problems with the approach of using two single-directional maps: they can get out of synch. This issue can be remedied with a bidirectional map as shown in the next code sample that employs the ImmutableBiMap implementation of the BiMap interface.

GuavaBiMapDemo

package dustin.examples;

import static java.lang.System.out;
import com.google.common.collect.BiMap;
import com.google.common.collect.ImmutableBiMap;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

/**
* Simple demonstration of Google Guava's bidirectional map support.
*
* @author Dustin
*/
public class GuavaBiMapDemo
{
private final static BiMap<String, String> nationsToCapitals;

static
{
final Map<String, String> tempNationsToCapitals = new HashMap<String, String>();
tempNationsToCapitals.put("Canada", "Ottawa");
tempNationsToCapitals.put("England", "London");
tempNationsToCapitals.put("France", "Paris");
tempNationsToCapitals.put("Mexico", "Mexico City");
tempNationsToCapitals.put("Portugal", "Lisbon");
tempNationsToCapitals.put("Spain", "Madrid");
tempNationsToCapitals.put("United States", "Washington");
nationsToCapitals = ImmutableBiMap.copyOf(Collections.unmodifiableMap(tempNationsToCapitals));
}

/**
* Print the capital city of the nation whose name is provided.
*
* @param nationName Name of nation for which capital is decided.
*/
public void printCapitalOfNation(final String nationName)
{
out.println(
"The capital of " + nationName + " is "
+ (nationsToCapitals.containsKey(nationName) ? nationsToCapitals.get(nationName) : "unknown" )
+ ".");
}

/**
* Print the name of the nation whose capital name is provided.
*
* @param capitalName Name of capital city for which nation is desired.
*/
public void printNationOfCapital(final String capitalName)
{
out.println(
capitalName + " is the the capital of "
+ (nationsToCapitals.containsValue(capitalName) ? nationsToCapitals.inverse().get(capitalName) : "unknown" )
+ ".");
}

/**
* Main function demonstrating this use of two mono-directional maps.
*
* @param arguments Command-line arguments; none expected.
*/
public static void main(final String[] arguments)
{
final GuavaBiMapDemo me = new GuavaBiMapDemo();
me.printCapitalOfNation("United States");
me.printCapitalOfNation("England");
me.printCapitalOfNation("France");
me.printNationOfCapital("Washington");
me.printNationOfCapital("London");
me.printNationOfCapital("Paris");
}
}

When the above is executed, the output shows more consistent mappings for London and for Paris/France because there was no need to maintain two separate maps.

Guava's bidirectional maps provide a safer and more readable approach to implementing data structures that map keys to values and values to key in such a way that one can be accessed via the other. Normal Java Maps only access use of a key to access a value directly, but both directions of access are supported by Guava's bidirectional maps.

Guava seems to be receiving more attention these days. Google's guava java: the easy parts was written about one year ago and is a nice introduction to the "easier" portions of Guava. Tom Jefferys's September 2011 post Multimaps - Google Guava also provides a nice overview of Guava's map support with focus on Multimaps followed by separate posts focusing on BiMaps and Multisets. Recent post 5 Reasons to use Guava includes Guava's map support as one of five reasons that Java developers should embrace Guava. Section 16.9. retrieving a key by value (working with bi-directional maps) of the Java Commons Cookbook (download) also covers Guava's support for bidirectional maps.

Thứ Tư, 19 tháng 10, 2011

Java Posts of Interest - 19 October 2011

JavaOne 2011 and announcements from JavaOne have been big news recently in the world of Java. However, there are some other Java-related posts of interest that are not directly related to JavaOne 2011 that have been of interest and I reference and briefly summarize some of them here.

Java SE 7 Update 1 Available

Java SE 7 Update 1 is now available for download and contains numerous security fixes. The article Oracle patches Java flaw exploited in SSL BEAST attack states that Oracle-provided security fixes have led to Mozilla deciding not to block Java in Firefox.

JDK 7 Adoption Guide

The JDK 7 Adoption Guide has been recently highlighted on the Oracle Technology Network page. It provides a concise summary for each of several categories of enhancements such as Java language enhancements and JVM enhancements. The JDK 7 Adoption Guide also lists the versions of specifications included with JDK 7. For example, it states that "JDK 7 now supports JAXB 2.2.3" and "JDK 7 now supports JAX-WS 2.2.4." It also contains links to other references with greater details such as Java SE 7 Features and Enhancements, Java SE 7 and JDK 7 Compatibility, JDK 7 Release Notes, and New JDK 7 Feature: Support for Dynamically Typed Languages in the Java Virtual Machine.

javatuples 1.2 Released

The release of javatuples 1.2 was announced on 15 October 2011. Its main page describes the project: "javatuples is one of the simplest java libraries ever made. Its aim is to provide a set of java classes that allow you to work with tuples."

Java Losing Popularity Among Developers

Paul Krill begins Survey: Java losing popularity among developers with this sentence: "Despite the recent release of a major upgrade to the platform, Java is losing popularity based on the latest monthly assessment of programming languages by Tiobe Software." His article's subtitle adds, "If recent trends continue, C could supplant Java as the most popular programming language by next month."

UPDATE: Kevin Farnham has posted an interesting analysis of the programming language trends indicated in the Tiobe index referenced in this article ("Is Java Really Losing Popularity Among Developers?"). Significant interest has been generated in this java.net editorial as evidenced by the reddit comments (nearly 325 comments as of this writing).

NetBeans 7.1 Beta Released

NetBeans 7.1 beta was released in conjunction with JavaFX 2.0's release. I used NetBeans 7.1 beta to implement a Hello JavaFX 2.0 example.

Securing Java Code - Exceptions

Roman Kennke's Securing Java code – Exceptions advises, "When you want to put some interesting information in an exception to make your debugging life easier, think really hard to restrict the amount of information as much as necessary and to not expose any information that could be used by an attacker." I jave seen similar issues to the one Kennke describes in which exceptions provide a lot of detail on how a particular system is implemented. A stack trace is a great tool, but its value can be as great for hackers as for developers. The "offending" stack trace doesn't have to be part of an exception to provide dangerously valuable details. I blogged previously on how I've seen significant implementation details of Flash applications which debug accidentally left on.

Fix Common Java Exceptions

Fix Common Java Exceptions offers brief descriptions of regularly encountered standard Java exceptions such as ClassCastException, ClassNotFoundException, InvalidClassException, and NullPointerException.

Conclusion

The aftermath of JavaOne 2011 continues to include numerous interesting and insightful posts and articles about Java.

Thứ Ba, 18 tháng 10, 2011

Hello JavaFX 2.0: Introduction by NetBeans 7.1 beta

Over the years since the 2007 JavaOne announcement of JavaFX, I have been somewhat critical of what it has to offer. After Oracle's announcement at JavaOne 2010 that JavaFX would abandon the proprietary JavaFX Script and instead support standard Java APIs, I began to wonder if it was time to invest in learning JavaFX. With the JavaOne 2011 announcements that Oracle intends to pursue standardization of JavaFX as part of Java SE and to open source JavaFX, it is now an easy decision to invest time and energy into learning JavaFX 2.0. In this post, I publicly begin that process. The last couple times I looked at JavaFX, I stopped after feeling disillusioned and resentful. I am expecting better results this time.

One of the announcements at JavaOne 2011 was the general availability of JavaFX 2.0 for Windows. A related significant announcement was the release of JavaFX 2.0 Developer Preview for Mac OS X. For purposes of this post's examples, I downloaded the JavaFX SDK (which includes the JavaFX 2.0 runtime) for Windows.

The default installation directory for the JavaFX 2.0 SDK and runtime in my case is C:\Program Files\Oracle with the SDK installed in directory C:\Program Files\Oracle\JavaFX 2.0 SDK and the runtime installed in directory C:\Program Files\Oracle\JavaFX Runtime 2.0.

Although JavaFX applications be be built from the command-line, I'm going to build my first one with NetBeans. NetBeans 7.1 beta supports JavaFX 2.0, though JavaFX 2.0 SDK should be downloaded separately as I discussed above.

As usual, I downloaded the 'All' version of NetBeans 7.1 beta because I want the support for Groovy, Java EE, PHP, and C/C++ along with the support for Java SE and JavaFX. A person who doesn't want all of that, but does want JavaFX support can download the Java SE or Java EE bundles instead of the 250MB+ All bundle.

Getting Started with JavaFX is an excellent introduction to creating a first JavaFX application. However, my first example here will be even simpler than that one and is essentially a JavaFX version of Hello World.

Once NetBeans 7.1 (beta) is available, I can create a new Project in NetBeans 7.1 that is a JavaFX project. This process follows the normal approach in NetBeans of creating a new project via using of CTRL+SHIFT+N or right clicking in the "Projects" tab and selecting "New Project...." The following three screen snapshots show my configuring of this NetBeans 7.1 beta JavaFX project. In this case, I'm creating a JavaFX FXML project. The "Activating..." is required because this is the first time creating a JavaFX project in this newly installed NetBeans 7.1 beta installation.

Once I clicked on the "Finish" button to create this JavaFX project, three files were generated. These are HelloJavaFX.java, Sample.java, and Sample.fxml. The following three screen snapshots show all three of these files.

It is interesting to see what files NetBeans 7.1 beta generates for the JavaFX project after clicking "Build" on the project. This is shown in the next screen snapshot.

As the last image indicates, there is an HTML file generated in the 'dist' directory along with a JAR and a JNLP file.

As part of this example, I slightly changed the generated Sample.java to report "Hello JavaFX 2.0" (from "Hello World") when the button is clicked. The revised source code is shown next along with the original NetBeans-generated code for Sample.fxml and HelloJavaFX.java.

The generated HelloJavaFX Java class extends Application (Javadoc documentation calls this the "entry point for JavaFX applications") and features the normal static main function as well as an overridden start(Stage) method. It references the Sample.fxml in that start method where it loads the FXML content via FXMLLoader.

HelloJavaFX.java

package dustin.examples;

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;

/**
*
* @author Dustin
*/
public class HelloJavaFX extends Application
{
public static void main(String[] args)
{
Application.launch(HelloJavaFX.class, args);
}

@Override
public void start(Stage stage) throws Exception
{
Parent root = FXMLLoader.load(getClass().getResource("Sample.fxml"));

stage.setScene(new Scene(root));
stage.show();
}
}

The FXML file referenced by HelloJavaFX above is shown next. This file specifies its 'controller' as the Sample.java class.

Sample.fxml

<?xml version="1.0" encoding="UTF-8"?>

<?import java.lang.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>

<AnchorPane id="AnchorPane" prefHeight="200" prefWidth="320" xmlns:fx="http://javafx.com/fxml" fx:controller="dustin.examples.Sample">
<children>
<Button id="button" layoutX="126" layoutY="90" text="Click Me!" onAction="#handleButtonAction" fx:id="button" />
<Label id="label" layoutX="126" layoutY="120" minHeight="16" minWidth="69" prefHeight="16" prefWidth="69" fx:id="label" />
</children>
</AnchorPane>

The Sample.java class shown next is the class that I slightly tweaked from the NetBeans-generated version. This class implements Initializable and the initialize method. It also demonstrates use of the @FXML annotation, which designates that the annotated attribute and method are accessible from FXML markup.

Sample.java

package dustin.examples;

import java.net.URL;
import java.util.ResourceBundle;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Label;

/**
*
* @author Dustin
*/
public class Sample implements Initializable
{
@FXML
private Label label;

@FXML
private void handleButtonAction(ActionEvent event)
{
System.out.println("You clicked me!");
label.setText("Hello JavaFX 2.0!");
}

@Override
public void initialize(URL url, ResourceBundle rb)
{
// TODO
}
}

From within NetBeans, it is easy to run the JavaFX application. Right-clicking on the JavaFX project in the "Projects" page of NetBeans 7.1 beta and selecting "Run" is depicted in the following screen snapshot.

Once the NetBeans-generated (and slightly modified) JavaFX application is run in NetBeans, a pop-up appears and is updated with the "Hello" message when its only button is clicked. The next two screen snapshots attempt to demonstrate these events in static presentation.

The last two images shown above demonstrate that the expected messages do appear. The "Hello" message is partially shown and the message sent to standard out appears in the ""Output" pane at the bottom of the IDE.

Conclusion

JavaFX has new life with JavaFX 2.0 and Oracle announcements regarding JavaFX's future at JavaOne 2010 and at JavaOne 2011. In this post, I have demonstrated building a simple JavaFX application and deploying it locally with NetBeans 7.1 beta. Although the example is extremely simple, it does demonstrate a few key classes in JavaFX as well as FXML and interaction between the classes and markup. Thanks, NetBeans 7.1, for the introduction!

Thứ Hai, 10 tháng 10, 2011

The Coupling of JavaFX's History with JavaOne

With this year's big announcements surrounding JavaFX at JavaOne 2011, I cannot help but think that JavaFX's announcements seem inexorably coupled to JavaOne conferences. This post contains a simple outline of JavaFX announcements and coverage at annual editions of JavaOne since 2007 JavaOne Conference.

JavaOne
Edition
MonthDescription and Commentary
2007MayJavaFX announced, based on Form Follows Function (F3) with emphasis on new JavaFX Script language. JavaFX was mostly F3 + slideware at this point. Juixe's Java One 2007 Conference Notes asked the question many of us asked at the time (emphasis added), "The big announcement at JavaOne made by Sun have has JavaFX Script, formerly known as Form Follows Function (F3). I think of JavaFX Script as a scripting Domain Specific Language for Rich Internet Applications which begs the question, why a new language? Why not accomplish the same functionality using Groovy, JRuby, or a unified and simplified API?"
2008MayJavaFX progress highlighted and JavaFX 1.0 Preview SDK released. The general release of JavaFX 1.0 would be later that year (December).
Oracle announces its intention to purchase Sun in April 2009.
2009JuneOracle acquisition of Sun in progress. Java FX 1.2 released with beta support for Solaris and Linux.. Oracle announces intentions to use JavaFX to compete once finished acquiring Sun. JavaFX authoring/design tool (JavaFX Designer) previewed.
Oracle completes its acquisition of Sun on 27 January 2010.
My post O JavaFX, What Art Thou? asks questions about JavaFX such as why does it use its own language (answered in JavaOne 2010), why is it not standardized (answered in JavaOne 2011), and why is it not open source (answered in JavaOne 2011)?
2010SeptemberOracle's first JavaOne. Oracle announces deprecation of JavaFX Script, effective immediately, in favor of support for standard Java API. New JavaFX Roadmap laid out. JavaFX 2.0 announced.
My May 2011 post JavaFX 2 Beta: Time to Reevaluate JavaFX? publicly wondered if it was time to give JavaFX a chance again given the JavaOne 2010 announcement about standard Java API support replacing proprietary JavaFX Script. I stated nagging concerns I still had related to JavaFX such as questions about the nature of its license or open source and about its lack of standardization.
2011OctoberOracle announces general availability of Java FX 2.0 for Windows and JavaFX 2.0 for Mac OS X Preview. Oracle announces that JavaFX will be open sourced and submitted to JCP for potential standardization as part of Java SE. Demonstrations of JavaFX Scene Builder provided.

Contrary to what the table above might indicate, I'm not pretending that my blog posts led to the respective announcements at JavaOne 2010 and JavaOne 2011 about deprecation of JavaFX Script and standardization and open sourcing of JavaFX. However, I do believe my posts are reflective of the greater community's sentiment and concerns at the time and it seems clear that Oracle has listened to those concerns and responded effectively. The initial Sun aversion to having an XML-based layout mechanism like Flex's MXML or OpenLaszlo's LZX even seems to have been finally overcome with the advent of FXML. At this point, I am ready to start seriously considering JavaFX again.

Thứ Bảy, 8 tháng 10, 2011

JavaOne 2011 - A Tremendous Success: Blogosphere Round-up

The blogosphere is full of accounts of JavaOne 2011 and most of them are extremely positive. Peter Hendriks says of JavaOne 2011, "the Java vibe is back" and "Java is moving forward again." Cameron McKenzie says of JavaOne 2011, "Mark it up as a success." After one day at JavaOne 2011, Sean Landis stated, "There are good things happening" and "good things on the horizon." Cay Horstmann says of JavaOne 2011, "The message that I got from this year's JavaOne is that Java SE and EE are alive and kicking" and adds, "I look forward to Java One 2012." Ian Skerrett writes, "JavaOne is finished and I am leaving with a positive feeling about the conference and the Java community" and predicts "Next year JavaOne is going to be a LOT bigger." Terrence Barr observes about JavaOne 2011, "JavaOne has brought renewed excitement and energy to the Java community."

Other bloggers provided additional interesting commentary on JavaOne 2011. Juliano Viana states that he saw "the scariest Java talk I have ever been to" at JavaOne 2011. About JavaFX announcements at JavaOne 2011, Peter Pilgrim states, "Oracle have delivered on their promised, or may be it was Sun Microsystems vision, to reinvigorate the user interface on the desktop.." Al Hilwa is quoted as saying, "I would say that Java is in better strategic shape on several levels." Eric Bruno states, "I've been at JavaOne all week and the experience has been fantastic." The original set of JavaOne 2011 presentations on Parleys.com are available.

I have already dedicated a blog post to summarizing my JavaOne 2011 posts and I look at other peoples' JavaOne 2011 posts in this post. I don't look specifically reference JavaOne Conference Blog posts here because I figure their existence is fairly obvious.

Miscellaneous Individual Posts Dierk Koenig Posts Cay Horstmann Posts Adam Bien Posts Markus Eisele Posts Sean Landis Posts Juliano Viana Posts Peter Pilgrim Shaun Abram Posts Trisha's Posts Alex McGray's Posts Press Releases

Conclusion

The overall reaction to JavaOne 2011 seems to be extremely positive and I think most of us who were able to attend this year are already hoping that we will be able to attend JavaOne 2012.

Thứ Sáu, 7 tháng 10, 2011

JavaOne 2011 "Inspired by Actual Events" Round-up

Another edition of JavaOne has come to a close. Sitting at San Francisco International Airport (SFO) to head home seems like a good opportunity to provide a "round up" of my posts on JavaOne 2011. These are posts I wrote during the conference itself or immediately after it ended; I wrote more posts about JavaOne 2011 before the conference began.

Looking over this list of keynotes and sessions reminds me how much JavaOne 2011 had to offer. This is even more startling when one considers that each of the technical sessions above represents just one offering of many available in each session's timeslot. It truly was an information-packed conference.

Thứ Năm, 6 tháng 10, 2011

JavaOne 2011 Overall Impressions: The Good, The Bad, and The Ugly

There was much to like (and some to dislike) about JavaOne 2011. In this post, I look at my impressions of the good, the bad, and the ugly of JavaOne 2011.

Good: Announcements

JavaOne is famous for its announcements and this year's edition was full of them. Here are some I found most interesting (in no particular order).

Good: Technical Content

The technical sessions tended to be strong technically and even the keynotes generally had sufficient level of technical content. I focused on presentations involving core Java concepts, alternative JVM languages, and JavaFX, but was able to see some presentations on topics as diverse as cloud computing, JAXB, and REST.

Good: Networking and Community

There were many "big names" in the Java world present at JavaOne 2011 and it was nice to meet some of them and to see some of them speak. It was also nice to get a feel for the diversity of concerns and needs of the Java development community.

Good: Ideas to Take Home

There are too many good ideas that I want to take back home with me to play with and possibly blog about in select cases. Here are some of them, though I acknowledge now that I know I won't get to some of these anytime soon if at all.

Groovy is Increasingly Assumed Knowledge

I mentioned in my review of JavaOne 2010, "It seems to me that Groovy has either reached or is very close to reaching that point where it is no longer new or unusual to the majority of conference attendees." This definitely seemed to be even more the case this year at JavaOne 2011. I wasn't the only one with this impression: Dierk Koenig wrote, "It appears that in the mainstream, Groovy has become the default choice for dynamic programming on the JVM."

Bad: Limited Resources

The good news was dramatically increased interest in and attendance at JavaOne this year as compared to last year. The bad news is that not everyone seemed prepared for that large number. The restrooms were frequently out of paper towels and hand soap early in the week and I was only able to get the Wifi to work on a very sporadic basis.

Bad: Hotel Logistics

Many of the same negatives associated with hosting the sessions in the hotels remained issues this year because nothing was really different. I actually welcomed the opportunity to walk between the buildings to get fresh air and reinvigorate myself, but walking between the seemingly more narrow when crowded halls (especially in the Hilton) was not a positive experience in all cases. It didn't help that some attendees were more focused on their mobile device than on getting from Point A to Point B. Long conference rooms were okay for hearing and seeing the speaker, but did not lend themselves to seeing the screens that were not very far above the crowd. Because the screens are so low in many of these long conference rooms, it is difficult for attendees past the first several rows to see significant chunks of the screen. One idea that would help is if the slides were made available prior to or at the conference so that people could follow them on their laptops, mobile devices, or even printed hard copies. This would not help with the code examples shown in IDEs and on the command-line, but it would help with the slides. I noticed many people taking photographs of screens with reference details and having current access to slides would reduce the need for that as well.

Bad: The Weather

Last year, when it was the Mason Street Tent between Hilton San Francisco and Nikko Hotel, we had beautiful weather. This year, when it was the open area Mason Street Cafe between those same two hotels, we had rain and inclement weather nearly every day. Truth be told, I don't mind this type of weather as long as it's not down pouring. I like cooler weather as long as I'm not getting really wet in the cooler weather. However, there is no question that the weather dampened some of the outdoor activities. I'm just waiting for someone to blame Oracle for the bad weather.

Ugly: Overrunning Keynotes Combined With Throttled Foot Traffic

This is a particular subset of categories I've already mentioned (logistics and over-running keynotes), but the combination of these two led to a particularly ugly scene. The staff was throttling how many people could exit the Hilton Ballroom area at a time after the keynotes ended. This wasn't as big of a deal with the Technical (Opening) Keynote because people had left in large groups throughout the session from the time Mark Reinhold's presentation ended up until the actual end of the session which went well past its advertised time. This length of time seemed to distribute the exiting more naturally. A much higher percentage of attendees stayed for the entire Strategy Keynote and this led to a problem as the number of people allowed to leave was artificially throttled at the top of the escalator. It meant many people being late to the first of the technical sessions that day.

Ugly: "Queuing" for Presentations

Several of the sessions had long queues forming as either the previous session was getting out or the next session was not yet allowing entry. Sometimes these queues backed into the main hall thoroughfares. This was most problematic in the hotel (Hilton San Francisco) with the most conference room space.

Ugly: Keynotes Java Rapper Video

The looks on most attendees' faces seemed to be a mixture of disbelief and confusion. I even had people not attending the conference sending me e-mail and text messages asking what was going on at JavaOne when seeing the Java Life video. The video and lyrics are available here. It does seem to have gone viral among Java developers.

The Incidentals: Miscellaneous Observations

There were some things that happened this week that did not directly affect nor were directly affected by JavaOne 2011, but which happened at the same time and were watched by conference attendees. Apple's long-anticipated announcement of the iPhone 4s may have been slightly disappointing because iPhone 5 was anticipated, but truly sad news was received a couple days later when we learned of the passing of Steve Jobs. Jobs' unique mix of creativity and technical genius have been shown again and again via his involvement in the development of the personal computer, iPod, iPhone, iPad, and Pixar. As much as I loathe iTunes (the software, not the site), I must admit that it helped changed the music industry and the way we all purchase and listen to music.

I occasionally speak at conferences and so try to pick up good practices for my own presentations from speakers that I watch. I also try to observe which practices are not so effective and either avoid them myself or remove them from my own presentations. One such observation that I realized again this year and seem to realize at every conference I attend is the importance of limiting the time "spent in the IDE." I know presenters do this because we're all comfortable with IDEs, but the truth is that it is easier to see code in slides when the slides are carefully prepared, have color syntax highlighting, and focus only on what's important. Slides are often easier to see than IDE text in these large rooms of JavaOne. It takes a lot more work for a speaker to put code into slides with a nice presentation like that given in the IDE, but I think it's one of the best things a presenter can do for his or her attendees. If this is not possible, the next best thing s to make very quick excursions to the IDE (not long enough to need to sit down) and to use a very large font and make it obvious what one is looking at.

Conclusion

Although JavaOne 2011 had its good, its bad, and its ugly, the good dramatically outweighed the bad and the ugly. Although it's good that it's over because I don't know how much more I could have crammed into my mind and I want to go start trying some things I learned, I will miss it as well. If JavaOne 2012 is held simultaneously with Oracle OpenWorld again, it will be scheduled for September 30 - October 4, 2012.