Java Tips: Difference between revisions

From EggeWiki
No edit summary
 
No edit summary
 
(14 intermediate revisions by 2 users not shown)
Line 1: Line 1:
== [[RegexFieldValidation]] ==
== [[FindBugs]] ==


== [[JavaNaming]] ==
== [[Cobertura]] ==


== javax.activation.UnsupportedDataTypeException ==
== [[Java Unique List]] ==


Nothing like starting yout Monday morning with a Java classloader issue.  My fix to the problem is here: [[JavaMailFun]].
== Ant tips moved to [[Ant Tips]] ==


== Cannot run this command because Java services are not enabled ==
== [[Range]] ==


When connecting to Sybase via jconn3 and Spring 2.0, you receive the error:
==The ordinal 2821 could not be located in the dynamic link library LIBEAY32.dll==
<pre>
Cannot run this command because Java services are not enabled
</pre>


This can be caused by passing a '''char''' type as on of the arguments. Example:
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 [[http://www.changelogic.com/FrequentlyAskedQuestions#h72-1063406330 Changelogic]])


<pre>
== [[RegexFieldValidation]] ==
char gender = 'M';
jdbcTemplate.queryForObject(
                "SELECT top 1 first_name from people where gender = ?",
                String.class,
                gender);
</pre>


Fix:  Simply convert the char to a String.  I.e., String.valueOf(gender).
== [[JavaNaming]] ==


== xml-rpc and Weblogic 9.2 ==
== javax.activation.UnsupportedDataTypeException ==


xml-rpc with Basic Authentication works fine in Resin, but not WeblogicThis turned out to be a new feature in 9.2 which forces authentication checks when you specifically don't want one.
Nothing like starting yout Monday morning with a Java classloader issueMy fix to the problem is here: [[JavaMailFun]].
 
:Basic Authentication does not work with WebLogic 9.2. (Issue #55793)
:
:Workaround: If users do NOT want to authenticate basic authentication headers, they need to add this to their config.xml. Add this element:


:<enforce-valid-basic-auth-credentials>false</enforce-valid-basic-auth-credentials> to the last line of <security-configuration> in config.xml for the users domain, usually in /bea/user_projects/domains/mydomain/config/config.xml. This keeps WebLogic from trying to authenticate basic authentication headers.




Line 42: Line 28:


== Use platform dependent end of line character ==
== Use platform dependent end of line character ==
<pre>
<geshi lang="java5">
   private static final String EOL = System.getProperty("line.separator");
   private static final String EOL = System.getProperty("line.separator");
</pre>
</geshi>
See http://java.sun.com/j2se/1.5.0/docs/api/java/lang/System.html#getProperties()
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 ==
<pre>
    <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>
</pre>
== Replacement for StringBufferInputStream ==
[[http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4217782 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:
<pre>
class StringReaderInputStream extends InputStream {
    private final StringReader reader;
    public StringReaderInputStream(String s) {
        reader = new StringReader(s);
    }
    public int read() throws IOException {
        return reader.read();
    }
}
</pre>
== replaceAll Backreferences==
Regex functions can give you fast replacements in Java, along with the readability of Perl.
<pre>
        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);
</pre>


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


<pre>
<geshi lang="java5">
     public void testStringBuilderWTF() {
     public void testStringBuilderWTF() {
         StringBuilder a = new StringBuilder("foo");
         StringBuilder a = new StringBuilder("foo");
Line 102: Line 44:
         assertEquals(a, b);
         assertEquals(a, b);
     }
     }
</pre>
</geshi>


<font color="red">
<font color="red">
Line 122: Line 64:
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.
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.


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


==unmappable character for encoding UTF8==
==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.  [http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=5071879 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:  
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.  [http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=5071879 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:  
<pre>char currency = '£'</pre>
<geshi lang="java5">char currency = '£'</geshi>
write  
write  
<pre>char currency = '\u20A4'</pre>
<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 &copy; 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:
<pre>
log4j:WARN No appenders could be found for logger (net.sourceforge.cruisecontrol.Main).
log4j:WARN Please initialize the log4j system properly.
</pre>
 
Despite having an option like <code>-Dlog4j.configuration=/u/eggebr/mylog4j.properties</code> 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 <code>-Dlog4j.configuration=<b>file:</b>/u/eggebr/mylog4j.properties</code>. 
 
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:
 
<pre>
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
</pre>
 
==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]]
 
[http://www.java2html.de Offline HTML code formatter with Ant task]
 
[http://www.chamisplace.com/colorizer/cc.asp 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.
* [[CUSIP Source Code]]
 
==Apple uses Java for their iTunes Store==
 
<pre>
  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
</pre>
 
[http://www.datadosen.se/riverlayout/ 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==
 
* [http://www.amazon.com/Java-Concurrency-Practice-Brian-Goetz/dp/0321349601 Java Concurrency in Practice]
 
* [http://www.amazon.com/exec/obidos/tg/detail/-/0596006764/qid=1112042314/sr=8-1/ref=pd_csp_1/102-4376033-3626518?v=glance&s=books&n=507846 Better, Faster, Lighter Java]
* [http://www.amazon.com/exec/obidos/tg/detail/-/0596005687/qid=1090896157/sr=8-1/ref=sr_8_xs_ap_i1_xgl14/002-7988240-9687218?v=glance&s=books&n=507846 Hardcore Java]


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
[[Category:Java|Tips, Java]]

Latest revision as of 22:41, 8 October 2009

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