JavaRocks

 

The singleton pattern isn't inherently thread-safe, but you can write thread-safe singletons.

Any class that has no writable class or instance data members is inherently thread safe. Any method that uses only local variables or parameters is inherently thread-safe. If a class has writable class or data members, the sections of code that modifies them should appear in a synchronized block.

If your singleton meets these criteria, I believe it's thread safe.

 
 

The best way is:

public class ExampleSingleton {
 
  private static ExampleSingleton instance;
 
  public static ExampleSingleton getInstance() {
    if( instance == null ) {
      synchronized( ExampleSingleton.class ) {
        if ( instance == null ) {
           instance = new ExampleSingleton();
        }
      }//sync ends
    }
 
    return instance;
  }
}


 
 

When it comes to design web application with database access, hibernate and spring are the first choice.

Spring for dependency injection and hibernate for persisting objects.

 

There are two ways of integrating Hibernate Annotations with Spring.

Using only applicationcontext.xml
Using applicationContext.xml and hibernate.cfg.xml file.
 

Method 1:

 

When we use only applicationContext.xml, we set all the properties of sessionfactory in applicationContext.xml file and we use AnnotationSessionFactoryBean class to create sessionFactory.

 

Eg:

<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">

<property name="annotatedClasses">

        <list>

        <value>model.Employee</value>

        </list>

</property>

<property name="hibernateProperties">

        <props>

        <prop key="hibernate.dialect">org.hibernate.dialect.Oracle9iDialect</prop>

        <prop key="hibernate.show_sql">true</prop>

        <prop key="hibernate.jdbc.fetch_size">10000</prop>

        <prop key="hibernate.hbm2ddl.auto">create</prop>

        <prop key="hibernate.current_session_context_class">thread</prop>

        </props>

</property>

<property name="dataSource" ref="dataSource"/>

</bean>

 

This approach works fine only to some extent.

While using this approach we found that whenever you retrieve a small object (say just 1 row) using session.get(object), the unnecessary memory was getting used.

To retrieve a single row of object with two string fields was taking 5M of heap memory.

I was not having any idea where this memory is used but it was used.

Then we switched to other approach.

 

Method 2: (better method)

 

In this method we define our applicationContext.xml and hibernate.cfg.xml file.

hibernate.cfg.xml file is defined as usual.

Now we refer this hibernate.cfg.xml file in applictaionContext.xml file.

 

Following is the code snippet from  applicationContext.xml file referring hibernate.cfg.xml file.

 

Eg:

<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean" singleton="true">

<property name="configurationClass" value="org.hibernate.cfg.AnnotationConfiguration"/>

<property name="configLocation" value="classpath:hibernate.cfg.xml"/>

</bean>

 

Only above configuration is required to refer hibernate.cfg.xml file in applicationContext.xml file.

Instead of referring hibernate.cfg.xml file in classpath, you can also give direct path of hibernate.cfg.xml file.

 

Hibernate.cfg.xml file should be defined in normal way as it is defined.

Eg:

 

<hibernate-configuration>

    <session-factory>

<property name="hibernate.connection.driver_class">oracle.jdbc.OracleDriver</property>

        <property name="hibernate.connection.url">jdbc:oracle:thin:@host:database </property>

        <property name="hibernate.connection.username">uname</property>

        <property name="hibernate.connection.password">pword</property>

        <property name="hibernate.connection.pool_size">10</property>

        <property name="show_sql">true</property>

         <property name="dialect">org.hibernate.dialect.Oracle9iDialect</property>

        <property name="current_session_context_class">thread</property>

        <mapping class="model.Employee"/>

        </session-factory>

</hibernate-configuration>

 
 

Generally when we try to inject any value for a variable using spring we inject the non static variables.

But it is quite often that we need to initialize a static variable in a java pojo class.

The normal way of injecting the values in pojo class does not work for static variables.

The MethodInvokingFactoryBean class of spring needs to be used for this purpose.

 

Here is a example.

We have an employee class where company is static variable.

We will inject value for company using MethodInvokingFactoryBean.

 

Employee.java

 

public class Employee{

            private static String company;

private String emp_id;

 

public static void setCompany(String comp){

Employee.company=comp;

}

//other getter and setters

}

 

spring.xml

 

<bean id="abc" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">

<property name="staticMethod">

<value>Employee.setCompany</value>

</property>

<property name="arguments">

<list>

            My New Company

</list>

</property>

</bean>

 

Note: My New Company is the value which we want to set for static variable company. We are setting this value using setter method of employee.

 
 

To explain the cascading of save and delete lets take an example of Employee, Company and Acccount.

Many employees can belong to same company.
An employee can have many accounts with it.

Company.java
package model;
import javax.persistence.*;
import javax.persistence.Entity;

import java.util.List;

@Entity
public class Company {
    @Id
    private long id;

    private String name;

    @OneToMany(mappedBy = "company")

    private List<Employee> employees;

    public List<Employee> getEmployees() {
        return employees;
    }

    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

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

    public void setEmployees(List<Employee> employees) {
        this.employees = employees;
    }
}


Employee.java
package model;

import org.hibernate.annotations.*;

import javax.persistence.*;
import javax.persistence.Entity;
import java.util.List;
import java.util.ArrayList;

@Entity
public class Employee {
    @Id
    private long id;

    private String name;

    @ManyToOne

    @JoinColumn(name = "company_id")

@Cascade({org.hibernate.annotations.CascadeType.SAVE_UPDATE})  

private Company company;

    @OneToMany(mappedBy = "employee")

    @Cascade({org.hibernate.annotations.CascadeType.ALL})

    private List<Account> accounts;

    public Company getCompany() {
        return company;
    }

    public void setCompany(Company company) {
        this.company = company;
    }

    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

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

    public List<Account> getAccounts() {
        return accounts;
    }

    public void setAccounts(List<Account> accounts) {
        this.accounts = accounts;
    }

    public void addAccount(Account account){
        if(getAccounts()==null){
            accounts=new ArrayList<Account>();
        }
        getAccounts().add(account);
    }
}


Account.java
package model;

import javax.persistence.*;
import javax.persistence.Entity;

@Entity
public class Account {

    @Id
    private long id;

    private String name;

    @ManyToOne

    private Employee employee;

    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

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

    public Employee getEmployee() {
        return employee;
    }

    public void setEmployee(Employee employee) {
        this.employee = employee;
    }
}

Save Cascading

Cascading Save is a recursive process that could be described as "walking the object graph". The general algorithm for save goes:
·    Prior to saving a bean we save its ManyToOne associations (And appropriate OneToOnes)
·    Then we save the bean itself
·    Then we save any OneToMany, ManyToMany (And appropriate OneToOnes)
Note: OneToOnes will occur prior and post saving the bean depending on whether the OneToOne owns the foreign key or not. If that doesn't make sense don't worry too much.

Employee employee=new Employee();
………………………..

//employee is belonging to one company.
//employee has two accounts (assume two).

Session.save(employee);

In this example

Session.save(employee) will do the following things.

Prior to saving the employee, company will be saved.
After the company is saved the employee will be saved.
After the employee is saved the accounts are saved.

A "Relational" way of describing this is that we go "up the imported foreign keys", then save the bean, then go "down the exported foreign keys".
Perhaps another way of thinking about this is to take the example where every object is new and will need to be inserted.

Before we save the employee, we need company’s id, hence company is saved before employee.
Once the company is saved, employee is saved.
Accounts need employee_id before it is saved.
Hence once, employee is saved, accounts are also saved.

Delete Cascading

Delete cascading is very similar except the order is reversed.
      1 Prior to deleting a bean we delete its OneToMany, ManyToMany (And appropriate OneToOnes) associations
2 Then we delete the bean itself
3 Then we delte any ManyToOne (And appropriate OneToOnes)


Here is the test class which uses these three classes to create record in database.

package test;

import org.hibernate.SessionFactory;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import model.Employee;
import model.Company;
import model.Account;

public class MyTest {
    public static void main(String[] args) {
        Resource resource=new ClassPathResource("applicationContext.xml");
        BeanFactory factory=new XmlBeanFactory(resource);
        SessionFactory sessionFactory= (SessionFactory) factory.getBean("sessionFactory");
        Session session=sessionFactory.openSession();
        Transaction transaction=session.beginTransaction();

        Employee employee=new Employee();
        employee.setId(1);
        employee.setName("abcd");

        Company company=new Company();
        company.setId(1);
        company.setName("ABCDEFGH");

        employee.setCompany(company);

        Account account1=new Account();
        account1.setId(1);
        account1.setName("HDFC");
        account1.setEmployee(employee);

        Account accoutn2=new Account();
        accoutn2.setId(2);
        accoutn2.setName("ICICI");
        accoutn2.setEmployee(employee);

        employee.addAccount(account1);
        employee.addAccount(accoutn2);

        session.save(employee);
        transaction.commit();
        session.flush();
        session.close();
    }
}

 
 

Here a code for ajax request to server.

This code defines a function sendRequest(url,divId).
This function takes two arguments, first - the url to which ajax request is to be made. second - the divId in which the response is to be included.

<script>
var http = getHTTPObject();
function sendRequest(url,divId) {
SubmitRBData(url,divId);
}

function SubmitRBData(strUrl,divId) {
http.open("GET", strUrl, true);
http.onreadystatechange = function handleHttpResponse() {

if (http.readyState == 4) {
if (http.status == 200){
results = http.responseText;
document.getElementById(divId).innerHTML=results; // string response
}}};
http.send(null);
}

function getHTTPObject() {
var objXMLHttp=null;
if (window.XMLHttpRequest){
objXMLHttp=new XMLHttpRequest();
}
else if (window.ActiveXObject){
objXMLHttp=new ActiveXObject("Microsoft.XMLHTTP");
}
return objXMLHttp;
}
</script>


var http = getHTTPObject();

function sendRequest(url,divId) {
SubmitRBData(url,divId);
}

function SubmitRBData(strUrl,divId) {
http.open("GET", strUrl, true);
http.onreadystatechange = function handleHttpResponse() {

if (http.readyState == 4) {
if (http.status == 200)
{
results = http.responseText;
document.getElementById(divId).innerHTML=results; // string response
}
}

};
http.send(null);
}


function getHTTPObject() {

var objXMLHttp=null;

if (window.XMLHttpRequest)
{
objXMLHttp=new XMLHttpRequest();
}
else if (window.ActiveXObject)
{
objXMLHttp=new ActiveXObject("Microsoft.XMLHTTP");
}

return objXMLHttp;

}

To make a ajax call, simply include this javascript in your code and call the sendRequest method.

 
 

Recently, in one of our project we were using hibernate. We were having hibernate integrated with Velocity, Webwork and Spring. We wanted to show a webpage where the webwork action will make a hibernate query and get the fields from one table. example : We were having a database schema to store countries and cities. The cities were mapped to country. Now our webpage should show all the countries and all the cities within that country. Our hibernate objects were created in such a way that we could retrieve cities from country(One-To-Many). We have also made LAZY loading for cities from country. i.e a country should return cities only when asked. or in other words, the hibernate wont query the database for cities in particular country unless asked.
Since we were using LAZY loading, we faced a problem.
When user sends a request to view page, our webwork action method is called. In this action method we load all the countries, but since cities are lazily loaded, no cities are loaded in action method. In the same action method we open the sesison and query for country and then close the session. Now list of cities is returned to the velocity Parser, but the response is not yet rendered. The velocity page now tries to fetch the cities in each country. Since session is already closed the getter method for cities gives LAZY Initialization Exception. This is because our action method made a query for country and closed the session. When velocity asks for cities and hibernate tries to query for cities, it finds the session to be closed. Hence LAZY initialization error.

This problem can be solved if we open a session on client request and close it before sending a response back to client. This can be achieved with Spring's OpenSessionInViewFilter.

To use OpenSessionInViewFilter, edit your web.xml file and put this filter before webwork filter.

<filter>
<filter-name>hibernateFilter</filter-name>
<filter-class>org.springframework.orm.hibernate.support.OpenSess ionInViewFilter</filter-class>
</filter>

<filter-mapping>
<filter-name>hibernateFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>


Issues: Now when you are using OpenSessionInViewFilter, by default the session's flush mode is set to NEVER. So when you try to save something in your action using hibenate and commit it, it wont be reflected in your database. To solve this you need to flush the session in your action class or extend OpenSessionInViewFilter and override closeSession(Session session, SessionFactory sessionFactory).
public MyOSIVFilter extends OpenSessionInViewFilter{
public void closeSession(Session session, SessionFactory sessionFactory){
session.flush();
super.closeSession(session,sessionFactory);
}
}


change your web.xml to
<filter>
<filter-name>hibernateFilter</filter-name>
<filter-class>package.MYOSIVFilter</filter-class>
</filter>

<filter-mapping>
<filter-name>hibernateFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>


Now it is also possible that you are maintaining a single transaction for per request. In your action you edit the attributes of a object and update it using session.update(object). But it is not yet commited as some other processing is remaining. At the same time, some other request is invoking a action which tries to retrieve the object which you were updating. Since the object is not yet commited the other request will get the old object. To solve this you need to begin a transaction before you load object and commit the transaction after you update the object. So that as soon as the object is saved/updated it is commited. With this there can be many transaction in single user request but only one session.

Now there is another way to do the same thing using Spring TransactionProxyFactoryBean.
This is actually a proxy factory which takes the target object which needs to be proxied, the method to be proxied and the transactionManager.

below is the code snippet from applicationContext.xml

<bean id="repository" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="transactionManager" ref="hibernateTransactionManager"/>
<property name="transactionAttributeSource" ref="transactionAttributeSource"/>
<property name="target" ref="daoImpl"/>
<property name="proxyInterfaces">
<list>
<value>package.DAO</value>
</list>
</property>
</bean>

<bean id="transactionAttributeSource"
class="org.springframework.transaction.interceptor.NameMatchTransactionAttributeSource">
<property name="properties">
<value>
get*=PROPAGATION_REQUIRED,readOnly
find*=PROPAGATION_REQUIRED,readOnly
create*=PROPAGATION_REQUIRED,readOnly
delete*=PROPAGATION_REQUIRED
</value>
</property>
</bean>

<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean" >
.........................
.............
.....
......
</bean>

<bean id="hibernateTransactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>

<bean id="daoImpl" class="package.daoImpl">
...................................
..................................
</bean>


Above code says the TransactionProxyFactoryBean that all the methods in daoImpl starting with get, find, create, delete should be proxied and for all this methods the transaction should be begin before method starts and should get commited after method finishes.

 
 

We were having a requirement to index PDF document. To index it is necessary to convert it into text form. After searching for some API, we finally got PDFBox which is freeware. Using PDFBox it is very easy to extract text from the PDF document.
Following is the code snippet to extract text from PDF document.

Download PDFBox at http://www.pdfbox.org/

Writer output = new StringWriter();
PDFTextStripper stripper = null;
try {
stripper = new PDFTextStripper();
stripper.setSortByPosition(false);
stripper.setStartPage(1);
stripper.setEndPage(Integer.MAX_VALUE);

PDDocument document = PDDocument.load(path of the file to be read);
stripper.writeText(document, output);
document.close();
} catch (IOException e) {
log.error(e);
e.printStackTrace();
}
return result.toString();

 
 

We were having a issue with one of our design. We were having a table which used to store entire file in blob column. When we query a table with some criteria and if the query returns large number of results or the rows and each row containing large blob, we were getting Out of Memory error in Java. To solve this we made a slight modification to our design of tables.

We created two tables file and filecontent and mapped them by one-to-one mapping using hibernate. The blob column was now shifted to filecontent table. We were using lucene to index the content of file. Since blob column was now moved to filecontent table, the indexing which we did on file table didn’t work. To solve this, we used @EmbeddedObject annotation in file object. Our lucene indexing problem was now solved. Indexes were getting created, but now the same problem occurred again. The hibernate-lucene in turn does a join query when we search through index. As a result again the huge blob is getting retrieved along with other columns. To solve this we again changed our design, but this time only in hibernate configuration.

We created a transient field of type byte[] in file object and made it indexable. So we were having the file’s content in two object (file and filecontent), but in file it was transient and indexable and in filecontent it was persistent and non-indexable.
Also while mapping file and filecontent object using hibernate, we specified LAZY loading filecontent object.

 
 

By default, in MySQL we can store BLOB of size 1M. To increase the size of this you have to change the my.conf file.
You can find my.conf file in Program Files\MySQL\MySQL Server 5.0\my.ini
Open the file and Under the [mysqld], add the following line.
max_allowed_packet = 16M
eg:
[mysqld]max_allowed_packet = 16M