J2EE - deklaratívne riešenie programátorských problémov• Posun od memory managmentu ďalej...• Prenos zložitých implementačných konceptov na ramená
kontajnera a resource adapterov:– Distribuovanosť– Transakčnosť– Multithreading– Deklaratívna bezpečnosť– Resource management
• Vyvojár sa môže zamerať len na business logiku, kontajnerinterpretáciu vyššie uvedených konceptov
• Vývojár uvádza niektorý z konceptov deklaratívnym spôsobom
• Rozdelenie úloh a zodpovedností medzi viac rolí
Zodpovednosti v J2EE
• J2EE rieši aj životný cyklus projektu rozdelením zodpovedností v tomto cykle medzi 6 rolí– Enterprise bean provider
– Application assembler
– EJB deployer
– EJB server provider
– EJB container provider
– System administrator
• Toto rozdelenie malo zásadný vplyv aj na spôsob akým sa implementujú komponenty. Hlavne ide o oddelenierolí bean provider assembler a deployer.
Viacvrstvová architektúra
• J2EE rozdeľuje aj problematiku riešenú v aplikáciach na viac vrstiev
– Vrstva dát a dátových služieb
– Vrstva manipulácie s dátami, resp vrstva business logiky
– Prezentačná vrstva
Enterprise JavaBeans• Enterprise Java Beans – server side komponenty, každá na
rieši špecifický typ úlohy– Session Beans – určené na implementáciu business logiky
• Staless• Statefull
– Entity Beans – reprezentujú perzistentné objekty– Message Driven Beans (MDB) – spracovanie asynchrónnych JMS
správ– TimerBean (EJB 3.0)
• Bežia v kontajneri. Zverejňujú rozhranie pre kontajner aj pre klienta
• Nikdy nie su prístupné priamo klientovi. kontajner implementuje proxies. Proxy rieši implementáciu transakčnosti, multithreadingu atď.
Kontajner
• Vytvára runtime prostredie pre beh komponentov –implementuje zložité implementačné koncepty v tzv. Proxy triedach - sú to vlastne interceptory volaní.
• Spravuje všetky zdroje: inštancie komponentov, databázové pripojenia, thready. Rieši pooling (reuse) týchto zdrojov atď.
• 3 typy– EJB Container – beh EJB komponentov
– Web Container – beh servletov a JSP
– Client container – klient aplikácie, GUI, console..., je klientom EJB kontajnera.
EJB Programming Restrictions
• EJB Bean– must not use the java.io package to attempt to access files and
directories in the file system.– must not use thread synchronization primitives to synchronize
execution of multiple instances.– must not attempt to listen on a socket, accept connections on a
socket, or use a socket for multicast.– must not attempt to load a native library.– must not attempt to access or modify the security configuration
objects (Policy, Security, Provider, Signer, and Identity).– must not use the AWT functionality to attempt to output information
to a display, or to input information from a keyboard.– must not use read/write static fields. Using read-only static fields is
allowed. Therefore, it is recommended that all static fields in the enterprise bean class be declared as final.
– ...
Rozhrania komponent
• Len Beany, nie MDB
• Business metódy – component interfaces
– Local a Remote interfaces
• Životný cyklus komponenty – home interfaces
– Local Home a Remote Home interface
Component interfaces
• Local – rýchlejšie rozhranie– určené pre časté volania a volania v rámci jednej VM.– Pozor, parametre sa predávajú odkazom, nie hodnotou– Typické použitie
• Web komponenta volá bean komponentu, Jsp volá bean • implementácia WS over stateless bean• Session bean používa entity beans
– Odporúča sa pri prístupe ku entity beanom. Viď Session facade.
• Remote – rozhranie sprístupňuje komponentu v distribuovanom prostredí– Dostupné klientovi zo vzdialenej VM– Paremetre sú predávané hodnotou -> marshaling overhead– Generovanie “heavy” stubov (proxy) – Transportný mechanizmus je RMI over IOOP
Component interfacesLocal interface musí implementovať javax.ejb.EJBLocalObject
public interface SapServiceLocal extends javax.ejb.EJBLocalObject {public String SendObjMsgToSap(Object obj) throws ClientException;public String sapPrijatieRec(String transXmlEnc) throws ClientException;
}
Remote interface musí implementovať javax.ejb.EJBObject, metódy na rozhraní musia deklarovať aj java.rmi.RemoteException
public interface SapService extends javax.ejb.EJBObject {public String sapPrijatieRec(String transXmlEnc) throws ClientException,java.rmi.RemoteException;public String vyhSapZaslanieVozidla(String transXmlEnc)throws ClientException,java.rmi.RemoteException;
}
Home interfaces
• Opať sa delia Home Local a Remote• Umožňujú klientovi vytvoriť, zrušiť, alebo nájsť komponenty daného
typu• Bean musí implementovať Home interfaces:
Local Home interface musí implementovať javax.ejb.EJBLocalHome:
public interface SapServiceLocalHome extends javax.ejb.EJBLocalHome {public sk.regobsa.sap.applogic.ejb.SapServiceLocal create() throws javax.ejb.CreateException;
}
Remote home interface musí implementovať javax.ejb.EJBHome, metódy na rozhraní musia deklarovať aj java.rmi.RemoteException:
public interface SapServiceHome extends javax.ejb.EJBHome {public sk.regobsa.sap.applogic.ejb.SapService create() throws
javax.ejb.CreateException,java.rmi.RemoteException;}
Deployment descriptor - interfaces
Priradenie home a component interfaces ku bean triede je uvedené v deployment descriptore
<ejb-jar xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" id="ejb-jar_ID" version="2.1" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/ejb-jar_2_1.xsd"><display-name>SapEJB</display-name><enterprise-beans>
<session id="SapService"><ejb-name>SapService</ejb-name><home>sk.regobsa.sap.applogic.ejb.SapServiceHome</home><remote>sk.regobsa.sap.applogic.ejb.SapService</remote><local-home>sk.regobsa.sap.applogic.ejb.SapServiceLocalHome</local-home><local>sk.regobsa.sap.applogic.ejb.SapServiceLocal</local><service-endpoint>sk.regobsa.sap.applogic.ejb.SapServiceService</service-endpoint><ejb-class>sk.regobsa.sap.applogic.ejb.SapServiceBean</ejb-class><session-type>Stateless</session-type>
...</session>
Príklad získania Remote interface :
InitialContext ic = new InitialContext();Object oRef = ic.lookup( "java:comp/env/ejb/SapService" );SapServiceHome SapServiceHome = (SapServiceHome)PortableRemoteObject.narrow( oRef, SapServiceHome.class ); // IOOP Idiom
Príklad získania Local interface:
InitialContext ic = new InitialContext();SapServiceLocalHome MyEJBHome = (SapServiceLocalHome)ic.lookup( " java:comp/env/ejb/SapService " );
• Klient používa JNDI lookup na získanie Home interface• ENC – environment naming context – klient používa alias ku skutočnej JNDI ceste,
alias kontajner identifikuje cez ENC– Alias - ejb/SapService– ENC - java:comp/envLookup string potom vyzera takto java:comp/env/ejb/SapService
• Skutočná JNDI cesta je uvedená až pri deploymente
Získanie inštancie komponentu
Referencie
• Aliasy uvádzané v lookup metóde sú vlatne názvy referencií• Každý resource, ktorý komponenta potrebuje referencuje
vo svojom deployment deskriptore cez referenciu– EJB referencies
• Local, alebo remote EJB referencia
– Service referencies• Web Service referencia
– Resource referencies• DataSource, URL, Queue, Topic, mail.Session, ConnectionFactory
– ...
• Referencie sa resolvujú vždy volanímnew InitialContext().lookup(String)
JNDI Tree• kontajner pri zavádzaní EAR registruje všetky
komponenty (ich home rozhrania) do JNDI stromu
• Bean developer používa referencie na adresovanie beanov, ale iných resources
• Deployer binduje aliasy na konkrétne cesty v JNDI strome
<ejb-local-ref id="EJBLocalRef_1246448602354">
<ejb-ref-name>ejb/AppConfig</ejb-ref-name>
<ejb-ref-type>Session</ejb-ref-type>
<local-home>sk.regob.ejb.appconfig.AppConfigLocalHome</local-home>
<local>sk.regob.ejb.appconfig.AppConfigLocal</local>
<ejb-link>InfrastructureBeans.jar#AppConfig</ejb-link>
</ejb-local-ref>
<resource-ref id="ResourceRef_1246448649480">
<res-ref-name>jms/EVO2SAPQueue</res-ref-name>
<res-type>javax.jms.Queue</res-type>
<res-auth>Container</res-auth>
<res-sharing-scope>Shareable</res-sharing-scope>
</resource-ref>
<resource-ref id="ResourceRef_1246450679373">
<res-ref-name>jdbc/EVO</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
<res-sharing-scope>Shareable</res-sharing-scope>
</resource-ref>
<resource-ref id="ResourceRef_1246450736188">
<res-ref-name>url/EVOTimeOutConfig</res-ref-name>
<res-type>java.net</res-type>
<res-auth>Container</res-auth>
<res-sharing-scope>Shareable</res-sharing-scope>
</resource-ref>
Deployment descriptor - referencie
Deployment archív
• Aplikácie a komponenty su balené do Java Archive JAR súborov. Rôzne prípony určujú ich presný účel– EAR Enterprise ARchive – súbor obsahuje celú aplikáciu
– JAR - EJB komponenty a klient knižnice
– WAR - Web ARchive – Web komponenty
• Deployment deskriptory sú obsiahnuté v JAR súboroch– Xml súbory, popisujú konfiguráciu komponentov
– Deskriptor pre EJB súbor je ejb-jar.xml, ktorý sa nachádza v adresári META-INF
– Deskriptor pre WEB komponenty je web.xml v adresári WEB-INF
EJB JAR
WAR
EAR
State mamagment - Stateless vs. Statefull• Statefull
– Stav medzi volaniami je udržiavaný v pamäti J2EE servera• Dáta ktoré sú predmetom volania• Pripojenia do DB, resp iných resources.• Teta odchadza na obed....
– Nutnost riešiť /réžia J2EE servra/
• Afinity• Session namagment• Recyklácia pamäte, memory to memory replikácia, persistencia sessions
– Nutnost riešiť /réžia J2EE vývojára/• Dlho trvajúce transakcie, možnosť vzniku kolízii na DB úrovni• Vyššia pamäťová náročnosť, možné performance problémy• Nekompatibilita s WS
(http://java.sun.com/blueprints/patterns/SessionFacade.html)
– Výhoda• Vývojár nemusí znovu získavať z DB údaje ktoré už pred tým získal
• Stateless– Po ukončení volania nezostáva v aplikačnom serveri žiaden údaj
súvisiaci s transakciou– Kazdé volanie je samostatnou transakciou. Po ukončení volania
je DB v konzistentnom stave.• Transakcia je buď committed, alebo rolled back
– Viackrokový proces je riešený ako sekvencia transakcií• Snaha vytvárať malé, krátko trvajúce transakcie.
– Volanie je možné vykonať na ľubovoľnom servri• „ľahké“ clustrovanie
– WS je stateless by definition– Nevýhoda
• Údaje s ktorými sa pracuje treba vždy získať z DB znova, keďže po ukonční volania sú dáta zabudnuté (sú len v DB)
State mamagment - Stateless vs. Statefull
Session FacadeKombinácia prístupu: http://java.sun.com/blueprints/patterns/SessionFacade.html
Transakcia
• Základný mechanizmus na ktorom stavia J2EE ??Najdôležitejší??
• Potrebujete napríklad zapísať narodenie osoby a zaslať správu o narodení do centrálneho registra. Operácie sa musia udiať buď obe, alebo žiadna z nich tak aby boli oba zdroje aktualizované konzistentne– Jednoduchšie: zapisujem osobu a jej mená, dve tabulky, kardinalita
1..N.
• ACID - atomicity, consistency, isolation, durability• Zložitosť transakcií implementuje kontajner v spolupráci s resource
adapters (JDBC, JMS, SAP, ...)• kontajner je transakčný koordinátor• Pre distribuované transakcie sa používa 2PC – two-phase commit
protocol (XA Transakcie)
Transakčnosť• Beany podporujú dva typy spravovania transakcií
– Container-Managed Transactions– Bean-Managed Transactions
• Container-Managed– kontajner štartuje transakciu pred volaním metódy a
comituje po ukončení volania– To ako sa má transakcia vytvoriť, alebo priradiť metóde
definujeme transakčnými atribútmi na úrovni metódy. Metóda nemusí mať transakčný kontext
– Developer nevolá commit, alebo rollback (nemôže). Ak chce rollbacknut transakciu môže:• Throw unchecked exception• Alebo hlasovat za rollback transakcie volaním setRollbackOnly
Transakčné atribútyRequired Metóda sa vykoná v kontexte klientovej transakcie. Ak
transakcia neexistuje kontajner vytvorí novú.
RequiresNew Metóda je vždy vykonaná v novej transakcii. Ak existuje klient transakcia kontajner su suspendne.
Mandatory Metóda musí byť vykonaná v klientskej transakcii. Ak klientska transakcia neexistuje kontajner vytvorí výnimku
NotSupported Metóda nevyžaduje beh v transakcii. Ak existuje klient transakcia, kontajner ju pred volaním suspendne.
Supports Ak transakcia existuje metóda sa vykoná v nej. Ak nie kontajner nevytvára novú transakciu
Never Klient transakcia nesmie existovať pri volaní metódy. Ak existuje kontajner vytvorí výnimku
Prakticky najčastejšie sa používa Requires, alebo RequiresNew
Bean-managed transactions
• JDBC transactions asi len ak treba wrapnuť starý Java kód. Používa transaction manager priamo v ovládači pre danú DB
• JTA transactions: Java Transaction API. V J2EE implementovaný transaction provider. Nezávisle od ovládača pre danú DB.
• V zodpovednosti vývojára volať begin, commit, rollback na rozhraní javax.transaction.UserTransaction.
• Nesmie volať setRollBackOnly/getRollbackOnly
• Pred ukončením volania musí stateless bean resolvnúťtransakciu
EJB Exception handling
• Dva typy výnimiek– Checked
• Application exception• Odvodené od java.lang.Exception• Musia sa deklarovať v throws klauzuje• Klient môže zareagovať
– Unchecked• System exceptions (nullpoiner, arraybounds)• Odvodené od java.lang.RuntimeException• Považované za bug• kontajner robí automaticky rollback transakcie, pretože nie je
dôvod reagovať na takúto výnimku
– Checked to Unchecked thow javax.ejb.EJBException
Multithreading
• Prečo?– Paralelnost
• využitie výkonu, rozvetvenie výpočtu, resp. paralelnáobsluha requestov
• Veľmi zjednodušené pri stateless princípe
• Avsak veľmi zložité, preto:
• Thready striktne managuje kontajner– EJB komponenty nesmú vytvárať thready! Je zakázané
používať akékoľvek synchronizačné objekty.
– Java thread napr. nemá „J2EE“ kontext, je vlastne obyčajným java klientom.
Multithreading
• Nemožnosť vytvoriť thread však znemožňuje– Asynchrónnosť
– Background processing
• Našťastie existuje– MDB (od verzie 2)
– TimerBean (od verzie 3)
• Obe riešenia však nevyžadujú použitie synchronizačných objektov a teda zachovávajú jednoduchý implementačný model.
Declarative security
• Role based– Na úrovni EAR deployment descriptora definujeme
role a ich väzbu na používateľov a skupiny, – Mapovanie na na reálnych používateľov definuje
administrátor J2EE servera.– Prístup ku metódam riadený v deployment
deskriptore EJB komponenty• Riadenie prístupu,
– Vývojár môže volať isCallerInRole/isUserInRole a getCallerPrincipal().getName()
• Riadenie spúšťania pod účtom
• Pozor definícia rolí je úplne statická
Session Beanpublic class ExtServiceBean implements javax.ejb.SessionBean {
private javax.ejb.SessionContext mySessionCtx;
public javax.ejb.SessionContext getSessionContext() {
return mySessionCtx;
}
public void setSessionContext(javax.ejb.SessionContext ctx) {
mySessionCtx = ctx;
}
public void ejbCreate() throws javax.ejb.CreateException {
}
public void ejbActivate() {
}
public void ejbPassivate() {
}
public void ejbRemove() {
}
public String hello(String hello) {
return hello + " EXT";
}
}
Stateless Session Bean
• Obsahuje state len počas vykonávania metódy• kontajner nerieši pasiváciu, po vykonaní metódy je
instancia pripravená na ďalšie pouzitie• Najjednoduchší typ beanu, najlepšie škálovateľný =
najlepší výkon.• Z pohľadu klienta sa môže tváriť ako knižnica funkcií
– Môže obsahovať lokálne premenné avšak nesmú obsahov dáta špecifické pre konkrétneho klienta
• Knižničnému pohľadu treba podriadiť aj analýzu aplikácie – viac na seba nadväzujúcich transakcií namiesto jednej
veľkej
Stateless Session Bean - lifecycle
Statefull Session Bean
• Obsahuje state aj medzi volaniami business metód
• Kontajner sa môže rozhodnúť, že bean deaktivuje, tj. uvoľní pamäť a uloží bean na nejaké úložisko
• Ak príde požiadavka na vykonanie metódy a bean je deaktivovaný kontaner ho aktivuje a vykoná volanie
Statefull Session Bean - lifecycle
Message Driven Bean - MDB
• Priniesli do EJB možnosť asynchrónneho spracovania správ
• Správy pochádzajú z queue, alebo topic
• MDB musí implementovat rozhranie javax.jms.MessageListener– onMessage(javax.jms.Message msg)
• MDB je stateless
• Samozrejme možnosť paralelného spracovania správ
• Nutnosť definovat spoľahlivost doručovania– Od non persistent non reliable až po assured
persistent reliable
• Vačšina business problémov požaduje maximal reliability v doručovaní správ– Garantované doručenie správy -> Správa sa nesmie za
žiadnych okolností stratiť -> striktne transakčnéspracovanie
– Veľmi často vyžadovaná garancia poradia doručovania správ
– Poison message problem
MDB - spoľahlivosť
Table 1. The five levels of reliability
Messages: Messages survive:
Best effort nonpersistent
Nonpersistent No, individual messages can be discarded
No Yes No No No No No No
Express™ nonpersistent
Nonpersistent Yes: messages are not discarded and never survive server restart
Possibly: when messages build up on a destination
No Possibly: state data can be lost on server crash resulting in duplication
No No Yes No No
Reliable nonpersistent
Nonpersistent Yes: messages are not discarded and never survive server restart
Possibly: when messages build up on a destination
No Possibly: state data can be lost on server crash resulting in duplication
No Yes Yes No No
Reliable persistent
Persistent Yes Yes: asynchronously
No Possibly: as deletion from the database is asynchronous with respect to user requests
Yes: hardened messages are recovered, planned shutdown hardens cached messages
Yes Yes Possibly: hardened messages are recovered
Possibly: hardened messages can be backed up and recovered
Assured persistent
Persistent Yes
http://publib.boulder.ibm.com/infocenter/wasinfo/v6r0/index.jsp?topic=/com.ibm.websphere.express.doc/info/exp/ae/cjj9000_.html
MDB – poison message problem
• Správa nie je vykonateľná, jej spracovanie padá s chybou– Rôzne systémy riešia rôzne.
• Vo všeobecnost rôzne retry politiky (Retry delivery count, retry delay, maximal retry cycles, ...) pred tým ako je message označená ako poison
– Problém hlavne ak je požadované poradie doručenia.• Nespracovateľná správa nemôže byť automaticky
odsmerovaná do Exception queue, pretože by sa porušilo poradie
MDB – ďalšie scenáre použitia
• Zdrojový systém vykonáva zmenu. Tá musí byť transkačne vykonaná aj vo vzdialenom systéme, ale– Zdrojový systém nechce/nemuože byť zdržovaný vzdialeným systémom– Pravdepodobne treba dodržiavať poradie správ! Transactional & Not Parallel
• Zber metrík– minimal reliability– Príklad netransakčného spracovania– výpadok vzorky nie je dôležitý! Not Transactional & Parallel
• Zasielanie log správ z aplikácie– Centrálna aplikácia – príjemca – musí z dôvodu veľkej priepustnosti
paralelne spracovávať správy. Nezáleží však na poradí! Transactional & Parallel
• Sync 2 Async– Cez WS prichádza správa, ktorá má veľa operácií
rovnakého typu. Správa musí byt spracovaná transakčne. Jej business spracovanie by bolo náročné (čas, DB locking).
– Riešením je „rozobrať“ správu na N malých operácií a v transakcii 1 (jedna transakcia ) ich vložiť do queue. Po vložení kontajner aktivuje N inštancií MDB a v N samostatných menších transakciách vykoná spracovanie.
– Samozrejme je možnosť paralelného spracovania ak netreba garantovať poradie správ
MDB – ďalšie scenáre použitia
EJB methodN
QUEUE
EJB method1
...
...
...
Transaction 1 Transaction N
MDB onMessage
EJB method1
MDB onMessage
EJB method1
MDB onMessage
EJB method1
MDB onMessage
EJB method1
MDB onMessagemethodN - metóda vie prijať správu
obsahujúcu N operácií. Metóda je exponovaná na klienta
method1 - metóda vie prijať správuobsahujúcu 1 operáciu. Metóda je interná.
MDB - lifecycle
Entity Bean
• Slúži na prístup k dátam• Inštancia EntityBeanu reprezentuje „riadok“ tabuľky• V Home rozhraní môže deklarovať
– viac create metód. Sú určené na vytvorenie inštancie s rôzným iniciálnym stavom. Všetky začínajú slovom create a vracajú componentrozhranie
– Viac find metód. Sú určené na vyhľadanie inštancie. Všetky začínajú slovom find a tiež vracajú component rozhranie
– Možno deklarovať aj business metódu, ak treba vykonať businessoperáciu, ktorá sa týka triedy a nie konkrétnej inštancie
• Entity bean je z povahy statefull beanom• Aktuálne existujú alternatívy, ktoré sa považujú za efektívnejšie
riešenie pre prístup k dátam– Pozri napr. Hibernate, DAO, resp ORM.
Entity Beam - lifecycle
Timer Bean
• Umožňuje naplánovať spustenie v špecificky čas, po určitom čase, alebo v intervaloch
• Timer je – perzistentný: ak je server down a timer ma timeoutnúť,
kontajner zavolá timeout aspoň raz po štarte
– transankčný –kontajner garantuje pri zlyhaní opakované spustenie
• Bean implemenetuje rozhranie javax.ejb.TimedObject
• Timer sa síce plánuje v milisekundách, ale nie je presný.
Praktická ukážka …
Code snippetsJSP Bean reference lookup
<%@page import="ejbs.SampleServiceLocalHome"%><%@page import="ejbs.SampleServiceLocal"%>
<%SampleServiceLocalHome home=(SampleServiceLocalHome)new
javax.naming.InitialContext().lookup("java:comp/env/ejb/SampleService");SampleServiceLocal sslocal=home.create();
String entries=sslocal.getEntries();%>
<pre><%=entries %></pre>
DataSource resource lookup
DataSource ds=(DataSource) mySessionCtx.lookup("java:comp/env/jdbc/SampleDB");
Connection conn=ds.getConnection();
PreparedStatement ps=conn.prepareStatement("create table KEYTABLE (ID INT PRIMARY KEY,
VALUE VARCHAR(12))");
ps.close();conn.close();
Code snippets
JMS message sending
javax.jms.ConnectionFactory cf=(ConnectionFactory) mySessionCtx.lookup("java:comp/env/jms/QueueCF");
javax.jms.Connection conn=cf.createConnection();
conn.start();
javax.jms.Session session=conn.createSession(true, AcknowledgeMode.AUTO_ACKNOWLEDGE);
javax.jms.Destination dest=(Destination) mySessionCtx.lookup("java:comp/env/jms/Queue");
javax.jms.MessageProducer queueSender=session.createProducer(dest);
javax.jms.TextMessage tm=session.createTextMessage();
tm.setText(message+i);
queueSender.send(tm);
queueSender.close();
conn.close();
session.close();
Top Related