Monday, 23 January 2012

Copying Java Objects: Shallow copy and Deep copy

This post gives you overview different type of object copying mechanism in JAVA.

Shallow Copy

  This is done using clone() method in any class. When you clone the object using clone() method, (of course the class of object type should implement cloneable interface before you do this) a new object is created and the instance variables are newly created. If all the instance variables of the object are of primitive data type, then no work is needed inside clone() method other than calling super.clone().

Please take a close look at the following example, in which instance variable of type "StringBuffer" is just copied while cloning and not created newly. The output shows any modification to the value of this instance variable affects both the original and cloned object.

package samples.clone;

public class ShallowCopySample implements Cloneable
{
 private String myName;
 private int mySalary;
 private StringBuffer myFamilyMembers = new StringBuffer().append("K").append("P");
 public StringBuffer getMyFamilyMembers()
 {
  return myFamilyMembers;
 }
 public void setMyFamilyMembers(StringBuffer myFamilyMembers)
 {
  this.myFamilyMembers = myFamilyMembers;
 }
 public String getMyName()
 {
  return myName;
 }
 public void setMyName(String myName)
 {
  this.myName = myName;
 }
 public int getMySalary()
 {
  return mySalary;
 }
 public void setMySalary(int mySalary)
 {
  this.mySalary = mySalary;
 }

 ShallowCopySample(String name, int salary)
 {
  this.myName = name;
  this.mySalary = salary;
 }

 @Override
 protected Object clone() throws CloneNotSupportedException
 {
  return super.clone();
 }
 public static void main(String[] args) throws CloneNotSupportedException
 {
  ShallowCopySample scs1 = new ShallowCopySample("Suresh", 50000);
  System.out.println("SCS1 before cloning:"+scs1.getMyName()+","+scs1.getMySalary());

  // shallow cloning
  ShallowCopySample scs2 = (ShallowCopySample)scs1.clone();
  scs2.setMySalary(30000);
  scs2.setMyName("Transmode");
  scs2.setMyFamilyMembers(scs2.getMyFamilyMembers().append("A"));

  System.out.println("SCS1 after cloning:"+scs1.getMyName()+","+scs1.getMySalary()+","+scs1.getMyFamilyMembers());
  System.out.println("SCS2 after cloning:"+scs2.getMyName()+","+scs2.getMySalary()+","+scs2.getMyFamilyMembers());
 }
}

The output of the above program is,

 
SCS1 before cloning:Suresh,50000
SCS1 after cloning:Suresh,50000,KPA
SCS2 after cloning:Transmode,30000,KPA



Deep Copy

  This is nothing but serialization of object, the class should implement java.io.Serializable interface. This copies the object through stream of bytes or writes the object into a file. It ensures that original and cloned object instances and it's instance variables are different.
Note: The serialization mechanism is used in Java RMI.

Please take a close look at the following example,

package samples.clone;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
public class DeepCopySample implements Serializable
{
 /**
  *
  */
 private static final long serialVersionUID = 1L;
 private String myName;
 private int mySalary;
 private StringBuffer myFamilyMembers = new StringBuffer().append("K").append("P");

 public StringBuffer getMyFamilyMembers()
 {
  return myFamilyMembers;
 }
 public void setMyFamilyMembers(StringBuffer myFamilyMembers)
 {
  this.myFamilyMembers = myFamilyMembers;
 }
 public String getMyName()
 {
  return myName;
 }
 public void setMyName(String myName)
 {
  this.myName = myName;
 }
 public int getMySalary()
 {
  return mySalary;
 }
 public void setMySalary(int mySalary)
 {
  this.mySalary = mySalary;
 }

 DeepCopySample(String name, int salary)
 {
  this.myName = name;
  this.mySalary = salary;
 }
 /**
  * copy the object using stream of bytes serializable mechanism
  * @param orig
  * @return
  */
 public static Object copy(Object orig) {
        Object obj = null;
        try {
            // Write the object out to a byte array
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            ObjectOutputStream out = new ObjectOutputStream(bos);
            out.writeObject(orig);
            out.flush();
            out.close();
            // Make an input stream from the byte array and read
            // a copy of the object back in.
            ObjectInputStream in = new ObjectInputStream(
                new ByteArrayInputStream(bos.toByteArray()));
            obj = in.readObject();
        }
        catch(IOException e) {
            e.printStackTrace();
        }
        catch(ClassNotFoundException cnfe) {
            cnfe.printStackTrace();
        }
        return obj;
    }

 public static void main(String[] args) {
  DeepCopySample dcs1 = new DeepCopySample("Suresh", 50000);

  System.out.println("DCS1 before cloning:"+dcs1.getMyName()+","+dcs1.getMySalary());

  // deep cloning
  DeepCopySample dcs2 = (DeepCopySample)DeepCopySample.copy(dcs1);
  dcs2.setMySalary(30000);
  dcs2.setMyName("Transmode");
  dcs2.setMyFamilyMembers(dcs2.getMyFamilyMembers().append("A"));

  System.out.println("DCS1 after cloning:"+dcs1.getMyName()+","+dcs1.getMySalary()+","+dcs1.getMyFamilyMembers());
  System.out.println("DCS2 after cloning:"+dcs2.getMyName()+","+dcs2.getMySalary()+","+dcs2.getMyFamilyMembers());
 }
}

The output of the above program is,
DCS1 before cloning:Suresh,50000
DCS1 after cloning:Suresh,50000,KP
DCS2 after cloning:Transmode,30000,KPA

Thursday, 19 January 2012

JAVA Persistence: A Quick review of Hibernate, EJB2.1 & EJB3.0 tool

This article gives you complete overview of Hibernate and EJB and also comparison b/w them.

Comparing EJB and Hibernate

EJBs are supposed to be components, in the sense that they're not just one class, but a set of classes, descriptors (thats an XML and/or annotations in EJB 3), usage and management contracts. All of this in order to allow a container (JBoss, Weblogic, etc.) to provide services to those components, and to be able to reuse and distribute this components. This services are, among others, transactions, concurrent access control, security, instance pooling, etcetera.
Hibernate is "just" an ORM (Object/Relational Mapping) tool. Quick and dirty, this means you can store an object tree belonging to an class hierarchy in a relational DB without writing a single SQL query. Very easy way to achieve persistence, IMO. But no transaction control, no instance pooling, no concurrency control, and certainly no security.
Just look at the below simple example to get an idea about persistence using Hibernate,

Hibernate needs configuration file (hibernate.cfg.xml) to create database connection which will look like as below,

<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
          "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
          "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
 <session-factory>
  <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/StockMarket</property>
  <property name="hibernate.connection.username">root</property>
  <property name="hibernate.connection.password">admin123</property>
      <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
            <property name="hibernate.connection.isolation">2</property>
  <property name="dialect">org.hibernate.dialect.MySQLDialect</property>
  <property name="transaction.factory_class">org.hibernate.transaction.JDBCTransactionFactory</property>
         <property name="current_session_context_class">thread</property>
           <property name="hibernate.show_sql">false</property>

  <!-- mapping files -->
  <mapping resource="com/example/Stock.hbm.xml" />
 </session-factory>
</hibernate-configuration>

// The Stock object will be mapped to "Stock" table in Hibernate
public class Stock implements Serializable {
  String name;
  float price;  
  // getters and setters for "name" and "price" member variables
  ...................
}

Stock.hbm.xml will look like,

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
 <class name="com.example.Stock" table="Stock" lazy="false">
  <id name="name" column="Name" type="string">
   <generator class="assigned" />
  </id>
  <property column="Price" name="price" type="float"/>
 </class>
</hibernate-mapping>

One need to write the CRUD (Create, Retrieve, Update and Delete) operation in DAO class to operate/control the Stock object in database. Take a loot at StockDAO class as below,

public final class HibernateUtil {
  public static Session getSession() {
    return Configuration.configure().buildSessionFactory().getCurrentSession();
  }
}

public class StockDAO {
     public void addStock(Stock s) {
    Session session = HibernateUtil.getSession();
    Transaction t = session.getTransaction();
    try {
          t.beginTransaction();
          session.persist(s);
          t.commit();         
    } catch(Exception e) {
          t.rollback();
    }
}

Look at the below simple example to get an idea about persistence using EJB 2.1,
Note: this example uses the bean-managed way to persit JAVA objects. One more way of persisting is container-managed


// primary key
public class StockBeanPK implement java.io.Serializable {
  private String name;
  StockBeanPK(String name) { this.name = name;}
  public int hashcode() { name.hashcode());
  public boolean equals(Object name) {   this.name.equals(name);}
}


// entity bean
public interface StockBean extends javax.ejb.EntityBean {
  public void setPrice(Float price) throws RemoteException;
}


// home interface
public interface StockHome extends javax.ejb.EJBHome {
  public Stock create(Stock s) throws RemoteException, CreateException;
}


// remote interface
public interface Stock extends javax.ejb.EJBObject {
  public Stock create(Stock s) throws RemoteException, CreateException;
}


// entity bean object impl
public class StockImpl implements StockBean {
   StockBeanPK pk;
   float price;  
  // getters and setters for "price" member variables
  ...................
}


// remote object impl
public class StockImpl implements Stock {  
  public Stock create(Stock s) {
  InitialContext it = new InitialContext();
  // this lookup url refers to the database in which entity beans are persisted
  ds = (DataSource)it.lookup("java:comp/env/jdbc/StockMarketDB");
  Connection conn = ds.getConnection();
 
  try {
    // store Object state in DB
    stmt = conn.prepareStatement("insert into stock values(?,?)");
    String pk = (String)entityContext.getPrimaryKey();
    stmt.setString(1, pk.name);
    stmt.setFloat(2, s.getPrice());
    stmt.executeUpdate();
   } catch (SQLException e) {
     throw new javax.ejb.EJBException("Failed to store bean to database", e);
   } finally {
      try {
        if (stmt != null) stmt.close();  // close statement
        if (conn != null) conn.close();  // release connection
      } catch (Exception ignore) {}
   }
  }
}

/** Implement the local interface as same as above remote object implementation **/


Look at the below simple example to get an idea about persistence using EJB 3.0,

In EJB3.0, the configuration file (Persistence.xml) looks like as below,
Note: this file is almost same as hibernate.cfg.xml file in Hibernate. EclipseLink is one of the Persistence Provider that wraps the EJB 3.0 implementations.

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
  <persistence-unit name="tnm_alarm_implPU" transaction-type="RESOURCE_LOCAL">
    <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
    <class>com.example.Stock</class>
    <properties>
      <property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/StockMarket"/>
      <property name="javax.persistence.jdbc.user" value="root"/>
      <property name="javax.persistence.jdbc.password" value="root"/>
      <property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver"/>
      <property name="eclipselink.ddl-generation" value="create-tables"/>
    </properties>
  </persistence-unit>
</persistence>

// The Stock entity will be mapped to "Stock" table in EJB3.0 annotations
@Entity
@Table(name="Stock");
public class Stock implements Serializable {
 @Id
 @Column(name="name")
  String name;
  @Column(name="price")
  float price;  
  // getters and setters for "name" and "price" member variables
  ...................
}

public final class EntityManagerEAO {
  final String PERSISTENCE_UNIT = "EntityService";
 static final emFactory;
  private static final Map<String, Object> properties = new HashMap<String, Object>()
    {
        private static final long serialVersionUID = -6262745355119727515L;
       
        {
            put(PersistenceUnitProperties.TRANSACTION_TYPE,  PersistenceUnitTransactionType.RESOURCE_LOCAL.name());
            put("provider", "org.eclipse.persistence.jpa.PersistenceProvider");
            put(PersistenceUnitProperties.JDBC_DRIVER, "com.mysql.jdbc.Driver");
            put(PersistenceUnitProperties.DDL_GENERATION, PersistenceUnitProperties.NONE);
            put(PersistenceUnitProperties.BATCH_WRITING, "JDBC");
        }
    };
  public static EntityManager createEntityManager() {
     emFactory = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT, properties);
     return emFactory.createEntityManager();
  }
}
public class StockEAO {
  public void addStock(Stock s) {
     EntityManager em = EntityManagerEAO.createEntityManager();
     try {
       em.getTransaction().begin();
       em.persist(s);
       em.getTransaction().commit();
     }
     catch(Exception e) {
      em.getTransaction().rollback();
     }
     finally {
      em.close();
     }
  }
}

Overall I conclude that EJB 3.0 is a nice feature to persist JAVA objects and it overcomes all the drawbacks of EJB 2.1 and also inherits the features of Hibernate as well.

Enjoy Persisting JAVA objects!!!