320 likes | 502 Views
EJB - laboratorium. Agenda. tworzenie i instalacja session oraz entity EJB dostęp do zdalnego obiektu Konfiguracja serwera aplikacji JBoss. Proces tworzenia aplikacji. interfejsy Beana (local, remote, home) implementacja Beana deskryptory (application, ejb-jar, serwera aplikacji)
E N D
Agenda • tworzenie i instalacja session oraz entity EJB • dostęp do zdalnego obiektu • Konfiguracja serwera aplikacji JBoss
Proces tworzenia aplikacji • interfejsy Beana (local, remote, home) • implementacja Beana • deskryptory (application, ejb-jar, serwera aplikacji) • kod klienta (jsp, servlet, pure Java) • złożenie (assemblacja – jar, war, ear)
Nazewnictwo – dobre praktyki <nazwaBeana> np. Fortune • implementacja bean sesyjnego- FortuneEJB • implementacja bean encji CMP- FortuneCMP • implementacja bean encji BMP- FortuneBMP • Interfejs zdalny beana sesyjnego- FortuneSB • Interfejs lokalny beana sesyjnego - FortuneSBLocal • Interfejs zdalny beana encji- FortuneEB • Interfejs lokalny beana encji - FortuneEBLocal • Interfejs domowy zdalny beana sesyjnego- FortuneSBHome • Interfejs domowy lokalny beana sesyjnego - FortuneSBLocalHome • Interfejs domowy zdalny beana encji- FortuneEBHome • Interfejs domowy lokalny beana encji - FortuneEBLocalHome
Fortune Teller Fortune Teller Jeśli istnieje wiele rekordów tylko jeden pobierany losowo! getFortune() Serwer Aplikacji FortuneTellerSB addFortune(String) klient FortuneEBLocal SQL/JDBC Baza Danych
FortuneTeller – kod bean-a sesyjnego publicclassFortuneTellerEJBimplementsSessionBean,FortuneTellerSB{ publicvoidejbCreate()throwsCreateException{} publicStringgetFortune(){ .... } publicStringaddFortune(String fortune){ .... } publicvoidsetSessionContext(SessionContextarg0)throws....{} publicvoidejbRemove()throws....{} publicvoidejbActivate()throws.... {} publicvoidejbPassivate()throws.... {} }
Fortune Teller – interfejsy • zdalny (remote) publicinterfaceFortuneTellerSB extends javax.ejb.EJBObject{ publicStringgetFortune() throws RemoteException; publicStringaddFortune(String fortune) throws RemoteException; } • domowy (home) publicinterfaceFortuneTellerSBHome extends javax.ejb.EJBHome{ FortuneTellerSBcreate()throwsCreateException, RemoteException; }
FortuneCMP – interfejs lokalny publicinterfaceFortuneEBLocalextendsjavax.ejb.EJBLocalObject{ publicStringgetText(); publicvoidsetText(Stringtext); publicIntegergetId(); }
FortuneCMP – lokalny interfejs domowy publicinterfaceFortuneEBLocalHomeextendsjavax.ejb.EJBLocalHome{ publicFortuneEBLocalcreate(Stringtext) throwsCreateException; publicjava.util.CollectionfindAll() throwsjavax.ejb.FinderException; publicFortuneEBLocalfindByPrimaryKey(Integerid) throwsjavax.ejb.FinderException; } • tworzenie • wyszukiwanie
FortuneCMP 1/2 publicabstractclassFortuneCMPimplementsEntityBean{ publicabstractIntegergetId(); publicabstractvoidsetId(Integerid); publicabstractStringgetText(); publicabstractvoidsetText(Stringtext); publicIntegerejbCreate(Stringtext)throwsCreateException{ //enumerator bean albo sekwencje z bazy danych ... setId(id); setText(text); returnnull; } publicvoidejbPostCreate(Stringtext)throwsCreateException{}
FortuneCMP 2/2 /*****Entitybeanspecificmethods********/ publicvoidsetEntityContext(EntityContextarg0) throws(...){} publicvoidunsetEntityContext()throws(...){} publicvoidejbLoad()throws(...){} publicvoidejbStore()throws(...){} publicvoidejbRemove()throws(...) {} publicvoidejbActivate()throws(...){} publicvoidejbPassivate()throws (...){} }
FortuneCMP – deskryptor ejb-jar.xml (...)<enterprise-beans> <entity> <ejb-name>FortuneCMP</ejb-name><local-home>edu.(...).FortuneEBLocalHome</local-home> <local>edu.(...).FortuneEBLocal</local><ejb-class>edu.(...).FortuneCMP</ejb-class> <persistence-type>Container</persistence-type><prim-key-class>java.lang.Integer</prim-key-class> <reentrant>False</reentrant> <cmp-version>2.x</cmp-version> <abstract-schema-name>FortuneCMP</abstract-schema-name> <cmp-field><field-name>id </field-name></cmp-field> <cmp-field><field-name>text </field-name></cmp-field> <primkey-field>id</primkey-field> </entity> (...)
FortuneCMP – deskryptorjbosscmp-jdbc.xml 1/2 <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE jbosscmp-jdbc PUBLIC "-//JBoss//DTD JBOSSCMP-JDBC 3.0//EN" "http://www.jboss.org/j2ee/dtd/jbosscmp-jdbc_3_0.dtd"> <jbosscmp-jdbc> <defaults> <datasource>java:/DefaultDS</datasource> <datasource-mapping>Hypersonic SQL</datasource-mapping> </defaults> <enterprise-beans> -------- opisy wszystkich CMP bean ------- na następnym slajdzie </enterprise-beans> </jbosscmp-jdbc>
FortuneCMP – deskryptorjbosscmp-jdbc.xml 2/2 <enterprise-beans> <entity> <ejb-name>FortuneCMP</ejb-name> <create-table>true</create-table> <remove-table>false</remove-table> <table-name>t_fortune</table-name> <cmp-field> <field-name>id</field-name> <column-name>id</column-name> </cmp-field> <cmp-field> <field-name>text</field-name> <column-name>text</column-name> </cmp-field> </entity> </enterprise-beans>
FortuneCMP – jboss.xml <?xml version="1.0" encoding="UTF-8"?><!DOCTYPE jboss PUBLIC "//JBoss//DTD JBOSS 3.0//EN http://www.jboss.org/j2ee/dtd/jboss_3_0.dtd"> <jboss> <enterprise-beans> <entity> <ejb-name>FortuneCMP</ejb-name> <local-jndi-name>ejb/FortuneCMP</local-jndi-name> </entity> <session> <ejb-name>MyFortuneSB</ejb-name> <jndi-name>ejb/FortuneSB</jndi-name> </session> </enterprise-beans> </jboss>
FortuneTeller – dostęp do EB 1/2 publicvoidejbCreate()throwsCreateException{ try{ InitialContextic=newInitialContext(); StringfortuneEBHomeJNDI= (String)ic.lookup("java:/comp/env/fortuneCMPRef"); java.lang.Objectobjref=ic.lookup(fortuneEBHomeJNDI); fortuneEBLocalHome=(FortuneEBLocalHome)objref; }catch(NamingExceptione){ thrownewCreateException( "could not get reference to entity bean"+e); } }
FortuneTeller – dostęp do EB 2/2 publicStringgetFortune(){ try{ Collection fortunes=fortuneEBLocalHome.findAll(); //w EJBQL można zrobić count()... if(fortunes.size()>0){ intwhich= (int)(Math.random()*fortunes.size()); FortuneEBLocalfortune= (FortuneEBLocal)fortunes.toArray( newFortuneEBLocal[0])[which]; returnfortune.getText(); }else logger.info("no fortunes in db - dummyFortune"); }catch(FinderExceptione){ logger.error("could not find fortune",e); } return"dummyFortune";}
Fortune Teller – ejb-jar.xml 1/2 <?xml version="1.0"?> <!DOCTYPE ejb-jar PUBLIC "-//Sun Microsystems, Inc.//DTD Enterprise JavaBeans 2.0//EN„ "http://java.sun.com/dtd/ejb-jar_2_0.dtd"> <ejb-jar> <display-name>FortuneBeans</display-name> <enterprise-beans> <.......................... Na następnej stronie..........> </enterprise-beans> <assembly-descriptor> <container-transaction> <method> <ejb-name>MyFortuneSB</ejb-name> <method-name>*</method-name> </method> <trans-attribute>Required</trans-attribute> </container-transaction> </assembly-descriptor> </ejb-jar>
Fortune Teller – ejb-jar.xml 2/2 <enterprise-beans> <session> <ejb-name>MyFortuneSB</ejb-name> <home>edu.agh.dsrg.sius.fortune.FortuneTellerSBHome</home> <remote>edu.agh.dsrg.sius.fortune.FortuneTellerSB</remote> <ejb-class>edu.agh.dsrg.sius.fortune.FortuneTellerEJB</ejb-class> <session-type>Stateless</session-type> <transaction-type>Container</transaction-type> <env-entry> <env-entry-name>fortuneCMPRef</env-entry-name> <env-entry-type>java.lang.String</env-entry-type> <env-entry-value>ejb/FortuneCMP</env-entry-value> </env-entry> </session> </enterprise-beans>
FortuneTeller – jboss.xml <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE jboss PUBLIC "-//JBoss//DTD JBOSS 3.0//EN" "http://www.jboss.org/j2ee/dtd/jboss_3_0.dtd"> <jboss> <enterprise-beans> <session> <ejb-name>MyFortuneSB</ejb-name> <jndi-name>ejb/FortuneSB</jndi-name> </session> </enterprise-beans> <resource-managers> </resource-managers> </jboss>
FortuneTeller – plik jar Struktura pliku jar: • /META-INF/jboss.xml • /META-INF/ejb-jar.xml • /edu/agh..../*.class (pliki klas zgodnie z nazwami pakietów) Uwaga na wielkość liter....
FortuneTeller – desktyptor aplikacji Deskryptor aplikacji – application.xml <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE application PUBLIC '-//Sun Microsystems, Inc.//DTD J2EE Application 1.2//EN' 'http://java.sun.com/j2ee/dtds/application_1_2.dtd'> <application> <display-name>Fortune</display-name> <module> <ejb>FortuneEJB.jar</ejb> </module> </application> Pominięto plik war dla aplikacji webowych
FortuneTeller – plik ear Struktura pliku ear: • /META-INF/application.xml • /FortuneEJB.jar nazwa zgodna z tą w deskryptorze!! • /FortuneWEB.war (opcjonalnie plik war – tu pomijamy)
JBoss - uruchomienie aplikacji • Serwer aplikacji (JBoss) • www.jboss.org - rozpakować i ustawić JAVA_HOME • u nas JBHome = np. /tmp/${id}/jboss-3.2.7 • uruchomienie {JBHome}/bin/run.sh • Plik aplikacji (ear lub jar) do • {JBHome}/server/default/deploy • Logi w • {JBHome}/server/default/log • Konsola admina – localhost:8080/jmx-console
JBoss - pokaz • kompletny kod *.java • zawartość plików jar, ear • uruchomienie JBoss’a • instalowanie aplikacji (deploying) • Analiza logów
Dostęp do Bean – aplikacja klienta, podstawowe kroki • Uzyskanie kontekstu JNDI • Pobranie referencji do obiektu Home Bean poprzez JNDI • Uzyskanie referencji do interfejsu Beana metodą create() wywołaną na interfejsie home • Wywołanie metody biznesowej beana
Kontekst JNDI InitialContext (jndi.properties) • INITIAL_CONTEXT_FACTORY • java.naming.factory.initial= org.jnp.interfaces.NamingContextFactory • PROVIDER_URL • java.naming.provider.url= jasmin.ics.agh.edu.pl:1099 try{ Context ctx =newInitialContext(); }catch(NamingExceptionne){;}
Dostęp do metod Beana try{ FortuneTellerSBHomehome=(FortuneTellerSBHome) ctx.lookup("java:/ejb/FortuneSB"); FortuneTellerSBfortuneTeller=home.create(); fortuneTeller.createFortune( „myfortune1” ); fortuneTeller.createFortune( „myfortune2” ); String myFortune = fortuneTeller.getFortune(); log( „ Found fortune:” + myFortune); }catch(NamingExceptione){; } catch(CreateExceptione){;}
Uruchomienie klienta • fortuneClient.jar • FortuneClient • FortuneSB • FortuneSBHome • plik jbossall-client.jar • zgodność wersji! • {JBOSS_HOME}/client/ • plik jndi.properties java -classpath jbossall-client.jar;fortuneClient.jar edu.agh.dsrg.sius.fortune.FortuneClient
FortuneTeller - pokaz • kompletny kod • uruchomienie i analiza • wyjścia programu • logów serwera aplikacji • integracja z loggerem Jboss’a
JBoss – uruchomienie aplikacji • Tworzmy jar, ear (jak poprzednio) • Konfigurujemy bazę danych • nazwa (taka jak w jbosscmp-jdbc.xml ) • domyślnie DefaultDB - Hypersonic (hsqldb-ds.xml) • Inne (Postgress, Oracle) – • pliki w {JBossRoot}/docs/examples/jca/*.xml • ustawić parametry – host, port, hasło – i do katalogu deploy • Klient się nie zmienia !!!!! – podstawa zaleta architektury wielowarstwowej
Projektowanie CMP - uwagi • Dostęp bezpośredni – specyfikacja zezwala ale nie używać – uzywać Fasady Sesyjnej • Przesyłanie danych – wzorzec Value Object • Generowanie kluczy głównych • XDoclet – programowanie deklaratywne - recepta na wiele ale nie na brak wiedzy • W EJB 3.0 wykorzystywane są tzw. anotacje