Thursday, 6 December 2012

Hibernate Second Level EHCache Example

Hibernate Second Level EHCache Example


In an application when the database traffic is very heavy, hibernate is well used because of its high performance. To overcome from this problem hibernate caching is the best technique. This technique is optimizing the database applications by caching the already loaded data from the database.
so the traffic between our application and the database will be reduced when the application want to access that data again.

Cache Types in Hibernate:

    First-level cache
    Second-level cache.

Hibernate Cache Implementations:

    OSCache  (Open Symphony Cache)
    EHCache  (Easy Hibernate Cache)
    JBoss TreeCache
    SwarmCache

Hibernate Caching Strategies:

    Read-only.
    Read-Write.
    Nonstriict read-write.
    Transactional.

First-level cache:-

First-level cache always associates with the Session object. Hibernate uses this cache by default. First level cache is enabled by default. Here, it processes one transaction after another one, it means it wont process one transaction many times. Mainly it is reducing the number of SQL queries it needs to generate within a given transaction i.e. instead of updating after every modification done in the transaction, it updates the transaction only at the end of the transaction. 

Second-level cache:-

Second level cache was introduced in hibernate 3.0.Second-level cache always associates with the Session Factory object. Second level cache works while running the transactions, in between it loads the objects at the Session Factory level, so that those objects will available to the entire application, don’t bounds to single user. Since the objects are already loaded in the cache, whenever an object is returned by the query, at that time no need to go for a database transaction. We can use query level cache also. 


Hibernate Cache Implementations:-

a) OSCache (Open Symphony Cache) (org.hibernate.cache.OSCacheProvider)

  1. It is a powerful .
  2. It supports read-only and read/write caching.
  3. It supports memory- based and disk-based caching.
  4. It provides basic support for clustering via either JavaGroups or JMS.

 b) EHCache (Easy Hibernate Cache) (org.hibernate.cache.EhCacheProvider)

  1. It is lightweight and that's why it is fast.
  2. It is Easy-to-use.
  3. It supports read-only and read/write caching.
  4. It supports memory-based and disk-based caching.
  5. It does not support clustering.

c) JBoss TreeCache (org.hibernate.cache.TreeCacheProvider)

  1. It is a powerful replicated and transactional cache.
  2. It is useful when we need a true transaction-capable caching architecture .

d)SwarmCache (org.hibernate.cache.SwarmCacheProvider)

  1. It is a cluster-based caching.
  2. It supports read-only or nonstrict read/write caching .
  3. It is very much appropriate for applications those have more read operations than write operations.

 

Hibernate Caching/Concurrency Strategies

A concurrency strategy is a way which is responsible for storing items of data in the cache and retrieving them from the cache.  

a) Read-only

  1. It is useful for those data which is frequently read but never updated.
  2. It is Simple.
  3. This is the best performer among the all caching strategy.
Advantage if this one is, It is safe for using in a cluster. Here is an example for using the read-only cache strategy. 





Refer the below example:- 
<class name="com.gaurav.bean.Customer" mutable="true">
<cache usage="read-only"/>
..........................
</class>

b) Read-Write

  1. It is used, when our data needs to be updated frequently.
  2. It is having more overhead than read-only caches.
  3. It is never used if serializable transaction isolation level is required.
  4. In a JTA environment, for obtaining the JTA TransactionManager we must specify the property hibernate.transaction.manager_lookup_class.
  5. To use it in a cluster the cache implementation must support locking.
Here is an example for using the read-write cache strategy.








<class name="com.gaurav.bean.Customer" .... >
<cache usage="read-write"/>
..............................
<set name="test" ... >
<cache usage="read-write"/>
................................
</set>
</class>

C) Nonstrict read-write

  1. It is needed if the application needs to update data rarely.
  2. we must specify hibernate.transaction.manager_lookup_class to use this in a JTA environment .
Here is an example for using the nonstrict read-write cache strategy.




<class name="com.gaurav.bean.Customer" .... >
<cache usage=" nonstrict-read-write"/>
...............................................
</class>

d) Transactional

  1. It supports only transactional cache providers such as JBoss TreeCache.
  2. It is only used in JTA environment.

 

Configuring Cache in Hibernate

We can use hibernate.cfg.xml file for the cache configuration. A typical configuration file is shown below. 

<hibernate-configuration>
    <session-factory>
        .............................
        <property name="cache.provider_class">org.hibernate.cache.EhCacheProvider</property>
        .............................
    </session-factory>
</hibernate-configuration>



The name in <property> tag must be hibernate.cache.provider_class or cache.provider_class for activating second-level cache. We can use hibernate.cache.use_second_level_cache property, which allows you to activate and deactivate the second-level cache. By default, the second-level cache is activated and uses the EHCache. 

Hibernate cache tag element

The <cache> element has the following attributes:




<cache
    usage=" caching strategy"
    region="RegionName"
    include="all | non-lazy"/>
  1. usage (mandatory) specifies the caching strategy: transactional, read-write, nonstrict-read-write or read-only.
  2. region (optional) specifies the name of the second level cache region .
  3. include (optional) non-lazy specifies that properties of the entity mapped with lazy=”true” may not be cached when attribute-level lazy fetching is enabled.


Hibernate queries Caching

Hibernate is providing a property through which we can cache the queries. Many times it is happening that some queries are running frequently with same parameters, we can cache those queries. Just We have to set hibernate.cache.use_query_cache to true by calling Query.setCacheable(true) for enabling the query cache.
  1.     For storing the most recent updates.
  2.     For storing the results.
Query cache always used second-level cache only. Queries wont cached by default. Below is an example implementation of query cache.

        Session session = SessionFactory.openSession();
        Query query = session.createQuery("FROM CUSTOMER");
        query.setCacheable(true);
        query.setCacheRegion("customer");
        List users = query.list();
        SessionFactory.closeSession();

Note: - This(query.setCacheRegion("customer")) code uses the method to tell Hibernate to store and look for the query in the customer area of the cache.
   

hibernate.cache.use_query_cache property We need to set in the hibernate.cfg.xml file to true like below :

<property name="hibernate.cache.use_query_cache">true</property>

Then, we can use the setCacheable() method on any query we wish to cache.

Hibernate second level cache example

Required files are as below:-
  1. Customer.java  [ Pojo class]
  2. Customer.hbm.xml
  3. ehcache.xml
  4. hibernate.cfg.xml 
  5. log4j.properties
  6. HibernateSendLevelCacheTest.java
Customer.java

package com.gaurav.bean;

public class Customer {

    private int customerId;
    private String customerName;
    private double expenditure;

    /**
     * @return the customerId
     */
    public int getCustomerId() {
        return customerId;
    }

    /**
     * @param customerId
     *            the customerId to set
     */
    public void setCustomerId(int customerId) {
        this.customerId = customerId;
    }

    /**
     * @return the customerName
     */
    public String getCustomerName() {
        return customerName;
    }

    /**
     * @param customerName
     *            the customerName to set
     */
    public void setCustomerName(String customerName) {
        this.customerName = customerName;
    }

    /**
     * @return the expenditure
     */
    public double getExpenditure() {
        return expenditure;
    }

    /**
     * @param expenditure
     *            the expenditure to set
     */
    public void setExpenditure(double expenditure) {
        this.expenditure = expenditure;
    }
}

Customer.hbm.xml

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping>
    <class name="com.gaurav.bean.Customer" table="customer">
        <cache usage="read-only" />
        <id name="customerId" column="CUSTOMER_ID" />
        <property name="customerName" column="CUSTOMER_NAME" length="50" />
        <property name="expenditure" column="TOTAL_EXPENDITURE" />
    </class>
</hibernate-mapping>

ehcache.xml

<?xml version="1.0"?>

<ehcache>
    <defaultCache maxElementsInMemory="100" eternal="false"
        timeToIdleSeconds="120" timeToLiveSeconds="200" />
    <cache name="com.gaurav.bean.Customer" maxElementsInMemory="100" eternal="false"
        timeToIdleSeconds="5" timeToLiveSeconds="200" />
</ehcache>

hibernate.cfg.xml

<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">

<hibernate-configuration>
    <session-factory>
        <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
        <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/test</property>
        <property name="hibernate.connection.username">root</property>
        <property name="connection.password">root</property>
        <property name="cache.provider_class">org.hibernate.cache.EhCacheProvider</property>
        <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
        <property name="show_sql">true</property>
        <property name="hibernate.hbm2ddl.auto">update</property>
        <mapping resource="Customer.hbm.xml"></mapping>
    </session-factory>
</hibernate-configuration>

log4j.properties

### direct log messages to stdout ###
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n

### set log levels - for more verbose logging change 'info' to 'debug' ###
log4j.rootLogger=warn, stdout
log4j.logger.org.hibernate=debug
log4j.logger.org.hibernate.type=trace

### log schema export/update ###
log4j.logger.org.hibernate.tool.hbm2ddl=debug






HibernateSendLevelCacheTest.java

package com.gaurav.impl.test;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

import com.gaurav.bean.Customer;

public class HibernateSendLevelCacheTest {

    public static void main(String[] args) {

        Configuration cfg = new Configuration();
        cfg.configure("hibernate.cfg.xml");

        SessionFactory sessionFactory = cfg.buildSessionFactory();
        Session firstSession = sessionFactory.openSession();
        Object object1 = firstSession.load(Customer.class, new Integer(1));

        Customer customer1 = (Customer) object1;

        System.out.println("Object Loaded first and here customer name is-->"
                + customer1.getCustomerName());
        System.out.println("Object Loaded first and here customer id is-->"
                + customer1.getCustomerId());
        System.out
                .println("Object Loaded first and here customer expenditure is-->"
                        + customer1.getExpenditure());
        System.out.println("***** Object is loaded here *****");

        firstSession.clear();
        firstSession.close();

        System.out.println("Thread.sleep called Status-Waiting......");

        try {
            Thread.sleep(10000);
        } catch (Exception e) {
        }

        System.out
                .println("----------------------------Waiting---------------------------------------------------------");

        System.out.println("10 seconds compelted during wait");

        Session secondSession = sessionFactory.openSession();
        Object object2 = secondSession.load(Customer.class, new Integer(1));

        System.out
                .println("-------------------------------------------------------------------------------------");

        Customer customer2 = (Customer) object2;

        System.out
                .println("Second time object loaded and here customer name is -->"
                        + customer2.getCustomerName());
        System.out
                .println("Second time object loaded and here customer id is-->"
                        + customer1.getCustomerId());
        System.out
                .println("Second time object loaded and here customer expenditure is-->"
                        + customer1.getExpenditure());
        System.out.println("***** Object loaded from the database *****");

        secondSession.close();

        Session thirdSession = sessionFactory.openSession();

        Object object3 = thirdSession.load(Customer.class, new Integer(1));

        System.out
                .println("-------------------------------------------------------------------------------------");

        Customer customer3 = (Customer) object3;

        System.out
                .println("Third time object loaded and here customer name is-->"
                        + customer3.getCustomerName());
        System.out
                .println("Third time object loaded and here customer id is-->"
                        + customer1.getCustomerId());
        System.out
                .println("Third time object loaded and here customer expenditure is-->"
                        + customer1.getExpenditure());
        System.out
                .println("***** Object loaded from global cache successfully *****");

        thirdSession.close();

        sessionFactory.close();
    }

}

Below is the project directory structure:-


About ehcache.xml

    In ehcache.xml, if eternal=”true” then we should not write timeToIdealSeconds, timeToLiveSeconds, 
    hibernate will take care about these values, If you want to give values manually then we can
    use eternal=''false'' and we can assign values into timeToIdealSeconds, timeToLiveSeconds manually,
   
   a) timeToIdealSeconds = ''seconds'' means, if the object in the global cache is not using by any other class or object then it will be waited for some time we specified and deleted from the global cache if time is exceeds more than timeToIdealSeconds value.

   b) timeToLiveSeconds = ''seconds'' means if once the time specified is completed then it will be removed from the global cache by hibernate.

  c) <defaultCache … /> will reflects to all the pojo classes in our application,  and we can also assign the ehcache values to specified pojo class by
    <cache name=”– package name.pojo class name —” …….. />


Hibernate Caching Tips

  1. All the objects those are passed to methods save(), update() or saveOrUpdate() or those you get from load(), get(), list(), iterate() or scroll() will be saved into cache.
  2. evict() is used to delete the object from cache.
  3. flush() is used to synchronize the object with database.
  4. Session.clear() used to delete all objects from the cache . 
  5. contains() used to find whether the object belongs to the cache or not.
  6. If the query wants to force a refresh of its query cache region, we should call Query.setCacheMode(CacheMode.REFRESH).

Tuesday, 4 December 2012

How to send Email in Specific time interval continously Using Timer threads

How to send Email in Specific time interval continously Using Timer

FreeMarker is a "template engine"; a generic tool to generate text output (anything from HTML to autogenerated source code) based on templates. It's a Java package, a class library for Java programmers. It's not an application for end-users in itself, but something that programmers can embed into their products. 
reference(http://freemarker.sourceforge.net/)

I am using freemarker template for creating the email body. I have used my gmail a/c username and password for the email send test purpose. So if you want to execute your program then in the Constant.java file use your gmail username and password for FROM_MAIL_ID and FROM_MAIL_ID_PASS property.

Before going through the below program few jars are required, the references are given below:-
1) http://www.java2s.com/Code/Jar/a/Downloadactivationjar.htm - activation.jar
2) mirrors.ibiblio.org/pub/mirrors/maven2/freemarker/freemarker/2.3.4/freemarker-2.3.4.jar - freemarker.jar
3) http://www.java2s.com/Code/Jar/m/Downloadmailjar.htm - mail.jar

STEP - 1

1) Create java file and name it as Constants.java file as below:-

package com.gaurav.examples.mail;

public class Constants
{
    public static final String TEMPLATE_FILENAME = "html-mail-template.ftl";
    public static final String ATTACHMENT_FILENAME = "
welcome.txt";
    public static final String MAIL_SEND_SUCCESS_STATUS = "mail Sent successfully";
    public static final String MAIL_SEND_SUCCESS_FAIL = "mail send failed";
    public static final String FROM_MAIL_ID = "test@gmail.com";//This is From mail-id.
    public static final String FROM_MAIL_ID_PASS ="Please keep ur password here";//From Mail-id password.
    public static final String TO_MAIL_ID = "tomailIdUsername@gmail.com";//Please use to mail id here.
    public static final String MAIL_SUBJECT = "Sending a Test mail through Java Mail API";
    public static final String TO_MAIL = "to";
    public static final String TO_MAIL_NAME = "Gollu";
    public static final String MAIL_BODY = "body";
    public static final String EMAIL_BODY_CONTENT = "See the text file and reply the answer?";
    public static final String FROM_MAIL = "from";
    public static final String FROM_MAIL_NAME = "Kumar.";
    public static final String PROPERTY_FILENAME ="settings.properties";
    public static final String BODY_CONTENT_TYPE="text/html";
}

STEP - 2

1) Create a java file and name it as SendMail.java, use the below contents
 
package com.gaurav.examples.mail;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.StringWriter;
import java.io.Writer;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

import javax.activation.DataHandler;
import javax.activation.DataSource;
import javax.activation.FileDataSource;
import javax.mail.Authenticator;
import javax.mail.BodyPart;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Multipart;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;

import freemarker.template.Configuration;
import freemarker.template.Template;

public class SendMail {

    private String strMailSendStatus = null;

    public String mailSend() throws Exception {

        Properties props = new Properties();
        try {
            props.load(new FileInputStream(
                    new File(Constants.PROPERTY_FILENAME)));
        } catch (FileNotFoundException e1) {
            e1.printStackTrace();
        } catch (IOException e1) {
            e1.printStackTrace();
        }

        Session session = Session.getDefaultInstance(props,
                new Authenticator() {

                    protected PasswordAuthentication getPasswordAuthentication() {
                        return new PasswordAuthentication(
                                Constants.FROM_MAIL_ID,
                                Constants.FROM_MAIL_ID_PASS);
                    }
                });

        try {
            Message message = new MimeMessage(session);

            message.setFrom(new InternetAddress());
            message.setRecipients(Message.RecipientType.TO,
                    InternetAddress.parse(Constants.TO_MAIL_ID));
            message.setSubject(Constants.MAIL_SUBJECT);

            BodyPart body = new MimeBodyPart();

            // freemarker api use for using it's template.
            Configuration cfg = new Configuration();
            Template template = cfg.getTemplate(Constants.TEMPLATE_FILENAME);
            Map<String, String> rootMap = new HashMap<String, String>();
            rootMap.put(Constants.TO_MAIL, Constants.TO_MAIL_NAME);
            rootMap.put(Constants.MAIL_BODY, Constants.EMAIL_BODY_CONTENT);
            rootMap.put(Constants.FROM_MAIL, Constants.FROM_MAIL_NAME);
            Writer out = new StringWriter();
            template.process(rootMap, out);
            // freemarker api use for using it's template ends here.

            /* we can keep html tags in our text for the decoration purpose. */
            body.setContent(out.toString(), "text/html");

            Multipart multipart = new MimeMultipart();
            multipart.addBodyPart(body);

            body = new MimeBodyPart();

            String filename = Constants.ATTACHMENT_FILENAME;
            DataSource source = new FileDataSource(filename);
            body.setDataHandler(new DataHandler(source));
            body.setFileName(filename);
            multipart.addBodyPart(body);

            message.setContent(multipart, "text/html");

            Transport.send(message);

            strMailSendStatus = Constants.MAIL_SEND_SUCCESS_STATUS;

        } catch (MessagingException e) {
            e.printStackTrace();
            strMailSendStatus = Constants.MAIL_SEND_SUCCESS_FAIL;
        }

        return strMailSendStatus;
    }
}
 
STEP - 3

1) Create a java file and name it as SendMailCaller.java as below

package com.gaurav.examples.mail;

import java.util.TimerTask;


public class SendMailCaller extends TimerTask
{

    public void run()
    {

        SendMail sender = new SendMail();
                String mailSendStatus = null;
                try{
                    mailSendStatus = sender.mailSend();
                }catch(Exception e){
                    e.printStackTrace();
                }
               System.out.println("Email Sent status ->"+mailSendStatus);

            }
}

STEP - 4 

1) Create a java file and name it as EmailJobScheduler.java like below:-

package com.gaurav.examples.mail;

import java.util.Timer;

public class EmailJobScheduler {

    public void callScheduler() throws Exception {

        System.out.println("Scheduler Starterd...");
        Timer timer = new Timer();
        timer.scheduleAtFixedRate(new SendMailCaller(), getTimeDelayAndPeriod("2s"),
                getTimeDelayAndPeriod("10s"));

    }

    public long getTimeDelayAndPeriod(String value) throws Exception {
        long l = 0;
        String val = "";
        try {
            if (value.endsWith("d") || value.endsWith("D")) {
                val = value.substring(0, value.length() - 1);
                l = Long.parseLong(val) * 24 * 60 * 60 * 1000;
            }

            else if (value.endsWith("h") || value.endsWith("H")) {

                val = value.substring(0, value.length() - 1);
                l = Long.parseLong(val) * 60 * 60 * 1000;

            } else if (value.endsWith("m") || value.endsWith("M")) {
                val = value.substring(0, value.length() - 1);
                l = Long.parseLong(val) * 60 * 1000;
            } else if (value.endsWith("s") || value.endsWith("S")) {

                val = value.substring(0, value.length() - 1);
                l = Long.parseLong(val) * 1000;
            } else {

                l = Long.parseLong(value);
            }

        } catch (Exception e) {

            throw new Exception(e);
        }

        return l;
    }

    public static void main(String a[]) throws Exception {
        EmailJobScheduler emailJobScheduler = new EmailJobScheduler();
        emailJobScheduler.callScheduler();
    }

}

STEP - 5

1) Create a file and name it as html-mail-template.ftl, use the below contents:-

<html>
<body>
Hi ${to},

<p style='color:midnightblue;'>${body}</p>

Regards,<br/>
${from}.
</body>
</html>


STEP - 6

1) Create a text file and name it as welcome.txt, use the below content:-

Who is elected as the president of India in 2012?

STEP - 7

1) Create a file and name it as settings.properties, and use the below content:

mail.smtp.socketFactory.class=javax.net.ssl.SSLSocketFactory
mail.smtp.auth=true
mail.smtp.port=465
mail.smtp.host=smtp.gmail.com
mail.smtp.socketFactory.port=465

STEP - 8

In order to run  this application three external jars are required which is as below:-

Required Jars    -       (download link)

References are given above.

The project directory structure is given below:-