The Java EE 5 Tutorial

Chapter 26 Persistence in the EJB Tier

This chapter describes how to use the Java Persistence API from enterprise beans. The material here focuses on the source code and settings of two examples. The first example called order is an application that uses a stateful session bean to manage entities related to an ordering system. The second example is roster, an application that manages a community sports system. This chapter assumes that you are familiar with the concepts detailed in Chapter 24, Introduction to the Java Persistence API.

The order Application

The order application is a simple inventory and ordering application for maintaining a catalog of parts and placing an itemized order of those parts. It has entities that represent parts, vendors, orders, and line items. These entities are accessed using a stateful session bean that holds the business logic of the application. A simple command-line client adds data to the entities, manipulates the data, and displays data from the catalog.

The information contained in an order can be divided into different elements. What is the order number? What parts are included in the order? What parts make up that part? Who makes the part? What are the specifications for the part? Are there any schematics for the part? order is a simplified version of an ordering system that has all these elements.

The order application consists of two modules: order-ejb, an enterprise bean JAR file containing the entities, the support classes, and a stateful session bean that accesses the data in the entities; and order-app-client, the application client that populates the entities with data and manipulates the data, displaying the results in a terminal.

Entity Relationships in the order Application

The order application demonstrates several types of entity relationships: one-to-many, many-to-one, one-to-one, unidirectional, and self-referential relationships.

Self-Referential Relationships

A self-referential relationship is a relationship between relationship fields in the same entity. Part has a field bomPart that has a one-to-many relationship with the field parts, which is also in Part. That is, a part can be made up of many parts, and each of those parts has exactly one bill-of-material part.

The primary key for Part is a compound primary key, a combination of the partNumber and revision fields. It is mapped to the PARTNUMBER and REVISION columns in the EJB_ORDER_PART table.

...
@ManyToOne
@JoinColumns({
    @JoinColumn(name="BOMPARTNUMBER",
        referencedColumnName="PARTNUMBER"),
    @JoinColumn(name="BOMREVISION",
        referencedColumnName="REVISION")
})
public Part getBomPart() {
    return bomPart;
}
...
@OneToMany(mappedBy="bomPart")
public Collection<Part> getParts() {
    return parts;
}
...

One-to-One Relationships

Part has a field, vendorPart, that has a one-to-one relationship with VendorPart’s part field. That is, each part has exactly one vendor part, and vice versa.

Here is the relationship mapping in Part:

@OneToOne(mappedBy="part")
public VendorPart getVendorPart() {
    return vendorPart;
}

Here is the relationship mapping in VendorPart:

@OneToOne
@JoinColumns({
    @JoinColumn(name="PARTNUMBER",
        referencedColumnName="PARTNUMBER"),
    @JoinColumn(name="PARTREVISION",
        referencedColumnName="REVISION")
})
public Part getPart() {
    return part;
}

Note that, because Part uses a compound primary key, the @JoinColumns annotation is used to map the columns in the EJB_ORDER_VENDOR_PART table to the columns in EJB_ORDER_PART. EJB_ORDER_VENDOR_PART’s PARTREVISION column refers to EJB_ORDER_PART’s REVISION column.

One-to-Many Relationship Mapped to Overlapping Primary and Foreign Keys

Order has a field, lineItems, that has a one-to-many relationship with LineItem’s field order. That is, each order has one or more line item.

LineItem uses a compound primary key that is made up of the orderId and itemId fields. This compound primary key maps to the ORDERID and ITEMID columns in the EJB_ORDER_LINEITEM database table. ORDERID is a foreign key to the ORDERID column in the EJB_ORDER_ORDER table. This means that the ORDERID column is mapped twice: once as a primary key field, orderId; and again as a relationship field, order.

Here’s the relationship mapping in Order:

@OneToMany(cascade=ALL, mappedBy="order")
    public Collection<LineItem> getLineItems() {
    return lineItems;
}

Here is the relationship mapping in LineItem:

@ManyToOne
    public Order getOrder() {
    return order;
}

Unidirectional Relationships

LineItem has a field, vendorPart, that has a unidirectional many-to-one relationship with VendorPart. That is, there is no field in the target entity in this relationship.

@ManyToOne
    public VendorPart getVendorPart() {
    return vendorPart;
}

Primary Keys in the order Application

The order application uses several types of primary keys: single-valued primary keys, compound primary keys, and generated primary keys.

Generated Primary Keys

VendorPart uses a generated primary key value. That is, the application does not assign primary key values for the entities, but instead relies on the persistence provider to generate the primary key values. The @GeneratedValue annotation is used to specify that an entity will use a generated primary key.

In VendorPart, the following code specifies the settings for generating primary key values:

@TableGenerator(
    name="vendorPartGen",
    table="EJB_ORDER_SEQUENCE_GENERATOR",
    pkColumnName="GEN_KEY",
    valueColumnName="GEN_VALUE",
    pkColumnValue="VENDOR_PART_ID",
    allocationSize=10)
@Id
@GeneratedValue(strategy=GenerationType.TABLE,
    generator="vendorPartGen")
public Long getVendorPartNumber() {
    return vendorPartNumber;
}

The @TableGenerator annotation is used in conjunction with @GeneratedValue’s strategy=TABLE element. That is, the strategy used to generate the primary keys is use a table in the database. @TableGenerator is used to configure the settings for the generator table. The name element sets the name of the generator, which is vendorPartGen in VendorPart.

The EJB_ORDER_SEQUENCE_GENERATOR table, which has two columns GEN_KEY and GEN_VALUE, will store the generated primary key values. This table could be used to generate other entity’s primary keys, so the pkColumnValue element is set to VENDOR_PART_ID to distinguish this entity’s generated primary keys from other entity’s generated primary keys. The allocationSize element specifies the amount to increment when allocating primary key values In this case, each VendorPart’s primary key will increment by 10.

The primary key field vendorPartNumber is of type Long, as the generated primary key’s field must be an integral type.

Compound Primary Keys

A compound primary key is made up of multiple fields and follows the requirements described in Primary Key Classes. To use a compound primary key, you must create a wrapper class.

In order, two entities use compound primary keys: Part and LineItem.

Part uses the PartKey wrapper class. Part’s primary key is a combination of the part number and the revision number. PartKey encapsulates this primary key.

LineItem uses the LineItemKey class. LineItem’s primary key is a combination of the order number and the item number. LineItemKey encapsulates this primary key. This is the LineItemKey compound primary key wrapper class:

package order.entity;

public final class LineItemKey implements
             java.io.Serializable {

    private Integer orderId;
    private int itemId;

    public int hashCode() {
        return ((this.getOrderId()==null
                        ?0:this.getOrderId().hashCode())
                 ^ ((int) this.getItemId()));
    }

    public boolean equals(Object otherOb) {
        if (this == otherOb) {
            return true;
        }
        if (!(otherOb instanceof LineItemKey)) {
            return false;
        }
        LineItemKey other = (LineItemKey) otherOb;
        return ((this.getOrderId()==null
                        ?other.orderId==null:this.getOrderId().equals
                (other.orderId)) && (this.getItemId ==
                    other.itemId));
    }

    public String toString() {
        return "" + orderId + "-" + itemId;
    }
}

The @IdClass annotation is used to specify the primary key class in the entity class. In LineItem, @IdClass is used as follows:

@IdClass(order.entity.LineItemKey.class)
@Entity
...
public class LineItem {
...
}

The two fields in LineItem are tagged with the @Id annotation to mark those fields as part of the compound primary key:

@Id
public int getItemId() {
    return itemId;
}
...
@Id
@Column(name="ORDERID", nullable=false,
    insertable=false, updatable=false)
public Integer getOrderId() {
    return orderId;
}

For orderId, you also use the @Column annotation to specify the column name in the table, and that this column should not be inserted or updated, as it is an overlapping foreign key pointing at the EJB_ORDER_ORDER table’s ORDERID column (see One-to-Many Relationship Mapped to Overlapping Primary and Foreign Keys). That is, orderId will be set by the Order entity.

In LineItem’s constructor, the line item number (LineItem.itemId) is set using the Order.getNextId method.

public LineItem(Order order, int quantity, VendorPart
        vendorPart) {
    this.order = order;
    this.itemId = order.getNextId();
    this.orderId = order.getOrderId();
    this.quantity = quantity;
    this.vendorPart = vendorPart;
}

Order.getNextId counts the number of current line items, adds one, and returns that number.

public int getNextId() {
    return this.lineItems.size() + 1;
}

Part doesn’t require the @Column annotation on the two fields that comprise Part’s compound primary key. This is because Part’s compound primary key is not an overlapping primary key/foreign key.

@IdClass(order.entity.PartKey.class)
@Entity
...
public class Part {
...
    @Id
    public String getPartNumber() {
        return partNumber;
    }
...
    @Id
    public int getRevision() {
        return revision;
    }
...
}

Entity Mapped to More Than One Database Table

Part’s fields map to more than one database table: EJB_ORDER_PART and EJB_ORDER_PART_DETAIL. The EJB_ORDER_PART_DETAIL table holds the specification and schematics for the part. The @SecondaryTable annotation is used to specify the secondary table.

...
@Entity
@Table(name="EJB_ORDER_PART")
@SecondaryTable(name="EJB_ORDER_PART_DETAIL", pkJoinColumns={
    @PrimaryKeyJoinColumn(name="PARTNUMBER",
        referencedColumnName="PARTNUMBER"),
    @PrimaryKeyJoinColumn(name="REVISION",
        referencedColumnName="REVISION")
})
public class Part {
...
}

EJB_ORDER_PART_DETAIL shares the same primary key values as EJB_ORDER_PART. The pkJoinColumns element of @SecondaryTable is used to specify that EJB_ORDER_PART_DETAIL’s primary key columns are foreign keys to EJB_ORDER_PART. The @PrimaryKeyJoinColumn annotation sets the primary key column names and specifies which column in the primary table the column refers to. In this case, the primary key column names for both EJB_ORDER_PART_DETAIL and EJB_ORDER_PART are the same: PARTNUMBER and REVISION, respectively.

Cascade Operations in the order Application

Entities that have relationships to other entities often have dependencies on the existence of the other entity in the relationship. For example, a line item is part of an order, and if the order is deleted, then the line item should also be deleted. This is called a cascade delete relationship.

In order, there are two cascade delete dependencies in the entity relationships. If the Order to which a LineItem is related is deleted, then the LineItem should also be deleted. If the Vendor to which a VendorPart is related is deleted, then the VendorPart should also be deleted.

You specify the cascade operations for entity relationships by setting the cascade element in the inverse (non-owning) side of the relationship. The cascade element is set to ALL in the case of Order.lineItems. This means that all persistence operations (deletes, updates, and so on) are cascaded from orders to line items.

Here is the relationship mapping in Order:

@OneToMany(cascade=ALL, mappedBy="order")
public Collection<LineItem> getLineItems() {
    return lineItems;
}

Here is the relationship mapping in LineItem:

@ManyToOne
    public Order getOrder() {
    return order;
}

BLOB and CLOB Database Types in the order Application

The PARTDETAIL table in the database has a column, DRAWING, of type BLOB. BLOB stands for binary large objects, which are used for storing binary data such as an image. The DRAWING column is mapped to the field Part. drawing of type java.io.Serializable. The @Lob annotation is used to denote that the field is large object.

@Column(table="EJB_ORDER_PART_DETAIL")
@Lob
public Serializable getDrawing() {
    return drawing;
}

PARTDETAIL also has a column, SPECIFICATION, of type CLOB. CLOB stands for character large objects, which are used to store string data too large to be stored in a VARCHAR column. SPECIFICATION is mapped to the field Part.specification of type java.lang.String. The @Lob annotation is also used here to denote that the field is a large object.

@Column(table="EJB_ORDER_PART_DETAIL")
@Lob
public String getSpecification() {
    return specification;
}

Both of these fields use the @Column annotation and set the table element to the secondary table.

Temporal Types in the order Application

The Order.lastUpdate persistent property, which is of type java.util.Date, is mapped to the EJB_ORDER_ORDER.LASTUPDATE database field, which is of the SQL type TIMESTAMP. To ensure the proper mapping between these types, you must use the @Temporal annotation with the proper temporal type specified in @Temporal’s element. @Temporal’s elements are of type javax.persistence.TemporalType. The possible values are:

Here is the relevant section of Order:

@Temporal(TIMESTAMP)
public Date getLastUpdate() {
    return lastUpdate;
}

Managing the order Application’s Entities

The RequestBean stateful session bean contains the business logic and manages the entities of order.

RequestBean uses the @PersistenceContext annotation to retrieve an entity manager instance which is used to manage order’s entities in RequestBean’s business methods.

@PersistenceContext
private EntityManager em;

This EntityManager instance is a container-managed entity manager, so the container takes care of all the transactions involved in the managing order’s entities.

Creating Entities

The RequestBean.createPart business method creates a new Part entity. The EntityManager.persist method is used to persist the newly created entity to the database.

Part part = new Part(partNumber,
    revision,
    description,
    revisionDate,
    specification,
    drawing);
em.persist(part);

Finding Entities

The RequestBean.getOrderPrice business method returns the price of a given order, based on the orderId. The EntityManager.find method is used to retrieve the entity from the database.

Order order = em.find(Order.class, orderId);

The first argument of EntityManager.find is the entity class, and the second is the primary key.

Setting Entity Relationships

The RequestBean.createVendorPart business method creates a VendorPart associated with a particular Vendor. The EntityManager.persist method is used to persist the newly created VendorPart entity to the database, and the VendorPart.setVendor and Vendor.setVendorPart methods are used to associate the VendorPart with the Vendor.

PartKey pkey = new PartKey();
pkey.partNumber = partNumber;
pkey.revision = revision;

Part part = em.find(Part.class, pkey);
VendorPart vendorPart = new VendorPart(description, price,
    part);
em.persist(vendorPart);

Vendor vendor = em.find(Vendor.class, vendorId);
vendor.addVendorPart(vendorPart);
vendorPart.setVendor(vendor);

Using Queries

The RequestBean.adjustOrderDiscount business method updates the discount applied to all orders. It uses the findAllOrders named query, defined in Order:

@NamedQuery(
    name="findAllOrders",
    query="SELECT o FROM Order o"
)

The EntityManager.createNamedQuery method is used to run the query. Because the query returns a List of all the orders, the Query.getResultList method is used.

List orders = em.createNamedQuery(
    "findAllOrders")
    .getResultList();

The RequestBean.getTotalPricePerVendor business method returns the total price of all the parts for a particular vendor. It uses a named parameter, id, defined in the named query findTotalVendorPartPricePerVendor defined in VendorPart.

@NamedQuery(
    name="findTotalVendorPartPricePerVendor",
    query="SELECT SUM(vp.price) " +
    "FROM VendorPart vp " +
    "WHERE vp.vendor.vendorId = :id"
)

When running the query, the Query.setParameter method is used to set the named parameter id to the value of vendorId, the parameter to RequestBean.getTotalPricePerVendor.

return (Double) em.createNamedQuery(
    "findTotalVendorPartPricePerVendor")
    .setParameter("id", vendorId)
    .getSingleResult();

The Query.getSingleResult method is used for this query because the query returns a single value.

Removing Entities

The RequestBean.removeOrder business method deletes a given order from the database. It uses the EntityManager.remove method to delete the entity from the database.

Order order = em.find(Order.class, orderId);
em.remove(order);

Building and Running the order Application

This section describes how to build, package, deploy, and run the order application. To do this, you will create the database tables in the Java DB server, then build, deploy, and run the example.

Creating the Database Tables in NetBeans IDE

To create the database tables in Java DB, the database server included with Application Server, you need to create the database connection and execute the SQL commands in tut-install/examples/common/sql/javadb/tutorial.sql.

Creating the Database Connection

    To create the database connection do the following:

  1. Click the Services tab.

  2. Right-click the Databases node and select New Connection to open the New Connection dialog.

  3. Under Name, select Java DB (Network).

  4. Set Database URL to the following:


    jdbc:derby://localhost:1527/sun-appserv-samples
  5. Set User Name to APP.

  6. Set Password to APP.

  7. Select the Remember Password during this Session box.

  8. Click OK.

Creating the Tables

    To create the tutorial tables, do the following:

  1. Select File->Open File.

  2. Navigate to tut-install/examples/common/sql/javadb/ and open tutorial.sql.

  3. In the editor pane, select the connection URL to Java DB:


    jdbc:derby://localhost:1527/sun-appserv-samples
  4. Click the Run SQL button at the top of the editor pane.

    You will see the output from the SQL commands in the Output tab.

Deleting the Tables

    To delete the tutorial tables, do the following:

  1. Select File->Open File.

  2. Navigate to tut-install/examples/common/sql/javadb/ and open delete.sql.

  3. In the editor pane, select the connection URL to Java DB:


    jdbc:derby://localhost:1527/sun-appserv-samples
  4. Click the Run SQL button at the top of the editor pane.

    You will see the output from the SQL commands in the Output tab.

Creating the Database Tables Using Ant

    The database tables are automatically created by the create-tables task, which is called before you deploy the application with the ant deploy task. To manually create the tables, do the following:

  1. In a terminal window, navigate to tut-install/javaeetutorial5/examples/ejb/order/.

  2. Type the following command:


    ant create-tables
    

    Note –

    The first time the create-tables task is run, you will see error messages when the task attempts to remove tables that don’t exist. Ignore these error messages. Subsequent calls to create-tables will run with no errors and will reset the database tables.


Building, Packaging, Deploying, and Running order In NetBeans IDE

    Follow these instructions to build, package, deploy, and run the order example to your Application Server instance using NetBeans IDE.

  1. In NetBeans IDE, select File->Open Project.

  2. In the Open Project dialog, navigate to tut-install/javaeetutorial5/examples/ejb/.

  3. Select the order folder.

  4. Select the Open as Main Project and Open Required Projects check boxes.

  5. Click Open Project.

  6. In the Projects tab, right-click the order project and select Run.

You will see the following output from the application client in the Output tab:


...
Cost of Bill of Material for PN SDFG-ERTY-BN Rev: 7:  $241.86
Cost of Order 1111:  $664.68
Cost of Order 4312:  $2,011.44

Adding 5% discount
Cost of Order 1111:  $627.75
Cost of Order 4312:  $1,910.87

Removing 7% discount
Cost of Order 1111:  $679.45
Cost of Order 4312:  $2,011.44

Average price of all parts:  $117.55

Total price of parts for Vendor 100:  $501.06

Ordered list of vendors for order 1111
200 Gadget, Inc. Mrs. Smith
100 WidgetCorp Mr. Jones

Counting all line items
Found 6 line items

Removing Order 4312
Counting all line items
Found 3 line items

Found 1 out of 2 vendors with ’I’ in the name:
Gadget, Inc.
run-order-app-client:
run-ant:
run:
BUILD SUCCESSFUL (total time: 22 seconds)

Building, Packaging, Deploying, and Running order Using Ant

To build the application components of order, enter the following command:


ant

This runs the default task, which compiles the source files and packages the application into an EAR file located at tut-install/examples/ejb/order/dist/order.ear.

To deploy the EAR, make sure the Application Server is started, then enter the following command:


ant deploy

After order.ear is deployed, a client JAR, orderClient.jar, is retrieved. This contains the application client.

To run the application client, enter the following command:


ant run

You will see the following output:


...
run:
    [echo] Running appclient for Order.

appclient-command-common:
    [exec] Cost of Bill of Material for PN SDFG-ERTY-BN Rev: 7:
         $241.86
    [exec] Cost of Order 1111:  $664.68
    [exec] Cost of Order 4312:  $2,011.44

    [exec] Adding 5% discount
    [exec] Cost of Order 1111:  $627.75
    [exec] Cost of Order 4312:  $1,910.87

    [exec] Removing 7% discount
    [exec] Cost of Order 1111:  $679.45
    [exec] Cost of Order 4312:  $2,011.44

    [exec] Average price of all parts:  $117.55

    [exec] Total price of parts for Vendor 100:  $501.06

    [exec] Ordered list of vendors for order 1111
    [exec] 200 Gadget, Inc. Mrs. Smith
    [exec] 100 WidgetCorp Mr. Jones

    [exec] Counting all line items
    [exec] Found 6 line items

    [exec] Removing Order 4312
    [exec] Counting all line items
    [exec] Found 3 line items

    [exec] Found 1 out of 2 vendors with ’I’ in the name:
    [exec] Gadget, Inc.

BUILD SUCCESSFUL

Note –

Before re-running the application client, you must reset the database by running the create-tables task.


The all Task

As a convenience, the all task will build, package, deploy, and run the application. To do this, enter the following command:


ant all

Undeploying order

To undeploy order.ear, enter the following command:


ant undeploy

The roster Application

The roster application maintains the team rosters for players in recreational sports leagues. The application has four components: Java Persistence API entities (Player, Team, and League), a stateful session bean (RequestBean), an application client (RosterClient), and three helper classes (PlayerDetails, TeamDetails, and LeagueDetails).

Functionally, roster is similar to the order application described earlier in this chapter with three new features that order does not have: many-to-many relationships, entity inheritance, and automatic table creation at deploytime.

Relationships in the roster Application

A recreational sports system has the following relationships:

In roster this is reflected by the following relationships between the Player, Team, and League entities:

The Many-To-Many Relationship in roster

The many-to-many relationship between Player and Team is specified by using the @ManyToMany annotation.

In Team.java, the @ManyToMany annotation decorates the getPlayers method:

@ManyToMany
@JoinTable(
    name="EJB_ROSTER_TEAM_PLAYER",
    joinColumns=
        @JoinColumn(name="TEAM_ID", referencedColumnName="ID"),
    inverseJoinColumns=
        @JoinColumn(name="PLAYER_ID", referencedColumnName="ID")
)
public Collection<Player> getPlayers() {
    return players;
}

The @JoinTable annotation is used to specify a table in the database that will associate player IDs with team IDs. The entity that specifies the @JoinTable is the owner of the relationship, so in this case the Team entity is the owner of the relationship with the Player entity. Because roster uses automatic table creation at deploytime, the container will create a join table in the database named EJB_ROSTER_TEAM_PLAYER.

Player is the inverse, or non-owning side of the relationship with Team. As one-to-one and many-to-one relationships, the non-owning side is marked by the mappedBy element in the relationship annotation. Because the relationship between Player and Team is bidirectional, the choice of which entity is the owner of the relationship is arbitrary.

In Player.java, the @ManyToMany annotation decorates the getTeams method:

@ManyToMany(mappedBy="players")
public Collection<Team> getTeams() {
    return teams;
}

Entity Inheritance in the roster Application

The roster application demonstrates how to use entity inheritance, as described in Entity Inheritance.

The League entity in roster is an abstract entity with two concrete subclasses: SummerLeague and WinterLeague. Because League is an abstract class it cannot be instantiated:

...
@Entity
@Table(name = "EJB_ROSTER_LEAGUE")
public abstract class League implements java.io.Serializable {
...
}

Instead, SummerLeague or WinterLeague are used by clients when creating a league. SummerLeague and WinterLeague inherit the persistent properties defined in League, and only add a constructor that verifies that the sport parameter matches the type of sport allowed in that seasonal league. For example, here is the SummerLeague entity:

...
@Entity
public class SummerLeague extends League
         implements java.io.Serializable {

    /** Creates a new instance of SummerLeague */
    public SummerLeague() {
    }

    public SummerLeague(String id, String name,
             String sport) throws IncorrectSportException {
        this.id = id;
        this.name = name;
        if (sport.equalsIgnoreCase("swimming") ||
                sport.equalsIgnoreCase("soccer") ||
                sport.equalsIgnoreCase("basketball") ||
                sport.equalsIgnoreCase("baseball")) {
            this.sport = sport;
        } else {
            throw new IncorrectSportException(
                "Sport is not a summer sport.");
        }
    }
}

The roster application uses the default mapping strategy of InheritanceType.SINGLE_TABLE, so the @Inheritance annotation is not required. If you wanted to use a different mapping strategy, decorate League with @Inheritance and specify the mapping strategy in the strategy element:

@Entity
@Inheritance(strategy=JOINED)
@Table(name="EJB_ROSTER_LEAGUE")
public abstract class League implements java.io.Serializable {
    ...
}

roster uses the default discriminator column name, so the @DiscriminatorColumn annotation is not required. Because you are using automatic table generation in roster the Persistence provider will create a discriminator column in the EJB_ROSTER_LEAGUE table called DTYPE, which will store the name of the inherited entity used to create the league. If you want to use a different name for the discriminator column, decorate League with @DiscriminatorColumn and set the name element:

@Entity
@DiscriminatorColumn(name="DISCRIMINATOR")
@Table(name="EJB_ROSTER_LEAGUE")
public abstract class League implements java.io.Serializable {
    ...
}

Automatic Table Generation in the roster Application

At deploytime the Application Server will automatically drop and create the database tables used by roster. This is done by setting the toplink.ddl-generation property to drop-and-create-tables in persistence.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"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"
version="1.0">
    <persistence-unit name="em" transaction-type="JTA">
        <jta-data-source>jdbc/__default</jta-data-source>
        <properties>
            <property name="toplink.ddl-generation"
                             value="drop-and-create-tables"/>
        </properties>
    </persistence-unit>
</persistence>

This feature is specific to the Java Persistence API provider used by the Application Server, and is non-portable across Java EE servers. Automatic table creation is useful for development purposes, however, and the toplink.ddl-generation property may be removed from persistence.xml when preparing the application for production use, or when deploying to other Java EE servers.

Building and Running the roster Application

This section describes how to build, package, deploy, and run the roster application. You can do this using either NetBeans IDE or Ant.

Building, Packaging, Deploying, and Running roster in NetBeans IDE

    Follow these instructions to build, package, deploy, and run the roster example to your Application Server instance using NetBeans IDE.

  1. In NetBeans IDE, select File->Open Project.

  2. In the Open Project dialog, navigate to tut-install/javaeetutorial5/examples/ejb/.

  3. Select the roster folder.

  4. Select the Open as Main Project and Open Required Projects check boxes.

  5. Click Open Project.

  6. In the Projects tab, right-click the roster project and select Run.

You will see the following partial output from the application client in the Output tab:


List all players in team T2:
P6 Ian Carlyle goalkeeper 555.0
P7 Rebecca Struthers midfielder 777.0
P8 Anne Anderson forward 65.0
P9 Jan Wesley defender 100.0
P10 Terry Smithson midfielder 100.0

List all teams in league L1:
T1 Honey Bees Visalia
T2 Gophers Manteca
T5 Crows Orland

List all defenders:
P2 Alice Smith defender 505.0
P5 Barney Bold defender 100.0
P9 Jan Wesley defender 100.0
P22 Janice Walker defender 857.0
P25 Frank Fletcher defender 399.0
...

Building, Packaging, Deploying, and Running roster Using Ant

To build the application components of roster, enter the following command:


ant

This runs the default task, which compiles the source files and packages the application into an EAR file located at tut-install/examples/ejb/roster/dist/roster.ear.

To deploy the EAR, make sure the Application Server is started, then enter the following command:


ant deploy

The build system will check to see if the Java DB database server is running and start it if it is not running, then deploy roster.ear. The Application Server will then drop and create the database tables during deployment, as specified in persistence.xml.

After roster.ear is deployed, a client JAR, rosterClient.jar, is retrieved. This contains the application client.

To run the application client, enter the following command:


ant run

You will see the output, which begins:


[echo] running application client container.
[exec] List all players in team T2:
[exec] P6 Ian Carlyle goalkeeper 555.0
[exec] P7 Rebecca Struthers midfielder 777.0
[exec] P8 Anne Anderson forward 65.0
[exec] P9 Jan Wesley defender 100.0
[exec] P10 Terry Smithson midfielder 100.0

[exec] List all teams in league L1:
[exec] T1 Honey Bees Visalia
[exec] T2 Gophers Manteca
[exec] T5 Crows Orland

[exec] List all defenders:
[exec] P2 Alice Smith defender 505.0
[exec] P5 Barney Bold defender 100.0
[exec] P9 Jan Wesley defender 100.0
[exec] P22 Janice Walker defender 857.0
[exec] P25 Frank Fletcher defender 399.0
...

The all Task

As a convenience, the all task will build, package, deploy, and run the application. To do this, enter the following command:


ant all

Undeploying order

To undeploy roster.ear, enter the following command:


ant undeploy