9/24/2014

Diff tools: diff, vimdiff, opendiff & twdiff

4 diff tools that can be executed from command line:

  1. diff (/usr/bin/diff): pure CLI with text output, available in any terminals:
    /tmp > diff Hello.java Hello2.java
    1c1
    < public class Hello {
    ---
    > public class Hello2 {
    3c3
    <         System.out.println("Hello from " + Hello.class);
    ---
    >         System.out.println("Hello2 from " + Hello2.class);
    

    use -wub option to view contextual diff:
    /tmp > diff -wub Hello.java Hello2.java
    --- Hello.java 2014-09-24 13:16:55.000000000 -0400
    +++ Hello2.java 2014-09-24 13:18:01.000000000 -0400
    @@ -1,5 +1,5 @@
    -public class Hello {
    +public class Hello2 {
         public static void main(String[] args) {
    -        System.out.println("Hello from " + Hello.class);
    +        System.out.println("Hello2 from " + Hello2.class);
         }
     }
    

  2. vimdiff (/usr/bin/vimdiff): part of vim, available in any terminals, pure CLI but blocks the current terminal:
    vimdiff Hello.java Hello2.java
    

  3. opendiff (/usr/bin/opendiff): part of Mac OS xcode tools, launches a FileMerge window for diff and merge:  
    opendiff Hello.java Hello2.java
    



  4. twdiff (/usr/local/bin/twdiff): command line tool of TextWrangler, and launches 3 separate TextWrangler windows for diff and merge.
    twdiff Hello.java Hello2.java
    


7/24/2014

java.util.Properties and character encoding

java.util.Properties class (see Java SE 7 Javadoc) by default assumes ISO 8859-1 character encoding in reading and writing. So when a properties file is in other character encoding, you will see strange characters and behaviors.

Properties class has no method or constructor that takes encoding or locale parameter. Fortunately, in Java SE 6, two new methods were added to allow for reading from java.io.Reader and writing to java.io.Writer:

public synchronized void load(Reader reader) throws IOException;

public void list(PrintWriter out)
So you can create Reader or Writer instances with appropriate encoding, and pass them to Properties load or list methods. For example,
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.util.Properties;

import org.junit.Test;

public class MyTest {

    @Test
    public void loadPropertiesTest() throws Exception {
        final File jndiPropertiesFile = new File(System.getProperty("user.home"), "tmp/jndi.properties");
        final FileInputStream fileInputStream = new FileInputStream(jndiPropertiesFile);

        // FileReader does not have any constructor that takes encoding, so use InputStreamReader instead
        final InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream, "UTF-8");

        final Properties jndiProperties = new Properties();
        jndiProperties.load(inputStreamReader);

        //now dump the properties to verify
        jndiProperties.list(System.out);
    }
}
Output from running loadPropertiesTest test:
-- listing properties --
java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory
java.naming.provider.url=jnp://localhost:1099
java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces

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 = or : characters 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.