Monday, October 11, 2010

LazyHolder Pattern

Design Pattern

A pattern describes a proven solution to a recurring design problem, placing particular emphasis on the context and forces surrounding the problem, and the consequences and impact of the solution. Find more details about design patterns in http://java.sun.com/blueprints/corej2eepatterns/Patterns/index.html

Singleton Pattern

This pattern helps to create only one instance of a class in a ClassLoader. This is achieved by holding the created object in class level variable.

Eagerly Initialization:

Following are the points needs to be done

  • All constructor method has to be decalared with private access specifier
  • A variable has to be declared to hold the object with private access specifier and static and finalaccess modifier and singleton object created and assigned here itself
  • A method has to be created with public access specifier and static access modifier
SingleTonEarlyInitialization.java

public class SingleTonEarlyInitialization {
private static final SingleTonEarlyInitialization sObj = new SingleTonEarlyInitialization();

private SingleTonEarlyInitialization() {}

public static SingleTonEarlyInitialization getInstance() {
return sObj;
}
}

Lazy Initialization:

Following are the points needs to be done

  • All constructor method has to be decalared with private access specifier
  • A variable has to be declared to hold the object with private access specifier and static access modifier
  • A method has to be created with public access specifier and static access modifier and object will be created and returned from here.
SingleTonLazyInitialization.java

public class SingleTonLazyInitialization {
private static SingleTonLazyInitialization sObj = null;

private SingleTonLazyInitialization() {
}

public static SingleTonLazyInitialization getInstance() {
if(null == sObj)
sObj = new SingleTonLazyInitialization();
return sObj;
}
}

Thread Safe

In multi-threaded environment, Lazy Initialization based singleton is not threadsafe. Hence, getInstance() method has to be enforced with class level monitoring to achieve threadsafe.

Option 1 - Make getInstance() as Synchronized method
public static synchronized SingleTonLazyInitialization getInstance() {  
  if(null == sObj)
  sObj = new SingleTonLazyInitialization();  
  return sObj;
 }
Option 2 - Introduce Synchronized block on the class
public static SingleTonLazyInitialization getInstance() {
  synchronized(SingleTonLazyInitialization.class)
  {
  if(null == sObj)   
  sObj = new SingleTonLazyInitialization();
  }  
  return sObj;
 }
Option 3 - Introduce Synchronized block on the dummy Object
private static final Object lockObj=new Object();
 public static SingleTonLazyInitialization getInstance() {  
  synchronized(lockObj)
  {
  if(null == sObj)   
  sObj = new SingleTonLazyInitialization();
  }  
  return sObj;
 }
Performance Bottleneck

Introducing the synchronized block/method performs slightly slower than the normal and causes performance bottleneck. In the object instantiation time, we need to make sure that not more than one object get instantiated. Afterwards, any number of threads can possibly access with zero delay. While introducing the synchronized block/method, some delay may occur.

To overcome this delay, we may need to introduce the null-if check before obtaining the monitoring-lock.

private static final Object lockObj=new Object();
 public static SingleTonLazyInitialization getInstance() {
  if(null != sObj)
   return sObj;  
  synchronized(lockObj)
  {
  if(null == sObj)   
  sObj = new SingleTonLazyInitialization();
  }  
  return sObj;
 }

LazyHolder Pattern

Before object initialization itself, we get more than 100 threads span and waits to obtain the lock on synchronized block, then the above sample also will not perform good.

As per Java Language Specification, in JVM, class load and initialization phase is serial. Utilizing this as an advantage, we can initialize the singleton object through some other class initialization phase. This approach works as on-demand(lazy loading) initialization object.

public class SingletonLazyHolder { 
 private SingletonLazyHolder() {
 }
 
 private static class LazyHolder {
  private static final SingletonLazyHolder sObj = new SingletonLazyHolder();
 }
 
 public static SingletonLazyHolder getInstance() {  
  return LazyHolder.sObj;
 }
}

Multiton Pattern

Multiton pattern alows to have map of named instances as key-value pairs, in which getInstance() method key has to be passed and specific instance get initialized and returned.

MultitonSample.java:
import java.util.HashMap;
import java.util.Map;

public class MultitonSample {
 private static final Map<String,MultitonSample> maps = new HashMap<String,MultitonSample>();

 private MultitonSample() {
 }

 public static MultitonSample getInstance(String key) {
  MultitonSample mObj = null;
  synchronized(maps)
  {
   mObj = maps.get(key);
   if(null == mObj)
   {
    mObj = new MultitonSample();
    maps.put(key, mObj);
   }
  }
  return mObj;
 }
}

Monday, October 4, 2010

DataTypeConverter usage in JAXB

JAXB : DataTypeConverter

Accessing the actual value as-it-is using JAVA API will be pain in some cases. For instance, list of values get stored in attribute with comma separation. Now, these value has to be retrieved as List object rather String object, then only it make sense and simple to use.

We are extending the sample written in JAXB Sample post to explain DataTypeConverter and XMLAdapter.

fruits.xsd

<?xml version="1.0" encoding="utf-8"?>
<schema targetNamespace="http://mycompany.org/jaxbsample"
 xmlns="http://www.w3.org/2001/XMLSchema" xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified"
 xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" jaxb:version="2.1">
 <annotation>
  <appinfo>
   <jaxb:schemaBindings>
    <jaxb:package name="jaxbexample.model" />
   </jaxb:schemaBindings>
  </appinfo>
 </annotation>


 <element name="Fruits">
  <complexType>
   <sequence>
    <element name="Fruit" maxOccurs="unbounded">
     <complexType>
      <attribute name="name" type="string" />
      <attribute name="qty" type="int" />
      <attribute name="listValue" type="string">
       <annotation>
        <appinfo>
         <jaxb:property>
          <jaxb:baseType>
           <jaxb:javaType
            name="Object"
            parseMethod="jaxbexample.DataTypeConverter.parseStringToList"
            printMethod="jaxbexample.DataTypeConverter.printListToString" />
          </jaxb:baseType>
         </jaxb:property>
        </appinfo>
       </annotation>
      </attribute>
     </complexType>
    </element>
   </sequence>
  </complexType>
 </element> 
</schema>

jaxbexample.DataTypeConverter is a JAVA file and it has two methods parseStringToList, printListToString. In the time of generating JAXB beans, Adapter1.java is get created in jaxbexamples.model package.

DataTypeConverter.java

package jaxbexample;

import java.util.ArrayList;
import java.util.List;

public class DataTypeConverter {

 /** This method called in the time of unmarshalling
  * XML to Java
  * @param value
  * @return
  */
 public static List<String> parseStringToList(String value) {
  
  List<String> list = new ArrayList<String>();
  if (null == value || "".equals(value))
   return list;

  
  String[] strs = value.split(",");
  for (String str : strs) {
   list.add(str);
  }

  return list;
 }

 /** This method called in the time of marshalling
  * Java to XML
  * @param val
  * @return
  */
 public static String printListToString(List<String> val) {

  if (null == val)
   return null;

  StringBuilder sb = new StringBuilder();
  for (String str : val) {
   if (sb.length() > 0)
    sb.append(",");
   sb.append(str);
  }

  return sb.toString();
 }
}

JAXBAdapterSample.java

package jaxbexample;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;

import jaxbexample.model.Fruits;
import jaxbexample.model.Fruits.Fruit;

public class JAXBAdapterSample {

 public static void main(String[] args) throws Exception {

  String filename = "./jaxbexample/fruits.xml";
  InputStream is = new FileInputStream(filename);

  Fruits fruits = (Fruits) unmarshallObject(is);

  for (Fruit fruit : fruits.getFruit()) {
   System.out.println("Name : " + fruit.getName() + " Qty:"
     + fruit.getQty());

   fruit.setQty(fruit.getQty() + 1);
   int i = 1;
   for (String possiblefruit : (List<String>) fruit.getListValue()) {
    System.out.println(i++ + ". " + possiblefruit);
   }
  }
 }

 public static Object unmarshallObject(InputStream is) throws Exception {
  String packageName = "jaxbexample.model";
  JAXBContext context = JAXBContext.newInstance(packageName);
  Unmarshaller unmarshaller = context.createUnmarshaller();
  Object jaxbObject = unmarshaller.unmarshal(is);
  return jaxbObject;

 }

 public static void marshallObject(Object o, String filename)
   throws Exception {
  String packageName = "jaxbexample.model";
  File f = new File(filename);

  JAXBContext context = JAXBContext.newInstance(packageName);
  Marshaller marshaller = context.createMarshaller();
  marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
  marshaller.setProperty(Marshaller.JAXB_ENCODING, "UTF-8");

  OutputStream fos = new FileOutputStream(f);
  marshaller.marshal(o, fos);

  try {
   fos.close();
  } finally {
   // do nothing
  }
 }

}

output

Name : Apple Qty:10
1. Apple
2. Orange
3. Banana
Name : Orange Qty:5
1. Apple
2. Orange
3. Banana
Name : Banana Qty:20
1. Apple
2. Orange
3. Banana

Simple JAXB Sample

JAXB

Java Architecture for XML Binding (JAXB) helps to read/write XML Document using simple JAVA APIs. Based on the structure of the XSD, JAVA classes and APIs are generated.

JAXB implementation from eclipse can be downloaded from Nightly Build. MoXy(JAXB) has the necessary tools, and runtime jars. To create java classes jaxb-compiler command get used

jaxb-compiler.cmd /tmp/fruits.xsd -d /eclipse/work/TestProject

Now, JAVA files will be created in /eclipse/work/TestProject location under the package jaxbexample.model. Since this package name mentioned in XSD.

fruits.xsd

<?xml version="1.0" encoding="utf-8"?>
<schema targetNamespace="http://mycompany.org/jaxbsample"
 xmlns="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified"
 xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" jaxb:version="1.0">
 <annotation>
  <appinfo>
   <jaxb:schemaBindings>
    <jaxb:package name="jaxbexample.model" />
   </jaxb:schemaBindings>
  </appinfo>
 </annotation>


 <element name="Fruits">
  <complexType>
   <sequence>
    <element name="Fruit" maxOccurs="unbounded">
     <complexType>
      <attribute name="name" type="string" />
      <attribute name="qty" type="int" />
      <attribute name="listValue" type="string">
      </attribute>
     </complexType>
    </element>
   </sequence>
  </complexType>
 </element> 
</schema>

UnMarshalling

Load the XML content and convert to JAVA object in runtime.


public static Object unmarshallObject(InputStream is) throws Exception {
  String packageName = "jaxbexample.model";
  JAXBContext context = JAXBContext.newInstance(packageName);
  Unmarshaller unmarshaller = context.createUnmarshaller();
  Object jaxbObject = unmarshaller.unmarshal(is);
  return jaxbObject;

 }

Marshalling

Convert/persist JAVA object into XML Document content.


public static void marshallObject(Object o, String filename) throws Exception {
  String packageName = "jaxbexample.model";
  File f = new File(fileName);
  
  JAXBContext context = JAXBContext.newInstance(packageName);
  Marshaller marshaller = context.createMarshaller();
  marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
  marshaller.setProperty(Marshaller.JAXB_ENCODING, "UTF-8");

  OutputStream fos = new FileOutputStream(f);
  marshaller.marshal(o, fos);

  try {
   fos.close();
  } finally {
   // do nothing
  }
 }

fruits.xml

Create fruits.xml file in jaxbexamples package as below

<?xml version="1.0" encoding="UTF-8"?>
<Fruits xmlns="http://mycompany.org/jaxbsample" xmlns:ns0="http://mycompany.org/jaxbsample">
   <Fruit name="Apple" qty="10" listValue="Apple,Orange,Banana"/>
   <Fruit name="Orange" qty="5" listValue="Apple,Orange,Banana"/>
   <Fruit name="Banana" qty="20" listValue="Apple,Orange,Banana"/>
</Fruits>

JAXBSample.java


package jaxbexample;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;

import jaxbexample.model.Fruits;
import jaxbexample.model.Fruits.Fruit;

public class JAXBSample {

 public static void main(String[] args) throws Exception {

  String filename = "./jaxbexample/fruits.xml";
  InputStream is = new FileInputStream(filename);

  Fruits fruits = (Fruits) unmarshallObject(is);

  for (Fruit fruit : fruits.getFruit()) {
   System.out.println("Name : " + fruit.getName() + " Qty:"
     + fruit.getQty());

   fruit.setQty(fruit.getQty() + 1);
  }
  marshallObject(fruits, filename);
 }

 public static Object unmarshallObject(InputStream is) throws Exception {
  String packageName = "jaxbexample.model";
  JAXBContext context = JAXBContext.newInstance(packageName);
  Unmarshaller unmarshaller = context.createUnmarshaller();
  Object jaxbObject = unmarshaller.unmarshal(is);
  return jaxbObject;

 }

 public static void marshallObject(Object o, String filename)
   throws Exception {
  String packageName = "jaxbexample.model";
  File f = new File(filename);

  JAXBContext context = JAXBContext.newInstance(packageName);
  Marshaller marshaller = context.createMarshaller();
  marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
  marshaller.setProperty(Marshaller.JAXB_ENCODING, "UTF-8");

  OutputStream fos = new FileOutputStream(f);
  marshaller.marshal(o, fos);

  try {
   fos.close();
  } finally {
   // do nothing
  }
 }
}

Output

After running first time the above given JAXBSample program, the @qty will be increased by 1.

Name : Apple Qty:11
Name : Orange Qty:6
Name : Banana Qty:21

Some useful links JAXB @ Oracle | jaxb.dev.java.net

Recent Posts

Unix Commands | List all My Posts

Texts

This blog intended to share the knowledge and contribute to JAVA Community such a way that by providing samples and pointing right documents/webpages. We try to give our knowledege level best and no guarantee can be claimed on truth. Copyright and Terms of Policy refer blogspot.com