Java Tips: Difference between revisions

From EggeWiki
No edit summary
 
Line 21: Line 21:
Nothing like starting yout Monday morning with a Java classloader issue.  My fix to the problem is here: [[JavaMailFun]].
Nothing like starting yout Monday morning with a Java classloader issue.  My fix to the problem is here: [[JavaMailFun]].


== Cannot run this command because Java services are not enabled ==
When connecting to Sybase via jconn3 and Spring 2.0, you receive the error:
<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:
<geshi lang="java5">
char gender = 'M';
jdbcTemplate.queryForObject(
                "SELECT top 1 first_name from people where gender = ?",
                String.class,
                gender);
</geshi>
Fix:  Simply convert the char to a String.  I.e., String.valueOf(gender).
== xml-rpc and Weblogic 9.2 ==
xml-rpc with Basic Authentication works fine in Resin, but not Weblogic.  This turned out to be a new feature in 9.2 which forces authentication checks when you specifically don't want one.
: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 61: Line 33:
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()


== 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:
<geshi lang="java5">
class StringReaderInputStream extends InputStream {
    private final StringReader reader;
    public StringReaderInputStream(String s) {
        reader = new StringReader(s);
    }
    public int read() throws IOException {
        return reader.read();
    }
}
</geshi>
== replaceAll Backreferences==
Regex functions can give you fast replacements in Java, along with the readability of Perl.
<geshi lang="java5">
        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);
</geshi>
Another fun regex can simulate the the unix 'basename' function.
<geshi lang="java5">
assertEquals("RegexTest", this.getClass().getName().replaceAll("(?:\\w+\\.)*(\\w+)", "$1"));
</geshi>


== StringBuilder ==
== StringBuilder ==

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