![]() |
|
||
|
|
|
Enterprise JavaBeans. Часть 6(Гопалан Суреш Рай) Создание многоуровневого приложения EJB - Разработка Session-бинов Вы можете создать session-бин следующим образом:
Session-бин, который мы должны разработать, ведёт себя как клиент по отношению к нескольким entity-бинам и управляет последовательностью выполняемых действий между данными компонентами. Session-бины также могут быть использованы при создании новых экземпляров entity-бинов и их данных в базе данных. Реализованный нами session-бин "тележка для покупок" содержит методы, которые помогают пользователю делать различные покупки. Определение Home-интерфейса Давайте определим наш home-интерфейс. У нас имеется только один метод create для создания каждого session-бина. В Примере 13 показано как задаётся CartHome-интерфейс.
package com.gopalan.Shop.Cart;
import javax.ejb.*;
import java.rmi.*;
public interface CartHome extends EJBHome {
Cart create () throws RemoteException, CreateException;
}
Пример 13: Определение интерфейса CartHome Определение Remote-интерфейса Теперь нам нужно задать remote-интерфейс, который будет содержать интерфейсы наших business-методов. Если вы заметили, мы задаём два интерфейса — createNewBook() и createNewAlbum(), которые помогут нам создавать entity-бины. Мы задаём методы, такие как getBook()и getAlbum(), позволяющие получать данные. Кроме того, мы задаём методы addToBooksCart() и addToMusicCart(), которые помогут нам создать тележку для покупок. Методы, такие как getNumberBooks(),getNumberAlbums(), getBooksTotal() getAlbumsTotal()и getGrandTotal() позволяют получать статистические данные, которые мы можем предоставлять пользователю. Пример 14 демонстрирует Cart Remote Interface.
package com.gopalan.Shop.Cart;
import javax.ejb.*;
import java.rmi.*;
import java.util.*;
import com.gopalan.Shop.Books.*;
import com.gopalan.Shop.Music.*;
public interface Cart extends EJBObject {
public Books createNewBook (int isbn, String title, String authors,
double price, int discount)
throws RemoteException, CreateException;
public Music createNewAlbum (int code, String album, String authors,
double price, int discount)
throws RemoteException, CreateException;
public Books getBook (int isbn)
throws RemoteException, FinderException;
public Music getAlbum (int code)
throws RemoteException, FinderException;
public void addToBooksCart (int code) throws RemoteException;
public void addToMusicCart (int code) throws RemoteException;
public void flushBooksCart () throws RemoteException;
public void flushMusicCart () throws RemoteException;
public int getNumberBooks () throws RemoteException;
public int getNumberAlbums () throws RemoteException;
public double getBooksTotal () throws RemoteException;
public double getAlbumsTotal () throws RemoteException;
public double getGrandTotal () throws RemoteException;
public Vector getBooksList () throws RemoteException;
public Vector getMusicList () throws RemoteException;
public Vector getBooksCart () throws RemoteException;
public Vector getMusicCart () throws RemoteException;
}
Пример 14: Определение Cart Remote-интерфейса Имплементация Session-бина Наш session bean инициирует home-интерфейсы двух entity-бинов — BooksBean и MusicBean. Исходный код MusicBean, который пока не приводится здесь, аналогичен entity-бину BooksBean и доступен на сопровождающем данный пакет CD со всеми исходными данными. Если посмотреть на методы setSessionContext(), то можно увидеть, что у нас есть ссылка на factory-объекты home-интерфейса для компонента Books and Music. Метод setSessionContext() -- один из тех методов, которые вызываются в первую очередь при создании контейнером session-бина. Данный метод также вызывает закрытый метод init(), который мы будем использовать для инициализации данных. Отметим, что эти данные хранятся в session-бине. Это позволяет вызывать entity-бин автоматически каждый раз, когда клиент к нему обращается, что разгружает доступ к базе данных, и, в свою очередь, улучшает работу всей системы. Все remote-интерфейсы, которые мы создали для наших business-методов, теперь имеют содержание, заданное в session-бине. При чтении данного примера вы встретите некий класс ReturnSet, о функции которого вы узнаете немного позже. Код для CartBean приводится в Примере 15.
package com.gopalan.Shop.Cart;
package com.gopalan.Shop.Cart;
import java.rmi.*;
import javax.ejb.*;
import java.util.*;
import com.gopalan.Shop.Books.*;
import com.gopalan.Shop.Music.*;
import com.gopalan.Shop.Cart.ReturnSet;
public class CartBean implements SessionBean {
SessionContext sessionContext;
public BooksHome booksHome;
public MusicHome musicHome;
public Vector booksList = null, booksCart = null;
public Vector musicList = null, musicCart = null;
int totalBooks = 0, totalMusic = 0;
double booksCost = 0, musicCost = 0, grandTotal = 0;
void init () {
booksList = new Vector ();
booksCart = new Vector ();
musicList = new Vector ();
musicCart = new Vector ();
ReturnSet result = null;
for (int i=0; ;i++) {
try{
BooksPK key = new BooksPK (i+1);
Books found = booksHome.findByPrimaryKey (key);
if (null == found) {
break;
}
result = new ReturnSet (key.code, found.getTitle (),
found.getAuthors (),
found.getPrice (),
found.getDiscount (),
found.getDiscountedPrice ());
System.out.println ("isbn = "+ result.code +
" Title = "+result.title+
" Authors = "+result.authors+
" Price = " + result.price);
booksList.addElement (result);
} catch (Exception e) { e.printStackTrace(); break; }
}
for (int i=0; ;i++) {
try {
MusicPK key = new MusicPK (i+1);
Music found = musicHome.findByPrimaryKey (key);
if (found == null) {
break;
}
result = new ReturnSet (key.code, found.getAlbum (),
found.getComposers (),
found.getPrice (),
found.getDiscount (),
found.getDiscountedPrice ());
System.out.println ("code = "+ result.code +
" Album = "+result.title+
" Composers = "+result.authors+
" Price = " + result.price);
musicList.addElement (result);
} catch (Exception e) { e.printStackTrace (); break; }
}
}
// Implementation for all the Remote Interface business methods
public Books createNewBook (int isbn, String title,
String authors, double price, int discount)
throws RemoteException, CreateException {
Books book = booksHome.create (isbn, title, authors,
price, discount);
if (null != book) {
booksList.addElement (new ReturnSet(isbn, title,
authors,
price, discount,
book.getDiscountedPrice ()));
}
return book;
}
public Music createNewAlbum (int code, String album, String authors,
double price, int discount)
throws RemoteException, CreateException {
Music music = musicHome.create (code, album, authors,
price, discount);
if (null != music) {
musicList.addElement(new ReturnSet(code, album, authors,
price, discount,
music.getDiscountedPrice ()));
}
return music;
}
public void addToBooksCart (int isbn) throws RemoteException {
try {
Books book = getBook (isbn);
if (null != book) {
booksCart.addElement(new ReturnSet(isbn, book.getTitle (),
book.getAuthors (),
book.getPrice (),
book.getDiscount (),
book.getDiscountedPrice()));
++totalBooks;
booksCost += book.getDiscountedPrice ();
grandTotal+= book.getDiscountedPrice ();
}
} catch (Exception e) { e.printStackTrace (); }
}
public void flushBooksCart () throws RemoteException {
grandTotal -= booksCost;
totalBooks = 0;
booksCost = 0;
booksCart.removeAllElements ();
}
public void flushMusicCart () throws RemoteException {
grandTotal -= musicCost;
totalMusic = 0;
musicCost = 0;
musicCart.removeAllElements ();
}
public void addToMusicCart (int code) throws RemoteException {
try {
Music music = getAlbum (code);
if (null != music) {
musicCart.addElement(new ReturnSet(code, music.getAlbum (),
music.getComposers (),
music.getPrice (),
music.getDiscount (),
music.getDiscountedPrice()));
++totalMusic;
musicCost += music.getDiscountedPrice ();
grandTotal+= music.getDiscountedPrice ();
}
} catch (Exception e) { e.printStackTrace(); }
}
public Books getBook (int isbn)
throws RemoteException, FinderException {
return booksHome.findByPrimaryKey (new BooksPK (isbn));
}
public Music getAlbum (int code)
throws RemoteException, FinderException {
return musicHome.findByPrimaryKey (new MusicPK (code));
}
public Vector getBooksList () throws RemoteException {
return booksList;
}
public Vector getMusicList () throws RemoteException {
return musicList;
}
public Vector getBooksCart () throws RemoteException {
return booksCart;
}
public Vector getMusicCart () throws RemoteException {
return musicCart;
}
public int getNumberBooks () throws RemoteException {
return totalBooks;
}
public int getNumberAlbums () throws RemoteException {
return totalMusic;
}
public double getBooksTotal () throws RemoteException {
return booksCost;
}
public double getAlbumsTotal () throws RemoteException {
return musicCost;
}
public double getGrandTotal () throws RemoteException {
return grandTotal;
}
// Implementation for all the Home Interface methods
public void ejbCreate () throws RemoteException, CreateException {
}
// Implement all the mandatory methods required by the EJB Spec
public void ejbActivate () throws RemoteException {}
public void ejbPassivate () throws RemoteException {}
public void ejbRemove () throws RemoteException {}
public void setSessionContext (SessionContext context)
throws RemoteException {
sessionContext = context;
try {
booksHome = (BooksHome)Naming.lookup ("Books");
musicHome = (MusicHome)Naming.lookup ("Music");
init();
} catch (Exception ex) {
throw new RemoteException ("Shop not found", ex);
}
}
}
Пример 15: Имплементация CartBean enterprise-бина Чтобы облегчить работу с векторами, мы создали сериализуемый класс ReturnSet, который содержит отдельный элемент для каждого из полей enterprise-бина, который нас интересует. Это даёт возможность хранить и извлекать каждый элемент, принадлежащий Vector, как объект ReturnSet. Ниже в Примере 16 приводится образец кода для класса ReturnSet:
package com.gopalan.Shop.Cart;
public class ReturnSet implements java.io.Serializable {
public int code;
public String title;
public String authors;
public double price;
public int discount;
public double ourPrice;
public ReturnSet(int no, String name, String author,
double cost, int disc, double cp) {
code = no; title = name; authors = author;
price = cost; discount = disc; ourPrice = cp;
}
}
Пример 16: Определение класса ReturnSet Скомпилируйте EJB-классы Теперь вы можете собрать воедино все исходные данные, которые вы разработали, с помощью команды: javac *.java Задайте свойства внедрения Начиная с данного момента и далее, всё о чём мы будем говорить, будет касаться имплементации конкретного сервера EJB. Для сервера EJBHome мы должны задать свойства в четырёх разных файлах. Данные свойства используются как для генерации классов контейнера, так и в процессе установки и применения. Необходимо определить различные свойства для генерирования классов контейнера. Для этого в файл свойств Shop.ejbml введите код из Примера 17: <!----------------------------------------------------------> <!------- Cart Session Bean ----------------> <!----------------------------------------------------------> <ejbml><session-bean name="cart" descriptor="Cart/CartDeployment" package="com.gopalan.Shop.Cart" home="com.gopalan.Shop.Cart.CartHome" remote="com.gopalan.Shop.Cart.Cart" bean="com.gopalan.Shop.Cart.CartBean" type="stateful" timeout="3600" tx-attribute="TX_SUPPORTS" ></session-bean></ejbml> Пример 17: Описания для бина Cart EJB В первых строках указываются имена интерфейсов и то, что этот бин является session-бином. Кроме того, здесь также говорится о том, что весь сгенерированный код должен находиться в пакете cup.chap8.Shop.Cart. Создание классов контейнера Следующим шагом, который нам предстоит предпринять, является создание классов контейнера с помощью инструментальных средств, предоставленных производителем сервера/контейнера EJB. При развёртывании бинов entity и session, генерируется определённое количество исходных файлов и классов контейнера с префиксами. Контейнер представляет собой набор классов, созданных средством внедрения (deployment tool), которые управляют персистентностью enterprise-бина, его транзактными свойствами и защитой данных. Теперь когда наш файл Shop.ejbml готов, мы можем создать и скомпилировать классы контейнера. Для этого нам необходимо вызвать генератор файлов сервера HomeBase. В командной строке вводим следующие данные: java com.ejbhome.Deployer .\conf\Shop.ejbml Теперь запускаем сервер: java com.ejbhome.Server Ниже приводятся сообщения, которые появляются на консоли экрана в процессе работы сервера, готового к приёму обращений клиента. Жирным шрифтом выделены комманды, которые мы вводим. E:\>java com.ejbhome.Server Клиент Session-бина В Примере 18 приводится код, который используется для тестирования нашего session-бина:
package com.gopalan.Shop.Cart;
import java.rmi.*;
import java.util.*;
public class CartTest {
static final int NUMITEMS = 2;
public static void main (String[] args) throws Exception {
CartHome home = (CartHome)Naming.lookup ("Cart");
System.out.println ("Naming.lookup successful...");
if (null == home) {
System.out.println ("null CartHome returned...");
}
Cart cart = home.create ();
String title = "Title";
String author= "Author";
for (int i = 0; i < CartTest.NUMITEMS; i++) {
System.out.println ("code = " +(i+1) +
" Title = " +title+(i+1) +
" Author = " +author+(i+1) +
" Creating cart.create...");
cart.createNewBook ((i+1),title+(i+1),author+(i+1),100.00,10);
cart.createNewAlbum ((i+1),title+(i+1),author+(i+1),20.00,5);
}
for (int i = 0; i < CartTest.NUMITEMS; i++) {
cart.addToBooksCart (i+1);
cart.addToMusicCart (i+1);
}
Vector bookList = cart.getBooksList ();
System.out.println ("Book List of size "+
bookList.size ()+" is...");
for (int i = 0; i < bookList.size(); i++) {
ReturnSet set = (ReturnSet)bookList.elementAt (i);
System.out.println ("code = " +set.code +
" Title = " +set.title +
" Author = " +set.authors);
}
Vector musicList= cart.getMusicList ();
System.out.println ("Music List of size "+
musicList.size ()+" is...");
for (int i = 0; i < musicList.size(); i++) {
ReturnSet set = (ReturnSet)musicList.elementAt (i);
System.out.println ("code = " +set.code +
" Title = " +set.title +
" Author = " +set.authors);
}
Vector bookCart = cart.getBooksCart ();
System.out.println ("Book Cart of size "+
bookCart.size ()+" is...");
for(int i = 0; i < bookCart.size (); i++) {
ReturnSet set = (ReturnSet)bookCart.elementAt (i);
System.out.println ("code = " +set.code +
" Title = " +set.title +
" Author = " +set.authors);
}
Vector musicCart = cart.getMusicCart ();
System.out.println ("Music Cart of size "+
musicCart.size ()+" is...");
for (int i = 0; i < musicCart.size (); i++) {
ReturnSet set = (ReturnSet)musicCart.elementAt (i);
System.out.println ("code = " +set.code +
" Title = " +set.title +
" Author = " +set.authors);
}
System.out.println ("Total Books = " +cart.getNumberBooks () +
" Total Albums = " +cart.getNumberAlbums () +
" Book Cost = " +cart.getBooksTotal () +
" Album Cost = " +cart.getAlbumsTotal () +
" Grand Total =" + cart.getGrandTotal ());
}
}
Пример 18: Клиентское приложение для session-бина CartTest Заметим, что мы получаем ссылку на home-интерфейс нашего session-бина, выполняя Naming.lookup("Cart"), а затем создаём сам session-бин, используя для этого home.create(). Далее создаются новые объекты, данные о которых заносятся в базу данных через cart.createNewBook(). Далее, вызывая метод cart.addToBooksCart()и просматривая различные списки, которые у нас хранятся, мы добавляем эти объекты в нашу тележку для покупок. |
| Справка | Условия | |
| В начало | Логин | Комментарий к колонке | Поиск | Почта |