Java Tips

From EggeWiki

FindBugs

Cobertura

Java Unique List

Ant tips moved to Ant Tips

Range

The ordinal 2821 could not be located in the dynamic link library LIBEAY32.dll

If your java.exe crashes with this message, you should download and install latest openssl library from http://www.slproweb.com/products/Win32OpenSSL.html (Thanks [Changelogic])

RegexFieldValidation

JavaNaming

javax.activation.UnsupportedDataTypeException

Nothing like starting yout Monday morning with a Java classloader issue. My fix to the problem is here: JavaMailFun.


How to test System.exit

Why I dislike mocks

Use platform dependent end of line character

<geshi lang="java5">

 private static final String EOL = System.getProperty("line.separator");

</geshi> See http://java.sun.com/j2se/1.5.0/docs/api/java/lang/System.html#getProperties()


StringBuilder

StringBuilder is a drop in replacement for StringBuffer. Today, after much pulling out of hair, I discovered neither override the equals method.

<geshi lang="java5">

   public void testStringBuilderWTF() {
       StringBuilder a = new StringBuilder("foo");
       StringBuilder b = new StringBuilder("foo");
       assertEquals(a, b);
   }

</geshi>

junit.framework.AssertionFailedError: expected:<foo> but was:<foo>

StringUtil.java

Handy collection of functions for Strings. The pluralize function was ported from Ruby.

RFC-822

I'm not sure why Java doesn't have any built in support for generating or parsing RFC-822 dates. I noticed Google has a class which does this: http://code.google.com/apis/gdata/javadoc/com/google/gdata/data/DateTime.html. It would be nice if they would add it into the DateFormatter class. Until then, CPP (copy-paste programming) will have to do.

<geshi lang="java5">

   // The publication date is in RFC 822 format which is in english
   // see http://blogs.law.harvard.edu/tech/rss
   SimpleDateFormat rfc822Format = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss Z", Locale.ENGLISH);

</geshi>

unmappable character for encoding UTF8

I received this error today when compiling a Java program, that has been compiling for quite a long time. Turns out the cause was I switched to the Java 1.5.0_02 compiler, and this one is a little more strict than the previous ones. Sun's bug id 5071879 states this is not a 'bug', but rather a side affect of the compiler being more strict. Generally, your source code is written in 8-bit ASCII, and when the compiler reads the file it has to translate it into 16 bit unicode characters. On *nix platforms, javac apparently figures out which encoding to use based on your LANG environment variable. However, you can also specify a -encoding option with the compiler. Probably the best solution is to use proper unicode escape sequences in your source file. So instead of something like: <geshi lang="java5">char currency = '£'</geshi> write <geshi lang="java5">char currency = '\u20A4'</geshi>

This way you code will compile the same regardless of the users local character set. Where this doesn't make a lot of sense is in comments. Many people like to use the copyright © symbol in their header file, or accent marks on their name. For something which is only displayed in a comment, using the unicode escape character makes no sense. In this case, it's probably best to save the file as UTF-8, and specify this encoding your ant script.

Configure log4j

I used to always get this warning when I would start Java apps:

log4j:WARN No appenders could be found for logger (net.sourceforge.cruisecontrol.Main).
log4j:WARN Please initialize the log4j system properly.

Despite having an option like -Dlog4j.configuration=/u/eggebr/mylog4j.properties in my Java startup.

The reason this was failing is because log4j.configuration expects a URL, not a file. Of course the URL can be a file if you specify it like -Dlog4j.configuration=file:/u/eggebr/mylog4j.properties.

If I don't want the to use the normal log4j configuration, but rather have the output go to the stdout, a config file like this works fine:

log4j.rootLogger=INFO, stdout

log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d [%t] %-5p %c - %m%n

Find classes which exist in multiple jars:

<geshi lang="bash"> find . -name "*.jar" -type f -exec jar -tvf \{\} \; | cut -b 37- | grep "\.class" | sort | uniq -dc | sort </geshi>

JBoss Ideas

Offline HTML code formatter with Ant task

Online HTML code formatter

Validate CUSIPs using their checksum

Here's a class which validates the checksum of a CUSIP. The algorimth is slightly different than the LUHN algorithm, but the principle is the same. This is useful for validating CUSIPs.

Apple uses Java for their iTunes Store

  Dear Podcast Owner

  An error was encountered in your Podcast feed [ http://www.ccnorthjersey.org/podcast/rss.php ] preventing update. We will not be able to update the directory from your feed until this error is resolved:

  We had difficulty reading this feed. *java.net.~SocketTimeoutException*: Read timed out


  Sincerely,

  The iTunes Music Store Team

River Layout

Patches for Java CUP, a parser generator.

Convert from dos to unix and unix to dos formats:

<geshi lang="java5">

 private static final Pattern DOS = Pattern.compile("\\r\\n", Pattern.MULTILINE);
 public static String dos2unix(String text) {
   return DOS.matcher(text).replaceAll("\n");
 }
 private static final Pattern UNIX = Pattern.compile("([^\\r])(\\n)", Pattern.MULTILINE);
 public static String unix2dos(String text) {
   return UNIX.matcher(text).replaceAll("$1\r\n");
 }

</geshi>


Directory Permissions for JVM

Help! When run as my user this works fine. When I run as 'foo', it gives me this nasty error <geshi lang="bash"> $ sudo -u foo java -version Error occurred during initialization of VM java.lang.Error: Properties init: Could not determine current working directory.

-or-

$ sudo -u foo java -version Segmentation Fault (core dumped) </geshi>

Fix, make the current directory & it's parent world-readable. Or run java in a different directory where foo has read permissions.

Extract one file from a jar

<geshi lang="bash"> jar xvf archive.jar filename.txt </geshi>

Code Conventions

Sun has a fairly complete coding conventions document. The main thing I dislike is they recommend four space indents, while I prefer two.

http://java.sun.com/docs/codeconv/html/CodeConvTOC.doc.html

Get a stack dump from a java app running on Windows

http://tmitevski.users.mcs2.netarray.com/stacktrace.jsp


TibRv Library Error On Linux

How to refactor away the warning "The method UTC(int, int, int, int, int, int) from the type Date is deprecated"

<geshi lang="java5">

 public static void main(String[] args) {
   final int year = 2004;
   final int month = 8;
   final int day = 24;
   // Old (easy) way:
   Date d1 = new Date(Date.UTC(year - 1900, month - 1, day, 0, 0, 0));
   // New way:
   final Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
   calendar.setTimeInMillis(0); // Current milliseconds linger around - set this to get rid of them.
   calendar.set(year,month-1,day,0,0,0);
   Date d2 = calendar.getTime();
   assert d1.getTime() == d2.getTime();
 }

</geshi>

Q: How do you get the local hostname in Java?

<geshi lang="java5">

 protected static String getHostname() {
   try {
     return java.net.InetAddress.getLocalHost().getHostName();
     // or java.net.InetAddress.getLocalHost().getCanonicalHostName();
   } catch (UnknownHostException ex) {
     return "Unknown";
   }
 }

</geshi>

Java Books I recommend