Archive for the ‘Java’ Category

Phipps is Wrong

Sun’s Simon Phipps is wronger than wrong:

Whether you agree with Sun policing it or not, Java compatibility has served us all very well for over a decade. That includes being sure as a developer that all core classes are present on all platforms. Creating sub-sets of the core classes in the Java platform was forbidden for a really good reason, and it’s wanton and irresponsible to casually flaunt the rules.

He’s talking about Google’s JRE Class White List for Google App Engine. The white list is a subset of JRE classes that work on Google’s App Engine hosting environment.

I seriously doubt Google set out to “casually flaunt the rules”. I find it far more likely that Google sought to support as much of Java as possible within the confines of their data centers.

Progress

Java is over ten years old, yet I write this blog on WordPress, a PHP application. PHP is ubiquitous and cheap with virtually any ISP, Java is not. Java hosting is expensive and consumes a lot of server resources. For this reason, server-side Java is largely limited to in-house deployments on company servers.

Now Google offers a way to cheaply host server-side Java applications that gracefully scale to hundreds…perhaps thousands of servers. This is wonderful news!

Yes, Google only supports a subset of Java. Rather than calling this “wanton and irresponsible”, how about recognizing this as an engineering tradeoff? We programmers give up some flexibility in return for the ability to scale cheaply and easily.

Other Examples

There are other ways to scale Java to many servers. None are possible without tradeoffs. MapReduce tools like Hadoop require a completely different way of designing your applications and are not appropriate for most applications.

Terracotta tries really hard to be transparent, but you won’t have much luck running it with Java WebStart apps. That’s one of the engineering tradeoffs you live with. Much like Google App Engine’s white list, Terracotta has a list of Non-Portable Classes. Those are the breaks with distributed computing.

GWT

Much like App Engine, GWT also supports a subset of the full JRE. That’s because GWT needs to generate JavaScript to run in the browser.

Is GWT another example of Google casually flaunting the rules? Really? GWT is one of the most innovative, cutting edge products I’ve ever seen. It is a marvel of ingenuity and can only support a subset of the JRE because of its nature.

Fully supporting every JRE class and method in a sandboxed environment like GWT is impossible.

Java ME

Sun’s own Java ME supports a subset of the JRE, currently limited to JRE 1.3. See CLDC and MIDP.

Some people say Sun chose a subset of JRE 1.3 as an engineering tradeoff because mobile devices and embedded systems cannot support the full JRE.

But we all know the truth. Sun is wanton and irresponsible to casually flaunt the rules with Java ME. Shame on you, Sun.

JavaFX Fail

JavaFX never seems to work for me. I assumed it was because I use a Mac, but developers assure me the examples work on Leopard. Not my Leopard, apparently.

Step 1

Click the Launch button at this page. This is on Leopard with Firefox version 3.0.7.

Step 2

Receive error.

Step 3

The details:

This happened to me the other day on a completely different web site with a similar kind of example. The error message — Server response code: 500 — makes it look like the problem is on Sun’s end.

Not good enough.

UPDATE

Now it works. This makes me believe the frequent errors I see are on Sun’s servers.

A Swing JComboBox for Enums

Here is a quick and dirty combo box class I wrote the other day. It displays all of the values from a Java enum.

public class EnumCombo<E extends Enum<E>> extends JComboBox {
  private final Class<E> enumClass;

  public EnumCombo(Class<E> enumClass) {
    this.enumClass = enumClass;

    for (E e : enumClass.getEnumConstants()) {
      addItem(e);
    }
  }

  public E getSelectedItem() {
    return enumClass.cast(super.getSelectedItem());
  }
}

Using the combo box looks like this:

EnumCombo<Status> statusCombo = new EnumCombo<Status>(Status.class);

You’ll probably want to override toString() in the enum to display friendly values in the combo box.

Override versus Overwrite

How well do you know your OO terminology?

Nimbus ToolTip Bug

I just submitted a bug report to Sun for this bug. With Nimbus on Java6u11, tool tips for disabled components have no border, and the tool tip background exactly matches the panel background color. Here is a sample program with the workaround commented out.

public class TooltipBug extends JFrame {
    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                try {
                    UIManager.setLookAndFeel(
                      "com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel");
                } catch (Exception e) {
                    e.printStackTrace();
                }
                new TooltipBug().setVisible(true);
            }
        });
    }

    public TooltipBug() {
        // un-comment these lines for the workaround
        //UIManager.put("ToolTip[Disabled].backgroundPainter",
        //        UIManager.get("ToolTip[Enabled].backgroundPainter"));

        JButton b1 = new JButton("One");
        b1.setToolTipText("Button 1");

        JButton b2 = new JButton("One");
        b2.setEnabled(false);
        b2.setToolTipText("Button 2");

        Container c = getContentPane();
        c.setLayout(new FlowLayout());
        c.add(b1);
        c.add(b2);

        pack();
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }
}

*** UPDATE: They accepted my bug report. It is Bug ID 6789983.

Nimbus JToolBar Bug

I just submitted a workaround for this Nimbus bug: 6780500. I am unable to watch or vote for bugs…the bug tracking tool seems to have a bug.

The problem is, disabled items in JToolBar use a black font and don’t look any different than enabled items.

This example requires Java6u10 or later, and demonstrates the bug:

public class ToolbarBug extends JFrame {
  public static void main(String[] args) {
    SwingUtilities.invokeLater(new Runnable() {
      public void run() {
        try {
          UIManager.setLookAndFeel(
               "com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel");
        } catch (Exception e) {
          throw new RuntimeException(e);
        }
        new ToolbarBug().setVisible(true);
      }
    });
  }

  public ToolbarBug() {
    /*
    // un-comment these lines for the workaround
    UIManager.put("ToolBar:Button[Disabled].textForeground",
            UIManager.getColor("nimbusDisabledText"));
    UIManager.put("ToolBar:ToggleButton[Disabled].textForeground",
            UIManager.getColor("nimbusDisabledText"));
    */

    JToolBar tb = new JToolBar();
    tb.add(new JButton("Enabled"));
    JButton disabled = new JButton("Disabled");
    disabled.setEnabled(false);
    tb.add(disabled);

    add(tb, BorderLayout.NORTH);

    pack();
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  }
}

With the fix, the example looks right:

Is This a Nimbus Bug?

This code uses Java 6u11 with the Nimbus Look and Feel. I know how to create and apply custom Painters, but I’d rather avoid any com.sun.* dependencies. Those package names will change in Java 7, so I’d rather keep my code “clean”.

Case 1: JButton Background Color

This works:

JButton btn = new JButton("red");
btn.setBackground(Color.RED);

As expected, the button paints with a red background. That’s because deep inside com.sun.java.swing.plaf.nimbus.ButtonPainter, they override getExtendedCacheKeys(JComponent c). In that method, the painter asks the component for its background, on line 398:

if ("background".equals(property)) {
    color = c.getBackground();
}

Case 2: JButtons in a JToolBar

When you put buttons into a JToolBar, setBackground() no longer has any effect. That’s because ToolBarButtonPainter fails to override getExtendedCacheKeys(). ToolBarButtonPainter also has a private array named componentColors like ButtonPainter, but the array is not used.

As I see it, there is no way to set the background color on buttons in a JToolBar without introducing com.sun.* dependencies in our code.

Is this a bug, or a feature? It seems awfully convenient to simply call setBackground(...), even if we’re using Nimbus painters behind the scenes.

VisualVM on Vista

I wanted to use VisualVM to track down a problem in a Java application running under Java 6u11, but it would not work. In the VisualVM local process list, all I could see was “<Unknown Application> (pid ###)”. When trying to connect, I’d see “not supported by this JVM”. This is on a Vista machine.

My domain username is “EBurke”, and Sun creates this directory:

%temp%\hsperfdata_eburke

In this directory, you’ll find one file for each Java process. The filenames are the PIDs.

The Fix

  1. Exit all Java apps
  2. Erase the hsperfdata_xxxx directory
  3. Create a new one, with correct capitalization.

In my case, the correct directory is:

%temp%\hsperfdata_EBurke

You can determine your username by typing “set” at the command prompt, and then finding the USERNAME setting.

Now when I run visualvm, I see the processes and I can connect to local Java apps successfully.

I submitted bug 236 for this issue.

JavaFX Launch

OCI Java Lunch: Android

The first 30 minutes of my OCI Java Lunch presentation on Android is on YouTube. We had to split it up into 3 10-minute segments due to YouTube size limits.

The remaining two segments are on the OCItv Channel.

I haven’t watched this myself…I think I was really nervous the first few minutes, but the talk really picked up steam in segments 2 and 3. The second part of the hour isn’t online yet. That’s when I did live demos with my G1, Eclipse, and the SDK. Mario is working on getting that online as well.