Java Tips: Difference between revisions

From EggeWiki
No edit summary
Line 1: Line 1:
== [[Why I dislike mocks]] ==
== Use platform dependent end of line character ==
== Use platform dependent end of line character ==
<pre>
<pre>

Revision as of 00:17, 12 March 2007

Why I dislike mocks

Use platform dependent end of line character

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

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

Use ant to create a properties java file which can be compiled

    <target name="build-properties">
       <copy todir="src">
            <fileset dir="src">
                <include name="**/*.hava"/>
            </fileset>
           <globmapper from="*.hava" to="*.java"/>
           <filterset>
               <filtersfile file="src/resources/messages_en_AU_company.properties" />
           </filterset>
        </copy>
    </target>

Replacement for StringBufferInputStream

[Bug ID: 4217782] States that StringBufferInputStream is depreciated and should be replaced with StringReader, but StringReader is not an input stream. I frequently need to turn a String into a stream for testing, so I created this class:

class StringReaderInputStream extends InputStream {

    private final StringReader reader;

    public StringReaderInputStream(String s) {
        reader = new StringReader(s);
    }

    public int read() throws IOException {
        return reader.read();
    }
}

replaceAll Backreferences

Regex functions can give you fast replacements in Java, along with the readability of Perl.

        String account = "1234567890123456";
        String replacement = account.replaceAll("(\\d{4})(\\d{2})(\\d{6})(\\d{4})", "$1 $2XX XXXX $4");
        assertEquals("1234 56XX XXXX 3456", replacement);

StringBuilder

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

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

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.

    // 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);

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:

char currency = '£'

write

char currency = '\u20A4'

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:

find . -name "*.jar" -type f -exec jar -tvf \{\} \; | cut -b 37- | grep "\.class" | sort | uniq -dc | sort

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:

  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");
  }

Ant is great, but the XML gets to suck after a while.

 Excerpt from James Duncan Davidson, the author of Ant.
 If I knew then what I knew now, I would have tried using a real scripting language, such as ~JavaScript via the Rhino component or Python via JPython, with bindings to Java objects which implemented the functionality expressed in todays tasks. Then, there would be a first class way to express logic and we wouldn't be stuck with XML as a format that is too bulky for the way that people really want to use the tool.

Ant is giving you this error when using a fileset:

java.lang.NoClassDefFoundError: org/apache/oro/text/regex/MalformedPatternException

You need to download the Jararta ORO libarary. Install the jar in you ant/lib directory.

! You get some stack trace like this:

 java.lang.NumberFormatException: multiple points
  at java.lang.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:1067)
  at java.lang.Double.parseDouble(Double.java:220)
  at java.text.DigitList.getDouble(DigitList.java:127)
  at java.text.DecimalFormat.parse(DecimalFormat.java:1070)
  at java.text.SimpleDateFormat.subParse(SimpleDateFormat.java:1705)
  at java.text.SimpleDateFormat.parse(SimpleDateFormat.java:1156)
  at java.text.DateFormat.parse(DateFormat.java:333)

This might be caused by your ~SimpleDateFormat object being used concurrently. The spec says you can't:

  Date formats are not synchronized. It is recommended to create separate format instances for
  each thread. If multiple threads access a format concurrently, it must be synchronized externally.

Directory Permissions for JVM

Help! When run as my user this works fine. When I run as 'foo', it gives me this nasty error

$ 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)

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

jar xvf archive.jar filename.txt

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

Remove Ant Configuration Dialog from Eclipse

In Eclipse 3.0 you can launch Ant tasks. This is a great feature. If you don't want to run with the default settings, you can open the configuration settings and add environment variables and add flags. Sometimes I like to add a "-verbose" flag. The problem is after this you are stuck with the configuration dialog popping up each time you launch a target. To stop this, you must delete files in your Eclipse workspace settings. My files are in:

H:\eclipseworkspace\.metadata\.plugins\org.eclipse.debug.core\.launches

Then restart Eclipse, and you can now run Ant tasks simply by double clicking on them.

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"

  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();
  }

How to require an environment variable in an Ant file

<property environment="env"/><BR>
<fail message="Provide MY_VAR" unless="env.MY_VAR"/>

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

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

Java Books I recommend