ejbCreate()
methods
are called by the container when a client invokes the corresponding
create()
method on the bean’s home. With
bean-managed persistence, the ejbCreate()
methods
are responsible for adding new entities to the database. This means
that the BMP version of ejbCreate()
will be much
more complicated than the equivalent methods in container-managed
entities; with container-managed beans,
ejbCreate()
doesn’t have to do much more
than initialize a few fields. Another difference between bean-managed
and container-managed persistence is that the EJB specification
states that ejbCreate()
methods in bean-managed
persistence must return the primary key of the newly created entity.
By contrast, in container-managed beans
ejbCreate()
is required to return
null
.
The following code contains the ejbCreate()
method
of the ShipBean
. Its return type is the Ship
EJB’s primary key, Integer
. The method uses
the JDBC API to insert a new record into the database based on the
information passed as parameters:
public Integer ejbCreate(Integer id, String name, int capacity, double tonnage) throws CreateException { if ((id.intValue() < 1) || (name == null)) throw new CreateException("Invalid Parameters"); this.id = id; this.name = name; this.capacity = capacity; this.tonnage = tonnage; Connection con = null; PreparedStatement ps = null; try { con = this.getConnection(); ps = con.prepareStatement( "insert into Ship (id, name, capacity, tonnage) " + "values (?,?,?,?)"); ps.setInt(1, id.intValue()); ps.setString(2, name); ps.setInt(3, capacity); ps.setDouble(4, tonnage); if (ps.executeUpdate() != 1) { throw new CreateException ("Failed to add Ship to database"); } return id; } catch (SQLException se) { throw new EJBException (se); } finally { try { if (ps != null) ps.close(); if (con!= null) con.close(); } catch(SQLException se) { se.printStackTrace(); } } }
At the beginning of the method, we verify that the parameters are
correct and throw a CreateException
if the
id
is less than 1 or the name
is null
. This shows how you would typically use a
CreateException
to report an application-logic
error.
The ShipBean
instance fields are initialized using
the parameters passed to ejbCreate()
by setting
the instance fields of the ShipBean
. We will use
these values to manually insert the data into the
SHIP
table in our database.
To perform the database insert, we use a JDBC
PreparedStatement
for SQL requests, which makes it
easier to see the parameters being used (we could also have used a
stored procedure through a JDBC CallableStatement
or a simple JDBC Statement
object). We insert the
new bean into the database using a SQL INSERT
statement and the values passed into ejbCreate()
parameters. If the insert is successful (i.e., no exceptions are
thrown), we return the primary key to the container.
If the insert operation is unsuccessful we throw a new
CreateException
, which illustrates this
exception’s use in a more ambiguous situation. Failure to
insert the record could be construed as an application error or a
system failure. In this situation, the JDBC subsystem hasn’t
thrown an exception, so we shouldn’t interpret the inability to
insert a record as a failure of the subsystem. Therefore, we throw a
CreateException
instead of an
EJBException
. Throwing a
CreateException
allows the application to recover
from the error, a transactional concept that is covered in more
detail in Chapter 14.
When the insert operation is successful, the primary key is returned
to the EJB container from the ejbCreate()
method.
In this case we simply return the same Integer
object passed into the method, but in many cases a new key might be
derived from the method arguments. This is especially true when using
compound primary keys, which are discussed in Chapter 11. Behind the scenes, the container uses the
primary key and the ShipBean
instance that
returned it to provide the client with a reference to the new Ship
entity. Conceptually, this means that the ShipBean
instance and primary key are assigned to a newly constructed EJB
object, and the EJB object stub is returned to the client.
Our home interface requires us to provide a second
ejbCreate()
method with different parameters. We
can save work and write more bulletproof code by making the second
method call the first:
public Integer ejbCreate(Integer id, String name) throws CreateException { return ejbCreate(id,name,0,0); }