To create a practical session Bean
The main purpose of the helloworldsession example is to help you familiarize yourself with the overall structure of a session bean. Now that you are familiar with the structure of the session bean, you can write a more useful bean. In particular, you can write a bean that receives data from the database.
The following example assumes that you have a SQL form that contains the code and price of the product, and you can use the following SQL command to create it:
create table price
(product_code varchar(10) not null primary key,
price decimal(10,2) not null)
The Pricing session bean can list all valid product codes and can return the price of a product code that is specified by the remote interface, as shown in the 6.9 list:
Listing 6.9 Source Code for Pricing.java
package usingj2ee.pricing;
import java.rmi.*;
import javax.ejb.*;
/** Defines the methods you can call on a Pricing session */
public interface Pricing extends EJBObject
{
/** Returns all the available product codes */
public String[] getProductCodes() throws RemoteException;
/** Returns the price for a specific product code */
public double getPrice(String productCode)
throws RemoteException, InvalidProductCodeException;
}
The Pricing session Bean does not need to remember any information about a customer, so it can be implemented with a stateless session bean. The Pricinghome interface, as shown in Listing 6.10, requires only a create method.
Listing 6.10 Source Code for PricingHome.java
package usingj2ee.pricing;
import java.rmi.*;
import javax.ejb.*;
/** Defines the methods for creating a Pricing session */
public interface PricingHome extends EJBHome
{
/** Creates a Pricing session bean */
public Pricing create() throws RemoteException, CreateException;
}
When a session bean needs to access a database connection, it typically assigns a connection in the Setsessioncontext method and finally frees it in the Ejbremote method. Of course, if you have a connection to a database, you must be prepared to close it when the container invokes the Ejbpassivate method, and reconnect when the container calls Ejbactivate.
You will find that most EJB developers use a method to return a connection so that you can later modify the method of getting the connection without affecting the code that uses those connections. You should also use the DataSource object to create the connection. DataSource makes it easy to modify the database driver and can use connection pooling when needed.
Listing 6.11 shows the implementation class for the pricing session Bean Pricingimpl
Listing 6.11 Source Code for Pricingimpl.java
Package usingj2ee.pricing;
Import java.rmi.*;
Import java.util.*;
Import javax.ejb.*;
Import java.sql.*;
Import javax.sql.*;
Import javax.naming.*;
/** the implementation class for the Pricing Bean * *
public class Pricingimpl implements Sessionbean
{
/** The session context provided by the EJB container. A Session Bean must
Hold on to the "context" it is given. */
Private Sessioncontext context;
/** The database connection used by this session *
Private Connection Conn;
/** an EJB must have a public, parameterless constructor * *
Public Pricingimpl ()
{
}
/** called by the EJB container to set this session \ s context/
public void Setsessioncontext (Sessioncontext acontext)
{
context = Acontext;
}
/** called by the EJB container when a client calls the Create ()
The Home interface * *
public void Ejbcreate ()
Throws CreateException
{
Try
{
Allocate a database connection
conn = getconnection ();
}
catch (Exception exc)
{
throw New CreateException (
"Unable to Access database:" +exc.tostring ());
}
}
/** called by the EJB container to tell this session bean, it is being
Suspended from use (it's being put to sleep). */
public void Ejbpassivate ()
Throws Ejbexception
{
Try
{
Shut down the current database connection
Conn.close ();
conn = null;
}
catch (Exception exc)
{
throw new Ejbexception ("Unable to close database connection:" +
Exc.tostring ());
}
}
/** called by the EJB container to wake this session bean over it
has been put to sleep with the Ejbpassivate method. */
public void Ejbactivate ()
Throws Ejbexception
{
Try
{
When the Bean wakes back up and get a database connection again
conn = getconnection ();
}
catch (Exception exc)
{
throw New Ejbexception (
"Unable to Access database:" +exc.tostring ());
}
}
/** called by the EJB container to the "session Bean" it has been
removed, either because the client invoked the Remove () method or the
Container has timed. */
public void Ejbremove ()
Throws Ejbexception
{
Try
{
Shut down the current database connection
Conn.close ();
conn = null;
}
catch (Exception exc)
{
throw new Ejbexception ("Unable to close database connection:" +
Exc.tostring ());
}
}
/** Returns A list of the available product codes * *
Public string[] Getproductcodes ()
Throws Ejbexception
{
Statement s = null;
Try
{
s = conn.createstatement ();
ResultSet results = S.executequery (
"Select Product_code from Price");
Vector v = new vector ();
Copy the results into a temporary vector
while (Results.next ())
{
V.addelement (results.getstring ("Product_code"));
}
Copy the vector into a string array
string[] ProductCodes = new string[v.size ()];
V.copyinto (ProductCodes);
return productcodes;
}
catch (Exception exc)
{
throw new Ejbexception ("Unable to get product codes:" +
Exc.tostring ());
}
Finally
{
Close down the statement in a finally blocks to guarantee that it gets
Closed, whether a exception occurred or not
Try
{
S.close ();
}
catch (Exception Ignore)
{
}
}
}
/** Gets The price for a particular product code * *
Public double GetPrice (String ProductCode)
Throws Ejbexception, Invalidproductcodeexception
{
PreparedStatement PS = null;
Try
{
It ' s always better to use a prepared statement than to try to insert
A string directly into the query string. This is way you don ' t have to
Worry if there ' s a quote in the product code
PS = Conn.preparestatement (
"Select price from price where Product_code =?");
Store the product code in the prepared statement
Ps.setstring (1, ProductCode);
ResultSet results = Ps.executequery ();
If There are any results, get the "one" (there should only one)
if (Results.next ())
{
Return results.getdouble ("price");
}
Else
{
Otherwise, if there were no results, this product code doesn ' t exist
throw new Invalidproductcodeexception (ProductCode);
}
}
catch (SQLException exc)
{
throw new Ejbexception ("Unable to get Price:" +
Exc.tostring ());
}
Finally
{
Close down the statement in a finally blocks to guarantee that it gets
Closed, whether a exception occurred or not
Try
{
Ps.close ();
}
catch (Exception Ignore)
{
}
}
}
Protected Connection getconnection ()
Throws SQLException, Namingexception
{
Get a reference to the naming service
InitialContext context = new InitialContext ();
Get the data source for the pricing database
DataSource ds = (DataSource) context.lookup (
"Java:comp/env/jdbc/pricedb");
Ask the data source to allocate a database connection
return Ds.getconnection ();
}
}