Sunday, July 28, 2013

Spring OXM

OXM is Spring's Object/XML Mapping support which helps in conversion of Object to XML(Marshalling) and XML to Object(Unmarshalling). For this, spring has two interfaces Marshaller and Unmarshaller defined in spring-oxm under the package org.springframework.oxm.Marshaller . These can be defined as normal beans like other spring beans.
Marshaller and Unmarshaller has one method each for the actions as below.
public interface Marshaller {
    /**
     * Marshals the object graph with the given root into the provided Result.
     */
    void marshal(Object graph, Result result) throws XmlMappingException, IOException;
}
public interface Unmarshaller {
    /**
     * Unmarshals the given provided Source into an object graph.
     */
    Object unmarshal(Source source) throws XmlMappingException, IOException;
}
Implementation:
There are different marshaller instances in spring-oxm. We will go through CastorMashaller because it's easy to implement and configure.
<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://www.springframework.org/schema/beans
 http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

 <bean id="converter" class="com.test.spring.oxm.converter.Converter">
  <property name="marshaller" ref="castorMarshaller" />
  <property name="unmarshaller" ref="castorMarshaller" />
 </bean>
 
 <bean id="castorMarshaller" class="org.springframework.oxm.castor.CastorMarshaller">
  <property name="mappingLocation" value="classpath:mapping.xml" />
 </bean>
</beans>
CastorMarshaller is the marshaller and it requires one optional property "mappingLocation" which defines the mapping of class to xml. Sample mapping.xml file is
<?xml version="1.0" encoding="UTF-8"?>
<mapping>
 <class name="com.test.spring.oxm.entity.Employee">
  <map-to xml="employee" />
  <field name="empid" type="integer">
   <bind-xml name="id" node="element" />
  </field>
  <field name="name" type="string">
   <bind-xml name="ename" node="element" />
  </field>
   <field name="dob" type="date" >
   <bind-xml name="dob" node="element"  />
  </field>
   <field name="salary" type="double">
   <bind-xml name="salary" node="element" />
  </field>
 </class>
</mapping>
Points to be noted
  • property "mappingLocation" is optional. We can create CastorMarshaller without mappingLocation but it takes default values while binding
  • Each class tag defines the Object which to be marshalled/unmarshalled with set of field tags. Each corresponds to XML and object mapping.
  • type on the field indicates the type of the node and is mapped to Java Type.
  • map-to and bind-xml tags defines the elements and attributes in the xml. 
  • node attribute in bind-xml defines whether the field should be attribute or element

Code for bean "converter" is as below. Converter internally calls the marshall and unmarshall methods of CastorMarshaller.
package com.test.spring.oxm.converter;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;

import org.springframework.oxm.Marshaller;
import org.springframework.oxm.Unmarshaller;

public class Converter
{
    private Marshaller marshaller;
    private Unmarshaller unmarshaller;

    public Marshaller getMarshaller()
    {
        return marshaller;
    }

    public void setMarshaller(Marshaller marshaller)
    {
        this.marshaller = marshaller;
    }

    public Unmarshaller getUnmarshaller()
    {
        return unmarshaller;
    }

    public void setUnmarshaller(Unmarshaller unmarshaller)
    {
        this.unmarshaller = unmarshaller;
    }
    
    public String convertToXml(Object obj,String filepath)
    {
        String finalString = new String();
        FileOutputStream fos = null;
        try {
            fos = new FileOutputStream(filepath);
            getMarshaller().marshal(obj, new StreamResult(fos));
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
        finally {
            if(fos != null)
            {
                try
                {
                    fos.close();
                }
                catch (IOException e)
                {
                    e.printStackTrace();
                }
            }
        }
        return finalString;
    }
    
    public Object convertToObject(String filepath)
    {
        FileInputStream fis = null;
        try {
            fis = new FileInputStream(filepath);
            return getUnmarshaller().unmarshal(new StreamSource(fis));
        } 
        catch (Exception e)
        {
            e.printStackTrace();
        }
        finally {
            if(fis != null)
            {
                try
                {
                    fis.close();
                }
                catch (IOException e)
                {
                    e.printStackTrace();
                }
            }
        }
        return null;
    }
}
The object which to marshalled or unmarshalled is
package com.test.spring.oxm.entity;

import java.util.Date;

public class Employee
{
    private int empid;
    private String name;
    private Date dob;
    private Double salary;

    public int getEmpid()
    {
        return empid;
    }
    public void setEmpid(int empid)
    {
        this.empid = empid;
    }
    public String getName()
    {
        return name;
    }
    public void setName(String name)
    {
        this.name = name;
    }
    public Date getDob()
    {
        return dob;
    }
    public void setDob(Date dob)
    {
        this.dob = dob;
    }
    public Double getSalary()
    {
        return salary;
    }
    public void setSalary(Double salary)
    {
        this.salary = salary;
    }
}
Finally, the main program is
package com.test.spring.oxm;

import java.util.Date;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.test.spring.oxm.converter.Converter;
import com.test.spring.oxm.entity.Employee;

public class Application
{
    public static void main(String[] args)
    {
        ApplicationContext context = new ClassPathXmlApplicationContext("spring-context.xml");
        Converter converter = (Converter)context.getBean("converter");
        Employee emp = new Employee();
        
        emp.setDob(new Date());
        emp.setEmpid(1234);
        emp.setName("Employee Name");
        emp.setSalary(2500.122);
       
        converter.convertToXml(emp,"cust.xml");
        
        Employee emp2 = (Employee)converter.convertToObject("cust.xml");
        System.out.println("Empid : "+emp2.getEmpid());
        System.out.println("Name  : "+emp2.getName());
        System.out.println("Salary: "+emp2.getSalary());
        System.out.println("DOB   : "+emp2.getDob());
    }
}
The xml file generated out of it is :
<?xml version="1.0" encoding="UTF-8"?>
<employee>
 <id>1234</id>
 <ename>Employee Name</ename>
 <dob>2013-07-28T21:17:29.331+05:30</dob>
 <salary>2500.122</salary>
</employee>

Friday, July 26, 2013

What's in .Class File

I never looked what's inside .class file except knowing that .class file consists of compiled byte code of Java Program. I was looking at quite a few articles, specifications, posts etc to get to know about byte class exact contents.
We already know what compiler does, what is a byte code, how byte code is executed by jre. Below is the brief definition.
Byte code: Java compiler (javac) generates the byte code for each Java file compiled. Byte-code is a sequence of mnemonics. Each of them will be translated by java run time environment to execute.
There are many mnemonics byte code consists of. Let's take a look at some of them with some examples which are very frequent.
Example 1:
package com.test;
public class Main
{
     public static void main(String...args)
     {
          System.out.println("Hello World");
     }
}
After compiling the Main.java, the generated class file looks like as below when you open in any hexa-decimal supported editor.




















To view the byte code in ASCII, we can use javap command.
Example: javap <class-name> displays the Class with methods in it where as -c option shows the each line of code inside the methods.












There are some basic points in the above lines of byte-code. As we know, each and every class we write, will be a sub-class of java.lang.Object ( as we can see extends java.lang.Object even we don't have that in .java file) and a default constructor is added with no parameters.
javap prints more detailed information
-s : the internal signature
-l : the line numbers and local variables used inside each function
And to print all the information, just give -verbose. Sample output looks like this

Interesting fact is, even though the java file is so simple with very few statements, compiler generated very large set of statements with tables, signatures, etc. We will see the details of few instructions in the next posts.

Thursday, July 25, 2013

Hibernate Caching - Second Level Cache

First Level Cache of hibernate (Detailed in the last post) is more specific to Session. Second Level Cache is another level where the cache is maintained in different regions across the sessions. The second level cache is divided into four regions: entity, collection, query, and timestamp.
Entity and Collection regions cache data from entities and their relations. 
The Query cache caches the result set of the database against the query. 
The Timestamp cache keeps track of last updated time of each table.
There will be on timestamp cache enabled for each query cache. The following properties to be set to enable the second level caching
hibernate.cache.use_second_level_cache = true|false
hibernate.cache.use_query_cache = true|false
hibernate.cache.region.factory_class=net.sf.ehcache.hibernate.EhCacheRegionFactory
Since Hibernate4, the factory "org.hibernate.cache.ehcache.EhCacheRegionFactory" to be used instead of "net.sf.ehcache.hibernate.EhCacheRegionFactory"
In addition to above lines, the objects to be specified with the cache strategy. The line to be specified in the hibernate hbm file in <class> tag is
<cache usage="read-write|nonstrict-read-write|read-only" />
If to be specified in Annotations on the Entity Class, use
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
How it Works

  • When we fetch an object using hibernate, it searches the object in first level cache. If found, it returns the object
  • If the object not found in first level cache, checks the second level cache. If found, stores the object in first level cache returns
  • If the entity is not found both the levels, a database query is fired and stores in both the levels and returns.
  • The second level cache validates all of its entities, if any modifications are done through hibernate APIs. But, it never know if the database object is modified by any other resource unless "timeToLiveSeconds" duration has passed 

Notes:
To view the statistics of Entity fetches, second level cache hits, etc. We need to configure explicitly as.
hibernate.generate_statistics=true|false
and using "sessionFactory.getStatistics()" which retunrs an object of Statistics type. 

Hibernate Caching - First Level Cache

Caching is one of the basic feature provided by ORM frameworks. Caching make the application to run faster by reducing number of queries to the database. Hibernate provides two levels of cache for this.
  1. First Level Cache: First level cache is associated with each session. This cache is by default and you cannot switch off this. As we can create sessions on demand, there will be first level cache associated with each session.
  2. Second Level Cache: Second level cache is associated with Session Factory. Basically, there is only one second level cache as only one Session Factory is maintained by application.
When a session is closed, the first level cache associated with it will be cleared. When a session factory is cleared, full second level cache associated with it will be lost.

Example for First level cache:

   SessionFactory sessionFactory = (SessionFactory) context.getBean("sessionFactory");
   Session session = sessionFactory.openSession();
        
   Employee emp = null;
   emp = (Employee) session.load(Employee.class, new Integer(1));
   System.out.println("Employee Name : "+emp.getName());
        
   emp = (Employee) session.load(Employee.class, new Integer(1));
   System.out.println("Employee Name : "+emp.getName());
        
   Session newSession = sessionFactory.openSession();
   emp = (Employee) newSession.load(Employee.class, new Integer(1));
   System.out.println("Employee Name : "+emp.getName());
        
   session.evict(emp);
   emp = (Employee) session.load(Employee.class, new Integer(1));
   System.out.println("Employee Name : "+emp.getName());
        
   newSession.clear();
   emp = (Employee) newSession.load(Employee.class, new Integer(1));
   System.out.println("Employee Name : "+emp.getName());
The log for the above program will be :
Hibernate: select employee0_.id as id0_0_, employee0_.age as age0_0_, employee0_.name as name0_0_ from EMP employee0_ where employee0_.id=?
Employee Name : name
Employee Name : name
Hibernate: select employee0_.id as id0_0_, employee0_.age as age0_0_, employee0_.name as name0_0_ from EMP employee0_ where employee0_.id=?
Employee Name : name
Hibernate: select employee0_.id as id0_0_, employee0_.age as age0_0_, employee0_.name as name0_0_ from EMP employee0_ where employee0_.id=?
Employee Name : name
Hibernate: select employee0_.id as id0_0_, employee0_.age as age0_0_, employee0_.name as name0_0_ from EMP employee0_ where employee0_.id=?
Employee Name : name

Explanation:
First time when load method called, the object is fetched by firing a query to database. When the second time loaded, no query was fired as the object is cached in first level cache.
Even though the object is cached by session "session", the new session "newSession" is fetched the object by firing a new query.
To clear the cache from the session, evict() or clear() method can be used. Once it's cleared, the session tries to get the object from the database. The last two queries of hibernate in the log explains that.

Notes:

  • First level cache is only associated to Session. Each session will have it's own first level cache.
  • There is no extra configuration required for first level cache. No way to switch off configuration.
  • Cache will be cleared by closing the session, by using clear() method.
  • Individual object can be removed from the cache by using evict method.