11/26/2013

java.util.Properties, trim, null, whitespace, and escaping

This is the simple test to show the values of properties when loading from a properties file. It tries to answer some common questions about properties value:

Do I need to trim whitespaces from a property value loaded from a properties file?

Yes. Leading whitespaces in a property value are automatically trimmed by Java, but trailing whitespaces are preserved. So if whitespaces are not significant, then property values need to be trimmed val.trim()


Do I need to check null when operating on a property value loaded from a properties file?

Yes. If a property does not exit in the properties file, then calling props.getProperty(key) will return null.


Do I need to check isEmpty when operating on a property value loaded from a properties file?

Yes. If only the key exits in the properties file without assigning any value, then calling props.getProperty(key) will return an empty string. If the value line contains only multiple whitespaces, they will be trimmed away and its value is still empty string.


Do I need to escape = : in property file?

No need to escape = or : in property value, but if the = or : is part of the property key, then you need to escape them. Java treats the first occurrence of = or : or whitespace as the key-value delimiter. So after the delimiter is identified, any use of them no longer needs escaping.

import java.util.*;
import java.io.*;

public class PropertiesTest {
    public static void main(String args[]) throws Exception {
        Properties props = new Properties();
        props.load(new FileInputStream(new File("a.properties")));
        for(String key : props.stringPropertyNames()) {
            System.out.printf("'%s' --> '%s'%n", key, props.getProperty(key));
        }

        System.out.printf("property.not.defined = %s%n", props.getProperty("adsfadsfdjsakfads"));
    }
}
The properties file a.properties:
no.value =
no.value.with.trailing.spaces =
prop.with.leading.trailing.spaces =      value              
prop.with.leading.spaces =      value
equal.sign.in.value = user=admin
colon.in.value = user:password
equal.sign.colon.in.value = user=admin:password=secrete
equal.sign.in.value.escaped = user\=admin
equal.sign.colon.in.value.escaped = user\=admin\:password\=secrete
\=\:in.key.escaped = value for =:in.key.escaped
=:in.key.not.escaped = value for =:in.key.not.escaped
To compile and run this program:
javac PropertiesTest.java
java PropertiesTest

'equal.sign.in.value' --> 'user=admin'
'equal.sign.colon.in.value' --> 'user=admin:password=secrete'
'no.value' --> ''
'prop.with.leading.spaces' --> 'value'
'equal.sign.in.value.escaped' --> 'user=admin'
'=:in.key.escaped' --> 'value for =:in.key.escaped'
'prop.with.leading.trailing.spaces' --> 'value     '
'colon.in.value' --> 'user:password'
'no.value.with.trailing.spaces' --> ''
'equal.sign.colon.in.value.escaped' --> 'user=admin:password=secrete'
'' --> ':in.key.not.escaped = value for =:in.key.not.escaped'
property.not.defined = null
For complete description, see java.util.Properties javadoc.

9/13/2013

NoSuchMethodError: javax.xml.parsers.DocumentBuilderFactory.newInstance

This is the error from running a webapp deployed to appserver:

java.lang.NoSuchMethodError: javax.xml.parsers.DocumentBuilderFactory.newInstance(Ljava/lang/String;Ljava/lang/ClassLoader;)Ljavax/xml/parsers/DocumentBuilderFactory;
The cause: there is an xml-apis.jar under JBOSS_HOME/lib/endorsed directory, and so javax.xml.* classes in xml-apis.jar override those same class from JDK. In particular, DocumentBuilderFactory class in xml-apis.jar is of old version and only has newInstance() method, but not newInstance(String, ClassLoader) method. DocumentBuilderFactory.newInstance(String factoryClassName, ClassLoader) is introduced in Java 6.

The fix is to remove xml-apis.jar from JBOSS_HOME/lib/endorsed directory. XML parser has been in Java proper for a long time, and there is no need for xml-apis.jar in most modern applications.

5/27/2013

java.io.IOException: No such file or directory and URI

You need to create a new file with a file URI like file:/tmp/a.txt, but had this error:

java.io.IOException: No such file or directory
 at java.io.UnixFileSystem.createFileExclusively(Native Method)
 at java.io.File.createNewFile(File.java:947)
 at FileTest.main(FileTest.java:7)
The directory /tmp (or java.io.tmpdir) should already exist and should have write permission for the application. So the error message may be complaining the file (a.txt) does not exist. But a.txt is the new file you are trying to create and of course it doesn't exist. Take another look at the source code:
import java.io.File;
import java.net.URI;

public class FileTest {
    public static void main(String args[]) throws Exception {
        File f = new File(args[0]);
        boolean b = f.createNewFile();
        if(b) {
            System.out.printf("Successfully created new file: %s%n", f);
        } else {
            System.out.printf("Failed to create new file: %s%n", f);
        }
    }
}
Run this class with different input, such as /tmp/a.txt, file:/tmp/a.txt:
$ java FileTest /tmp/a
Successfully created new file: /tmp/a

$ java FileTest /tmp/a
Failed to create new file: /tmp/a
# This failure is expected since /tmp/a already exists.

$ java FileTest file:/tmp/a
Exception in thread "main" java.io.IOException: No such file or directory
So the cause of the IOException is input file URI is not a valid file path. If you have a file URI, then you should use another File constructor to instantiate the File:

//to instantiate a file with URI
//TODO: need to handle java.net.URISyntaxException 
File f = new File(new URI(args[0]));

//to instantiate a filw with path string
File f = new File(args[0]);

12/10/2012

Java Thread Pools and their Thread Dumps

When analysing a thead dump, if the thread is created with a custom thread name, we can easily trace it to where the thread pool is created by the unique thread name.

Otherwise, we will have to guess which type of thread pool is created from the stack trace, and then search the usage of creation methods like newCachedThreadPool, newSingleThreadScheduledExecutor, newScheduledThreadPool, or newCachedThreadPool.

When using Executors.newCachedThreadPool on JDK 6:

"pool-1-thread-2" prio=5 tid=7ffb30143000 nid=0x117fde000 waiting on condition [117fdd000]
   java.lang.Thread.State: TIMED_WAITING (parking)
    at sun.misc.Unsafe.park(Native Method)
    - parking to wait for  <7f310c388> (a java.util.concurrent.SynchronousQueue$TransferStack)
    at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:196)
    at java.util.concurrent.SynchronousQueue$TransferStack.awaitFulfill(SynchronousQueue.java:424)
    at java.util.concurrent.SynchronousQueue$TransferStack.transfer(SynchronousQueue.java:323)
    at java.util.concurrent.SynchronousQueue.poll(SynchronousQueue.java:874)
    at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:945)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:907)
    at java.lang.Thread.run(Thread.java:680)

When using Executors.newCachedThreadPool on JDK 7:
"pool-1-thread-2" prio=5 tid=0x00007f90b38c9800 nid=0x5603 waiting on condition [0x000000016cb92000]
   java.lang.Thread.State: TIMED_WAITING (parking)
 at sun.misc.Unsafe.park(Native Method)
 - parking to wait for  <0x000000014c55bbd8> (a java.util.concurrent.SynchronousQueue$TransferStack)
 at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:226)
 at java.util.concurrent.SynchronousQueue$TransferStack.awaitFulfill(SynchronousQueue.java:460)
 at java.util.concurrent.SynchronousQueue$TransferStack.transfer(SynchronousQueue.java:359)
 at java.util.concurrent.SynchronousQueue.poll(SynchronousQueue.java:942)
 at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1043)
 at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1103)
 at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
 at java.lang.Thread.run(Thread.java:722)


When using Executors.newScheduledThreadPool(numOfCoreThreads) on JDK 6:
"pool-3-thread-1" prio=6 tid=0x4a5cc000 nid=0xc810 waiting on condition [0x4c96f000]
   java.lang.Thread.State: TIMED_WAITING (parking)
 at sun.misc.Unsafe.park(Native Method)
 - parking to wait for  <0x0934ccc8> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
 at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:196)
 at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(AbstractQueuedSynchronizer.java:2025)
 at java.util.concurrent.DelayQueue.take(DelayQueue.java:164)
 at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:609)
 at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:602)
 at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:947)
 at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:907)
 at java.lang.Thread.run(Thread.java:662)

When using Executors.newScheduledThreadPool(numOfCoreThreads) on JDK 7:
"pool-1-thread-1" prio=5 tid=0x00007f8075802000 nid=0x5503 waiting on condition [0x00000001610ed000]
   java.lang.Thread.State: WAITING (parking)
 at sun.misc.Unsafe.park(Native Method)
 - parking to wait for  <0x0000000140bbc108> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
 at java.util.concurrent.locks.LockSupport.park(LockSupport.java:186)
 at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2043)
 at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:1079)
 at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:807)
 at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1043)
 at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1103)
 at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
 at java.lang.Thread.run(Thread.java:722)


When using Executors.newSingleThreadScheduledExecutor on JDK 6:
"pool-1-thread-1" prio=5 tid=7ff0fe159800 nid=0x11442e000 waiting on condition [11442d000]
   java.lang.Thread.State: WAITING (parking)
    at sun.misc.Unsafe.park(Native Method)
    - parking to wait for  <7f310c8c0> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
    at java.util.concurrent.locks.LockSupport.park(LockSupport.java:156)
    at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:1987)
    at java.util.concurrent.DelayQueue.take(DelayQueue.java:160)
    at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:609)
    at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:602)
    at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:947)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:907)
    at java.lang.Thread.run(Thread.java:680)
  
When using Executors.newSingleThreadScheduledExecutor on JDK 7:
"pool-1-thread-1" prio=5 tid=0x00007ff7fb0aa000 nid=0x5503 waiting on condition [0x0000000169c4d000]
   java.lang.Thread.State: WAITING (parking)
 at sun.misc.Unsafe.park(Native Method)
 - parking to wait for  <0x000000014971c208> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
 at java.util.concurrent.locks.LockSupport.park(LockSupport.java:186)
 at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2043)
 at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:1079)
 at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:807)
 at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1043)
 at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1103)
 at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
 at java.lang.Thread.run(Thread.java:722)


When using Executors.newFixedThreadPool on JDK 6:
"pool-1-thread-2" prio=5 tid=7ff7c4854000 nid=0x118682000 waiting on condition [118681000]
   java.lang.Thread.State: WAITING (parking)
 at sun.misc.Unsafe.park(Native Method)
 - parking to wait for  <7f44c0048> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
 at java.util.concurrent.locks.LockSupport.park(LockSupport.java:156)
 at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:1987)
 at java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:399)
 at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:947)
 at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:907)
 at java.lang.Thread.run(Thread.java:680)

When using Executors.newFixedThreadPool on JDK 7:
"pool-1-thread-1" prio=5 tid=0x00007fb3b4070000 nid=0x5503 waiting on condition [0x000000016c6bf000]
   java.lang.Thread.State: WAITING (parking)
 at sun.misc.Unsafe.park(Native Method)
 - parking to wait for  <0x000000014c18b888> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
 at java.util.concurrent.locks.LockSupport.park(LockSupport.java:186)
 at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2043)
 at java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:442)
 at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1043)
 at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1103)
 at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
 at java.lang.Thread.run(Thread.java:722)