Printing out an array

When printing out an array if you simply do a toString on the array you will get a “fairly useless result such as [C@16f0472”. Consider using Arrays.toString to convert the array into a readable String that gives the contents of the array.” I used to use Arrays.asList followed by toString but Arrays.toString is definitely more efficient and is available as of JDK 1.5.0.

This method is useful when you want to report on the values of an JDK 1.5 enum since the values method returns an array.

The quote is from a FindBugs report.

Accessing JavaBean’s Getters and Setters

A JavaBeans is simply a Java class with a set of properties, each property which has a getter and/or a setter. For example if the Java class has a name property it could be defined like this.

public class Foo {
  private String mName;
  public String getName() { return mName; }
  public void setName(String pName) { mName = pName; }
}

Typically one accesses the property by directly calling its getter and/or setter. But sometimes you may not know the name of the property in advance but still might want to access the getter and/or setter. To do this one can use Java’s beans and reflection packages.

Here is an example of how one would read the value of a property of a JavaBean. Note that the property name should not be capitalized.

import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;

public Object getProperty(MyBean myBean, String propertyName) {

  // get descriptor of property
  PropertyDescriptor descriptor = new PropertyDescriptor(propertyName, myBean.getClass());

  // invoke read method on property of myBean
  Method readMethod = descriptor.getReadMethod();
  return readMethod.invoke(memberSavingsProfile, (Object []) null);
}

Note that if your property only has a getter then you would create the PropertyDescriptor like this.

// get descriptor of property that only has a getter
String readMethodName = "get" + org.apache.commons.lang.StringUtils.capitalize(propertyName);
String writeMethodName = null;
PropertyDescriptor descriptor = new PropertyDescriptor(propertyName, myBean.getClass(), readMethodName, writeMethodName);

Accessing the class from a static method which the class owns

Accessing the class from a static method which the class owns is a bit tricky. From a non-static method accessing the class is as simple as doing this.

Class thisClass = this.getClass(); In a static method there are two different ways to access the class. One way, which I learned from this forum discussion, is to create a stack trace and use the fact that the top of the stack trace will have the class we want.
// get stack trace
StackTraceElement[] stackTrace = new Throwable().getStackTrace();

// get the class name at the top level of the stack trace
StackTraceElement stackTraceTopLevelElem = stackTrace[0];
String thisClassName = stackTraceTopLevelElem.getClassName();

// get the class using the class loader
Class thisClass;
try {
  thisClass = Class.forName(thisClassName);
} catch (ClassNotFoundException exc) {
  // this should never happen
}

The other way is to use Java’s SecurityManager class as described in this article. This way seems preferable because it is not as costly as creating an exception as done in the other way.

Here is some sample code using the SecurityManager. Note that we need to use an inner class because the getClassContext() method is protected.

public static void main(String[] args) {
  Class clazz = new ClassGetter().getClazz();
}

// inner class is necessary since getClassContext is protected
private static class ClassGetter extends SecurityManager {

  protected ClassGetter() {
    // do nothing
  }

  protected Class getClazz() {
    Class [] classes = getClassContext();
    Class clazz = classes[1];
    return clazz;
  }
}

Java allocation is no longer expensive

Beginning in JDK 1.4.2, allocation of new objects is no longer expensive according to this article, Java theory and practice: Urban performance legends, revisited. According to this article.

… allocation in modern JVMs is far faster than the best performing malloc implementations…

The malloc/free approach deals with blocks of memory one at a time, whereas the garbage collection approach tends to deal with memory management in large batches, yielding more opportunities for optimization (at the cost of some loss in predictability).

This “plausibility argument” — that it is easier to clean up a mess in one big batch than to pick up individual pieces of dust throughout the day — is borne out by the data.

So allocate away, never object pool, don’t do strange, non-intuitive things to avoid allocating objects on the heap. Life is good.

How to schedule tasks or perform tasks repeatedly

There is an excellent tutorial at The Java Tutorial called
Using the Timer and TimerTask Classes.

It explains how to use a timer to schedule tasks or to perform tasks repeatedly. With the Timer and TimerTask classes you don’t have to create your own threads, it’s all done for you. Thank you Joshua Bloch for writing these classes.

On a side note, Joshua Bloch is one of the premier Java engineers. Recently he left Sun for Google. Gosh, that must have hurt Sun.

java.io.FileNotFoundException for valid URL

In one of our ATG servlet’s we were making a normal HTTP call to a page located on our ATG Dynamo server.

url = new URL(urlString);
connection = (HttpURLConnection)url.openConnection();
reader = new InputStreamReader(connection.getInputStream());

Free Daddy and His Little Shadow Girls at The Skate Park Creative Commons on FlickrHowever when trying to get the input stream we got a FileNotFoundException yet we were able to go to the same URL using a browser. Googling around we found this lovely thread about the same problem.

To summarize the thread, the problem was in our proxy settings which are set on Windows in localconfig/environment.bat and on UNIX in localconfig/environment.sh. An example of proxy settings on Windows is set PROXY_ARGS=-Dhttp.proxyHost=192.168.1.134 -Dhttp.proxyPort=8080.

The proxy server did not recognize our machines as valid clients so it rejected our requests. Once we changed the proxyHost argument to point to a valid server then this problem was fixed.

Find a class’s runtime origin

JavaWorld has a great article on finding a class’s runtime origin called Back to your Class roots. Below is the highly useful getClassLocation method from the article.

/**
 * Given a Class object, attempts to find its .class location.
 * Use for testing/debugging only.
 * 
 * @return URL that points to the class definition; null if not found
 */
public static URL getClassLocation (final Class cls) {
  if (cls == null) throw new IllegalArgumentException ("null input");
  
  URL result = null;
  final String clsAsResource = cls.getName ().replace ('.', '/').concat (".class");
  
  final ProtectionDomain pd = cls.getProtectionDomain ();
  // java.lang.Class contract does not specify if 'pd' can ever be
  // null; it is not the case for Sun's implementations, but guard
  // against null just in case:
  if (pd != null) {
    final CodeSource cs = pd.getCodeSource ();
    // 'cs' can be null depending on the classloader behavior:
    if (cs != null) result = cs.getLocation ();
    
    if (result != null) {
      // Convert a code source location into a full class file location
      // for some common cases:
      if ("file".equals (result.getProtocol ())) {
        try {
          if (result.toExternalForm ().endsWith (".jar") ||
            result.toExternalForm ().endsWith (".zip")) 
            result = new URL ("jar:".concat (result.toExternalForm ())
              .concat("!/").concat (clsAsResource));
          else if (new File (result.getFile ()).isDirectory ())
            result = new URL (result, clsAsResource);
        }
        catch (MalformedURLException ignore) {}
      }
    }
  }
  
  if (result == null) {
    // Try to find 'cls' definition as a resource; this is not
    // documented to be legal, but Sun's implementations seem to allow
    // this:
    final ClassLoader clsLoader = cls.getClassLoader ();
    
    result = clsLoader != null ?
      clsLoader.getResource (clsAsResource) :
      ClassLoader.getSystemResource (clsAsResource);
  }
  
  return result;
}

Serial Version UID

It is simple to make a class serializable, just have it implement the java.io.Serializable interface. However it is not easy to support the serialized form forever.

One issue is the serial version UID. Every serializable class has a unique identification number associated with it. If you do not specify the identification number explicitly by declaring a private static final long field named serialVersionUID, the system automatically generates it by applying a complex deterministic procedure to the class… If you change [the class] in any way … the automatically generated serial version UID changes. If you fail to declare an explicit serial version UID, compatibility will be broken.

Bloch, Joshua. Effective Java. p. 214

To generate the serial version UID for a class use the serialver tool which comes with the Java SDK. The serialver tool returns the serial version UID for one or more classes.

Example:

$ serialver -classpath 'build;C:/foo/classes.jar' com.bar.FooMessage

or

> serialver -classpath build;C:\foo\classes.jar com.bar.FooMessage

An even easier way to generate the serial version UID is to use the Eclipse IDE. If your class implements the java.io.Serializable interface and it does not have a serial version UID then Eclipse will give a warning about this next to the class name. If you click on the warning you can choose the option “Add generated serial version ID.”

Note, currently there is a bug with Eclipse and generating the serial version UID. When attempting to generate a serial version UID you will see a dialogue window which says “Computing serial version ID….” and “Starting virtual machine…”. Unfortunately this hangs and you are forced to kill your Eclipse IDE. I started seeing this bug yesterday after installing some JDBC plugins and the GEF plugin, I’m not sure if it’s related to that. I tried disabling the plugins but I still see the problem. Before I wasn’t having this problem.