Friday, October 19, 2012

Best Practice when XML Content Writing to Files

For performance, there are many developers who create XML content using traditional StringBuffer or StringBuilder by appending values with start and end tags. This has a performance advantage than using a XML Library API to generate XML both memory wise as well as Computation wise. But many developers don't know a side effect which can occur by using this method.

For example if you create the XML content by appending strings and use the following

        StringBuilder xml = new StringBuilder("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
        xml.append("<envelope>");
        xml.append(String.format("<header>%s</header>", "Important"));
        xml.append(String.format("<body>%s</body>", "Hello, World!"));
        xml.append("</envelope>");
        BufferedWriter bw = null;
        try {
            bw = new BufferedWriter(new FileWriter("message.xml"));
            bw.write(xml.toString());
        } catch(Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if(bw != null) {
                    bw.close();
                }
            } catch (IOException e) {                
                e.printStackTrace();
            }
        }

The above code will work as long as for content of XML you have Characters which are accepted by the default character set of the Operating System you used to execute this code with. If the character set is not "UTF-8" as soon as you have something like this "CAFÉ" in your XML Content, the XML will be corrupted and will not be able to opened up using web browsers and cannot be parsed using any parsing API.

To fix this you can either ensure you will never have characters outside of the default character set of the Operating System or if you want "UTF-8" by any means, you can change the content writing as following which will fix the issue.

        try {
            FileOutputStream fos = new FileOutputStream("message.xml");
            bw = new BufferedWriter(new OutputStreamWriter(fos, "UTF8"));
            bw.write(xml.toString());
        } catch(Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if(bw != null) {
                    bw.close();
                }
            } catch (IOException e) {                
                e.printStackTrace();
            }
        }

In this scenario we are explicitly saying that we need the content to be written in UTF8 Character set using OutputStreamWriter.

Friday, October 5, 2012

Usage of ThreadLocal in Java

The ThreadLocal class is an important yet often neglected class in the java default library. Many developers don't understand the usage of this class so this is my attempt to explain it.

The definition of this class in official javadoc is

"This class provides thread-local variables. These variables differ from their normal counterparts in that each thread that accesses one (via its get or set method) has its own, independently initialized copy of the variable"

So according to the definition if an Instance of ThreadLocal variable is accessed by different threads each thread will get a copy of the variable which is not shared or visible by other threads. Simply put this class enables Thread confinement of variables. The usual approach developers use to have independent variables in different threads is they initialize and assign each thread an object instance which implements Runnable or extends Thread where the required variable is an instance variable in that object. 

But ThreadLocal is ideal where you want to initialize one object and assign them to different threads yet have independent variables. The following example shows the class at work.

public class ThreadLocalTest implements Runnable {
    private static ThreadLocal<Integer> no = new ThreadLocal<Integer>() {
        public Integer initialValue() {
            return 0;
        }
    };
    
    public static void main(String[] args) {
        Thread t1 = null;
        // Single Object
        ThreadLocalTest test = new ThreadLocalTest();
        for(int i=0;i<10;i++) {
            // test object is used in 10 Threads
            t1 = new Thread(test);        
            t1.start();
        }        
    }
    
    public void run() {
        System.out.printf("Before %s : %d\n", Thread.currentThread().getName(), no.get());
        no.set(no.get() + 1);
        System.out.printf("After %s : %d\n", Thread.currentThread().getName(), no.get());
    }
}

Only one object is created and used in 10 different threads yet each thread has its own initialized variable 'no'.