Все примеры этой главы следуют общей теме, иллюстрирующей концепцию. Мы построим простое приложение, называющуюся JavaTheater, для продажи и покупки билетов в кино. Приложение будет строится инкрементально, пример за примером, и мы будет иметь дело с адресами кинотеатров, шоу, билетами, покупателями, кредитными картами и так далее. У меня нет места, чтобы показать вам, как создавать полновесное законченное приложение, так что я сфокусируюсь на ядре функциональности.

Здесь будут классы, которые представляют постоянные сущности, такие как фильмы и шоу, и другие классы, которые реализуют большую часть логики приложения. Например, шаги, требующие реальной покупки одного или нескольких билетов на определенное шоу.

Прежде чем посмотрим на реальный код, я хочу упомянуть некоторые вещи относительно структуры исходных текстов. Все примеры находятся в директории c18 исходного кода для этой книги. Каждый поддиректорий является отдельным, самодостаточным примером, который собирается в корне поддиректория. На верхнем уровне директории каждого примера есть Ant скрипт для сборки. На этом же уровне есть директорий src, который содержит все файлы исходного кода для этого примера. Директорий src содержит поддиректории ejb-tier и rmiclient, в которых содержится код для реализации EJB и для клиентского приложения (включая JUnit тест), соответственно. Также, обратите внимание, когда вы будете собирать пример, что Ant скрипт будет создавать рабочий директорий для компиляции и сборки (смотрите комментарии в скрипте Ant более подробно), но ничего не создает и не изменяет в src директории. И, наконец, все наши классы определены в пакете javatheater, содержащем вложенные пакеты, которые тоже стоит упомянуть: javatheater.client содержит клиентское приложение; javatheater.test содержит классы JUnit тест; javatheater.ejb содержит наши EJB интерфейсы и связанные классы, а javatheater.ejb.implementation содержит классы реализации EJB.

Наш первый пример, example01, не использует никакую EJB функциональность. Это обычное и простое Java приложение, которое мы использует в качестве прототипа фундаментального класса. Наипростейший класс - это Movie, и вы можете видеть его реализацию ниже:

//: c18:example01:src:javatheater:Movie.java
//
package javatheater;

public class Movie {
  
int id;
   String title;
  
  
public Movie ( int id, String title ) {
     
this .id = id;
     
this .title = title;
  
}
  
  
public int getId () {
     
return id;
  
}
  
  
public void setId ( int id ) {
     
this .id = id;
  
}
  
  
public String getTitle () {
     
return title;
  
}
  
  
public void setTitle ( String title ) {
     
this .title = title;
  
}
  
  
public String toString () {
     
return "[" + id + "] " + title;
  
}
}
// /:~

Здесь определен класс Movie, который содержит два поля: id (типа int) и title (типа String). Класс также определяет конструктор плюс сеттеры и геттеры (setters и getters) для доступа к значениям полей. Конечно, более реалистичный объект фильма должен содержать много больше информации, такой как актеры, директор, рейтинг, краткий обзор; но реализация всего этого добавит ненужную сложность в пример.

Другой класс - это Show, который также достаточно прост: у него есть id (типа int), время начала показа time (строка) и количество мест (типа int). Он также содержит ссылку на объект Movie, что означает, что у нас есть однонаправленное отношение многие к одному между показами и фильмами: фильм может быть связан с многими показами, но на одном показе может быть только один фильм. Вот реализация класса Show:

//: c18:example01:src:javatheater:Show.java
//
package javatheater;

public class Show {
  
int id;
   Movie movie;
   String showtime;
  
int availableSeats;
  
  
public Show ( int id, Movie movie, String showtime, int availableSeats ) {
     
this .id = id;
     
this .movie = movie;
     
this .showtime = showtime;
     
this .availableSeats = availableSeats;
  
}
  
  
public int getId () {
     
return id;
  
}
  
  
public void setId ( int id ) {
     
this .id = id;
  
}
  
  
public Movie getMovie () {
     
return movie;
  
}
  
  
public void setMovie ( Movie movie ) {
     
this .movie = movie;
  
}
  
  
public String getShowtime () {
     
return showtime;
  
}
  
  
public void setShowtime ( String showtime ) {
     
this .showtime = showtime;
  
}
  
  
public int getAvailableSeats () {
     
return availableSeats;
  
}
  
  
public void setAvailableSeats ( int availableSeats ) {
     
this .availableSeats = availableSeats;
  
}
  
  
public String toString () {
     
return "[" + id + "] " + movie + ", " + showtime + ", "
           
+ availableSeats;
  
}
}
// /:~

Так как example01 это простейшее Java приложение, оно не употребляет многие службы, предоставляемые архитектурой EJB. Определенно, мы не имеет поддержки постоянства. Я не использовал JDBC для хранения и получения объектов из базы данных (что должно означать отображения объект/отношения, нечто более сложное для нашего первого примера), также в примере есть класс, называемый Storage, который эмулирует наличие постоянного хранилища данных.

//: c18:example01:src:javatheater:Storage.java
//
package javatheater;

public class Storage {
  
private static Storage ourInstance;
  
private Movie [] movies;
  
private Show [] shows;
  
  
public synchronized static Storage getInstance () {
     
if ( ourInstance == null ) {
        
ourInstance = new Storage () ;
     
}
     
return ourInstance;
  
}
  
  
private Storage () {
     
movies = new Movie [] { new Movie ( 1 , "Return of the JNDI" ) ,
           
new Movie ( 2 , "A Bug's Life" ) , new Movie ( 3 , "Fatal Exception" ) ,
           
new Movie ( 4 , "Silence of the LANs" ) ,
           
new Movie ( 5 , "Object of my Affection" ) } ;
      shows =
new Show [] { new Show ( 1 , movies [ 0 ] , "5:30pm" , 100 ) ,
           
new Show ( 2 , movies [ 0 ] , "7:00pm" , 300 ) ,
           
new Show ( 3 , movies [ 1 ] , "6:00pm" , 200 ) ,
           
new Show ( 4 , movies [ 4 ] , "9:00pm" , 200 ) } ;
  
}
  
  
public synchronized Movie findMovieById ( int id ) {
     
for ( int i = 0 ; i < movies.length; i++ ) {
        
Movie movie = movies [ i ] ;
        
if ( movie.id == id )
           
return movie;
     
}
     
return null ;
  
}
  
  
public synchronized Movie findMovieByTitle ( String title ) {
     
for ( int i = 0 ; i < movies.length; i++ ) {
        
Movie movie = movies [ i ] ;
        
if ( movie.title == title )
           
return movie;
     
}
     
return null ;
  
}
  
  
public synchronized Movie [] findAllMovies () {
     
return movies;
  
}
  
  
public synchronized Show findShowById ( int id ) {
     
for ( int i = 0 ; i < shows.length; i++ ) {
        
Show show = shows [ i ] ;
        
if ( show.id == id )
           
return show;
     
}
     
return null ;
  
}
  
  
public synchronized Show findShowByMovie ( Movie movie ) {
     
for ( int i = 0 ; i < shows.length; i++ ) {
        
Show show = shows [ i ] ;
        
if ( show.movie.id == movie.id )
           
return show;
     
}
     
return null ;
  
}
  
  
public synchronized Show [] findAllShows () {
     
return shows;
  
}
}
// /:~

Этот класс реализует дизайнерский шаблон Синглетона (при котором существует только одно хранилище данных в вашей системе). Его приватный конструктор заполняет фиктивную базу данных с фильмами по Java тематике и показами. Он также предоставляет публичный метод для получения фильмов и показов из фиктивной базы данных по разным критериям. В нем нет методов для обновления нашей фальшивой базы данных, но вы вольны добавить их в качестве упражнения, если чувствуете в этом необходимость.

Последний класс в example01 - это наш главный клас, ShowListing, который просто использует хранилище для нахождения группы показов, и распечатывает их.

//: c18:example01:src:javatheater:ShowListing.java
//
package javatheater;

public class ShowListing {
  
static Storage storage = Storage.getInstance () ;
  
  
public static void main ( String [] args ) {
     
Show [] shows = storage.findAllShows () ;
     
for ( int i = 0 ; i < shows.length; i++ ) {
        
Show show = shows [ i ] ;
         System.out.println
( show ) ;
     
}
   }
}
// /:~

Повторюсь, этот пример умышленно упрощен, но он вводит несколько фундаментальных концепций, которые мы применим при использовании EJB архитектуры: постоянство объектов, разделение сущностных классов он логики бизнес классов и связи между объектами. Плюс к этому, пример подал нам идею того, чем будет приложение, чтобы охватить все вопросы.