Author Archives: Parvinder

About Parvinder

Hi, I want to share my opinion,knowledge related to software technologies and related area.

Insert Operations in to Multiple Tables By Using SimpleJdbcInsert Class Of Spring Framework

When we want to insert data in table by using spring framework,We use usually use update() method from JdbcTemplate class.
 

public int insertSystemParameterDetail(String parameterName, String dcCode,
            String value) {
    String insertQuery = "insert into SYSTEM_PARAMETER_DETAIL (PARAMETER_NAME,CODE,VALUE) values(?,?,?)";
    int count = jdbcTemplate.update(insertQuery, new Object[] {
                parameterName, code, value });
        return count;

    }

 

Also we can use SimpleJdbcInsert class from spring for inserting the data in to table.SimpleJdbcInsert is having definitely
better capability then JdbcTemplate class for inserting data in to tables.

public int insertSystemParameterDetail(String parameterName, String dcCode,
String value) {
Map<String, Object> dcMasterMap = new HashMap<>();

dcMasterMap.put("PARAMETER_NAME", parameterName);
dcMasterMap.put("CODE", code);
dcMasterMap.put("VALUE", value);

SimpleJdbcInsert simpleJdbcInsert = new SimpleJdbcInsert(jdbcTemplate)
.withTableName("SYSTEM_PARAMETER_DETAIL");
int count = 0;

count = simpleJdbcInsert.execute(dcMasterMap);

return count;
}

Although making a  Java Data Access Object class for every table is a good practice in standard Java based enterprise application,There may be some situation in which you want to insert data in lot of tables and you may like to do less coding.In these situations, using of SimpleJdbcInsert can be a very good option.

 


public class GenericOperationDAOImpl implements GenericOperationDAO {

    private final Logger logger = Logger
            .getLogger(GenericOperationDAOImpl.class);
    private JdbcTemplate jdbcTemplate;

    public int genericInsert(Map<String, Object> genericMap, String tableName) {
        if (logger.isInfoEnabled()) {
            logger.info("Inserting Data into table : " + tableName);
        }
        SimpleJdbcInsert simpleJdbcInsert = new SimpleJdbcInsert(jdbcTemplate)
                .withTableName(tableName);
        int count = 0;

        count = simpleJdbcInsert.execute(genericMap);

        return count;

    }

    public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }

}

 

 


public class GenericDBOperationalAPIImpl implements GenericDBOperationalAPI {

private final Logger logger = Logger.getLogger(GenericDBOperationalAPIImpl.class);

GenericOperationDAO genericOperationDAO;

public int genericInsert(Map<String, Object> genericMap,String tableName) {

if (logger.isInfoEnabled()) {
logger.info("Starting Insertion of Data into table : " + tableName);
}

genericOperationDAO.genericInsert(GenericMapUtils.getCarrierMap("1", "WL-ST"), "CARRIER");
genericOperationDAO.genericInsert(GenericMapUtils.getMasterMap("ABC", "UTC", "1", "Unregistered"),"MASTER");
genericOperationDAO.genericInsert(GenericMapUtils.getAttributeMap("DDS", "ABC"),"ATTRIBUTE");
genericOperationDAO.genericInsert(GenericMapUtils.getDeliveryAreaCodeMap("DAC"), "DELIVERY_AREA_CODE");

}

public void setGenericOperationDAO(GenericOperationDAO genericOperationDAO) {
                 this.genericOperationDAO = genericOperationDAO;
}

}

 

 

public class GenericMapUtils {

    public static final Map<String, Object> getCarrierMap(String proNumber,
            String carrierId) {
        Map<String, Object> carrierMap = new HashMap<>();

        carrierMap.put("PRO_NUMBER", proNumber);
        carrierMap.put("CARRIER_ID", carrierId);
        return carrierMap;
    }

    public static final Map<String, Object> getMasterMap(String code,
            String timeZone, String defaultSystemFlag, String description) {
        Map<String, Object> masterMap = new HashMap<>();

        masterMap.put("CODE",code);
        masterMap.put("TIMEZONE", timeZone);
        masterMap.put("DEFAULT_SYSTEM_FLAG", defaultSystemFlag);
        masterMap.put("DESCRIPTION", description);

        return masterMap;

    }

    public static final Map<String, Object> getAttributeMap(
            String attributeName, String code) {

        Map<String, Object> attributeMap = new HashMap<>();

        attributeMap.put("ATTRIBUTE_NAME", attributeName);
        attributeMap.put("CODE", code);
        attributeMap.put("ATTRIBUTE_TYPE", "attT");
        attributeMap.put("ATTRIBUTE_ID", 32);
        return attributeMap;
    }

    
    public static final Map<String, Object> getDeliveryAreaCodeMap(
            String deliveryArea) {

        Map<String, Object> deliveryAreaCodeMap = new HashMap<>();

        deliveryAreaCodeMap.put("DELIVERY_AREA_CODE", deliveryAreaCode);

        return deliveryAreaCodeMap;
    }
}

 

and spring xml configuration is:


<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xmlns:oxm="http://www.springframework.org/schema/oxm" xsi:schemaLocation="http://www.springframework.org/schema/beans
     http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
     http://www.springframework.org/schema/context
     http://www.springframework.org/schema/context/spring-context-3.0.xsd
     http://www.springframework.org/schema/oxm
     http://www.springframework.org/schema/oxm/spring-oxm-3.0.xsd">

<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource" />
</bean>

<bean id="genericDBOperationalAPI" class="com.svg.move.api.GenericDBOperationalAPIImpl">
<property name="genericOperationDAO" ref="genericOperationDAO" />
</bean>

<bean id="genericOperationDAO" class="com.svg.move.dao.GenericOperationDAOImpl">
<property name="jdbcTemplate" ref="jdbcTemplate" />
</bean>

<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="oracle.jdbc.OracleDriver" />
<property name="url" value="jdbc:oracle:thin:@localhost:1521:Oracle" />
<property name="username" value="abc" />
<property name="password" value="abc" />
</bean>

</beans>

That is it,So by using SimpleJdbcInsert we can insert in to multiple tables with less and clean coding.This approach is very useful as well in writing junits which involves multiple tables insertion.

JdbcTemplate deprecated method queryForLong() and queryForInt() in Spring 4 and in spring 3.2.x

 sunflower   Since the jdbcTemplate.queryForInt() and jdbcTemplate.queryForLong() are deprecated in new version of spring(i think,After3.2.x,they are deprecated).We will have to use  jdbcTemplate.queryForObject() for the purpose .We should take care following coding practice otherwise  unwanted exceptions can come.

1.When we will use jdbcTemplate.queryForInt() for getting some int value in a query like:

Existing use of queryForInt() for getting int value:

public int getLineNumber(String orderId, String orderType) {
String sql = "SELECT MAX(order_line_no) FROM ORDER WHERE order_id = ? and order_type = ?";
int value = jdbcTemplate.queryForInt(sql, new Object[] {orderId, orderType});

return value
}

Or

public int getLineNumber(String orderId, String orderType) {
String sql = "SELECT MAX(order_line_no) FROM ORDER WHERE order_id = ? and order_type = ?";
return jdbcTemplate.queryForInt(sql, new Object[] {orderId, orderType});

}

 

Now because queryForInt() is deprecated,we will use queryForObject() for getting int value:

public int getLineNumber(String orderId, String orderType) {
String sql = "SELECT MAX(order_line_no) FROM ORDER WHERE order_id = ? and order_type = ?";
int value = jdbcTemplate.queryForObject(sql, new Object[] {orderId, orderType }, Integer.class);

return value
}

Or

public int getLineNumber(String orderId, String orderType) {
String sql = "SELECT MAX(order_line_no) FROM ORDER WHERE order_id = ? and order_type = ?";
return jdbcTemplate.queryForObject(sql, new Object[] {orderId, orderType }, Integer.class);

}

Now in the above code, if queryForObject return null value.It can not be assigned to primitive type int value .

So null pointer exception will come.To handle this , we should change our method like:

 

public int getLineNumber(String orderId, String orderType) {
String sql = "SELECT MAX(order_line_no) FROM ORDER WHERE order_id = ? and order_type = ?";
Integer value = jdbcTemplate.queryForObject(sql, new Object[] {orderId, orderType }, Integer.class);

return ((value == null) ? 0 : value.intValue());
}

This will ensure no exception if null is returned in the query.Similar changes can be applied to get an long value.

Quartz 2 (2.2.1) Scheduler integration with Spring 4 (4.0.5.RELEASE) and Maven build tool.

Coffe_Cup     Assumption is that you are having a maven project.Let divide whole task (Quartz 2.2.1 integration with Spring 4.0.5.RELEASE) in to 4 step process 

1. Add Spring 4.0.5.RELEASE and quartz 2.2.1 dependency in pom.xml file:
2.Creating a task class(in which our method is present which we want to schedule to run periodically)
3.Creating a job class(this will initiate task class and call the method in it)
4.Configuration in spring xml file(spring-quartz.xml)


 

1. Add Spring 4.0.5.RELEASE and quartz 2.2.1 dependency in pom.xml file:
 
<properties>
<spring.version>4.0.5.RELEASE</spring.version>
</properties>

<!-- Spring dependency -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.version}</version>
</dependency>

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.version}</version>
</dependency>

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
</dependency>

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-oxm</artifactId>
<version>${spring.version}</version>
</dependency>

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>${spring.version}</version>
</dependency>

And quartz dependency are:

<!-- Quartz framework -->
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.2.1</version>
</dependency>

 
Download above dependency in your ..../username/.m2/respository/* location by running mvn eclipse:eclipse or mvn install.
2.Creating a task class(in which our method is present which we want to schedule to run periodically)mentioned below:
package com.devil.space.quartz;

import java.util.List;
import org.apache.log4j.Logger;
import com.devil.space.exception.WebServiceUploadException;
import com.devil.space.model.Transaction;
import com.devil.space.service.TransactionProcessService;
import com.devil.space.xmlservice.XMLUploadService;

/*****************************************************************************
* Class used for processing<code>Transaction</code> records for
xml uploading.
*
*
******************************************************************************
public class TransactionRecordsProcessTask {
Logger logger = Logger.getLogger(TransactionRecordsProcessTask.class);
private XMLUploadService xmlUploadService;
private TransactionProcessService transactionProcessService;

public void processRecords() {

if (logger.isInfoEnabled()) {
logger.info("In TransactionRecordsProcessTask.Transaction records processing started");
}

try {
List<Transaction> transactionRecordForXMLUpload = transactionProcessService
.processTransactionRecords();

for (Transaction transaction : transactionRecordForXMLUpload) {
xmlUploadService.uploadTransactionRecord(transaction);
}
} catch (XMLUploadException e) {
logger.warn("error processing TransactionRecordsQuartzJob", e);
} catch (Throwable t) {
logger.warn("uncatchable error:", t);
}
}

public XMLUploadService getXmlUploadService() {
return xmlUploadService;
}

public void setXmlUploadService(XMLUploadService xmlUploadService) {
this.xmlUploadService = xmlUploadService;
}

public TransactionProcessService getTransactionProcessService() {
return transactionProcessService;
}

public void setTransactionProcessService(TransactionProcessService transactionProcessService) {
this.transactionProcessService = transactionProcessService;
}

}

 

3. Creating a job class(this will initiate task class and call the method in it)

 

package com.devil.space.quartz;

import java.util.Date;

import org.apache.log4j.Logger;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.scheduling.quartz.QuartzJobBean;

public class TransactionRecordsQuartzJob extends QuartzJobBean {
Logger logger = Logger.getLogger(TransactionRecordsQuartzJob.class);
TransactionRecordsProcessTask transactionRecordsProcessTask;

public void executeInternal(JobExecutionContext context)
throws JobExecutionException {
if (logger.isInfoEnabled()) {
logger.info("In TransactionRecordsQuartzJob - executing its JOB on "
+ new Date()
+ " by "
+ context.getTrigger().getDescription());
}

transactionRecordsProcessTask.processRecords();
}

public TransactionRecordsProcessTask getTransactionRecordsProcessTask() {
return transactionRecordsProcessTask;
}

public void setTransactionRecordsProcessTask(TransactionRecordsProcessTask transactionRecordsProcessTask) {
this.transactionRecordsProcessTask = transactionRecordsProcessTask;
}

}

 

4.Configuration in spring xml file(spring-quartz.xml) Create a xml file for spring-quartz configuration and put down the below content in it.

 

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xmlns:oxm="http://www.springframework.org/schema/oxm" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans

http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/oxm
http://www.springframework.org/schema/oxm/spring-oxm-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd"
>

<!-- Simple Trigger, run every 5 seconds -->
<bean id="simpleTrigger"
class="org.springframework.scheduling.quartz.SimpleTriggerFactoryBean">

<property name="jobDetail" ref="transactionRecordJob" />
<property name="repeatInterval" value="5000" />
<property name="startDelay" value="1000" />

</bean>

<bean id="transactionRecordJob"
class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
<property name="targetObject" ref="transactionRecordsProcessTask" />
<property name="targetMethod" value="processRecords" />
</bean>

<bean id="transactionRecordsProcessTask" class="com.devil.space.quartz.TransactionRecordsProcessTask">
<property name="xmlUploadService" ref="xmlUploadService" />
<property name="transactionProcessService" ref="transactionProcessService" />

</bean>

<bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="autoStartup" value="true" />
<property name="jobDetails">
<list>
<ref bean="transactionRecordJob" />
</list>
</property>
<property name="triggers">
<list>
<ref bean="simpleTrigger" />
</list>
</property>

</bean>

<bean id="xmlUploadService" class="com.devil.space.xmlservice.XMLUploadServiceImpl">
</bean>

<bean id="transactionProcessService" class="com.devil.space.service.TransactionProcessServiceImpl">
</bean>

</beans>

 

That is it.Now create a war file of the project by mvn install and deploy the application in a application server (Say apache-tomcat-7.0.29).Quartz will start working as expected.


					

How to make XSD validation in a REST based web service XML Request by using XSD file and JAXBMarshaller

Computer  Assuming we are using Jaxb2Marshaller class for marshaling/marshaling the XML request/response.Lets we want to use a xsd file named validate.xsd for validating XML REST Request.First put the validate.xsd file in to src/main/resources directory in the project workspace.Now set the JAXB configuration in your rest-servlet.xml file like:

<bean id="jaxb2Marshaller">
<property name="schema" value="classpath:/validate.xsd" />
<property name="classesToBeBound">
	<list>
<value>com.devil.space.RPCRequest</value>
<value>com.devil.space.RPCResponse</value>
</list>
</property>
</bean>

 

 

 

RPCRequest and RPCResponse are the rest request and response java xml object respectively.So the full rest-servlet.xml file would be like:

<?xml version=1.0 ?>
<beans xmlns=http://www.springframework.org/schema/beans
xmlns:xsi=http://www.w3.org/2001/XMLSchema-instance xmlns:context=http://www.springframework.org/schema/context
xmlns:mvc=http://www.springframework.org/schema/mvc xmlns:util=http://www.springframework.org/schema/util
xmlns:p=http://www.springframework.org/schema/p
xsi:schemaLocation=http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd></beans>

<!-- @Controllers -->
<context:component-scan
base-package=com.devil.space.controller,com.devil.space.rest />

<bean
class=org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping >

<bean
class=org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter>
<property name=messageConverters>
	<list>
<ref bean=marshallingHttpMessageConverter >
<bean
class=org.springframework.http.converter.StringHttpMessageConverter >
</list>
</property>
</bean>

<bean id=marshallingHttpMessageConverter
class=org.springframework.http.converter.xml.MarshallingHttpMessageConverter
p:marshaller-ref=jaxb2Marshaller p:unmarshaller-ref=jaxb2Marshaller >

<bean id=jaxb2Marshaller>
<property name=schema value=classpath:/validate.xsd >
<property name=classesToBeBound>
	<list>
<value<com.devil.space.RPCRequest</value>
<value<com.devil.space.RPCResponse</value>
</list>
</property>
</bean>

<bean id=viewResolver
class=org.springframework.web.servlet.view.InternalResourceViewResolver>
<property name=viewClass value=org.springframework.web.servlet.view.JstlView>
</bean>
</beans>


 

So if the xml file data is not as per xsd file validations,response message will be like :

“The request sent by the client was syntactically incorrect”

Thats it.You are done.!!

Now this message is kind of generic error message.If we want to know where exactly is the problem in our XML request,there are more things to be done:

1.Configuration in to rest-servlet.xml.

Add following configuration in to rest-servlet.xml:

<bean
class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerExceptionResolver">
<property name="messageConverters">
	<list>
<ref bean="marshallingHttpMessageConverter" />
<bean class="org.springframework.http.converter.StringHttpMessageConverter" />
</list>
</property>
</bean>


 

2.Adding method for handling exception.

Lets us assume your controller class is :


@Controller
@RequestMapping("/SaveXMLData")
public class DownloadXMLDataEndPointController {

@RequestMapping(value = "/SaveAndUpdateData", method = RequestMethod.POST)
@ResponseBody
public RPCResponse saveXMLRequestData(
@RequestBody RPCRequest request) throws Exception {

----Logic for processing request-----

RPCResponse response=new RPCResponse();

--construct response object----------

return response;

}
}

In the above controller class,add another method for handling exception:

@ExceptionHandler(HttpMessageNotReadableException.class)
@ResponseStatus(value = HttpStatus.BAD_REQUEST)
@ResponseBody
RPCResponse handleXMLException(HttpMessageNotReadableException ex) {

String error = "Invalid XML.Error is:-";
error = error + ex.getMessage();
String responseMessage = "FAILOVER";

RPCResponse response=new RPCResponse();

--construct response object----------

return response;
}

So the complete Controller class would be :


@Controller
@RequestMapping("/SaveXMLData")
public class DownloadXMLDataEndPointController {

@RequestMapping(value = "/SaveAndUpdateData", method = RequestMethod.POST)
@ResponseBody
public RPCResponse saveXMLRequestData(
@RequestBody RPCRequest request) throws Exception {

----Logic for processing request-----

RPCResponse response=new RPCResponse();

--construct response object----------
return response;

}

@ExceptionHandler(HttpMessageNotReadableException.class)
@ResponseStatus(value = HttpStatus.BAD_REQUEST)
@ResponseBody
RPCResponse handleXMLException(HttpMessageNotReadableException ex) {

String error = "Invalid XML.Error is:-";
error = error + ex.getMessage();
String responseMessage = "FAILOVER";

RPCResponse response=new RPCResponse();

--construct response object----------

return response;
}
}

Now if we deploy the application again.And send a xml request.If there is any validation error as per our XSD file,A detail error message will be in response stating in which line in XML request is the error.

 

 

Now if there is more than one XSD files which are been used to validate more than one type of  XML request,We can configure them in single XSD file.Lets there are three XSD files (ABCD.xsd,PQRS.xsd,XYZT.xsd)for validating three types of XML request..Our validate.xsd will be as

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified">
<xs:include schemaLocation="ABCD.xsd" />
<xs:include schemaLocation="PQRS.xsd" />
<xs:include schemaLocation="XYZT.xsd" />
</xs:schema>


That is it.Similarly we can configure more XSD files for validating different types of XML requests.

If still there is any issue that you encounter :mail me at–    parry.ism@gmail.com

Java Object Cloning:Cloning Java Object By Using Cloneable Interface

    Coffe_Cup   Cloning means coping a object’s internal contents to a new object which will have a different memory address. Assignment operator assigns the reference or memory address to other object.Any change made in that object will reflect in original object as well.But in cloning a new object having different reference is created.And any change made in this cloned object will not make any change in original object.So essentially cloning is object duplication having different memory address.There are several ways in Java to perform object duplication or cloning like:

1.Using Java Object class’s clone() method and Cloneable iterface

2.Using Copy Constructor

3.Using Factory Method.

4.Using Serialization

In this article ,We will discuss cloning by using first approach that is by using Object class’s clone() method and Cloneable Interface.

1.Using Java Object class’s clone() method and Cloneable iterface (Cloneable is a marker interface):

In this approach, the Java Class whose object we want to clone should have implement Cloneable interface and should override object class’s clone() method.Example class for this is(CodeSample1):

package com.devil;
/*-------------------------------------------------------------------------*/
/**
* Class which implement Cloneable interface and override object class's clone()
* method and thats why its object can be used for cloning or duplication or
* copying.This class is capable of doing Shallow Cloning only.
*
*/
/*-------------------------------------------------------------------------*/
public class NationalPark implements Cloneable{
public String name;
public String stateName;
public Integer yearOfEstablishment;
public Animal animal;
public NationalPark(String name, String stateName,
Integer yearOfEstablishment) {
this.name = name;
this.stateName = stateName;
this.yearOfEstablishment = yearOfEstablishment;
Animal animal = new Animal("Tiger", 9, "Sariska");
this.animal = animal;
}
@Override
public Object clone() {
try {
return super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
return null;
}
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getStateName() {
return stateName;
}
public void setStateName(String stateName) {
this.stateName = stateName;
}
public Integer getYearOfEstablishment() {
return yearOfEstablishment;
}
public void setYearOfEstablishment(Integer yearOfEstablishment) {
this.yearOfEstablishment = yearOfEstablishment;
}
public Animal getAnimal() {
return animal;
}
public void setAnimal(Animal animal) {
this.animal = animal;
}
}

The above class use another class Animal whose code is as (CodeSample2)::

package com.devil;

/*-------------------------------------------------------------------------*/
/*Animal class which is not cloneable
/*-------------------------------------------------------------------------*/

public class Animal {
public String name;
public Integer age;
public String sanctuaryName;
public Animal(String name, Integer age, String sanctuaryName) {
this.name = name;
this.age = age;
this.sanctuaryName = sanctuaryName;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getSanctuaryName() {
return sanctuaryName;
}
public void setSanctuaryName(String sanctuaryName) {
this.sanctuaryName = sanctuaryName;
}
}

 

 

Now lets use NationalPark class for creating cloned object.Example for this demonstration is (CodeSample3)::

package com.devil;
/*-------------------------------------------------------------------------*/
/* Code example for explaining basic cloning concept
/*-------------------------------------------------------------------------*/
public class JavaCloneExample1 {

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

NationalPark nationalPark1= new NationalPark("Sariska","Rajashthan",1955);
NationalPark nationalPark2=nationalPark1;
NationalPark clonedNationalPark1=(NationalPark) nationalPark1.clone();

System.out.println("Are object1 and object2 have same reference:- "+(nationalPark1==nationalPark2));
System.out.println("Are object1 and clone object have same reference:- "+(nationalPark1==clonedNationalPark1));
System.out.println("");

System.out.println("NationalPark object1 hashcode:-"+""+nationalPark1.hashCode());
System.out.println("NationalPark object2 hashcode:-"+""+nationalPark2.hashCode());
System.out.println("NationalPark cloned object hashcode:-"+""+clonedNationalPark1.hashCode());
System.out.println("");
}
}

 
Output  of the above code is:
 
Are object1 and object2 have same reference:- true
Are object1 and clone object have same reference:- false

NationalPark object1 hashcode:-1068505417
NationalPark object2 hashcode:-1068505417
NationalPark cloned object hashcode:-1112287305

From the above results,Cloned object has different memory address(reference)than the original object.Also since default implementation of hashcode() method(which is in Java Object class) driven by memory address,cloned object has different hashcode than that of original object.

Now what happens if  we do not override clone() method or do not implement Cloneable interface.

Well,implementing Cloneable interface can not be avoided if we want to give our class cloning capability.Lets we are not implementing Cloneable  interface in our NationalPark class(CodeSample1) and now we are trying to run our programme CodeSample3 ,Following exception will occur in the output:

java.lang.CloneNotSupportedException: com.devil.NationalPark
at java.lang.Object.clone(Native Method)
at com.devil.NationalPark.clone(NationalPark.java:30)
at com.devil.JavaCloneExample1.main(JavaCloneExample1.java:11)

Now,overriding clone() method can be avoided but of no use.It will be like we have something but we can not use.Its because if we are not overriding clone() method,It means we are using Java Object’s clone() method whose accessibility is “protected”.That means we can use this method only in the child class(in our case:NationalPark) whose base class in Object.If we will try to access this method outside(lets say in CodeSample3) of cloned class (NationalPark),

a compile error will come up saying :-”The method clone() from the type Object is not visible”.

So essence is that,Its completely necessary to implement Clone able interface for making  a class capable of cloning.And its necessary to override clone() method so that we can use cloning capability of class.

 

Now Java Cloning is of two types;Shallow copy and Deep copy which are explained as below

Shallow Copying :

Now if a java object(say NationalPark in our case) contains a reference of other objects (say Animal in our case) as well.The default cloning(as in above example) will not clone internal object(animal).Animal object reference will be same in cloned object(clonedNationalPark1) and original object(nationalPark1).So  any change made in animal object in Cloned Object will be reflected in animal object of Original Object also.This is called Shallow Copying.An example showing Shallow Copying is as:

package com.devil;
/*-------------------------------------------------------------------------*/
/* This Cloning Example demonstrates Shallow Copy
*
*
/*-------------------------------------------------------------------------*/
public class JavaCloneExample2 {
public static void main(String args[]) throws CloneNotSupportedException {
NationalPark nationalPark1= new NationalPark("Sariska","Rajashthan",1955);
NationalPark nationalPark2=nationalPark1;
NationalPark clonedNationalPark1=(NationalPark) nationalPark1.clone();
System.out.println("NationalPark object1:-"+nationalPark1.hashCode());
System.out.println("NationalPark object2:-"+nationalPark2.hashCode());
System.out.println("NationalPark cloned object:-"+clonedNationalPark1.hashCode());
System.out.println("");
Animal animal1=nationalPark1.getAnimal();
Animal animal2=clonedNationalPark1.getAnimal();
System.out.println("Are animal1 and animal2 have same reference:- "+(animal1==animal2));
System.out.println("");
//Any change in animal2 object will reflect in animal1 object as well.
animal2.setName("Elephant");
animal2.setSanctuaryName("Kajiranga");
System.out.println("NationalPark animal2 object attributes:- "+animal2.getName()+"--"+
animal2.getSanctuaryName()+"--"+animal2.getAge());
System.out.println("NationalPark animal1 object attributes:- "+animal1.getName()+"--"+
animal1.getSanctuaryName()+"--"+animal1.getAge());
}
}

The output of the above code will be as:

 

NationalPark object1:-1489230252
NationalPark object2:-1489230252
NationalPark cloned object:-570939579

Are animal1 and animal2 have same reference:- true

NationalPark animal2 object attributes:- Elephant--Kajiranga--9
NationalPark animal1 object attributes:- Elephant--Kajiranga--9

So in shallow coping internal object animal1 of original object(e.g nationalPark1) and internal object animal2 of cloned object(e.g clonedNationalPark1) points to the same memory reference.Any change made to animal2 object will reflect in animal1 object as well.So if we want to manipulate internal objects of cloned object and do not want to affect original object, we should choose Deep Copying cloning.

Deep Copying:

In Deep Copying all the internal objects which are used as an reference(e.g Animal) will also cloned with that of original object(e.g NationalPark).So in deep copying we will get a complete cloned object which can be changed anyhow without affecting the original object.If we want  a deep copy of cloned object,Following things should be keep in mind:

1. All the internal object which are used as an reference (e.g Animal) should implement Cloneable interface.

2.All the internal objects which are used as an reference (e.g Animal)should override clone()

method of Java Object class.

 

So w.r.t above example,If we want to make Deep Cloning of NationalPark object.We have to change Animal class as per above two points which will be as:

package com.devil;
/*-------------------------------------------------------------------------*/
/* Animal class which is Cloneable
/*-------------------------------------------------------------------------*/
public class Animal implements Cloneable {
public String name;
public Integer age;
public String sanctuaryName;
public Animal(String name, Integer age, String sanctuaryName) {
this.name = name;
this.age = age;
this.sanctuaryName = sanctuaryName;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getSanctuaryName() {
return sanctuaryName;
}
public void setSanctuaryName(String sanctuaryName) {
this.sanctuaryName = sanctuaryName;
}
@Override
public Object clone() {
try {
return super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
return null;
}
}
}
 
Last step will be to make change in Clone() method of the original object (NationalPark) so that internal objects are also cloneable.So the modified NationalPark class(only change is in clone() method) will be as:
 
package com.devil;
/*-------------------------------------------------------------------------*/
/*
* Class which implement Cloneable interface and override object class's clone()
* method and thats why its object can be used for cloning or duplication or
* copying.This Class is capable of doing Deep Cloning
*
*/
/*-------------------------------------------------------------------------*/
public class NationalPark implements Cloneable {
public String name;
public String stateName;
public Integer yearOfEstablishment;
public Animal animal;
public NationalPark(String name,String stateName,Integer yearOfEstablishment){
this.name=name;
this.stateName=stateName;
this.yearOfEstablishment=yearOfEstablishment;
Animal animal=new Animal("Tiger",9,"Sariska");
this.animal=animal;
}
//Clone() method implementation for Deep Cloning
@Override
protected Object clone() {
try {
NationalPark nationalPark= (NationalPark) super.clone();
nationalPark.animal=(Animal) this.animal.clone();
return nationalPark;
} catch (CloneNotSupportedException e) {
e.printStackTrace();
return null;
}
}
public String getName(){
return name;
}
public void setName(String name) {
this.name = name;
}
public String getStateName() {
return stateName;
}
public void setStateName(String stateName) {
this.stateName = stateName;
}
public Integer getYearOfEstablishment() {
return yearOfEstablishment;
}
public void setYearOfEstablishment(Integer yearOfEstablishment) {
this.yearOfEstablishment = yearOfEstablishment;
}
public Animal getAnimal() {
return animal;
}
public void setAnimal(Animal animal) {
this.animal = animal;
}
}
Below example demonstrate Deep Copying by using above class:
 
 
package com.devil;
/*------------------------------------------------------------------------------*/
/* This Cloning Example demonstrates Deep Copy
*
*
/*-----------------------------------------------------------------------------*/
public class JavaCloneExample3 {
public static void main(String args[]) throws CloneNotSupportedException {
NationalPark nationalPark1= new NationalPark("Sariska","Rajashthan",1955);
NationalPark nationalPark2=nationalPark1;
NationalPark clonedNationalPark1=(NationalPark) nationalPark1.clone();
System.out.println("Are object1 and object2 have same reference:- "+
(nationalPark1==nationalPark2));
System.out.println("Are object1 and clone object have same reference:- "+
(nationalPark1==clonedNationalPark1));
System.out.println("");

System.out.println("NationalPark object1:-"+nationalPark1.hashCode());
System.out.println("NationalPark object2:-"+nationalPark2.hashCode());
System.out.println("NationalPark cloned object:-"+clonedNationalPark1.hashCode());
System.out.println("");

Animal animal1=nationalPark1.getAnimal();
Animal animal2=clonedNationalPark1.getAnimal();
System.out.println("Are animal1 and animal2 have same reference:- "+(animal1==animal2));

System.out.println("");
//Any change in animal2 object will not reflect in animal1 object.
animal2.setName("Elephant");
animal2.setSanctuaryName("Kajiranga");
System.out.println("NationalPark animal2 object attributes:- "+animal2.getName()+"--"+
animal2.getSanctuaryName()+"--"+animal2.getAge());
System.out.println("NationalPark animal1 object attributes:- "+animal1.getName()+"--"+
animal1.getSanctuaryName()+"--"+animal1.getAge());
}
}

 

Output of the above code is as:

Are object1 and object2 have same reference:- true
Are object1 and clone object have same reference:- false

NationalPark object1:-1004958336
NationalPark object2:-1004958336
NationalPark cloned object:-375869497

Are animal1 and animal2 have same reference:- false

NationalPark animal2 object attributes:- Elephant--Kajiranga--9
NationalPark animal1 object attributes:- Tiger--Sariska--9
Above output clearly shows that animal1 and animal2 are having difference memory reference.Any change made in the animal2 object will not affect animal1 object and so original NationalPark object .So this was the Deep Copying.
 
One of the major application of using cloned object is for creating defensive copy in designing  of a immutable class.
 
 
So after reading this article ,you should be able to know the answer for the following questions:
 
1.What is Java Object Cloning or Java Cloning.And what is its uses ?

2.What is the use of Java Object clone() method.?

3.What is the use of Cloneable interface?

4.What is Shallow Cloning (or Shallow Copy) and Deep Cloning(or Deep Copy).?
What is the difference between these two types of cloning.?

5.When we should use Shallow Copy and when we should use Deep Copy.?