Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Wiki Markup
{scrollbar}

...

Java Persistence API deployment plans

The Java Persistence API is a new programming model under EJB3.0 specification (JSR220) for the management of persistence and object/relational mapping with Java EE and Java SE. With JPA, developers can easily develop java applications that perform operations on relational database management systems using java objects and mapping. In that way, java applications developed using JPA are not only portable across different platforms, but also applications can be easily developed using simple yet powerful programming model provided by JPA. This greatly improves application maintainability against ever changing database world. JPA insulates applications from all the complexity and non-portable boilerplate code involved in database connectivity and operations.

...

Below sections illustrate developing applications using JPA and how to write various deployment plans for apache geronimo.

ShareAccount sample

This H2. Shareholder example
In example illustrates developing an enterprise application that uses JPA for persistence. The database used is the embedded derby shipped with apache geronimo. Here, we present a persistence deployment plan (persistence.xml) that contains database connectivity and other information for the application. The persistence.xml is placed under META-INF/ directory of the application archive. The application contains an ejb module and a web module. Ejb module uses a stateless session bean ShareHolderBean that uses JPA to perform database operations on the database table SHAREACCOUNT in the ShareDB derby database. The SHAREACCOUNT table contains information about each shareholder along with the information regarding number shares he or she possesses currently in the account. The ShareHolderBean has methods that retrieve shareholder information, buy/sell shares of a particular shareholder, close the shareholder account etc. The web application has a servlet that looks up the {{ ShareHolderBean}} and trigger the operations on it. The deployment information for the ejb module is provided using Java EE annotations in the respective bean classes. However, the persistence plan is provided using META-INF/persistence.xml file.

Code Block
JAVA
JAVA
borderStylesolid
titlesample.jpa.ShareAccount.java
package sample.jpa;

import java.io.Serializable;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.NamedQuery;
import javax.persistence.PostLoad;
import javax.persistence.PostUpdate;
import javax.persistence.PrePersist;
import javax.persistence.PreUpdate;
import javax.persistence.Version;
import javax.persistence.Table;

@Entity
@Table(name = "SHAREACCOUNT")
@NamedQuery(name="findThem", query="SELECT a FROM ShareAccount a")
public class ShareAccount implements Serializable {

   
    @Id
    private int shareAccountNo;

    private String ownerName;

    private int numberOfShares;
    
    @Version
    private int version;

    public ShareAccount(int shareAccountNo, 
                        String ownerName, 
                        int numberOfShares) {

    	  this.shareAccountNo = shareAccountNo;
      this.ownerName = ownerName;
      this.numberOfShares = numberOfShares;
        
    }

    public String toString() {
        return "Acc.# " + shareAccountNo +
               ", owner" + ownerName + 
               ", numberOfShares: " + 
                  numberOfShares + " $";
    }

    @PrePersist
    void prepersist() {
        System.out.println("pre persist!!");
    }
    
    @PreUpdate
    void preupdate() {
        System.out.println("pre update!!");
    }
    
    @PostUpdate
    void postupdate() {
        System.out.println("post update!!");
    }
    
    @PostLoad
    void postload() {
        System.out.println("post load!!");
    }

	public int getShareAccountNo() {
		return shareAccountNo;
	}

	public void setShareAccountNo(int shareAccountNo) {
		this.shareAccountNo = shareAccountNo;
	}

	public String getOwnerName() {
		return ownerName;
	}

	public void setOwnerName(String ownerName) {
		this.ownerName = ownerName;
	}

	public int getNumberOfShares() {
		return numberOfShares;
	}

	public void setNumberOfShares(int numberOfShares) {
		this.numberOfShares = numberOfShares;
	}

	public int getVersion() {
		return version;
	}

	public void setVersion(int version) {
		this.version = version;
	}
  
}

Observe various annotations that represent various aspects of the entity in the class.

@Entity : Marks the ShareAccount class as an entity that can be persisted entirely in the database.

@Table(name = "SHAREACCOUNT") : Assigns Designates the database table SHAREACCOUNT whose columns to the entity. The columns in the database table map to the attributes of ShareAccount class. During @NamedQuery(name="findThem", query="SELECT a FROM ShareAccount a") entity.

@Id : This annotation designates primary key of to the entity. In this case, it is the shareAccountNo attribute of the entity class.

@NamedQuery(name="findAccounts", query="SELECT a FROM ShareAccount a") : This annotation declares a named query by name "findAccounts". This query retrieves all the share accounts from the database. Later in the ejb ShareHolderBean, the NamedQuery can be is executed by using the name "findAccounts".

@Version : The version attribute of the ShareAccount Entity class entity.

The annotations placed around some of the methods of the ShareAccount class (are @PrePersist, @PreUpdate, @PostUpdate , @PostLoad) designate callback methodsand @PostLoad. These are the callback methods called by persistence container when corresponding database operations are performed on the entity.

Code Block
JAVA
JAVA
borderStylesolid
titlesample.jpa.ShareHolder.java
package sample.jpa;

import java.util.List;

/**
 * Business interface of the Bank session bean, a facade for the
 * Account entity bean.
 */

public interface ShareHolder {

 
    public ShareAccount openShareAccount(int shareHolderNo, String ownerName, int numberOfShares);

    public ShareAccount findShareAccount(int shareHolderNo);
    
public    public ShareAccount closeShareAccount close(int shareHolderNo);
    
    public List<ShareAccount> listAccounts();
    
    public ShareAccount buyShares(int shareHolderNo, int numberOfShares);
    
    public int sellShares(int shareHolderNo, int numberOfShares);   
    
    public ShareAccount updateShareAccount(ShareAccount sa);
    
}

The ShareHolder.java is the remote interface of the stateless session bean.

Code Block
JAVA
JAVA
borderStylesolid
titlesample.jpa.ShareHolderBean.java
package sample.jpa;


import java.util.List;

import javax.ejb.Stateless;
import javax.ejb.Remote;
import javax.persistence.*;
import javax.ejb.TransactionManagement;
import javax.ejb.TransactionManagementType;
/**
 * Stateless session bean facade for account entities, remotely accessible
 */
@Stateless
@TransactionManagement(TransactionManagementType.CONTAINER) 
@Remote(ShareHolder.class)
public class ShareHolderBean implements ShareHolder { 
  
  /**
  @PersistenceContext
   * Theprivate entityEntityManager manager;

 object, injected by thepublic container
ShareAccount openShareAccount(int shareHolderNo, 
  */
    @PersistenceContext
    private EntityManager manager;


    public ShareAccount openShareAccount(int shareHolderNo, String ownerName, int numberOfShares){
    	
    	if (findShareAccount(shareHolderNo) == null){
    		ShareAccount sa = newString ShareAccount(shareHolderNo,ownerName,numberOfShares);
 
            	manager.persist(sa);
          	return sa;
    	}
    	
    	return null;
     	int numberOfShares){
    }
	
    public	if ShareAccount (findShareAccount(int shareHolderNoshareHolderNo) == null){
    		ShareAccount sa = new manager.find(ShareAccount.class, shareHolderNo);
ShareAccount
     	return sa;
    }
    
    public ShareAccount close(int shareHolderNo){
    	ShareAccount sa = manager.find(ShareAccount.class, shareHolderNo);      (shareHolderNo,
        
    	if (sa != null)manager.remove(sa);
    	return sa;

    }
    
    public List<ShareAccount> listAccounts(){ ownerName,
        Query query = manager.createNamedQuery("findThem");
        return query.getResultList();
    }
    
    public ShareAccount buyShares(int shareHolderNo, int numberOfShares){;
    	ShareAccount  sa = 	manager.find(ShareAccount.class, shareHolderNopersist(sa);
    	if(sa != null){
    		int new_balance = sa.getNumberOfShares() + numberOfShares; 
    	    sa.setNumberOfShares(new_balance);  return sa;
    	}
    	return sanull;
    }

    
    public intShareAccount sellSharesfindShareAccount(int shareHolderNo, int numberOfShares){
        	ShareAccount sa = manager.find(ShareAccount.class, shareHolderNo);
        if(sa  != null){
            if (numberOfShares > sa.getNumberOfShares()){
            	return -2shareHolderNo);
    	return sa;
    }
    }else{
    public ShareAccount   close(int shareHolderNo){
    	intShareAccount new_balancesa = samanager.getNumberOfShares() - numberOfShares;find(ShareAccount.class, 
            	sa.setNumberOfShares(new_balance);
            	manager.flush();
            	return numberOfShares;
  shareHolderNo);   
    	if (sa  }
!= null)manager.remove(sa);
    	return sa;

    }else{
    
    public 	return -1;List<ShareAccount> listAccounts(){
        }
Query query   }= manager.createNamedQuery("findThem");
    
    public ShareAccount updateShareAccount(ShareAccount sa){return query.getResultList();
    	ShareAccount sa1 = findShareAccount(sa.getShareAccountNo());}
    	
    public 	ifShareAccount buyShares(sa1int != null){shareHolderNo, 
    		manager.merge(sa1);
    		return sa1;
    	}
    	else return null;
             	 
   int }

numberOfShares){
    	ShareAccount sa  
}

The ShareHolderBean.java is the stateless session bean that uses JPA to perform database operations using ShareAccount entity.

...



<?xml version="1.0" encoding="UTF-8"?>
<persistence	xmlns="http://java.sun.com/xml/ns/persistence"
				xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.0"
				xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd">
	<persistence-unit name="PersistencePU">
		<description>ShareHolder</description>
		<provider>org.apache.openjpa.persistence.PersistenceProviderImpl</provider>
		<class>sample.jpa.ShareAccount</class>
		<properties>
			<property name="openjpa.ConnectionURL" value="jdbc:derby:ShareDB" />
			<property name="openjpa.ConnectionDriverName" value="org.apache.derby.jdbc.EmbeddedDriver" />
			<property name="ConnectionUserName" value="app" />
			<property name="openjpa.jdbc.SynchronizeMappings" value="false" />
		</properties>
	</persistence-unit>
	<!--
	<jta-data-source>PhoneBookPool</jta-data-source>
	<non-jta-data-source>PhoneBookPool</non-jta-data-source>
	-->
</persistence>

The Persistence.xml is the persistence plan for ShareAccount entity. It provides database connection information and declares entity classes among other things.

Note

The default namespace of the above XML document is http://java.sun.com/xml/ns/persistenceImage Removed. The XML elements that do not have a namespace prefix belong to the default namespace.

Code Block
JAVAJAVA
borderStylesolid
titlesample.jpa.Test.java

package sample.jpa;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class Test extends 
  javax.servlet.http.HttpServlet 
  implements javax.servlet.Servlet {
  
  static final long serialVersionUID = 1L;
   
   public Test() {
	super();
   }   	
	
   protected void doGet(HttpServletRequest request,= manager.find(ShareAccount.class, 
                                       shareHolderNo);
    	if(sa != null){
    		int new_balance = sa.getNumberOfShares() 
                                  + numberOfShares; 
    	    sa.setNumberOfShares(new_balance);  
    	}
    	return sa;
    }
    
    public int sellShares(int shareHolderNo, 
                          int numberOfShares){
        ShareAccount sa = manager.find(ShareAccount.class, 
                                       shareHolderNo);
        if(sa != null){
            if (numberOfShares > sa.getNumberOfShares()){
            	return -2;
            }else{
            	int new_balance = sa.getNumberOfShares() 
                                  - numberOfShares;
            	sa.setNumberOfShares(new_balance);
            	manager.flush();
            	return numberOfShares;
            }
        }else{
        	return -1;
        }
    }
    
  HttpServletResponse response) 
public ShareAccount updateShareAccount(ShareAccount sa){
    	ShareAccount sa1 = 
        throws ServletException, 
         findShareAccount(sa.getShareAccountNo());
    	if (sa1    IOException {
				
 	PrintWriter out = response.getWriter();
	!= null){
    		manager.merge(sa1);
    		return sa1;
   
	try {
	}
	   java.util.Properties env =  	else return null;
    	 
    }

          new java.util.Properties();

	   env.put(Context.INITIAL_CONTEXT_FACTORY
,"org.apache.openejb.client.RemoteInitialContextFactory");
	   env.put(Context.PROVIDER_URL, 
                   "ejbd://127.0.0.1:4201");
	    		
	   Context ctx = new InitialContext(env);
	            
	   out.println("Looking up ShareHolderBean");

	   ShareHolder shareHolder = (ShareHolder)
                 ctx.lookup("ShareHolderBeanRemote");
	            
	            
	   out.println("Creating ShareAccount 1, 
                        Phani, 10");
	            
	   ShareAccount sa = 
                shareHolder.openShareAccount(1, 
                             "phani", 10);
	   if(sa == null){
	       out.println("account could not be created.");
	       out.println("May be, account already 
                            exists. Check the database.");
           	
	   }
	   else {
	            	out.println("Account is successfully created");
	            }
	            
	            out.println("Looking up the ShareAccountNumber 1");
	            sa = shareHolder.findShareAccount(1);
	            
	            out.println("Printing the details of ShareAccountNumber 1");
	            printShareAccount(sa,out);
	            
	            
	            out.println("");
	            
	            out.println("______________________________________________________________________");
	         
	            out.println("buying shares 100");
	            sa = shareHolder.buyShares(1, 100);
	            
	            out.println("Printing the details of ShareAccountNumber 1");
	            printShareAccount(sa,out);
	            out.println("______________________________________________________________________");
	            
	            out.println("");
	            
	            out.println("______________________________________________________________________");
	
}

The ShareHolderBean.java is the stateless session bean that uses JPA to perform database operations using ShareAccount entity.

Code Block
XML
XML
borderStylesolid
titlePersistence.xml

<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.0"
  xsi:schemaLocation="http://java.sun.com/xml/ns/persistence 
  http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd">

 <persistence-unit name="PersistencePU">
 <description>ShareHolder</description>
 <provider>
  org.apache.openjpa.persistence.PersistenceProviderImpl
 </provider>
 <class>sample.jpa.ShareAccount</class>
 <properties>
  <property name="openjpa.ConnectionURL" 
           value="jdbc:derby:ShareDB" />
	  <property name="openjpa.ConnectionDriverName" 
        out.println("selling 50  value="org.apache.derby.jdbc.EmbeddedDriver" />
  <property name="ConnectionUserName" value="app" />
  <property name="openjpa.jdbc.SynchronizeMappings" value="false" />
 </properties>
 </persistence-unit>
 <!--
 <jta-data-source>PhoneBookPool</jta-data-source>
 <non-jta-data-source>PhoneBookPool</non-jta-data-source>
 -->
</persistence>

The Persistence.xml is the persistence plan for ShareAccount entity. It provides database connection information and declares entity classes among other things.

Note

The default namespace of the above XML document is http://java.sun.com/xml/ns/persistenceImage Added. The XML elements that do not have a namespace prefix belong to the default namespace.

Code Block
JAVA
JAVA
borderStylesolid
titlesample.jpa.Test.java

package sample.jpa;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class Test extends 
  javax.servlet.http.HttpServlet 
  implements javax.servlet.Servlet {
  
  static final long serialVersionUID = 1L;
   
   public Test() {
	super();
   }   	
	
   protected void doGet(HttpServletRequest request,
shares of ShareAccountNumber 1");
	            int numberShares = shareHolder.sellShares(1, 50);
	            
	            if(numberShares == 50){
	            	out.println("Printing the details of ShareAccountNumber 1");
	            	sa = shareHolder.findShareAccount(1);
		            printShareAccount(sa,out);
	            }
	            else if(numberShares == -1){
	            	out.println("ShareAccountNo can not be found");
	            }else {
	            	out.println("The number shares available are less thanHttpServletResponse 50"response);
	 
                  }
	throws ServletException, 
          out.println("______________________________________________________________________");
	        IOException {
				
    PrintWriter out = response.printlngetWriter("");
	        
    try {
	     java.util.Properties env =     out.println("______________________________________________________________________");
	            
	 
       new java.util.Properties();

     env.put(Context.INITIAL_CONTEXT_FACTORY
       ,"org.apache.openejb.client.RemoteInitialContextFactory"); 
     env.put(Context.PROVIDER_URL, 
           List<ShareAccount> saList = shareHolder.listAccounts( "ejbd://127.0.0.1:4201");
	    		
     Context ctx = new InitialContext(env);
	     out.println("Looking up ShareHolderBean");

     out.println("Printing all the available accounts");
	ShareHolder shareHolder = (ShareHolder)
            ctx.lookup("ShareHolderBeanRemote");
	            for (int
 i = 0; i < saListout.sizeprintln(); i++){
	     "Creating ShareAccount 1, 
       	out.println("*******");
	            	printShareAccount(saList.get(i),outPhani, 10");
	            	out.println("*******");
	   
     ShareAccount sa = 
         	outshareHolder.printlnopenShareAccount(1,"phani", 10);
	     if(sa == null){
	out.println("account could not   }
	    be created.");
	out.println("May be, account already 
        
	            out.println("______________________________________________________________________");
	          exists. Check the outdatabase.println("");
           	
     }
     else {
        out.println("Account is successfully 
	created");
     }
     out.println("Looking up the ShareAccountNumber 
	1");
     sa = shareHolder.findShareAccount(1);
       out.println("______________________________________________________________________Printing the details of ShareAccountNumber 1");
	     printShareAccount(sa,out);
     out.println("");

  
	   out.println("buying shares 100");
     sa = outshareHolder.println("Setting the ShareAccount 1 with 500 shares and updating the database");
	     buyShares(1, 100);
	            
     out.println("Printing the details of ShareAccountNumber 1");
       
	printShareAccount(sa,out);
     out.println("");

     out.println("selling 50 sashares =of newShareAccountNumber ShareAccount(1,"phani",0);
	     int numberShares =     sa.setNumberOfShares(500shareHolder.sellShares(1, 50);
	        if(numberShares == 50){
       out.println("Printing the 
	details of ShareAccountNumber 1");
       sa = shareHolder.updateShareAccountfindShareAccount(sa1);
	       printShareAccount(sa,out);
     }
	     else if(numberShares      
	  == -1){
          out.println("Printing the details of ShareAccountNumber 1");
	            printShareAccount(sa,out);
	ShareAccountNo can not be found");
     }else {
       out.println("______________________________________________________________________The number shares available are less than 50");
	       }
     out.println("");

	     List<ShareAccount> saList = shareHolder.listAccounts();
     out.println("Printing all the available 
	            out.println("______________________________________________________________________");
	            
	            out.println("Closing ShareAccountNumber 1");
	            
	            sa = shareHolder.close(1);
	            
	accounts");
     for (int i = 0; i < saList.size(); i++){
		out.println("*******");
		printShareAccount(saList.get(i),out);
		out.println("*******");
		out.println("");
	}
     out.println("");

     out.println("Setting the ShareAccount 1 with 500 shares 
            if(sa == null){
	      and updating the database");
   	out.println("Account is notsa found="+1);
	   new ShareAccount(1,"phani",0);
         }else{
		sa.setNumberOfShares(500);
     shareHolder.updateShareAccount(sa);
       out.println("Printing the details of ShareAccountNumber 1");
		            printShareAccount(sa,out);
	     out.println("");

     out.println("Closing ShareAccountNumber }1");
	     sa       
	    = shareHolder.close(1);
        out.println("______________________________________________________________________");
	       if(sa == null){
        out.println("Account is not found="+1);
     
	}else{
        out.println("Printing the details of ShareAccountNumber }1");
	printShareAccount(sa,out);
     }

   }
   catch(Exception e){
	        	e.printStackTrace();
	        	throw new ServletException(e);
	        }
	}  	
	
	/* (non-Java-doc)
	 * @see javax.servlet.http.HttpServlet#doPost protected void doPost(HttpServletRequest request, 
                      HttpServletResponse response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response) 
                  throws ServletException, IOException {
		// TODO Auto-generated method stub
	}  
	
	
 }  
 private void printShareAccount(ShareAccount sa, PrintWriter out){
		
		    if(sa != null){
	        out.println("Account Number = "+sa.getShareAccountNo());
	        out.println("Owner Name = "+sa.getOwnerName());
	        out.println("number of shares "+sa.getNumberOfShares());
	        out.println("version="+sa.getVersion());
		    }else{
			     out.println("ShareAccountNo can not be found");
		    }
		

		
	 }
}

The Servlet client Test.java, looks up the ShareHolderBean and executes various life cycle methods. When the url http://localhost:8080/ShareHolderWEB/Test is hit on a browser window, the following output is displayed.