Wprowadzenie do Enterprise JavaBeans 2.0

Transkrypt

Wprowadzenie do Enterprise JavaBeans 2.0
71
Wprowadzenie do
Enterprise JavaBeans 2.0
Maciej Zakrzewicz
[email protected]
http://www.cs.put.poznan.pl/mzakrzewicz/
72
Plan rozdziału
• Wprowadzenie do EJB
• Rodzaje komponentów
• Zdalny i lokalny dostęp do komponentów
73
Charakterystyka EJB
• Enterprise JavaBeans (EJB) to przenaszalne komponenty
implementujące przetwarzanie danych zgodne z logiką
biznesową
• Enterprise JavaBeans nigdy nie są wykonywane samodzielnie
– ich metody są wywoływane przez programy klientów EJB
(którymi mogą być inne EJB)
• Dwa rodzaje klientów EJB: zdalny i lokalny (ta sama JVM)
• Rodzaje komponentów EJB:
– Sesyjne EJB (Session EJB): pozwalają wykonywać dowolny kod w
architekturze RMI
– Encyjne EJB (Entity EJB): obsługują komunikację z bazą danych;
reprezentują rekordy znajdujące się w bazie danych
– Komunikatowe EJB (Message-Driven EJB): są odbiorcami
asynchronicznych komunikatów JMS (Java Messaging System)
74
Przegląd rodzajów komponentów EJB
EJB
Sesyjne
Stanowe
Bezstanowe
CMP
Wartości atrybutów
obiektu są tracone
pomiędzy wywołaniami
Wartości atrybutów obiektu
są przechowywane pomiędzy
wywołaniami
Komunikatowe
Encyjne
BMP
Interakcja z bazą danych
implementowana przez
programistę
Interakcja z bazą danych
implementowana przez
kontener
75
EJB 2.0: składniki (1/2)
• Interfejs Remote: (javax.ejb.EJBObject) deklaruje metody
komponentu, które będą dostępne dla klientów zdalnych
• Interfejs Local: (javax.ejb.EJBLocalObject) deklaruje metody
komponentu, które będą dostępne dla klientów lokalnych
• Obiekt EJB: wygenerowana przez kontener implementacja
interfejsu Remote; deleguje wywołania metod do obiektu
komponentu (EJB Bean)
• Interfejs Home: (javax.ejb.EJBHome) deklaruje metody
zarządzania cyklem życia komponentu dla klientów zdalnych
• Interfejs Local Home: (javax.ejb.EJBLocalHome) deklaruje
metody zarządzania cyklem życia komponentu dla klientów
lokalnych
• Obiekt Home: wygenerowana przez kontener implementacja
interfejsu Home; wykorzystuje metody callback klasy
komponentu
76
EJB 2.0: składniki (2/2)
• Klasa komponentu EJB: (javax.ejb.SessionBean/EntityBean)
implementuje metody biznesowe oraz metody zarządzania
cyklem życia komponentu
• Klasa komponentu EJB dla komponentów komunikatowych
implementuje interfejsy javax.ejb.MessageDrivenBean i
MessageListener; zawiera metodę onMessage(),
implementującą logikę biznesową
• Deskryptor instalacji: dokument XML opisujący wszystkie
pozostałe składniki komponentu EJB
Zdalny dostęp do komponentu EJB
(sesyjny EJB, encyjny EJB)
OC4J
3
Żądanie utworzenia obiektu EJB
kontener EJB
obiekt Home
Klient EJB
5
Referencja do obiektu EJB
4
Utworzenie
obiektu EJB
obiekt EJB
6
Wywołanie metody EJB
7
Delegacja wywołania
EJB Bean
2
Referencja do obiektu Home
JNDI
1
Pobranie referencji do obiektu Home
77
Zdalny dostęp do komponentu EJB
(komunikatowy EJB)
OC4J
Klient EJB
3
Nazwiązanie połączenia z kolejką
4
Wysłanie komunikatu
EJB Bean
6
Delegacja wywołania
obiekt EJB
5
2
Odbiór komunikatu
Referencja do kolejki
JNDI
1
Pobranie referencji do kolejki
JMS
78
79
Klient EJB dla sesyjnych i encyjnych EJB
• Klientem EJB może być samodzielna aplikacja Java, serwlet
Java, aplikacja JSP lub komponent EJB
– Klient lokalny:
• funkcjonuje w ramach tej samej JVM, w której pracuje komponent
• przekazuje argumenty metod komponentu za pomocą referencji
• posiada dostęp do metod komponentu EJB zadeklarowanych w interfejsie
Local
– Klient zdalny:
• może znajdować się na dowolnej maszynie
• przekazuje argumenty metod komponentu za pomocą wartości
• posiada dostęp do metod komponentu EJB zadeklarowanych w interfejsie
Remote
80
Zdalny klient EJB: przykład
1.
2.
3.
4.
5.
Przygotuj ustawienia JNDI
Utwórz obiekt klasy InitialContext()
Pobierz referencję do obiektu Home przy pomocy metody lookup
Dokonaj rzutowania otrzymanego obiektu przy pomocy interfejsu Local Home i
metody PortableRemoteObject.narrow()
Utwórz obiekt komponentu przy pomocy metody create()
Hashtable env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.evermind.server.rmi.RMIInitialContextFactory");
env.put(Context.SECURITY_PRINCIPAL, "admin");
env.put(Context.SECURITY_CREDENTIALS, "welcome");
env.put(Context.PROVIDER_URL, "http:ormi://miner.cs.put.poznan.pl/moja_aplikacja");
Context context = new InitialContext(env);
SessionEJBHome myHome = (SessionEJBHome) PortableRemoteObject.narrow(context.lookup("SessionEJB"),
SessionEJBHome.class);
SessionEJB myEJB;
myEJB = myHome.create();
System.out.println(myEJB.dodaj(2,3));
81
Lokalny klient EJB: przykład
1.
2.
3.
4.
5.
Zarejestruj wołany komponent EJB w pliku web.xml (application-client.xml, ejb-jar.xml)
– nadaj mu nazwę logiczną
Utwórz obiekt klasy InitialContext()
Pobierz referencję do obiektu Home przy pomocy metody lookup (stosuj lokalny adres
o postaci java:comp/env/...)
Dokonaj rzutowania otrzymanego obiektu przy pomocy interfejsu Local Home
Utwórz obiekt komponentu przy pomocy metody create()
web.xml
<ejb-local-ref>
<ejb-ref-name>ejb/MyEJB</ejb-ref-name>
<ejb-ref-type>Session</ejb-ref-type>
<local-home>SessionEJBLocalHome</local-home>
<local>SessionEJBLocal</local>
</ejb-local-ref>
serwlet Java
Context context = new InitialContext();
SessionEJBLocalHome myHome = (SessionEJBLocalHome) context.lookup("java:comp/env/ejb/MyEJB");
SessionEJBLocal myEJBLocal;
myEJBLocal = myHome.create();
out.println(myEJBLocal.dodaj(2,3));
82
Dostęp do EJB z poziomu JSP
• Użycie biblioteki znaczników OJSP EJB:
<%@ taglib uri="/WEB-INF/ejbtaglib.tld" prefix="ejb" %>
• Wyszukanie komponentu poprzez JNDI oraz utworzenie obiektu Home:
<ejb:useHome id = "nazwa_obiektu_home"
type = "nazwa_interfejsu_home" location = "nazwa_jndi"
[local = "true" | "false"]/>
• Utworzenie obiektu komponentu i rzutowanie przy pomocy interfejsu
Remote
<ejb:useBean id = "nazwa_obiektu_komponentu"
type = "nazwa_interfejsu_remote"
[scope="page"|"request"|"session"|"application"][local="true"|"false"]>
<ejb:createBean instance="<%=nazwa_obiektu_home.create()%>" />
</ejb:useBean>
• Wywoływanie metod obiektu komponentu
<% nazwa_obiektu_komponentu.metoda() %>
83
OJSP EJB: przykład
<%@ taglib uri="/WEB-INF/ejbtaglib.tld" prefix="ejb" %>
...
<!-- Utwórz obiekt Home -->
<ejb:useHome id="basketHome" type="mypackage6.BasketEJBLocalHome"
location="java:comp/env/ejb/BasketEJB" local="true" />
<!-- Utwórz obiekt EJB -->
<ejb:useBean id = "basketBean"
type = "mypackage6.BasketEJBLocal"
scope="session" local="true">
<ejb:createBean instance="<%=basketHome.create()%>" />
</ejb:useBean>
<!-- Dodaj nowy element do koszyka -->
<% if (request.getParameter("add")!=null)
basketBean.addToBasket(request.getParameter("add")); %>
...
84
Sesyjne komponenty EJB
85
Plan rozdziału
•
•
•
•
•
Wprowadzenie
Rodzaje sesyjnych EJB
Implementacja sesyjnych EJB
Przykład tworzenia prostego sesyjnego EJB
Tworzenie sesyjnego komponentu EJB w środowisku
JDeveloper9i/10g
86
Wprowadzenie
• Sesyjny EJB to komponent biznesowy o następującej
charakterystyce:
–
–
–
–
–
–
–
Jest używany przez jednego klienta lub użytkownika
Istnieje tylko przez czas trwania sesji
Jest niszczony w wypadku awarii kontenera
Nie jest obiektem trwałym
Może zostać przekroczony dla niego limit czasu życia
Może uczestniczyć w transakcjach
Może posłużyć do zamodelowania stanowej lub bezstanowej
komunikacji między klientem a komponentami warstwy biznesowej
87
Rodzaje sesyjnych EJB
• Stanowy sesyjny EJB (Stateful Session EJB)
– zapamiętuje stan pomiędzy kolejnymi wywołaniami przez tego samego klienta
– dla każdego klienta powoływane jest oddzielne wystąpienie komponentu
– stan komponentu może być zapisywany w systemie plików (pasywacja) –
algorytm LRU
– pasywacji nie podlegają zasoby: połączenia sieciowe, połączenia z bazą
danych, itp. – jest to zadaniem programisty (ejbPassivate(), ejbActivate())
– przykładowe zastosowania: koszyk zakupów, tymczasowe struktury danych
• Bezstanowy sesyjny EJB (Stateless Session EJB)
– nie zapamiętuje stanu
– przykładowe zastosowania: przeliczanie walut, wyliczanie rat kredytu
– kolejne odwołania pochodzące od tego samego klienta mogą być realizowane
przez różne obiekty komponentu, znajdujące się w puli kontenera EJB
– zwykle nie implementuje ciała żadnych metod interfejsu SessionBean
• Wyboru rodzaju sesyjnego EJB dokonuje się w pliku deskryptora instalacji
(ejb-jar.xml)
88
Implementacja sesyjnych EJB
• Implementują interfejs javax.ejb.SessionBean:
– setSessionContext(SessionContext ctx)
• W chwili utworzenia, obiekt komponentu otrzymuje tzw. obiekt kontekstu,
przydatny do interakcji z kontenerem (calback)
– ejbActivate()
• Wywoływana gdy kontener przywraca obiekt komponentu do pamięci, po
jego wcześniejszym przeniesieniu na dysk
– ejbPassivate()
• Wywoływana gdy kontener przenosi obiekt komponentu z pamięci na
dysk
– ejbCreate()
• Wywoływana gdy tworzony jest nowy obiekt komponentu
– ejbRemove()
• Wywoływana bezpośrednio przed likwidacją obiektu komponentu przez
kontener (np. zakończenie sesji)
89
Metoda setSessionContext()
• Obiekt SessionContext przekazywany przez kontener do metody
setSessionContext() oferuje następujące metody:
–
–
–
–
–
–
–
getEJBObject() – zwraca referencję do obiektu EJB
getEJBHome() – zwraca interfejs Home
getCallerIdentity() – obiekt opisujący tożsamość wołającego użytkownika
getEnvironment() – zwraca zmienne środowiska komponentu EJB
setRollbackOnly() – zaznacza bieżącą transakcję jako transakcję do wycofania
getUserTransaction() – zwraca kontekst transkakcji
isCallerInRole() – sprawdza, czy wołający użytkownik posiada podaną rolę
public class myBean implements SessionBean {
SessionContext sessctx;
void setSessionContext(SessionContext ctx) {
sessctx = ctx;
}
...
Typowa implementacja metody
setSessionContext() polega na
kopiowaniu obiektu SessionContext
do zmiennej wystąpienia, która
będzie dostępna dla innych metod
komponentu.
90
Cykl życia sesyjnego EJB
Brak
setSessionContext(ctx)
ejbCreate()
ejbRemove()
ejbPassivate()
Gotowy
Pasywny
ejbActivate()
wyłącznie dla stanowych sesyjnych EJB
91
Przykład tworzenia prostego sesyjnego EJB
Klasa komponentu
Interfejs Remote
import javax.ejb.*;
import javax.ejb.*;
import java.rmi.RemoteException;
public class SessionEJBBean implements SessionBean {
public void ejbCreate() {}
public interface SessionEJB extends EJBObject {
public void ejbActivate() {}
public void ejbPassivate() {}
double dodaj(double a, double b) throws RemoteException;
}
public void ejbRemove() {}
Deskryptor instalacji
public void setSessionContext(SessionContext ctx) {}
public double dodaj(double a, double b) {
...
<description>Session Bean ( Stateless )</description>
return a+b;
<display-name>SessionEJB</display-name>
}}
<ejb-name>SessionEJB</ejb-name>
Interfejs Home
<home>SessionEJBHome</home>
import javax.ejb.*;
<remote>SessionEJB</remote>
import java.rmi.RemoteException;
<ejb-class>SessionEJBBean</ejb-class>
<session-type>Stateless</session-type>
public interface SessionEJBHome extends EJBHome {
SessionEJB create() throws RemoteException,
CreateException;
}
...
Tworzenie sesyjnego komponentu EJB w 92
środowisku JDeveloper9i/10g
Utworzenie nowego komponentu EJB
Nazwa komponentu,
jego rodzaj (stanowy/bezstanowy)
Na kolejnych stronach: nazwa klasy komponentu, nazwy interfejsów Home,
Remote, Local Home, Local Remote
Tworzenie sesyjnego komponentu EJB w 93
środowisku JDeveloper9i/10g
• Utworzone pliki dla komponentu sesyjnego SessionEJB:
–
–
–
–
–
–
–
SessionEJB.java – interfejs Remote
SessionEJBBean.java – klasa komponentu
SessionEJBHome – interfejs Home
SessionEJBLocal.java – interfejs Local Remote
SessionEJBLocalHome.java – interfejs Local Home
ejb-jar.xml – standardowy deskryptor instalacji
orion-ejb-jar.xml – specyficzny dla OC4J deskryptor
instalacji
9i
10g
Tworzenie sesyjnego komponentu EJB w 94
środowisku JDeveloper9i/10g
• Implementacja metod komponentu:
– 9i: (Menu kontekstowe na ikonie reprezentującej komponent -> Edit EJB ->
Methods ->Add)
– 10g: (Dwuklik -> Methods-> Add)
Tworzenie sesyjnego komponentu EJB w 95
środowisku JDeveloper9i/10g
• Tworzenie aplikacji klienta EJB
• Uruchamianie lokalnie:
– „Run” na komponencie
– „Run” na kliencie
96
Komunikatowe komponenty EJB
97
Plan rozdziału
•
•
•
•
•
Wstęp: systemy przekazywania komunikatów
Charakterystyka OC4J Java Messaging Service
Wykorzystywanie JMS API
Przykładowy komunikatowy EJB
Tworzenie komunikatowego EJB w środowisku
JDeveloper9i/10g
Wstęp: systemy przekazywania
komunikatów
• Systemy przekazywania komunikatów (Messaging Systems) służą do
asynchronicznej wymiany danych pomiędzy aplikacjami
–
–
–
–
–
OC4J JMS
Oracle Advanced Queueing
IBM MQSeries
BEA WebLogic JMS
Sun iPlanet Message Queue
• Programy Java wykorzystują systemy przekazywania komunikatów przy
pomocy biblioteki JMS API (Java Messaging Service API)
Klient
JMS API
publisher
OC4J
JMS
Klient
JMS API
subscriber
98
99
OC4J JMS
• Obiekty zarejestrowane w JNDI:
– Connection Factory: odpowiada za tworzenie połączeń klientów z
usługą JMS
– Destination: tematy (topics) lub kolejki (queues) do których
komunikaty są wysyłane lub z których są odbierane
• Modele komunikacji:
– Point-to-point: nadawca wysyła wiadomość do kolejki, odbiorca
odbiera wiadomość z kolejki; z jednej kolejki może korzystać wielu
nadawców i wielu odbiorców, ale każdy nadawany komunikat jest
adresowany do konkretnego odbiorcy
– Publish-and-subscribe: nadawca wysyła wiadomość do tematu,
wiadomość jest automatycznie rozsyłana do wszystkich odbiorców
tematu; z jednego tematu może korzystać wielu nadawców i
odbiorców
100
Konfiguracja OC4J: jms.xml
<jms-server port="9127">
<topic name="Demo Topic" location="jms/demoTopic">
<description>Temat demo</description>
</topic>
<topic-connection-factory name="Demo Connection Factory"
location="jms/theTopicConnectionFactory">
<description>Connection Factory dla tematu demo</description>
</topic-connection-factory>
<log>
<file path="../log/jms.log" />
</log>
</jms-server>
101
JMS API
• Wysyłanie komunikatu do kolejki:
–
–
–
–
–
–
–
wyszukaj Connection Factory poprzez JNDI
wyszukaj kolejkę poprzez JNDI
otwórz połączenie i rozpocznij sesję Context ctx = new InitialContext();
QueueConnectionFactory cf =
utwórz obiekt-nadawcę
(QueueConnectionFactory) ctx.lookup(...);
utwórz komunikat
QueueConnection conn = cf.createQueueConnection();
wyślij komunikat
conn.start();
QueueSession sess = conn.createQueueSession(false,
zamknij używane obiekty
• Typy komunikatów:
–
–
–
–
–
TextMessage
MapMessage
BytesMessage
StreamMessage
ObjectMessage
Session.AUTO_ACKNOWLEDGE);
Queue queue = (Queue) ctx.lookup(...);
QueueSender sender = sess.createSender(queue);
TextMessage message = sess.createTextMessage();
message.setLongProperty("msgid", ...);
message.setText(...);
sender.send(message);
sender.close();
sess.close();
conn.close();
102
JMS API
• Wysyłanie komunikatu do tematu:
–
–
–
–
–
–
–
wyszukaj Connection Factory poprzez JNDI
wyszukaj temat poprzez JNDI
otwórz połączenie i rozpocznij sesję
utwórz obiekt-nadawcę
Context ctx = new InitialContext();
utwórz komunikat
TopicConnectionFactory topicFactory =
wyślij komunikat
(TopicConnectionFactory) ctx.lookup(...);
zamknij używane obiekty
TopicConnection topicConnection =
topicFactory.createTopicConnection();
TopicSession session = topicConnection.createTopicSession(
false, Session.AUTO_ACKNOWLEDGE);
Topic topic = (Topic) context.lookup("...");
TopicPublisher pub = session.createPublisher(topic);
TextMessage message = session.createTextMessage();
message.setText(...);
pub.publish(topic, message);
topicConnection.close();
103
Komunikatowe komponenty EJB
• Komunikatowe EJB (Message-Driven Beans):
–
–
–
–
–
są asynchronicznymi odbiorcami komunikatów JMS
są bezstanowe, wykonywane po stronie serwera aplikacji
nie łączą się bezpośrednio z klientami
nie posiadają interfejsu Home ani interfejsu Remote
są uruchamiane w chwili nadejścia nowego komunikatu (metoda
onMessage())
– implementują interfejsy javax.ejb.MessageDrivenBean i
javax.jms.MessageListener
– cykl życia jest identyczny jak cykl życia bezstanowego sesyjnego EJB
104
Przykładowy komunikatowy EJB
Klasa komponentu
public class MyMessageDrivenEJBBean implements MessageDrivenBean, MessageListener {
private MessageDrivenContext context;
public void ejbCreate() {}
<enterprise-beans>
Deskryptor instalacji
<message-driven>
public void onMessage(Message msg) {
<description>Message Driven Bean</description>
try {
<display-name>MyMessageDrivenEJB</display-name>
TextMessage textMessage = (TextMessage) msg;
<ejb-name>MyMessageDrivenEJB</ejb-name>
String text = textMessage.getText();
<ejb-class>mypackage7.impl.MyMessageDrivenEJBBean
System.out.println(text);
</ejb-class>
} catch (Exception e) {}
<transaction-type>Container</transaction-type>
}
<acknowledge-mode>Auto-acknowledge
</acknowledge-mode>
public void ejbRemove() {}
<message-driven-destination>
<destination-type>javax.jms.Queue</destination-type>
public void setMessageDrivenContext
(MessageDrivenContext ctx) {
this.context = ctx;
}
}
</message-driven-destination>
</message-driven>
</enterprise-beans>
Tworzenie komunikatowego EJB w
środowisku JDeveloper9i/10g
Utworzenie nowego komponentu EJB
Powiązanie z JMS (orion-ejb-jar.xml)
105

Podobne dokumenty