Showing posts with label EJB. Show all posts
Showing posts with label EJB. Show all posts

Saturday, February 25, 2012

Transaction Isolation Level and ACID Properties

Transaction Isolation Level and ACID Properties

Isolation levels represent how a database maintains data integrity against the problems like Dirty Reads, Phantom Reads 
and Non-Repeatable Reads which can occur due to concurrent transactions. You can avoid these problems by describing 
following isolation levels in vendor's deployment descriptor file (web.xml or any xml/properties file):
        TRANSACTION_READ_UNCOMMITED
        TRANSACTION_READ_COMMITED
        TRANSACTION_REPEATABLE_READ
        TRANSACTION_SERIALIZABLE

Databases use Read and Write locks depending on above isolation levels to control transactions. 

Dirty Read:  This occurs when one Transaction is modifying the record and another Transaction is reading the record before 
             the first Transaction either commits or rolls back. Here the second Transaction always read an invalid value
             if the first Transaction does rollback. Reason is: isolation attribute is set to READ UNCOMMITTED.

Phantom Read: Phantom read occurs when in a transaction same query executes twice, and the second query result includes 
              rows that weren't present in the first result set. This situation is caused by another transaction inserting 
              new rows between the execution of the two queries. Reason is: isolation attribute is set to READ COMMITTED.

Non Repeatable Read: Non Repeatable Reads happen when in a same transaction same query yields different results. This 
                     happens when another transaction updates the data returned by first transaction.              

Problems due to concurrent transactions: 
Transaction Level                Dirty_Read       Non_Repeatable_Read         Phantom_Read     Performance_Impact 
TRANSACTION_READ_UNCOMMITED         YES              YES                         YES             FASTEST
TRANSACTION_READ_COMMITED             NO               YES                         YES             FAST
TRANSACTION_REPEATABLE_READ         NO               NO                            YES             MEDIUM
TRANSACTION_SERIALIZABLE             NO               NO                          NO              SLOW

YES: means the transaction level does not prevent the problem.
NO: means the transaction level prevents the problem.
By setting isolation levels, you are having an impact on the performance as mentioned in the above table. 


Dirty Read:
You can control this problem by setting isolation level as TRANSACTION_READ_COMMITED.

Unrepeatable read problem :
You can control this problem by setting isolation level as TRANSACTION_REPEATABLE_READ.

Phantom read problem : 
You can control this problem by setting isolation level as TRANSACTION_SERIALIZABLE.

Examples of Isolation Levels:
1) Displaying a Product Catalog in UI: Use TRANSACTION_READ_UNCOMMITED
    As you are not worried if some records comes or goes out from display page. This is fastest in performance.

2) Writing a critical program like bank or stocks analysis program where you want to control all of the 
isolation problems, you can choose TRANSACTION_SERIALIZABLE for maximum safety. However this is Slow.

3) If your application needs only committed records, then TRANSACTION_READ_COMMITED isolation is the choice. 

4) If your application needs to read a row exclusively till you finish your work, then use TRANSACTION_REPEATABLE_READ.


Note: Database servers may not support all of these isolation levels. Oracle server supports only two isolation levels: 
    TRANSACTION_READ_COMMITED and TRANSACTION_SERIALIZABLE. Default is TRANSACTION_READ_COMMITED.
    Databases have their own locking strategy. However you can design locking in your application too. 
    Like Optimistic lock in Hibernate.
    
    
ACID Properties:
ACID is a set of properties which guarantee that database transactions are processed reliably, in fact these 
are Desirable Properties of any Transaction Processing Engine. A transaction is a collection of read/write 
operations. ACID is an acronym for:
    Atomicity
    Consistency
    Isolation
    Durability

    Atomicity: An entire document gets printed or nothing at all. Either commit all or nothing.
    Consistency: All printed pages will have same width and height as border/space. Make consistent records 
                 in terms of validating all rules and constraints of transactions.
     
    Isolation: No two documents get mixed up while printing. Two transactions are unaware to each other.
    Durability: The printer can guarantee that it was not "printing" with empty cartridges. This means 
                committed data is stored forever and post Server/DB restart also it can be accessed.     
----------------------End------------------

Friday, February 3, 2012

EJB 2.x with MyEclipse and Weblogic 9.x

EJB 2.x with MyEclipse and Weblogic 9.x

Dear reader,
Here is the basic example and how to run the EJB using Client, tested on the above mentioned platform:

Steps:
1) Create Weblogic domain using "Configuration Wizard" under "Tool" in Bea/Weblogic.
2) Create a "File-->New-->EJB Project" in Myeclipse. 
3) We need two projects: "EJB Project" for Server side and "Java Project" for client side.
4) Folder structure is as below, excluding other Supported Runtime libraries and Classpaths:
--------------EJB Project for Server side-------------
TestEJB3
--src
  --bean
    --TestBean.java
    --TestBeanHome.java
    --TestBeanRemote.java

  --META-INF
    --ejb-jar.xml
    --MANIFEST.MF
    --weblogic-ejb-jar.xml

--------------Java Project for Client side-------------
TestEJB3Client
--src
  --TestEJBClient.java

5) Below are the code for above mentioned files for Server Side:
//TestBeanRemote.java
package bean;
import java.rmi.RemoteException;
import javax.ejb.EJBObject;

public interface TestBeanRemote extends EJBObject {
    public void doSomething() throws RemoteException;
    public String calculateSum(int num1, int num2, int num3) throws RemoteException;
}
----------------------------------------------------
//TestBeanHome.java
package bean;
import java.rmi.RemoteException;
import javax.ejb.CreateException;
import javax.ejb.EJBHome;

public interface TestBeanHome extends EJBHome{
    public TestBeanRemote create() throws CreateException, RemoteException;    
}
----------------------------------------------------
//TestBean.java
package bean;
import javax.ejb.SessionBean;
import javax.ejb.SessionContext;

public class TestBean implements SessionBean {
    private SessionContext ctx;
    public void setSessionContext(SessionContext c) {
        ctx = c;
        System.out.println(" \n In setSessionContext() \n");
    }
    public void ejbCreate() {
        System.out.println("In ejbCreate().");
    }
    public void ejbRemove() {
        System.out.println("In ejbRemove().");
    }
    public void ejbActivate() {
        System.out.println("In ejbActivate().");
    }
    public void ejbPassivate() {
        System.out.println("In ejbPassivate().");
    }
    public void doSomething(){
        System.out.println("Hello deepak from TestBean");
    }
    public String calculateSum(int num1, int num2, int num3){
        int sum=num1+num2+num3;
        System.out.println("In calculateSum(): Sum="+sum);
        return sum+"";
    }        
} 
----------------------------------------------------
//ejb-jar.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE ejb-jar PUBLIC '-//Sun Microsystems, Inc.//DTD Enterprise JavaBeans 2.0//EN' 'http://java.sun.com/dtd/ejb-jar_2_0.dtd'>
<ejb-jar>
  <enterprise-beans>
    <session>
      <ejb-name>TestEJB3</ejb-name>
      <home>bean.TestBeanHome</home>
      <remote>bean.TestBeanRemote</remote>
      <ejb-class>bean.TestBean</ejb-class>
      <session-type>Stateless</session-type>
      <transaction-type>Container</transaction-type>
    </session>
  </enterprise-beans>
  <assembly-descriptor> 
     <container-transaction>
          <method>
                <ejb-name>TestEJB3</ejb-name>
                <method-intf>Remote</method-intf>
                <method-name>doSomething</method-name>                
         </method>
         <method>
                <ejb-name>TestEJB3</ejb-name>
                <method-intf>Remote</method-intf>
                <method-name>calculateSum</method-name>                
         </method>
         <trans-attribute>NotSupported</trans-attribute>
        </container-transaction>
   </assembly-descriptor>     
</ejb-jar>
----------------------------------------------------
//weblogic-ejb-jar.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE weblogic-ejb-jar PUBLIC "-//BEA Systems, Inc.//DTD WebLogic 8.1.0 EJB//EN" "http://www.bea.com/servers/wls810/dtd/weblogic-ejb-jar.dtd" >
<weblogic-ejb-jar>
  <weblogic-enterprise-bean>
    <ejb-name>TestEJB3</ejb-name>
    <stateless-session-descriptor>
      <pool>
        <max-beans-in-free-pool>200</max-beans-in-free-pool>
        <initial-beans-in-free-pool>20</initial-beans-in-free-pool>
      </pool>
      <stateless-clustering>
        <home-load-algorithm>RoundRobin</home-load-algorithm>
        <stateless-bean-is-clusterable>true</stateless-bean-is-clusterable>
      </stateless-clustering>
    </stateless-session-descriptor>
    <transaction-descriptor>
      <trans-timeout-seconds>120</trans-timeout-seconds>
    </transaction-descriptor>
    <enable-call-by-reference>true</enable-call-by-reference>
    <jndi-name>TestJNDI</jndi-name>
  </weblogic-enterprise-bean>
</weblogic-ejb-jar>
----------------------------------------------------
//MANIFEST.MF (No change is required).
Manifest-Version: 1.0
Class-Path: 
----------------------------------------------------

6) Below is the code for Client side only:
//TestEJBClient.java
import java.util.Hashtable;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.rmi.PortableRemoteObject;

import bean.TestBeanHome;
import bean.TestBeanRemote;

public class TestEJBClient {
    public static void main(String[] args) throws Exception{
        try {
            Hashtable<String, String> ht_env = new Hashtable<String, String>();
            ht_env.put(Context.INITIAL_CONTEXT_FACTORY,"weblogic.jndi.WLInitialContextFactory");
            ht_env.put(Context.PROVIDER_URL, "t3://localhost:7001");
            InitialContext ctx = new InitialContext(ht_env);
            Object o = ctx.lookup("TestJNDI");
            
            TestBeanHome home = (TestBeanHome) PortableRemoteObject.narrow(o,TestBeanHome.class);
            TestBeanRemote bean = home.create();
            bean.doSomething();
            bean.calculateSum(100, 160, 190);
        } catch (NamingException e) {
            e.printStackTrace();
        }
    }
}
----------------------------------------------------
7) Once the coding is done, we have to deploy the EJB in Server and test it via Client.
   For deploying, Left click on "TestBean.java" in your "EJB Project" in Myeclipse and click on 
   "Deploy MyEclipse J2EE Project to Server". This is a "Clickable Button" given on LEFT side of Myeclipse UI, before "Start Server" option.
   There you can "Remove/Redeploy/Edit" as well. Once it is deployed, done.

8) Now you have to execute the Java Client code to get the output from EJB, Simply run the EJBClient.java.
   This is a working example, so it should work, However if you are getting any "NameNotFound" kind of JNDI exception,
   Better check the Weblogic Console "Server-> AdminConsole->JNDI Tree". Your JNDI should appear.
   Hope you got this well and first step in EJB is completed well.