Java Platform, Enterprise Edition (Java EE) 8 The Java EE Tutorial

## 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, with three new features that `order` does not have: many-to-many relationships, entity inheritance, and automatic table creation at deployment time.

The database schema in Apache Derby for the `roster` application is shown in Figure 41-2.

Figure 41-2 Database Schema for the roster Application

Note: In this diagram, for simplicity, the `PERSISTENCE_ROSTER_` prefix is omitted from the table names.

### Relationships in the roster Application

A recreational sports system has the following relationships.

- A player can be on many teams.

- A team can have many players.

- A team is in exactly one league.

- A league has many teams.

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

- There is a many-to-many relationship between `Player` and `Team`.

- There is a many-to-one relationship between `Team` and `League`.

#### 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="PERSISTENCE_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 database table that will associate player IDs with team IDs. The entity that specifies the `@JoinTable` is the owner of the relationship, so the `Team` entity is the owner of the relationship with the `Player` entity. Because `roster` uses automatic table creation at deployment time, the container will create a join table named `PERSISTENCE_ROSTER_TEAM_PLAYER`.

`Player` is the inverse, or nonowning, side of the relationship with `Team`. As one-to-one and many-to-one relationships, the nonowning 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 shows 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 = "PERSISTENCE_ROSTER_LEAGUE")
    public abstract class League implements Serializable { ... }

Instead, when creating a league, clients use `SummerLeague` or `WinterLeague`. `SummerLeague` and `WinterLeague` inherit the persistent properties defined in `League` and add only 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 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 want 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="PERSISTENCE_ROSTER_LEAGUE")
    public abstract class League implements Serializable { ... }

The `roster` application 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 called `DTYPE` in the `PERSISTENCE_ROSTER_LEAGUE` table, 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="PERSISTENCE_ROSTER_LEAGUE")
    public abstract class League implements Serializable { ... }

### Criteria Queries in the roster Application

The `roster` application uses Criteria API queries, as opposed to the JPQL queries used in `order`. Criteria queries are Java programming language, typesafe queries defined in the business tier of `roster`, in the `RequestBean` stateful session bean.

The following topics are addressed here:

- Metamodel Classes in the roster Application

- Obtaining a CriteriaBuilder Instance in RequestBean

- Creating Criteria Queries in RequestBean’s Business Methods

#### Metamodel Classes in the roster Application

Metamodel classes model an entity’s attributes and are used by Criteria queries to navigate to an entity’s attributes. Each entity class in `roster` has a corresponding metamodel class, generated at compile time, with the same package name as the entity and appended with an underscore character (_). For example, the `roster.entity.Player` entity has a corresponding metamodel class, `roster.entity.Player_`.

Each persistent field or property in the entity class has a corresponding attribute in the entity’s metamodel class. For the `Player` entity, the corresponding metamodel class is as follows:

    @StaticMetamodel(Player.class)
    public class Player_ {
        public static volatile SingularAttribute<Player, String> id;
        public static volatile SingularAttribute<Player, String> name;
        public static volatile SingularAttribute<Player, String> position;
        public static volatile SingularAttribute<Player, Double> salary;
        public static volatile CollectionAttribute<Player, Team> teams;
    }

#### Obtaining a CriteriaBuilder Instance in RequestBean

The `CriteriaBuilder` interface defines methods to create criteria query objects and create expressions for modifying those query objects. `RequestBean` creates an instance of `CriteriaBuilder` by using a `@PostConstruct` method, `init`:

    @PersistenceContext
    private EntityManager em;
    private CriteriaBuilder cb;

    @PostConstruct
    private void init() {
        cb = em.getCriteriaBuilder();
    }

The `EntityManager` instance is injected at runtime, and then that `EntityManager` object is used to create the `CriteriaBuilder` instance by calling `getCriteriaBuilder`. The `CriteriaBuilder` instance is created in a `@PostConstruct` method to ensure that the `EntityManager` instance has been injected by the enterprise bean container.

#### Creating Criteria Queries in RequestBean’s Business Methods

Many of the business methods in `RequestBean` define Criteria queries. One business method, `getPlayersByPosition`, returns a list of players who play a particular position on a team:

    public List<PlayerDetails> getPlayersByPosition(String position) {
        logger.info("getPlayersByPosition");
        List<Player> players = null;

        try {
            CriteriaQuery<Player> cq = cb.createQuery(Player.class);
            if (cq != null) {
                Root<Player> player = cq.from(Player.class);

                // set the where clause
                cq.where(cb.equal(player.get(Player_.position), position));
                cq.select(player);
                TypedQuery<Player> q = em.createQuery(cq);
                players = q.getResultList();
            }
            return copyPlayersToDetails(players);
        } catch (Exception ex) {
            throw new EJBException(ex);
        }
    }

A query object is created by calling the `CriteriaBuilder` object’s `createQuery` method, with the type set to `Player` because the query will return a list of players.

The query root, the base entity from which the query will navigate to find the entity’s attributes and related entities, is created by calling the `from` method of the query object. This sets the `FROM` clause of the query.

The `WHERE` clause, set by calling the `where` method on the query object, restricts the results of the query according to the conditions of an expression. The `CriteriaBuilder.equal` method compares the two expressions. In `getPlayersByPosition`, the `position` attribute of the `Player_` metamodel class, accessed by calling the `get` method of the query root, is compared to the `position` parameter passed to `getPlayersByPosition`.

The `SELECT` clause of the query is set by calling the `select` method of the query object. The query will return `Player` entities, so the query root object is passed as a parameter to `select`.

The query object is prepared for execution by calling `EntityManager.createQuery`, which returns a `TypedQuery<T>` object with the type of the query, in this case `Player`. This typed query object is used to execute the query, which occurs when the `getResultList` method is called, and a `List<Player>` collection is returned.

### Automatic Table Generation in the roster Application

At deployment time, GlassFish Server will automatically drop and create the database tables used by `roster`. This is done by setting the `javax.persistence.schema-generation.database.action` property to `drop-and-create` in `persistence.xml`:

    <?xml version="1.0" encoding="UTF-8"?>
    <persistence version="2.1"
        xmlns="http://xmlns.jcp.org/xml/ns/persistence"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence
            http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
      <persistence-unit name="em" transaction-type="JTA">
        <jta-data-source>java:comp/DefaultDataSource</jta-data-source>
        <properties>
          <property name="javax.persistence.schema-generation.database.action"
                    value="drop-and-create"/>
        </properties>
      </persistence-unit>
    </persistence>

### Running the roster Example

You can use either NetBeans IDE or Maven to build, package, deploy, and run the `roster` application.

The following topics are addressed here:

- To Run the roster Example Using NetBeans IDE

- To Run the roster Example Using Maven

#### To Run the roster Example Using NetBeans IDE

1. Make sure that GlassFish Server has been started (see Starting and Stopping GlassFish Server).

2. If the database server is not already running, start it by following the instructions in Starting and Stopping Apache Derby.

3. From the File menu, choose Open Project.

4. In the Open Project dialog box, navigate to:

       tut-install/examples/persistence

5. Select the `roster` folder.

6. Select the Open Required Projects check box.

7. Click Open Project.

8. In the Projects tab, right-click the `roster` project and select Build.

   This will compile, package, and deploy the EAR to GlassFish Server.

   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

#### To Run the roster Example Using Maven

1. Make sure that GlassFish Server has been started (see Starting and Stopping GlassFish Server).

2. If the database server is not already running, start it by following the instructions in Starting and Stopping Apache Derby.

3. In a terminal window, go to:

       tut-install/examples/persistence/roster/roster-ear/

4. Enter the following command:

       mvn install

   This compiles the source files and packages the application into an EAR file located at tut-install`/examples/persistence/roster/target/roster.ear`. The EAR file is then deployed to GlassFish Server. GlassFish Server will then drop and create the database tables during deployment, as specified in `persistence.xml`.

   After successfully deploying the EAR, the client stubs are retrieved and the application client is run using the appclient application included with GlassFish Server.

   You will see the output, which begins as follows:

       [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

Copyright © 2017, Oracle and/or its affiliates. All rights reserved.