Rovnako ako pri entity beans, aj v prípade session beans je to, ako ju klient vidí, definované prostredníctvom jej komponentného rozhrania. Preto si pripomeňme, že každé remote rozhranie musí rozširovať triedu „EJBObject“ a každé lokálne rozhranie triedu „EJBLocalObject“. Už v prípade entity beans sme spomínali, že remote a lokálne rozhrania sú miestom, kde definujeme biznis metódy, ktoré chceme dať k dispozícii klientom. V tomto článku sa pozrieme na tieto rozhrania z pohľadu session beans.

Pripomeňme si tiež, že biznis metódy nesmú mať názov začínajúci na ejb, musia byť deklarované ako public, nesmú byť deklarované ako static alebo final, ďalej musia zahrnúť do throws klauzule výnimku java.rmi.RemoteException a nakoniec všetky argumenty a návratové typy týchto metód musia byť legálnym RMI-IIOP typom. Posledné dve podmienky platia iba pre remote rozhrania.

Požiadavka na legálny RMI-IIOP typ zaberá asi päť strán v dokumente Java Language to IDL Mapping konzorcia OMG. Vo všeobecnosti však platí, že legálny RMI-IIOP typ zahŕňa Java primitívne dátové typy, remote rozhrania, serializovateľné triedy, polia obsahujúce legálne typy a výnimky. Ak však chcete viac, môžete sa pozrieť priamo na spomínaný dokument na adrese http://www.omg.org/cgi-bin/doc?ptc/00-01-06.

Porovnávanie objektov session beans

Komponentné rozhranie, presnejšie jeho metóda isIdentical, ponúkajú určitý pohľad do toho, ako EJB kontajner vidí jednotlivé inštancie session beans. Na rozdiel od entity beans sú session beans z pohľadu klienta anonymné. Preto nemajú identitu, ktorá by mohla byť definovaná prostredníctvom primárneho kľúča. Avšak každý session bean objekt má v skutočnosti identitu, priradenú kontajnerom pri jeho vytváraní. Jej význam je však závislý od typu session beany. Napríklad každý stateful session bean objekt je odlišný pretože uchováva stav špecifický pre daného klienta, a preto má unikátnu identitu priradenú kontajnerom. Čo sa týka stateless session bean objektov vytvorených tou istou továrňou na objekty, všetky majú totožnú identitu a preto ich je možné navzájom dynamicky zamieňať.

Použitie metódy isIdentical pre Stateful Session Bean

Pretože každá inštancia stateful session bean je vytváraná pre konkrétneho klienta, referencie na session objekty tohto typu sú identické, iba ak odkazujú na objekt, ktorý bol vytvorený ako odpoveď na rovnakú požiadavku od klienta. Treba si uvedomiť, že kontajner priradí unikátnu identitu každej inštancii stateful session bean. A práve táto identita je to, na čom je založené ich vzájomné porovnávanie. Aby som ilustroval tento princíp na príklade, nasledovný fragment kódu deklaruje referencie na dva unikátne stateful session bean objekty:

//Získame referenciu na home rozhranie stateful session bean
AuctionCheckoutHome checkoutHome = …;
//Vytvoríme dva rôzne stateful session bean objekty
AuctionCheckout checkout1 = checkoutHome.create();
AuctionCheckout checkout2 = checkoutHome.create();

Ak by ste potom vykonali nasledovný test s použitím oboch získaných referencií, musí vám podmienka if vrátiť false. Platí to samozrejme aj opačne, teda pri porovnaní dvoch rovnakých referencií (napríklad checkout1) musí vrátiť true:

//Tento test vráti false
if ( checkout1.isIdentical( checkout2 ) ) {
 
}
//Tento test vráti true
if ( checkout1.isIdentical( checkout1 ) ) {
 
}

Použitie metódy isIdentical pre Stateless Session Bean

Správanie sa metódy isIdentical je úplne rovnaké aj v prípade stateless session beans, ak porovnávame dve rovnaké referencie. Avšak zmena nastane, ak porovnávame dve rôzne referencie na inštanciu stateless sesion bean objektu. Ak by sme zopakovali predchádzajúci príklad použitím nasledovného fragmentu…

//Získame referenciu na home rozhranie stateless session bean
AuctionHouseHome auctionHouseHome = …;
//Vytvoríme dva rôzne stateful session bean objekty
AuctionHouse auctionHouse1 = auctionHouseHome.create();
AuctionHouse auctionHouse2 = auctionHouseHome.create();

…a vykonali by sme tento test…

//Tento test vráti true
if ( auctionHouse1.isIdentical( auctionHouse2 ) ) {
 
}

…vráti nám true, pretože všetky inštancie stateless session bean tej istej home factory (napríklad AuctionHouseHome) sú identické a majú rovnakú unikátnu identitu.

Vytvorenie komponentného rozhrania pre aukčný systém

V predchádzajúcej časti sme navrhli zoznam session beans tried, ktoré po implementácii a nasadení na server môžu poskytovať svoje služby vzdialeným klientom. V tejto časti si tieto rozhrania vytvoríme. Nasledovný výpis obsahuje deklaráciu remote rozhrania AuctionHouse, ktoré môžeme využiť pre stateless session bean aukčného systému.

Remote rozhranie pre AuctionHouse session bean – AuctionHouse.java:

/**
* Title: AuctionHouse
* Description: EJB remote interface pre AuctionHouse bean
*/

import java.util.List;
import java.rmi.RemoteException;
import javax.ejb.EJBObject;
import javax.ejb.FinderException;
import InvalidAuctionStatusException;
import InvalidBidException;
import AuctionDetailView;
public interface AuctionHouse extends EJBObject {

 /**
 * Vráti zoznam všetkých otvorených, zatvorených
 * alebo zrušených aukcií
 *
 * @return zoznam AuctionSummaryView objektov
 */

 public List getNonPendingAuctions() throws RemoteException;

 /**
 * Vráti detailný popis špecifickej aukcie
 *
 * @param auctionId primárny kľúč pre vybranú aukciu
 * @return popis aukcie a jej položiek
 */

 public AuctionDetailView getAuctionDetail(int auctionId)
  throws FinderException, RemoteException;

 /**
 * Vloží ponuku do konkrétnej aukcie
 *
 * @param bidAmount hodnota ponuky
 * @param auctionId primárny kľúč pre vybranú aukciu
 * @param bidderId primárny kľúč dražiteľa
 *
 */

 public String submitBid(double bidAmount, int auctionId, int bidderId)
  throws InvalidBidException, InvalidAuctionStatusException, RemoteException;

 /**
 * Vráti zoznam BidView objektov popisujúcich jednotlivé
 * ponuky konkrétneho dražiteľa
 */

 public List getBids(int bidderId) throws FinderException, RemoteException;
}

Uvedený príklad remote rozhrania obsahuje iba nutné minimum biznis metód, ktoré by mala AuctionHouse session beana poskytovať. Toto rozhranie umožňuje klientovi získať zoznam aukcií, detailné informácie o jednotlivých aukciách, vložiť svoju ponuku a získať zoznam ponúk vložených týmto klientom. Metóda getNonPendingAuctions vracia zoznam objektov triedy AuctionSummaryView obsahujúcich informácie o jednotlivých aukciách v jednoduchej dátovej štruktúre. Nasledovný výpis obsahuje túto triedu.

Sumárny popis aukcie – AuctionSummaryView.java:

/**
* Title: AuctionSummaryView
* Description: Trieda určená na vytvorenie sumárneho pohľadu na zoznam definovaných aukcií.
*/

import java.io.Serializable;
import java.sql.Timestamp;
public class AuctionSummaryView implements Serializable {
 private Integer id;
 private String name;
 private String status;
 private Double leadingBidAmount;
 private Timestamp scheduledEndDateTime;
 public AuctionSummaryView() {
 }
 public AuctionSummaryView(Integer newId, String newName, String newStatus,
  Timestamp newScheduledEndDateTime, Double newLeadingBidAmount) {
  setId(newId);
  setName(newName);
  setStatus(newStatus);
  setScheduledEndDateTime(newScheduledEndDateTime);
  setLeadingBidAmount(newLeadingBidAmount);
 }
 public Integer getId() {
  return id;
 }
 public void setId(Integer newId) {
  id = newId;
 }
 public void setName(String newName) {
  name = newName;
 }
 public String getName() {
  return name;
 }
 public void setStatus(String newStatus) {
  status = newStatus;
 }
 public String getStatus() {
  return status;
 }
 public void setLeadingBidAmount(Double newLeadingBidAmount) {
  leadingBidAmount = newLeadingBidAmount;
 }
 public Double getLeadingBidAmount() {
  return leadingBidAmount;
 }
 public void setScheduledEndDateTime(Timestamp newScheduledEndDateTime) {
  scheduledEndDateTime = newScheduledEndDateTime;
 }
 public Timestamp getScheduledEndDateTime() {
  return scheduledEndDateTime;
 }
}

Návratové objekty, ako je AuctionSummaryView a AuctionDetailView, alebo inštancie vrátené metódami triedy AuctionHouse, separujú spotrebiteľa (klienta) týchto dát od objektov, ktoré tieto dáta spravujú (entity beans). Ako sme už spomínali, klienti málokedy priamo interagujú s entitnými objektmi. Preferovaným spôsobom prístupu je ísť cez metódy session beans a pracovať s entitami nepriamo.

Mohli by ste si pamätať, že entity beans v lokálnom rozhraní EnglishAuction deklarujú metódu getAuctionDetail vracajúcu objekt triedy AuctionDetailView. Toto view je však iba určitým generikom, pretože obsahuje kompletnú kópiu atribútov konkrétnej aukcie. Naproti tomu je AuctionSummaryView odlišná v tom, že obsahuje iba podskupinu atribútov odrážajúcich špecifické požiadavky klienta. Pretože je táto trieda klientovo špecifická, je vhodné, aby entity beana nemala o existencii tejto triedy ani tušenie. Platí teda, že klientovo závislé views je lepšie generovať prostredníctvom session beans. To zabezpečí, že vaše entity beans budú imúnne voči meniacim sa požiadavkám jednotlivých klientov.

Administratívne funkcie pre spravovanie samotných aukcií zveríme implementácii rozhrania AuctionManager. Nasledovný výpis obsahuje jednoduchú verziu tohto rozhrania.

Remote rozhranie pre AuctionManager session bean – AuctionManager.java:

/**
* Title: AuctionManager
* Description: EJB remote rozhranie pre AuctionManager bean
*/

import java.rmi.RemoteException;
import java.util.List;
import javax.ejb.CreateException;
import javax.ejb.EJBObject;
import javax.ejb.FinderException;
import InvalidAuctionStatusException;
import AuctionDetailView;
public interface AuctionManager extends EJBObject {

 /**
 * Vytvorí novú aukciu a vráti jej primárny kľúč.
 */

 public Integer createAuction(AuctionDetailView view)
  throws CreateException, RemoteException;
 /**
 * Vloží novú položku do aukcie.
 */

 public void assignItemToAuction(Integer auctionId, Integer itemId, int quantity)
  throws InvalidAuctionStatusException, FinderException, RemoteException;
 /**
 * Vráti aktuálny stav aukcie.
 */

 public AuctionDetailView getAuctionDetail(int auctionId)
  throws FinderException, RemoteException;
}

Nasledujúci výpis obsahuje remote rozhranie pre stateful session bean, ktorý môže byť využitý na spracovanie objednávky v prípade úspešného vydraženia predmetu aukcie. Mali by ste si všimnúť, že nikde tu nie je zmienka o použitom komponentnom rozhraní, ktoré by definovalo, či je session beana stateful alebo stateless.

Remote rozhranie pre AuctionCheckout session bean – AuctionCheckout.java:

/**
* Title: AuctionCheckout
* Description: Remote rozhranie pre AuctionCheckout stateful session bean
*/

import java.rmi.RemoteException;
import javax.ejb.EJBObject;
import AddressView;
public interface AuctionCheckout extends EJBObject {
 public void setBidder(int bidderId) throws RemoteException;
 /**
 * Vlož položku z aukcie do objednávky.
 * @param auctionId primárny kľúč vybranej aukcie
 */

 public void addAuctionWinToOrder(int auctionId) throws RemoteException;
 /**
 * Vlož dodaciu adresu pre danú objednávku.
 * @param shippingAddress adresa použitá pre túto objednávku
 */

 public void updateShippingAddress(AddressView shippingAddress)
  throws RemoteException;
 /**
 * Vyber prepravcu a spôsob doručenia
 * @param carrierId identifikátor prepravcu
 * @param priorityId identifikátor spôsobu doručenia
 */

 public void selectShippingMethod(int carrierCode, int priorityCode)
  throws RemoteException;
 /**
 * Odošli objednávku.
 */

 public void completeOrder() throws RemoteException;
}

V tejto časti sme zadefinovali komponentné remote rozhrania pre session beans nášho aukčného systému (kompletný zdroj). Ďalej nás čaká vytvorenie home rozhraní a implementácia jednotlivých session beans.

Žádný příspěvek v diskuzi

Odpovědět