| ★ wanayoo — archive 1999 http://developer.java.sun.com/developer/technicalArticles/Beans/EJBEntity/index.html | Nouvelle recherche | Portail wanayoo |
|
|
|
Today, more and more developers want to write distributed transactional applications for the enterprise, and leverage the speed, security, and reliability of server-side technology. One approach is to use a multitiered model where a thin-client application invokes business logic that executes on the server. Normally, thin-client multitiered applications are hard to write because they involve many lines of intricate code to handle transaction and state management, multithreading, resource pooling, and other complex low-level details. The Enterprise JavaBeansTM (EJB) architecture makes these applications easy to write because it separates the low-level details from the business logic. You concentrate on creating the best business solution and leave the rest to the underlying architecture. To show you how it works, this article walks through a very simple web-based application where the thin-client is a servlet. The servlet invokes enterprise Beans for database reads and writes and to perform a simple calculation. Enterprise Beans Defined An enterprise Bean is a body of code with fields and methods to implement modules of business logic. Client programs interact with one or more Beans, and an enterprise Bean can be implemented to interact with other enterprise Beans. An enterprise Bean is a building block that can be used alone or with other enterprise Beans to build a complete and robust thin-client multitiered application. There are two types of enterprise Beans: session Beans and entity Beans. An enterprise Bean that implements a business task is a session Bean, and an enterprise Bean that implements a business entity is an entity Bean.
Note: In the Enterprise Java Beans specification, EJB Server support for session Beans is mandatory. EJB Server Support for entity Beans is currently optional, but becomes mandatory for version 2.0 of the specification. Simple Example A high-level view of the simple example application is shown in the diagram. The client application is a servlet that receives data from and sends data to a browser, and interacts with an entity Bean and a session Bean through their home and remote interfaces. The EJB Home Server handles all the low-level details including the database read and write operations.
Deployment tools and an EJB Home Server are essential to running the application code. The deployment tools generate enterprise Bean containers, which are classes that provide an interface to the low-level implementations in a given EJB Server. The server provider can include containers and deployment tools for their server and will typically publish their low-level interfaces so other vendors can develop containers and deployment tools for their server. The simple example uses the EJB Server created by EJBHome. Visit this site for a free reference implementation that includes the EJB Server and deployment tools for generating containers. The site also provides tutorials to walk you through example programs that come with the download. Source Code
The source code files for the example are listed below.
The example program requires a database table named
CREATE TABLE BONUS
SOCSEC Integer,
BONUS Real,
primary key (SOCSEC)
The source code follows naming conventions so the EJB Home Server
can find the application classes, containers, and database table.
For example with The source for a given enterprise Bean, the enterprise
Bean, home interface, and primary key class names use the remote interface
name as a prefix.
Other naming conventions are used within the source code and discussed below where they appear. While source file-naming conventions are standard across EJB Server implementations, naming conventions used within the source are specific to the EJB Server or deployment tool you use.
When the entity and session Beans are deployed, a number of container source and class files are generated with the following prefixes. A container is a set of classes generated by the deployment tool that manages an enterprise Bean's persistence, transactional properties, and security.
Client Program
The thin-client BonusServlet.java
declares variables and parameter values of specific types to locate the
database table, create the home interface, and invoke the entity and
session Bean methods.
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
import java.util.Properties;
import javax.naming.*;
//location of Bean classes
import com.ejbhome.examples.*;
public class BonusServlet extends HttpServlet {
//Entity Bean home and remote interface variables
BonusHome homebonus;
Bonus theBonus, rec1;
//Session Bean home and remote interface variables
CalcHome homecalc;
Calc theCalculation;
int socsec = 0, retsocsec = 0;
int bonus = 0, retbonus = 0;
The EJB Home Server uses the beans.properties configuration file
to map enterprise Beans to the home interfaces for their respective container
classes. Here is how the mapping looks. The container classes are not created
until the Beans are deployed, but you can put the entry into this file
before you deploy because the naming convention is consistent.
The values calcs and bonuses are used
in the next code segment for the enterprise Bean lookup. The
values in this file and the strings used in the code have to match
exactly so the EJB Home Server can look up the enterprise Bean home
interface.
calcs=com.ejbhome.examples.EJBHomeCalcHome bonuses=com.ejbhome.examples.EJBHomeBonusHomeHere is the servlet init method implementation. The
JNDI API
is used to look up the Beans and containers.
public void init(ServletConfig config)
throws ServletException{
try{
Properties env = new Properties();
env.put("java.naming.factory.initial",
"com.ejbhome.naming.spi.rmi.RMIInitCtxFactory");
Context ctx = new InitialContext(env);
//Look up home interfaces and containers
//for entity and session beans.
//Strings map to settings in the beans.properties file.
homebonus = (BonusHome)ctx.lookup("bonuses");
homecalc = (CalcHome)ctx.lookup("calcs");
} catch (Exception NamingException) {
NamingException.printStackTrace();
}
}
In the next code segement, the socsec and bonus
variables are initialized with values that would normally come from user
input to a form in the browser. These values are used to create the entity Bean
home interface and two records
in the Bonus table. After each record is
created, its data is retrieved from the database and displayed
in the browser. For simplicity, the code to display the data in
the browser is not
included in the segment, but here is the entire source file for the
BonusServlet.java servlet.
try{
socsec = 555220000;
bonus = 200;
for(int i = 1; i < 3; i++){
//Use the entity Bean home interface to create a record
theBonus = homebonus.create(socsec, bonus);
//Get the data from the record and display it in the browser
retbonus = theBonus.getBonus();
retsocsec = theBonus.getSocSec();
socsec += 1;
}
} catch (Exception CreateException) {
CreateException.printStackTrace();
}
This next code segment uses the primary key class to retrieve
a record from the database, and uses the home interface to
retrieve the data in the record fields.
For simplicity, the code to display the retrieved data in the
browser is not
included in the segment, but here is the entire source file for the
BonusServlet.java servlet.
try{
//Instantiate a primary key object
BonusPK PK = new BonusPK(555220000);
//Locate a record with the primary key
rec1 = hmebonus.findByPrimaryKey(PK);
//Use the entity Bean home interface
//to retrieve current bonus value
retbonus = rec1.getBonus();
This next code segment creates the session Bean's home interface,
and uses the home interface to call the session Bean's
calcBonus method.
The hard-coded values passed to the
calcBonus method would normally be received
by user input to a form in the browser.
For simplicity, the code to display the final bonus in
the browser is not
included in the segment, but here is the entire source file for the
BonusServlet.java servlet.
//Calculate bonus
int base = 100;
int perf=5, company=2;
theCalculation = homecalc.create();
int calc = theCalculation.calcBonus(
base, perf, company);
System.out.println(calc);
rec1.addBonus(calc);
retbonus = rec1.getBonus();
} catch (Exception FinderException) {
FinderException.printStackTrace();
}
However, the thin-client servlet does not work directly with the entity Bean
to create rows or access data, but creates an instance of the
home interface. The home interface extends
package com.ejbhome.examples;
import javax.ejb.*;
import java.rmi.*;
public interface BonusHome extends EJBHome {
Bonus create(int bonus, int socsec)
throws CreateException, RemoteException;
Bonus findByPrimaryKey(BonusPK socsec)
throws FinderException, RemoteException;
}
When the home interface is instantiated, the EJB Home Server also creates
the remote interface and enterprise Bean instances. Here is the
remote interface. It extends
EJBObject and declares the BonusBean methods.
It also follows the rules of the RMI API in that the arguments and return
types for each method must be serializable and the methods should throw
java.rmi.RemoteException as one of its exception.
package com.ejbhome.examples;
import javax.ejb.*;
import java.rmi.*;
public interface Bonus extends EJBObject {
int getBonus() throws RemoteException;
int getSocSec() throws RemoteException;
void addBonus(int bonus ) throws RemoteException;
}
The EJBHome server requires a container-managed entity Bean to have
a primary key class with
a public primary key field (or fields, if using composite primary
keys). You can have the container manage an enterprise Bean or write
the code to manage the Bean yourself. In this example, both Beans
are container-managed, and you should always let the container
manage an entity Bean.
Here is the primary key class. The primary key in the
package com.ejbhome.examples;
public class BonusPK implements java.io.Serializable {
public int socsec;
public BonusPK(int socsec) {
this.socsec = socsec;
}
public BonusPK() {}
}
Now for a look at the entity bean
source code. It implements
package com.ejbhome.examples;
import java.rmi.RemoteException;
import javax.ejb.*;
public class BonusBean implements EntityBean {
public int bonus = 0;
public int socsec = 0;
protected EntityContext ctx;
public int getBonus() throws RemoteException {
return bonus;
}
public int getSocSec() throws RemoteException {
return socsec;
}
public void addBonus(int bonus) throws RemoteException {
this.bonus += bonus;
}
public void ejbCreate(int socsec, int bonus)
throws CreateException, RemoteException {
this.socsec=socsec;
this.bonus=bonus;
}
// Other interface methods
public void setEntityContext(javax.ejb.EntityContext ctx)
throws RemoteException
{
this.ctx = ctx;
}
public void unsetEntityContext() throws RemoteException {
ctx = null;
}
public void ejbRemove() throws RemoteException,
RemoveException { }
public void ejbActivate() throws RemoteException { }
public void ejbPassivate() throws RemoteException { }
public void ejbLoad() throws RemoteException { }
public void ejbStore() throws RemoteException { }
}
Session Bean Source Code
The session Bean performs a simple calculation. Its source code is similar
to the entity Bean source code with the few differences described here.
The home interface
does not have a
package com.ejbhome.examples;
import javax.ejb.*;
import java.rmi.*;
public interface CalcHome extends EJBHome {
Calc create() throws CreateException,
RemoteException;
}
The remote interface
declares the session Bean's one method.
package com.ejbhome.examples;
import javax.ejb.*;
import java.rmi.*;
public interface Calc extends EJBObject {
int calcBonus(int base, int perf, int company)
throws RemoteException;
}
The session Bean
implements SessionBean and
the developer-defined and interface methods.
package com.ejbhome.examples;
import java.rmi.RemoteException;
import javax.ejb.*;
public class CalcBean implements SessionBean
throws Remote Exception {
public int bonus;
protected SessionContext ctx;
public int calcBonus(int base, int perf, int company) {
int calc = (base*perf*company);
this.bonus += calc;
return this.bonus;
}
public void ejbCreate() throws CreateException,
RemoteException {}
// Other interface methods
public void setSessionContext(javax.ejb.SessionContext ctx)
throws RemoteException {
this.ctx = ctx;
}
public void ejbRemove() throws RemoteException { }
public void ejbActivate() throws RemoteException { }
public void ejbPassivate() throws RemoteException { }
public void ejbLoad() throws RemoteException { }
public void ejbStore() throws RemoteException { }
}
The Deployer tool generates these container classes for
Conclusion If you want to develop thin-client multitiered applications for the net, Enterprise JavaBeans is the way to go. You can write business applications with reusable and modular enterprise Beans and leave the system-level programming to the underlying architecture. You will not be alone--the Enterprise JavaBeans architecture has been adopted, supported, and put on the product roadmaps of more than 25 companies. Here are links to additional information on Enterprise JavaBeans.
Monica Pawlan is a staff writer on the JDC team. She has a background in 2D and 3D graphics, security, database products, and loves to explore emerging technologies. monica.pawlan@eng.sun.com
Reader FeedbackTell us what you think of this article.
|