Friday, November 20, 2009

Hiberante Event Listeners

Hibernate also provides a event System besides the Interceptor Model.The Event System can be used in place of Interceptor or besides the interceptors.The Hibernate system provides many methods that work with the operations that we perfom on a pojo object.there are events like save,saveOrUpdate and many other .

These events are linked with the session.what ever the event a session generates is handled by the appropriate event handler linked with the current

sessionfactory.these event listeners are said to be singleton.these events listeners are shared among many request.no values are to be hold in the instance variables of the event listeners.A custom listener implements the appropriate interface for the event it wants to process and/or extend one of the convenience base classes (or even the default event listeners used by Hibernate out-of-the-box as these are declared non-final for this purpose).


Lets see how we can write a simple event listener while storing an object , we will be seeing a event listener system for the save-update event.


There are 2 ways to perform the save-update event using event listener either implement a interface called “SaveOrUpdateEventListener” or either extends a class “DefaultSaveOrUpdateEventListener”.the method obtained when extending the class or by implementing the interface leads us to a method ,

Public void onSaveOrUpdate(SaveUpdateEvent event){ }


When we have written a event listener class, we need to attach it the current SessionFactory such that when ever a event of that is throw by the session, the listener class linked to the current session factory gets executed.


Now lets see how we write a event listener by extending the class ,


@SuppressWarnings("deprecated")
public class DefaultSaveOrUpdateListener extends DefaultSaveOrUpdateEventListener {


public void onSaveOrUpdate(SaveOrUpdateEvent object) {


MyData data=(MyData) object.getObject();
data.setFirstName(data.getFirstName().trim()+”Trimmed”);
super.onSaveOrUpdate(object);


}
}


Or else we can do the same thing by implementing the interface ,


@SuppressWarnings("deprecated")
public class DefaultListenerClass implements SaveOrUpdateEventListener {


public void onSaveOrUpdate(SaveOrUpdateEvent arg0)
throws HibernateException {


}
}
When ever we say saveOrUpdate , the event for the save-Update which we registered with the sessionFactory gets called and processed.this is the code for saving my object,


obtainedFactory=HibernateSessionFactory.getSessionFactory();
obtainedSession=obtainedFactory.getCurrentSession();
obtainedSession.beginTransaction();
obtainedSession.saveOrUpdate(new MyData("Very Much","MySelf"));
obtainedSession.connection().commit();
obtainedSession.close();




as We have written in the above onSaveOrUpdate() method , the first Name we send will be appended with “new Much “ value and is saved in the DataBase.but how are we going to register the eventListener to the SessionFactory ,


configuration.setListener("save-update", new DefaultListenerClass());


I just linked the Event Listener to save-Update event and attached it to the SessionFactory . we can do the same by adding in the Hiberante.cfg.xml file also.

This gives the same effect. We can write listeners for various events like
Save,update,delete , flush e.t.c.

Read More

Friday, October 30, 2009

Hibernate Interceptors

Consider that we have requirement where we need to trim the values of the strings in the model Object that we are going to save . but if we write a method like trim() which we will call the method by passing a object as an argument which returns the trimmed() values.

but consider , i have defined all the variables in my model classes as private , so we cannot access them in our super class even and cannot change the values [trimming the spaces and reset the values ] , may throw IllegalModifierException,IllegalArgumentException.we need to change all the variable to public .

we may call the code like this ,

SomeObject=trim(SomeObject);
getSession().save(SomeObject);

so we will be calling the trim() method before when ever we say save(),update(),saveOrUpdate() and flush().

so we need to chanage all the values . what happens when we need to save Batch of objects. the trim() method will be called many times.

Lets move for a more generic Option , we will Use the Hibernate Interceptors.

so interceptors provide us a way to process the object before some thing is being done with that object [ may be saved , updated .... ].so how does we write an interceptor .

Consider a MyData model class which i going to save in Databasse , the code looks like this

public class MyData implements Serializable {

@Id@GeneratedValue
public int ID;

public MyData() {
// TODO Auto-generated constructor stub
}

public MyData(String name,String last) {
this.firstName=name;
this.lastName=last;
}

private String firstName;
private String lastName;

public int getID() {
return ID;
}
public void setID(int id) {
ID = id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}

}


U can see the some of the variables are set to private .

Now lets write a Basic Interceptor .for this we have a inteceptor interface with some 15 methods . we will use a class "EmptyInterceptor " which already implements the "Interceptor" interface available in hiberante. the code looks like this


@SuppressWarnings("serial")
public class MyDataInterceptor extends EmptyInterceptor {

public boolean onSave(Object entity, Serializable id, Object[] state,
String[] propertyNames, Type[] types) {

for(int i=0;i
if(state[i] instanceof String){
String obtainedValue=(String)state[i];
state[i]=obtainedValue.trim();
}
}//close of loop
return super.onSave(entity, id, state, propertyNames, types);
}

}


what i have done is i just wrote a Interceptor which extends EmptyInterceptor , i implemented a method onSave() [ we have some more methods like onUpdate(),onDelete() and onLoad() .... ] . what this method does is it just perform the code that we have written in the onSave() method before any model class is going to get saved.

consider if we save as above

getSession().save(SomeObject);

before saving the SomeObject , the code in the onSave() method gets exceuted. i have written the code that satisfies our functionality [trimming the String values].

Object entity : the object that we are going to save
Serializable id: The id represents the Serializable primary key (which in our case will bea simple string object).
The state array represents the values of the properties of the persistent object
The propertyNames array holds a list of string values, which are firstName,lastName.

now what i have done , i written a loop which iterates through the state array [ containing values that we are passing ] and trimming them and resetting them.this even works for private variables [ no exception ] .

and final thing as how to link this interceptor to the Hibernate Application ,

Interceptors are 2 types
Global Interceptor : set to SessionFactory
Session Interceptor : set to Session

we will use global since all objects values will be trimmed if they contain strings.

configuration.configure(configFile);
//configuration.setListener("save-update", new DefaultSaveOrUpdateListener());
configuration.setInterceptor(new MyDataInterceptor());
sessionFactory = configuration.buildSessionFactory();

we just need to say configuration.setInteceptor(Our Interceptor class)

and all objects values will be trimmed , with no code changes in any model classes or any additional methods . just a few changes.
Read More

Hibernate Annotation - @Embedded and @Embeddable

In this blog, I will explain you how to map a component using @Embedded and @Embeddable Annotations.
Consider the Student Object which contains columns ,
StudentID
StudentName
StudentClass
StudentStreet
StudentCity
StudentState

We can see the columns StudentStreet , city and state can be kept in one more object “Address”.where as the Student Object contains only StudentID,StudentName and StudentClass.
So now we can make these fields into an Address object , but still we need to save these values in to a student object for which the details belong.for this we need to make sure that the address object created for a student should be inserted into the student as a internal component.
The @Embedded annotation says the same thing , when ever we define an child object as a @Embedded inside a parent object, the child object is said to saved as a component

@Embedded annotation says that the object should be saved as internal component to other object .
@Embeddable annotation says that the object defined as @Embeddable will be saved as an internal component of another object.the object defined as a @Embeddable will not have any Primary key since it will be saved according to the parent object.

Now consider the Student Object

Public class Student implements Serializable {

Private int StudentID;

public Student() {

}

public Student(String name,String studentClass ,Address address) {
this.studentName=name;
this.studentClass=studentClass;
this.address=address;
}

@Id
@GeneratedValue
private int ID;

private String studentName;
private String studentClass;
private String studentAge;

public int getID() {
return ID;
}

public void setID(int id) {
ID = id;
}

public String getStudentAge() {
return studentAge;
}

public void setStudentAge(String studentAge) {
this.studentAge = studentAge;
}

public String getStudentName() {
return studentName;
}
public void setStudentName(String studentName) {
this.studentName = studentName;
}
public String getStudentClass() {
return studentClass;
}
public void setStudentClass(String studentClass) {
this.studentClass = studentClass;
}


@Embedded
private Address address;
public Address getAddress() {
return address;
}

public void setAddress(Address address) {
this.address = address;
}


}


we can see from the above the address object is defined with an @Embedded annotation to make that address object saved as a internal component of student object.
Now consider the Address class ,
@Embeddable
public class Address implements Serializable {


private String Street;
private String City;
private String State;

public String getStreet() {
return Street;
}

public void setStreet(String street) {
Street = street;
}

public String getCity() {
return City;
}

public void setCity(String city) {
City = city;
}

public String getState() {
return State;
}

public void setState(String state) {
State = state;
}

public Address() {
}

public Address(String street,String city,String state) {
this.Street=street;
this.City=city;
this.State=state;
}

}

@Embeddable annotation says that the object will be treated as a component.

All these columns will be saved in a single table in database. No 2 tables.
Read More

Tuesday, May 19, 2009

Gwt Suggest box – Gmail

In this blog we will work on implementating a Suggest box which can work similarly as Gmail “To” field where it takes a multiple string by using a de-limiter “,” .


You can see the “,” element which divides the suggest items.this cannot be done by the normal gwt suggest box . lets see how we can make a suggest box like above,

From the java docs we can see a suggest box contains a constructor with suggest oracle and a TextboxBase as arguments. We will use this constructor in implementing the above thing .

public class SuggestTextBox extends TextBoxBase {

protected SuggestTextBox(Element elem) {

super(elem);

}

public SuggestTextBox() {

this(Document.get().createTextInputElement(), "gwt-TextBox");

}

public SuggestTextBox(Element elem,String styleName) {

super(elem);

if (styleName != null) {

setStyleName(styleName);

}

}

public String getText() {

String totalString=super.getText();

String newString=totalString;

if(totalString!=null && !totalString.trim().equals("")){

int lastComma=totalString.indexOf(",");

if(lastComma>0){

newString=totalString.trim().substring(lastComma+1);

}

}

return newString;

}//close of getText

public void setText(String text) {

String totalString=super.getText();

if(text!=null && text.equals("")){

super.setText(text);

}else {

if(totalString!=null){

int lastComma=totalString.trim().indexOf(",");

if(lastComma>0){

totalString=totalString.trim().substring(0, lastComma);

}else {

totalString="";

}

if (!totalString.trim().endsWith(",")

&& !totalString.trim().equals("")) {

totalString = totalString + ", ";

}

totalString = totalString + text + ", ";

super.setText(totalString);

}

}//close of if loop

}//Close of Set Text

}

Now in the onModuleLoad() , we will write the code as

SuggestionOracle oracle=new SuggestionOracle();

SuggestBox box=new SuggestBox(oracle,new SuggestTextBox());

box.setWidth("300px");

HorizontalPanel hPanel=new HorizontalPanel();

hPanel.add(new Label("Suggest Box"));

hPanel.add(box);

RootPanel.get().add(hPanel);


Read More