Thursday, October 2, 2008

Creating Custom Button in JavaFX

JavaFX is an exciting new technology to create RIA for different platforms and devices like desktop, web, mobile, tv etc. JavaFX provides a scripting language and API to create rich widgets, and user interfaces.
In this episode of blog, i will guide you how to create a custom button in JavaFX shown below. I also like to thanks Mr. Asim Rasool which guided me to choose color combinations. He is graphic designer and working for last five years as Graphic Expert.

First we create a Button class which extends from CustomNode class. In JavaFX, each UI Element is a Node. In order to design our own UI Nodes in JavaFX, one has to extend CustomNode.



public class Button extends CustomNode

{

}



Now if we think about features a button should provide to user then we come across width, height, x and y coordinates, and text which will appear on button. So we add following attributes to Button class.



public class Button extends CustomNode

{

attribute x:Number;

attribute y:Number;

attribute width:Number;

attribute height:Number;

attribute text:String;

private attribute txt:Text;


private attribute gradient:LinearGradient = LinearGradient {

startX: 0.0 startY: 0.0

endX: 0.0 endY: 1.0

proportional: true

stops: [

Stop { offset: 0.0 color: Color.web("#dceaff")},

Stop { offset: 0.49 color: Color.web("#6885b2") },

Stop { offset: 0.5 color: Color.web("#2c599c") },

Stop { offset: 1.0 color: Color.web("#bed3f4") }

]

}

}



In JavaFX, attribute is same as property in Java. Note that , there is a private attribute "txt" of type "Text" which is a node and used to draw text. In addition to txt, there is another private attribute which is gradient. I have used LinearGradient which is used to add gradient to node. In this case i have initialized LinearGradient using Object Literal notation. LinearGradient contains startX,startY, endX, and endY which specifies the area in which gradient should be applied. In this case, i want to apply gradient from top to bottom of button, so i mentioned startY as 0.0(top) and endY as 1.0(bottom). proportional attribute establishes smooth transition from one color to another color. As we know that gradient is a transition from one color to other, in order to mention those colors, stops array is used. Each Stop has two important attributes one is "offset" and second one is "color". offset is used to indicate where a particular color should be applied in full intensity. In my case it is from startX and startY.

Each class which extends from CustomNode, have to implement "create" function which returns Node object.


public function create():Node{
return Group{
translateX:x translateY:y;
content:[Rectangle{

width:width height:height
arcWidth:35 arcHeight:35
stroke:Color.web("#023493");
strokeWidth:1.5;
fill: bind gradient
onMouseEntered: function( e: MouseEvent ):Void {
gradient = LinearGradient {
startX: 0.0
startY: 0.0
endX: 0.0
endY: 1.0

proportional: true
stops: [
Stop { offset: 0.0 color: Color.web("#ffffff")},
Stop { offset: 0.49 color: Color.web("#6885b2") },
Stop { offset: 0.5 color: Color.web("#2c599c") },
Stop { offset: 1.0 color: Color.web("#ffffff") }
]
}
}
onMouseExited: function( e: MouseEvent ):Void {
gradient = LinearGradient {
startX: 0.0
startY: 0.0
endX: 0.0
endY: 1.0

proportional: true
stops: [
Stop { offset: 0.0 color: Color.web("#dceaff")},
Stop { offset: 0.49 color: Color.web("#6885b2") },
Stop { offset: 0.5 color: Color.web("#2c599c") },
Stop { offset: 1.0 color: Color.web("#bed3f4") }
]
}
}
},getText()

]
onMousePressed: function( e: MouseEvent ):Void {
txt.x = txt.x + 1;
txt.y = txt.y + 1;
}

onMouseReleased: function( e: MouseEvent ):Void {
txt.x = txt.x - 1;
txt.y = txt.y - 1;
}

}

}


In create function, i have returned Group which is a node used to combine two or more nodes in a single node. I have encapsulated a Rectangle node and Text node inside a Group node. Benefit of using Group will be that x, y coordinates of Rectangle and Text will be from left upper corner of Group, so just changing Group's coordinates, i can relocate Rectangle and Text automatically.
I have assigned gradient to fill attribute of Rectangle to produce gradient effect. I also used "bind" keyword which means, whenever gradient object will be changed, fill attribute of Rectangle will be recalculated. You can note it that i have changed gradient object on mouse events of Rectangle like onMouseEntered and onMouseExited. Other attributes are self explanatory. Text node is obtained through private function "getText".


private function getText():Text{
txt = Text{
content:text
fill:Color.WHITE
font:Font{
name:"Arial" size:14 style:FontStyle.BOLD
}
effect:DropShadow{
color:Color.BLACK
offsetX:1 offsetY:1

}

}
centralizeText(txt);

return txt;
}

private function centralizeText(text:Text):Void{
text.x = (width - text.getWidth())/2;
text.y = (height - text.getHeight())/2 + 12;

}


if you look at the getText function carefully, you will notice use of another function centralizeText, this function gets a Text node and sets its x and y on the basis of current width and height of text to appear on center of Rectangle. Best approach to centralize text is to get the text width in font and then adjust it but i don't find any such approach in JavaFX, so i have to get use of "Text" node's widht and height attributes which is i think not a good approach.
That's all now. You have created Custom Button successfully. Let's use it now. Code to use it given below:


Frame {
title: "Custom Button"
width: 220
height: 160
closeAction: function() {
java.lang.System.exit( 0 );
}
visible: true
stage: Stage {
content: [
Button{
x:20
y:20
width:120
height:30
text:"Submit"
onMouseClicked: function( e: MouseEvent ):Void {
System.out.println("This button has been clicked");
}
}
]
}
}



So, in this blog we explored following key concepts like:
  • Use of Object literal
  • Use of Group Node
  • How to implement events
  • How to create its own Node
In my coming blog i will create more complex nodes so stay in touch.

Tuesday, August 19, 2008

Abstract Classes and Interfaces

In java, Abstract classes and Interfaces are two building blocks which play an important role nearly in every java program.
Abstract classes are classes which can not be instantiated. It may or may not contain one or more than one methods which have only signature but don't have any body/definition. The methods which don't have body, are called as abstract methods. In order to use abstract classes, one has to extend it and provide definition for all abstract methods. If body of abstract method is not provided in extension class, that child class will also be abstract. Classes are declared abstract with keyword "abstract". Methods are also declared abstract using "abstract" keyword.

public abstract class Shape
{
public abstract void draw();
}

public class Rectangle extends Shape
{
public void draw()
{
//implementation for rectangle
}
}

public class Triangle extends Shape
{
public void draw()
{
//implementation for triangle
}
}

In the above example, Shape is an abstract class which contains one abstact method draw. Each class which extends from Shape like Rectangle and Triangle have to provide its own particular implementation of draw method and that is logical because drawing nature of each Shape is different and each Shape should know how to draw itself. So abstract class Shape provides a bond for all geometry figures that if they are Shape, then they have to provide definition of draw method.

Interfaces are same as Abstract classes in the sense that it contains only those methods which have only signatures but don't have any body. In order to declare interface, "interface" keyword is used before the name of interface. Since interface contains only abstract methods, so "abstract" keyword is not used in method's signature for interface.

public interface Shape
{
public void draw();
}

public class Rectangle implements Shape
{
public void draw()
{
//implementation for Rectangle
}
}

public class Triangle implements Shape
{
public void draw()
{
//implementation for Triangle
}
}

In the above example, an interface "Shape" has been declared which contains one method signature "draw". All those classes which want to have functionality of Shape, implements it and provide body of draw method.

In above examples, i achieved same functionality through abstract class and interface. Now suppose we want to display these shapes on Canvas. For that Canvas class provides a method to add those Shapes and then there is show method of Canvas which internally calls draw method of each Shape added on Canvas as shown below:
public class Canvas
{
private List shapes = new ArrayList();
public void add(Shape shape)
{
shapes.add(shape);
}
public void show()
{
for (Shape s : shapes)
{
s.draw();
}
}
}

public class Main
{
public static void main(String args[])
{
Canvas canvas = new Canvas();
Shape rec1 = new Rectangle();
canvas.add(rec1);
Shape tri1 = new Triangle();
canvas.add(tri1);
canvas.show();
}
}

You can see that Canvas class is usable whether you use Abstract class or interface. Now question arises in which situation one should go for Abstract class and other should go for interface. Suppose above Canvas is used to display both Shapes and Widgets and Canvas does not have any knowledge whether a particular item added on it, is Shape or Widget. Since Widget are not shapes so natural choice in this case is interface approach. There should be an interface like Drawable which should be implemented by both Shapes and Widget. Structure of Shape, Widget, and Canvas is shown below:
public abstract class Shape implements Drawable
{
public void draw();
}

//implementation of Rectangle, and Shape are same as above in abstract class approach, So i //am not mentioning it again.

public abstract class Widget implements Drawable
{
public void draw();
}

//all widgets will extend Widget and implement draw method

public class Canvas
{
private List items = new ArrayList();
public void add(Drawable drawable)
{
items.add(drawable);
}

public void show()
{
for (Drawable item:items)
{
item.draw();
}
}
}

public class Main
{
public static void main(String args[])
{
Canvas canvas = new Canvas();
Shape rec1 = new Rectangle();
canvas.add(rec1);
Widget wid1 = new Widget1();
canvas.add(wid1);
canvas.show();
}
}


So in the light of experience which we have gotten from above examples, i summarize the rule:
  • Use Abstract class for creating a bond between similar items like Rectangle and Triangle are similar entities so extend them from Shape
  • Use interface for creating a bond between dissimilar items like Shape and Widget are different from Canvas.
  • Always try to use Abstract class or interface whenever you need to upcast them to achieve simplicity e.g. add and show method of Canvas.
Now i discuss other properties of interface. Interfaces can also contain fields but those fields will be static and final. Interface can have public or package access. It can also be private only if defined inside of a class as inner interface.

In the last i explain another problem which usually hapens when interfaces are implemented. Supppose there are two interfaces one is ShapeClonable and second one is WidgetClonable. Body of these two interfaces are given below:

public interface ShapeClonnable
{
public Shape clone();
}

public interface WidgetClonnable
{
public Widget clone();
}

Now there is a class Figure which implements both interface as show below:

public class Figure implements ShapeClonnable, WidgetClonnable
{
public Shape clone()
{
//implementation
}

public Widget clone()
{
//implementation
}
}

Figure class contains two methods with same name. It is called method overloading but for that, two methods should have either different number of parameters or differnent types of parameters. In the above case, two methods differ in only return types which are not covered in method overloading, so there will be compile time error. You should give special attention in designing interfaces to avoid this type of error.

Wednesday, July 23, 2008

Inheritance Strategy - Class per hierarchy

Hibernate supports several types of inheritance strategies in which simplest of them is "Class-per-heirarchy". In this strategy, data for all classes involved in inheritance is stored in a single table and a record is identified by discriminator column. Lets discuss this strategy with an example. Suppose there are three classes: Person, Employee, and Physician. Inheritance relationship is shown in the fig below:Person is an abstract class. So either a person will exist as Employee or Physician. Hibernate mapping for Person is shown below:


Discriminator element creates a column with name "Type", value of which will indicate whether a particular record is Employee or Physician. There is also a special property "abstract" in class element which tells that object of person can't be created.

Hibernate mapping for Employee is shown below:



"subclass" element indicates that there is a class per hierarchy strategy of inheritance between Employee and Person. "extends" property of subclass element creates relationship of "Employee" with "Person". "discriminator-value" tells hibernate to use "Employee" in discriminator column to identify all employees.

Configuration for Physician is given below:



Now lets add two Persons: one is Employee and other is Physician as shown below:

Session session = HibernateUtil.getSessionFactory().openSession(); session.beginTransaction(); Emplo
yee emp = new Employee(); emp.setName("Amer Sohail"); emp.setPay(123f); session.save(emp); Physician phy = new Physician(); phy.setName("Dr. Amer Sohail"); phy.setPay(345f);
phy.setBillingAddress("Lahore");
phy.setSpeciality("Pediatrics");
session.save(phy); session.getTransaction().commit(); session.close();


a single table with name "person" will be created in the database with following two records:


Lets retrieve the all person from database and you will observe polymorphic feature of hibernate:

Session session = HibernateUtil.getSessionFactory().openSession();
session.beginTransaction();
List emp = session.createQuery("from Person emp").list();
if (emp != null && emp.size() > 0)
{
for (int index = 0; index <>
{
System.out.println("Name of employee is " +((Employee)emp.get(index)).getName());
if (emp.get(index) instanceof Person)
System.out.println("This is person");

if (emp.get(index) instanceof Employee)
System.out.println("This is Employee");

if (emp.get(index) instanceof Physician)
System.out.println("This is Physician");
}
}
session.getTransaction().commit();
session.close();


output of the code will be following:

Name of employee is Amer Sohail
This is person
This is Employee
Name of employee is Dr. Amer Sohail
This is person
This is Employee
This is Physician

As shown in output, i just retrieved "persons" but it instantiated objects of type to which they belong e.g. Amer Sohail was just an employee not a physician so hibernate created it of "Employee" type. This is really a very powerful feature of hibernate.

Now if i want to retrieve only employee not physician, then i will write the following query:


List emp = session.createQuery("from Employee emp where type = Employee").list();


I explained the strategy "class-per-heirarchy" in this blog's post. This strategy has one major drawback which you should notice while viewing records in table. It contains "nulls" against those records which are not in employee like "speciality" and "billing_address". Since DBMS has to handle null fields with a special case and it creates an impact on performance so that is the major drawback of this strategy because it will create a lot of nulls in the table. but on the other handle, no join is needed so no join cost improves the performance. Now there is very interesting situation bcz pros of this blog says it increase the performance while cons says it decreases the performance so what is the net effect. you have to wait for it for later posts in which i will compare all the strategies.

Saturday, July 19, 2008

Batch Insertion in Hibernate

Batch Insertion is a powerful feature of hibernate particularly useful when you are importing data from other systems in batch. If you do not use batch feature of hibernate, your application's performance may decrease dramatically at the time of insertion of many records.
There are two approaches in hibernate to handle batch insertion. Each one is explained below:

  • One approach is related to Session class. Let's discuss it with example. Suppose there is an application for library which uses hibernate as ORM layer. Now you want to insert 1 million books in library. For simplicity domain model contains two classes one is book and second one is publisher. Publisher is contained in book class and i have enabled cascade insert and cascade update so if i insert book which contains publisher that is not in the system, it will also be saved with book. Code to insert books are given below:

    Session session =HibernateUtil.getSessionFactory().openSession(); session.beginTransaction();
    for (int index = 0; index <> Book book = new Book();
    book.setAuthor("amer");
    book.setIsbn("34343");
    book.setName("Hibernate " + index);
    Publisher pub = new Publisher();
    pub.setName("Publisher " + index);
    book.setPublisher(pub);
    book.setPublishDate(new Date());
    session.save(book);
    }
    session.getTransaction().commit();
    session.close();


Above code is putting a lot of memory burden because whenever an object is saved, hibernate puts that object in cache which is called as "session cache" or "first level of cache" and probably you will face an error of Stack outofflow memory error. In order to avoid this, you have to clear the session, but question is when session should be cleared either after each insertion of after some interval. If you clear session, after each insertion, it will decrease your applications' performance dramatically because before calling clear operation on session, you have to call flush operation which will synchronize persistent data store to objects memory states. For this situation, there comes a concept of batch insertion. For batch insertion, first of all you will have to add "hibernate.jdbc.batch_size" property in your hibernate.cfg.xml file with value of 50.

By using this property, hibernate will use jdbc for batch insertion of 50 records at a time when you flush the session. Batch size "50" is my recommendation because i always got max application performance with this number. You also have to change code to flush objects from session as below:

session.save(book); if (index % 50== 0) { session.flush(); session.clear(); }

  • Second way of doing batch insertion is through "StatelessSession" class. StatelessSession class differs from Session class in that it does not cache the objects, does not call interceptors, does not save any persistence context of object, does not cascade to composed objects, does not take care of collections, directly transfers the object to jdbc insert statement. So in other way it is more close to jdbc. With StatelessSession, you have to save composed objects separately e.g. in above example, you have to insert publisher and books separately. Above code with StatelessSession will be:


    StatelessSession session = HibernateUtil.getSessionFacgtory().openStatelessSession(); session.beginTransaction();
    for (int index = 0; index < style="font-style: italic; color: rgb(255, 153, 102);"> {
    Book book = new Book();
    book.setAuthor("amer");
    book.setIsbn("34343");
    book.setName("Hibernate " + index);
    Publisher pub = new Publisher();
    pub.setName("Publisher " + index);
    book.setPublisher(pub);
    book.setPublishDate(new Date());
    session.insert(pub);
    session.insert(book);
    }
    session.getTransaction().commit();
    session.close();

Well its time now to conclude the things. I have used both ways and i prefer first approach over second one because of the following reasons:
  • StatelessSession does not provide any performance over Session when you have to save composed instances too.
  • It does not call any interceptors or evens which may complicate the application design if we heavily depend on interceptors or events for logging or data level security etc.
  • Even for a plain object, StatelessSession does not provide me much performance over Session. It only provided me performance when an object contains one or two attributes. e.g. if i only insert publisher through StatelessSession, i will get performance by 20 to 30 seconds.

Saturday, July 5, 2008

Packaging j2se application in jar

Jar file is distributable unit for j2se applications. It is a zipped file but with jar extension. Jar file contains following contents:

- Java compiled classes
- manifest.mf file which contains meta info regarding jar like name of main class, jars to be added in classpath etc, version info etc. (optional)
- other jars on which classes of this jar depends (optional)

There are two types of jars:

- Library Jar
- Executable Jar

Difference between the two jars is simply a main class. If your application runs standalone and contains main class, then you put name of main class in manifest file. This makes a jar an executable jar. You can run your executable jar just by double clicking on it or through java command with switch -jar. On the other hand, library jar does not contain any main class, and it always runs as a dependency jar for other java applications.

Now lets see how we can create a library jar
If you project just contains java classes and no other jars or manifest file, then you will create jar using following command:

project-folder>jar cvf mylibrary.jar -C classes .

cvf are three switches for jar. "c" means i want to create a new jar rather than updating previous one. "v" means i want to print all log info on console. "f" means supply an output to file i.e. mylibrary.jar in this case. -C is another switch which is used to tell which folders you want to include in jar. In my case all compiled java files are under classes folder but i don't want to include classes folder itself in jar so i used "-C classes .". Dot "." here tells jar command not to include classes folder. If you omit ".", then you have to change switch -C with this "-C classes/". it will tell jar command that all compiles files are under classes folder and include classes folder itself in jar file.
if you look at the contents of created jar file using any unzipped software, you will find that it contains classes + one more folder named as "META-INF". This folder contains manifest.mf. By default jar creates manifest.mf itself if you don't provide it. If you open this manfiest.mf using any text editor, you will see it just contains following two entries:

Manifest-Version: 1.0
Created-By: 1.6.0_03 (Sun Microsystems Inc.)

Important one is "Created-By" which tells which version of java was used to package jar file. In this case it is jse 6 with update 3.
If classes depend on other jars, you have to include those jars in classpath. This can be done at the time of running a program or writing all dependencis in manifest file, so java will automatically add it to classpath. Suppose above jar "mylibrary.jar" depends on other jars named as "other1.jar" and "other2.jar". Now to include these two jars in classpath through manifest file. Create a text file with any name let dependencies.txt and add following lines:

Class-Path: other1.jar other2.jar

Keep in mind that you have to provide spaced in between the every two jar file names.

Now you can add this manifest file to already created manifest file using following command:

project-folder> jar uvfm mylibrary.jar dependencies.txt

Console output will show that Manifest.mf updated. In this command i used switch "u" instead of "c" because i want to append manifest in already created jar. I also used "m" switch, which is used when you want to provide your own manifest file. If i want to create new jars with my own manifest file, then i have to use following command:

project-folder> jar cvfm mylibrary.jar dependencies.txt -C classes .

It is the same command as used previously to create jar with exception of extra "m" switch and name of manifest file.

Procedure of creating executable jar file is the same as library jar but you have to provide one extra attribute in your manifest file with name "Main-Class", So if i have name of main class as "org.engineers.java.MyMain", then i will have to added one entry in manifest file as:

Main-Class: org.engineers.java.MyMain

Saturday, June 21, 2008

Compiling and Executing Java program

There are three basic steps in development of a simple java program which are Coding, Compiling, and Executing the java program. Coding is to write different set of classes and interfaces using any text editor like notepad etc. There are three cases which a java program can have. Those are:

Case A: Classes in default package (no package) and does not use classes which are bundled in jar.
Case B: Classes which are grouped in different packages but does not use classes which are bundled in jar.
Case C: Classes which are group in different packages and also uses classes bundled in jar.

Now i discuss compilation and execution of java program in each case one by one.

Lets discuss Case A. It is most simplest case which does not have any dependency on classes of others which are bundled in jar. Morever, classes are not grouped in different packages. Classes which are not grouped in packages, are said to be contained in default package. Suppose you have created a folder named as "TestProject" and has placed all java files there, then you can do following in windows to compile and exeuctge java program:
Just go to directory "TestProject" through command prompt and write following command:
C:\TestProject>javac *
above command will compile all java files. Now In order to run the java program, write following command:
C:\TestProject>java MainClass
where MainClass is any class which contains "public static void main(String[] args)" method.

Now we discuss Case B in which classes are grouped under packages. Packages provide better management of code, easy maintenance, and good access control on classes. Morever, packages provide safety from class name collissions. This case has further two possibilities. One is that you have logical grouped java classes in packages but placed them together like in case A i.e. all classes in folder TestProject. Now you will use following command to compile the code:
C:\TestProject>javac * -d .
"d" switch is used to provide destination for compiled classes. When destination is ".", it means root directory (TestProject in this case) will be default directory. javac command will first create folder heirarchy similar to packages and will place compiled class files in respective folder e.g. if a class is in package "org.engineers.project", then javac will first create folder named as "org" at root directory, then will create "engineers" folder under "org" and "project" folder under "engineers" folder. and will place class in "project" folder. In order to execute java program, you have to write following command at root directory:
C:\TestProject>java fully_qualified_class_name
fully_qualified_class_name means name of class with package e.g. if a class "Main" is contained under package org.engineers.project, then fully_qualified_class_name will be "org.engineers.project.Main"

Now we talk about second possibility in Case B which is that you have placed java source files in same folder hierarchy, as of packages i.e. if a class "Main.java" is in package "org.engineers.project", you have placed Main.java in folder org/engineers/project folder. You can use same command to compile and execute java program as in first possibility but it will mix your compiled code with source code so in order to keep them separate create a directory named as "src" under root directory (TestProject in this case) and then place all folder hierarchy containing source files there. Now create another folder named as "classes" at root level and use following command to compile the code:
C:\TestProject>javac * -d classes
"classes" folder be treated as root folder for class files.
In order to run java program, you have to change java command slightly. New command will be:
C:\TestProject>java -cp classes org.engineers.project.Main
Difference with this command and with previous command is of addition switch named as "cp". it represents classpath and tells java command where to find compiled classes. Since compiled classes are in "classes" folder, so i added that folder in classpath.

Now its time to discuss Case C, which is more realistic case. In this case, java source files uses classes which are placed in "jar" file. Jar file is just a zip file but with extensino java archive ("jar") . Now you will have to include all jar files in classpath using same switch which we used in preceding case to run the program. but this time we will have to use switch in both javac and java command.
C:\TestProject> javac -cp test.jar * -d classes
where test.jar is jar file which contains other classes which my classes use.
To execute the java program use following command:
C:\TestProject> java -cp test.jar;classes org.enigneers.project.Main
Note that i have added both "test.jar" and "classes folder in classpath.

Saturday, June 14, 2008

Cloning of Java objects

Parent class of all objects in java is "Object" which contains several important methos. One of them is "clone" which is used to make a copy of object. There are certain things which you should keep in mind while using clone method of Object.
- implement "Cloneable" interface to each class which you want to clone. If a class does not implement "Cloneable" interface, clone method will throw "CloneableNotSupportedException". This interface does not contain any methods. It is just a marker interface. Suppose you have a Class "Book" of which you want to make a clone, then structure of that class will be:

public class Book implements Cloneable
{
//attributes
//methods
@Override protected Object clone() throws CloneableNotSupportedException
{
//Clone logic
}
}

- Obtain cloned object through super.clone
- if your class only contains primitive attributes or wrappers of primitive attributes or immutable object like String, then you don't need to do anything special inside clone method because clone method automatically makes a copy of primitive data types and immutable objects. Suppose above "Book" class contains following two attributes with accessor methdos for attributes:

private String name;
private Float price;
public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public Float getPrice() {
return price;
}

public void setPrice(Float price) {
this.price = price;
}

Now to clone Book class you just need to write following implementation in overriding of clone method:

protected Object clone() CloneNotSupportedException
{
return super.clone();
}

- by default clone method makes shallow copy and does not make a Deep copy of object. Deep copy means if your object contains references of other objects or collections, it will not make a copy of those referenced objects and will use same references as was in origianl objects. Suppose above mentioned "Book" class contains an attribute of class "Publisher". Structure of Publisher class is given below:


public class Publisher{
private String pubName;

public String getPubName() {
return pubName;
}

public void setPubName(String pubName) {
this.pubName = pubName;
}
}

Now try out the following code:

Publisher pub = new Publisher();
pub.setPubName("Java Publisher");
orig.setPub(pub);
Logger.getLogger(CloneTest.class.getName()).log(Level.INFO,orig.getPub().getPubName());
Book clone2 = (Book) orig.clone();
Logger.getLogger(CloneTest.class.getName()).log(Level.INFO,clone2.getPub().getPubName());
orig.getPub().setPubName("java Publisher Changed");
Logger.getLogger(CloneTest.class.getName()).log(Level.INFO,clone2.getPub().getPubName());

Output of above code will be:
15-Jun-2008 1:39:47 AM javasolutionsblog.clonetest.CloneTest main
INFO: Java Publisher
15-Jun-2008 1:39:47 AM javasolutionsblog.clonetest.CloneTest main
INFO: Java Publisher
15-Jun-2008 1:39:47 AM javasolutionsblog.clonetest.CloneTest main
INFO: Java Publisher Changed


Although expected output of third log was "Java Publisher" but since clone didn't make copy of refernce object publisher, it used same object in clone as in origignal object, when i make a change in the publisher name in original object, it also reflected in cloned object.

- In order to do deep copy of Book class, we will aso have to implement "Cloneable" interface in "Publisher" class + override clone method in Publisher class too. If Publisher class contains references of other objects, then you will have to implement Cloneable interface + override clone method in each sub class too.
In our case, structure of Publisher class will be:

public class Publisher implements Cloneable{
private String pubName;

public String getPubName() {
return pubName;
}

public void setPubName(String pubName) {
this.pubName = pubName;
}

@Override
protected Object clone() throws CloneNotSupportedException
{
return super.clone();
}

}

Now change the definition of clone method of Book class as follows:

protected Object clone() throws CloneNotSupportedException {
Book clonedBook = (Book) super.clone();
if (this.getPub() != null) {
clonedBook.setPub((Publisher) this.getPub().clone());
}

return clonedBook;
}

Thursday, June 12, 2008

Implementing Equals and HashCode

In my last blog i described how we can compare two java objects of same class by overriding equals method. In this blog i will explain best practices regarding implementing of equals method.
Whenever, we go for overriding of equals method, one question comes to our mind is, on which basis we will have to say that two objects are same. First answer comes to mind is that we should compare objects on the basis of primary key which is also used to distinguish the records in the database. Primary keys are good candidate to compare objects if we assign primary keys ourself not by database. When primary key is assigned by database like auto number, objects don't have primary key until they are persisted in the database so before persistent of objects, how we should compare the objects. Good practice is always compare objects on the basis of business key which uniquely describes objects. Suppose we have a class of Person with attributes (id, name, ssn,address) . In this class we have two unique attributes one is id and second one is ssn. id is used to distinguish the objects in the database and is assigned when objects are persisted, then only choice is SSN which we can use to compare different person because each person has his own SSN (Social Security Number). So best practice is always compare objects on business keys rather than on database keys.
Second best practice is whenever you go for overriding of equals method. also override "int hashCode()" method. This method returns hash of objects. Implementing hasCode facilitates us when we use objects as keys in HashTable. If we don't override hashCode method, each object created with new operator will always has different hash values irrespective of fact whether they are same or not. Suppose I have a class of Customer with attributes (id, name, ssn, address) and i create two objects with new operation having the same dataset. Although logically they are same but physically they are two different objects that's y they have differnt hashCode. So best practice is that if two objects are equals, then those two objects should always have same hashCode. Overriding of hashCode will also facilitate us when we save objects in sets. Sets store only one instance of an object at a time, so if we have two customer objects with same attributes, then only one instance of customer must be saved in sets. It is only possible by overriding of hashcode method.
Now question is how to generate hashCode for an object. Answer is same as for equals method. Always generate hashCode from business keys. In above example of Customer objects, we should generate hashCode of Customer from SSN. java has provided methods which generate hashCode for all primitive data types and for String. hashCode for primitive data types are generated by using wrappers of primitive data types e.g. for int we can generate hashCode by following code:

Integer i = new Integer(5);
int code = i.hashCode();

Similary we can get hashCode of other primitive datatypes by using respective wrapper classes.

So in this blog we have come to Two Best Practices regarding comparison of objects:
- One is always compare objects in equal method on the basis of business keys.
- Second is whenever override equals method, also override hashCode method and generate hash for objects on the basis of same business key as used in equals method.

Saturday, May 3, 2008

Comparison of Objects with equals

== relational operator is used to compare basic data types in java e.g. if we want to compare two integers, we will do it as follows:

int a = 5;
int b = 5;
if (a == b)
System.out.println("equal");
else
System.out.println("not equal");

Output of above java code will be "equal". but this "==" operator works only with basic data types, even it will not work if we use wrapper classes of basic data types e.g.

Integer a = new Integer(5);
Integer b = new Integer(5);
if (a == b)
System.out.println("equal");
else
System.out.println("not equal");


Output of above code will be "not equal". Why "==" operator does not applicable for objects is that because it compares two references of object not contents of objects. Now for comparison of contents of objects there is "equals" method in each object e.g. if we change above comparison of wrapper classes with this code, it will work correctly:

Integer a = new Integer(5);
Integer b = new Integer(5);
if (a.equals(b))

System.out.println("equal");
else
System.out.println("not equal");

Output of above code will be "equal" This "equals" work fine for wrapper classes but does not run correctly for custom classes because it compares two object references by default just like "==" operator. To change behaviour of "equals" we will have to override it in our classes. Suppose i have a class "Book" which has attributes like name, isbn, author, publisher. Now uniqueness of book is checked using isbn number so to compare two books, override "equals" method and in that implementation check the "isbn" of book. Code Structure is given below:

public class Book{
private String isbn;
private String name;
private String author;

public String getIsbn() {
return isbn;
}

public void setIsbn(String isbn) {
this.isbn = isbn;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public String getAuthor() {
return author;
}

public void setAuthor(String author) {
this.author = author;
}

@Override
public boolean equals(Object obj) {
Book book = (Book)obj;
if (this.isbn.equals(book.getIsbn()))
return true;

return false;
}

public static void main(String args[]) {
Book b1 = new Book();
b1.setName("Java");
b1.setAuthor("Amer");
b1.setIsbn("12334");
Book b2 = new Book();
b2.setName("Java");
b2.setAuthor("Amer");
b2.setIsbn("12334");
if (b1.equals(b2))
System.out.println("equal");
else
System.out.println(" not equal");
}
}

output of above code will be equal. even if name or author of two are different because my implementation of "equals" just checks for "isbn".

In my later post, i will exlain best practices related to overriding of "equals" method.

Friday, April 25, 2008

Object Oriented Programming vs Non Object Programming

Often people are confused about real benefits which are provided by OOP. I am trying to remove their confusion in this episode of blog. Every innovation in this world is related to solution of a problem. There is a problem, then we try to find out solution of that problem. So we have to work in two spaces. one is Problem-space in which we concentrate on problem only. and second one is Solution-space in which we develop solution. When we develop solution through computer, we have to think in terms of machine which happened in assembly language. It is impossible for one to get a sense of problem while reading an assembly program. So there is a big gap between problem and solution. People have to develop different artifacts to bridge this gap. After assembly, some other languages came like C, prolog and others , which provided some abstraction on machine but still there was a big gap e.g. prolog concentrates on reasoning and facts. After that OOP made its position, which really reduced the gap between problem-space and solution-space. What we understand and see in problem, we can easily map to a solution which provides us good sense of problem. I explain it with an example e.g. we are developing a solution for a library. Now everyone knows that library has some books and students draw books from library for some time and then return to library. Now if we think on problem, we will come to know that everything in library is relating to three entities Book, Students, and Library itself. Now when we develop solution of this in OOP, we will map these entities to classes and by taking a general look on it, one can easily understand what's going on in the solution and to what things this solution is related.
In short it is the OOP which reduced the gap between problem-space and soluton-space.