J2EE Part 2: Enterprise JavaBeans CSCI 4300 Images and code samples from jGuru EJB tutorial, .
EJB Tutorial Kommentare
-
Upload
chris-male -
Category
Documents
-
view
218 -
download
0
Transcript of EJB Tutorial Kommentare
-
8/3/2019 EJB Tutorial Kommentare
1/11
EJB3 Tutorial fr JBOSS5.1(http://www.jboss.org/ejb3/docs.html)
JBossAS5.html:You must set the JBOSS_HOME environment variable to run any of the tutorial
examples. Stimmt: Das Ant-File bezieht sich auf
Dann wird wie auf EJB3_TUTORIAL_HOME.html beschrieben: For easy referencethroughout the tutorials, we use the EJB3_TUTORIAL_HOME which points to the top level
folder where you downloaded the tutorials. Set it appropriately: wohl auch stimmen
Stateless_Beans.html: Chapter 2. Introduction to EJB3 Stateless Beans:To define this asthe remote interface of Calculator bean you either annotate the bean class and specify whatthe remote interfaces are, or you annotate each remote interface the bean class implements [email protected].
Die Alternative (fett) ist also:@Stateless@Remote(value=org.jboss.tutorial.stateless.bean.CalculatorRemote. class)publicclass CalculatorBean implements CalculatorRemote, CalculatorLocal{
Im Projekt callbacks (beschrieben unter Callbacks_and_Callback_Handlers.html) ist enweiteres Beispiel:@Stateless@Remote(CustomerDAO.class)()publicclass CustomerDAOBean implements CustomerDAO
{()
mitpublicinterface CustomerDAO{ int create(String first, String last, String street, String city, Stringstate, String zip);
Man kann fr Eclipse so vorgehen: Entweder Man erstellt ein neues EJB-Projekt mit der JBoss 5.0 Runtime. Dann muss
man nur die Surcen und die jndi.properties dort hin kopieren. Will man denClient aus Eclipse direkt starten, so muss die jndi.properties im src-Verzeichnis sein.
Man benutzt Ant: Dann gengt es ein einfaches Java-Projekt zu erstellen.Dann muss man die JBoss 5 Runtime hinzufgen. Die jndi.properties muss frAnt im Projektverzeichnis liegen ebenso wie die build.xml und die log4j.xml.
Blob_and_Clob_support_in_EJB3.html Man muss beachten, dass das META-INF Verzeichnis im Eclipse Java-Projekt im
Projektordner liegt und nicht im src-Ordner. Nur dort wird es von Ant gefunden mit:filesetdir=".">
Blobs and clobs must only be accessed within a transaction. Blobs and clobs are also notserializable or detachable.
Deswegen hat die EJB-Remote Interface-Methode long create(); auchkeinen Blob/Clob-Parameter. Man muss offenbar Daten roh bergeben unddann auf EJB-Seite ein Blob/Clob daraus basteln. Auch die Rckgabe
http://www.jboss.org/ejb3/docs.htmlhttp://www.jboss.org/ejb3/docs.html -
8/3/2019 EJB Tutorial Kommentare
2/11
fuktioniert nur ber einen Stream:ObjectInputStream ois = newObjectInputStream(blob.getBlobby().getBinaryStream());
Der Vollstndigkeit halber knnte man noch zeigen, wie aus dem BlobEntity2-Objekt danndie HashMap aus dem Blobby zu extrahieren ist (es ist ja nur der umgekehrte Weg des
Speicherns in der EJB):BlobEntity2 entity = test.findBlob2(blobId);ByteArrayInputStream bais = new ByteArrayInputStream(entity.getBlobby());try {
ObjectInputStream ois = new ObjectInputStream(bais);HashMap map2 = (HashMap) ois.readObject();System.out.println(map2.get("hello"));} catch (IOException e) {thrownew RuntimeException(e);}
und:String s = entity.getClobby();
System.out.println(s);
Caching_EJB3_Entities.html:JBoss EJB3 uses Hibernate as the JPA implementation whichhas support for a second-level cache.
Dazu in http://www.javalobby.org/java/forums/t48846.html: The second-level cache iscalled 'second-level' because there is already a cache operating for you in Hibernate for theduration you have a session open. () As implied above, this 'second-level' cache exists aslong as the session factory is alive. The second-level cache holds on to the 'data' for allproperties and associations (and collections if requested) for individual entities that aremarked to be cached.
Unbedingtbeachten: Make sure the "all" server configuration of JBossAS-5.x is running.Die in der persistence.xml genannte Klasse
org.hibernate.cache.jbc2.JndiMultiplexedJBossCacheRegionFactory ist in
der JBoss default-Konfiguration nicht vorhanden.Deswegen wird eineClassNotFoundException geworfen.
Und in der Tat: Wenn man das Caching ausstellt, sieht man, dass im zweiten Aufruf von
customer = tester2.findByCustomerId(customer.getId()); eine zweites Malein SELECT von Hibernate abgesetzt wird!
Callbacks_and_Callback_Handlers.html Ok, ist mal wieder nur sysout in den Callbacks. Immerhin, die Konfiguration als
Interceptor und die Regeln dort sind interessant. Auerdem sieht man hier ein JPA-typisches Idiom:public List findByLastName(String last)Gibt eine Liste von Costomer-Objekten zurck.
publicvoiddelete(List l)erwartet eine solche Liste. Damit die einzelnen Customer-Objekte removed werdenknnen, mssen sie erst attached werden: Dies geschieht mit Merge:for (Iterator it = l.iterator() ; it.hasNext() ; ){
Customer c = (Customer)it.next(); // First we merge the Customer that might have been detached.
Customer mergedCustomer = manager.merge(c); // Then we remove the customer manager.remove(mergedCustomer);
}
brigens: Wenn man die
@PreDestroy publicvoidpreDestroyCallback(){
mal in Aktion sehen will, muss man nur mal un- oder redeployen!
http://www.javalobby.org/java/forums/t48846.htmlhttp://www.javalobby.org/java/forums/t48846.html -
8/3/2019 EJB Tutorial Kommentare
3/11
Composite_Primary_Keys_for_Entities_in_EJB3.html: The @JoinTable must be defined onboth sides of the bi-directional relationship.
Kann ich nicht besttigen! Wenigstens dieses Beispiel funktioniert auch, wenn man,wie sonst auch, die @JoinTable nur auf der owning side angibt, also in class Flight. In
class Customer habe ich sie auskommentiert, redeployed und es funzt immer noch!Auch mit einer zustzlichen EJB-Methode:public Customer findCustomerById(CustomerPK cpk) throws Exception {
// TODO Auto-generated method stubreturnmanager.find(Customer.class, cpk);
}
und einem Aufruf im Client mitCustomer c = test.findCustomerById(new CustomerPK(0L,"Bill"));System.out.println(c);
Funzt es immer noch. Ausgabe:Customer [pk=CustomerPK [id=0, name=Bill]]
(ich habe Customer und CustomerPK noch eine ToString() spendiert)
Dependencies_in_EJB3.html The dependencies control the deployment of EJBs such that an EJB will not deploy until all of
it's dependencies have successfully deployed.
Soll heien es gibt einen Deploy-time Error:DEPLOYMENTS IN ERROR:Deployment "" is inerror due to the following reason(s): ** UNRESOLVED Demands'jboss.test:service=DependedOn' **
Ein einfaches Umbenennen der jboss-service.xml gengt. Injecting_EJB_in_Servlets.html
o Eclipse-technisch:
Kopiere die Ordner ear, ejbapp und webapp als einfache Ordner in daseinfache Java-Projekt.
build.xml wie blich im Projektordner ffne ejbapp/src/main/java und mache aus dem java-Ordner einen
Source-Folder: rechte Maustaste|new|Source Folder. Bei Folder nameBrowse. Hin zum java-Ordnerok
Analog fr webapp/src/main/java Extended_Persistence_Contexts.html: Usually, an EntityManager in JBoss EJB 3.0 lives
and dies within a JTA transaction.o Es ist doch der PersistenceContext, der lebt und stirbt mit einer JTA-
Transaction. Der EntityManager bleibt bestehen. In class StatelessSessionBeansieht man beim Debuggen, wie die EntityManager-Instanz dieselbe bleibt fr
jeden Aufruf von find().o This means that any persist(), merge(), or remove() method you call will not
actually result in a JDBC execution and thus an update of the database untilyou manually call EntityManager.flush().
Das wird hier allerdings nicht demonstriert. Stattdessen wird einer@Remove-Methode verwendet. Wie bekannt wirkt diese bei @StatefulSessionBeans, dass die Session beendet und aus dem peicher des ASentfernt wird. Damit ist klar, dass in diesem Moment auch die letztenausstehenden EntityManager-Aktionen ausgefhrt werden mssen.
o Hinweis: ShoppingCartBean.update2() und ShoppingCartBean.find() werdennie gerufen. Aber selbst, wenn man mal ShoppingCartBean.find() ruft, wird
-
8/3/2019 EJB Tutorial Kommentare
4/11
deswegen auch ohne EXTENDED-PersistenceContext nicht fters ein neuerEntityManager injiziert (s.o.)
Dependency_Injection.htmlo Interessanterweise hat das Calculator-Interface keine @Local-Annotation.
JBoss sagt beim Deployen:
CalculatorBean/local - EJB3.x Default Local Business InterfaceCalculatorBean/local-org.jboss.tutorial.injection.bean.Calculator - EJB3.x LocalBusiness Interface
genauso, als ob man an Interface Calculator @Local annotiert htte (habSausprobiert).
Dependency_Injection.htmlo Na das ist ja n bug:
@EJB private Calculator calculator; private Calculator set;
@EJB(beanName="CalculatorBean") publicvoidsetCalculator(Calculator c)
{ set = c;
}
Der AS denkt, dass diese Setter-Methode fr das Fieldprivate Calculator calculator;
ist. Darin wird aber tatschlich dieprivate Calculator set; injiziert. Folglichwird dieprivate Calculator calculator; nicht injiziert. Beim 2. Aufruf vonbuy() krachts dann mit einer NPE! Richtig ist es so:
@EJB
private Calculator calculator;
private Calculator set;
@EJB(beanName="CalculatorBean") publicvoidsetSet(Calculator set) {
this.set = set;}
o Noch etwas:@Resource(mappedName="DefaultDS")
private javax.sql.DataSource ds;
o
msste lauten :@Resource(mappedName="java:DefaultDS")
private javax.sql.DataSource ds;
o Und noch etwas:@Resource
javax.ejb.UserTransaction ut;
ist falsch!!! Es muss heissen:@Resource
javax.transaction.UserTransaction ut;
EJB3_Interceptors.html: We could have added more interceptor-class entries to bind
more interceptors, as shown here:
-
8/3/2019 EJB Tutorial Kommentare
5/11
org.jboss.tutorial.interceptor.bean.DefaultInterceptor
org.jboss.tutorial.interceptor.bean.AnotherInterceptor
o Ja, kann man machen. In der Konstellation dieses Projektes jedoch kommtweiter unten noch eine ejb-jar.xml-Deklaration zum ndern der Aufruf-Reihenfolge der Interceptors dazu. Man muss nun entweder:
AnotherInterceptor mit in die Liste aufnehmen oder Die Deklaration der Aufrufreihenfolge auskommentieren:
o The @Interceptors annotation can take an array of classes, so you can bindmore than one class-level interceptor this way, e.g.
@Stateless@Interceptors ({TracingInterceptor.class, SomeInterceptor.class})
Ja, kann man machen und diesmal gehts wirklich einfach so.o ctx.proceed();//Returns: the return value of the next method in
the chain
Frage: Wozu ist der Object-return Wert einer Interceptor-Methodeberhaupt gut?
o The call to ctx.proceed() causes the next object in the chain of interceptors to
get invoked. At the end of the chain of interceptors, the actual bean methodgets called. Es sollte aber schon auch erwhnt werden, dass es danach zum
Interceptor wieder zurck geht. Es heit ja auch @AroundInvoke!o Im AccountsConfirmInterceptor hat der Autor vergessen, auch die
QueueConnection zu schlieen. Das drfte die Ursache fr die manchmalauftretende Exception sein, bei der JBoss sagt: I'm closing a JMSconnection you left open. Please make sure you close all JMS
connections explicitly before letting them go out of scope!.Kann aber auch sein, dass das durch ein abgebrochenen Debug-Vorgangausgelst wurde.
o Method-level interceptors are in addition to default and class-levelinterceptors, meaning that when we callEmailSystemBean.sendBookingConfirmationMessage() we getintercepted by
DefaultInterceptor (default)
TracingInterceptor (class-level)
OtherInterceptor (class-level)
AccountsConfirmInterceptor (method-level)
Ok, es wre aber schon ok gewesen, explizit zu erwhnen, dassdie Bean-interne Interceptor-Methode NICHT gerufen wird unddurch den Method-level Interceptor ersetzt wurde.
-
8/3/2019 EJB Tutorial Kommentare
6/11
Hinweis: In der xml-Variante ist der beliebig. Beweis: Folgende ejb-ref.xmldeployt fehlerfrei:
org.jboss.tutorial.interceptor.bean.AccountsCancelInterceptor
jms/ConnFactory_bla
Setup fr Projekt interceptorJava7JBoss6Myo Die verwendeten Queues werden in der hornetq-jms.xml eingetragen unter
\server\default\deploy\hornetq z.B. so:
Achtung: Die Datei queue-example-service.xml aus Projektinterceptor\META-INF kann bedenkenlos entfernt werden. Sie dient
der Queue-Konfiguration fr JBoss 5.x. Achtung: Der fhrende / ist hier nicht ntig. Er ist auch etwas
irrefhrend, dass der lookup ohne / erfolgt:Queue queue = (Queue) ctx.lookup("queue/tutorial/email");
Achtung: Die bereits vorhandenen Queues DLQ und ExpiryQueuekann man nicht verwenden. Sie sind in hornetq-configuration.xmlals jms.queue.DLQjms.queue.ExpiryQueue
vorkonfiguriert.
-
8/3/2019 EJB Tutorial Kommentare
7/11
Eine Database Connection in Eclipse wre (mit Treiber unterM:\00632PowertrainingJEE\jboss-6.1.0.Final\common\lib):
Die InMemory-HSQLDB kann jedoch nur von 1 Nutzer zur gleichen Zeit benutztwerden. Deswegen besser:http://localhost:8090/jmx-console/HtmlAdaptor?action=inspectMBean&name=jboss%3Aservice%3DHypersonic%2Cdatabase%3DlocalDB
runter scrollen zu startDatabaseManager Button Invoke klicken.
Das hier hat auch nicht funktioniert. Es msste aber so hnlich gehen
16: jboss.xml_deployment_descriptor.html
http://localhost:8090/jmx-console/HtmlAdaptor?action=inspectMBean&name=jboss%3Aservice%3DHypersonic%2Cdatabase%3DlocalDBhttp://localhost:8090/jmx-console/HtmlAdaptor?action=inspectMBean&name=jboss%3Aservice%3DHypersonic%2Cdatabase%3DlocalDBhttp://localhost:8090/jmx-console/HtmlAdaptor?action=inspectMBean&name=jboss%3Aservice%3DHypersonic%2Cdatabase%3DlocalDBhttp://localhost:8090/jmx-console/HtmlAdaptor?action=inspectMBean&name=jboss%3Aservice%3DHypersonic%2Cdatabase%3DlocalDB -
8/3/2019 EJB Tutorial Kommentare
8/11
o Dran denken: Hier wieder die JBoss All-Konfiguration! (nur wegen clustered)o Dieses im Vergleich zu 27: Security_and_Transactions_in_EJB3.html
kompliziertere Verfahren braucht man vor allem deshalb, weil hier mehr alseine SecurityDomain verwendet werden soll. Deswegen mssen die properties-Dateien auch vom Standardnamen abweichend benannt werden und also in
einer zustzlichen Konfigurationsdatei registriert werden: jaas-test-config.xml.Und damit der Security-Dienst des JBoss berhaupt weiss, dass diese Dateidiese Konfigurationen enthlt, muss er wiederum mit der jboss-service.xmldarauf hingewiesen werden.
17: Quartz_scheduler_integration.htmlo Dem Build-Path des Projektes muss die quartz.jar aus
\common\lib hinzugefgt werdeno Was bedeutet der String: propertyValue = "0/2 * * * * ?"
Siehehttp://quartz-scheduler.org/documentation/quartz-2.x/tutorials/tutorial-lesson-06
Darin steht:Cron-Expressions are used to configure instances ofCronTrigger. Cron-Expressions are strings that are actuallymade up of seven sub-expressions, that describe individualdetails of the schedule. These sub-expression are separatedwith white-space, and represent:SecondsMinutesHoursDay-of-MonthMonth
Day-of-WeekYear (optional field)An example of a complete cron-expression is the string "0 0 12? * WED" - which means "every Wednesday at 12:00:00 pm".The '/' character can be used to specify increments to values.For example, if you put '0/15' in the Minutes field, it means'every 15th minute of the hour, starting at minute zero'. If youused '3/20' in the Minutes field, it would mean 'every 20thminute of the hour, starting at minute three' - or in other wordsit is the same as specifying '3,23,43' in the Minutes field. Notethe subtlety that "/35" does *notmean "every 35 minutes" - it
mean "every 35th minute of the hour, starting at minute zero"- or in other words the same as specifying '0,35'.The '?' character is allowed for the day-of-month and day-of-week fields. It is used to specify "no specific value". This isuseful when you need to specify something in one of the twofields, but not the other. See the examples below (andCronTrigger JavaDoc) for clarification.
18: JNDI_Bindings.htmlo In der META-INF/persistence.xml sind 2 JNDI Namen deklariert:
http://quartz-scheduler.org/documentation/quartz-2.x/tutorials/tutorial-lesson-06http://quartz-scheduler.org/documentation/quartz-2.x/tutorials/tutorial-lesson-06http://quartz-scheduler.org/documentation/quartz-2.x/tutorials/tutorial-lesson-06http://quartz-scheduler.org/documentation/quartz-2.x/tutorials/tutorial-lesson-06 -
8/3/2019 EJB Tutorial Kommentare
9/11
Muss man dieEntityManagerFactoryunbedingt mit deklarieren? In CustomerBean wirdnmlich nur der EntityManagerge-lookup-t!Antwort: Nein muss nicht! Ist nur zu Demonstrationszwecken, falls man sich einenEntityManager ber eine EntityManagerFactory holen will. 20: Message_Driven_Beans.html
o Man muss die META-INF/queue-example-service.xml einfach lschen, dannfunktionierts. Darin wird die nicht mehr verwendete Klasseorg.jboss.mq.server.jmx.Queue deklariert. Sie wird jetzt durch HornetQersetzt. Aber jene wiederum zu deklarieren ist nicht ntig. Alles, was man tunmuss ist:
Alle Deklarationen der Form@Depends("jboss.mq.destination:service=Queue,name=tutorial" )
lschen (hier: aus class ExampleMDB) In derMETA-INF/queue-example-service.xml (oder den MDBsselbst) nachgucken, wie die JNDI-Namen der Queues heien. Danndiese in der hornetq-jms.xml unter /server\default\deploy\hornetq mit dazu eintragen:
Message_Driven_Beans_with_deployment_descriptor.htmlo Funzt nicht. ToDo: HornetQ-JMS Beispiel von
http://docs.jboss.org/hornetq/2.2.5.Final/user-manual/en/html/using-jms.htmlzum Laufen bringen
24: EJB3_Entity_Relationships.htmlo Die Zeile
manager.persist(firstOne);
wird abgesetzt noch bevor das HashSet customers1 dem Flight onehinzugefgt wird. Dies soll wohl demonstrieren, dass in diesem Fall diecustomer nicht mit persistiert werden. Schreibt man diese Zeile direktunter oder bermanager.persist(second); so werden sie mit persistiert.
Im HSQL DatabaseManager:
SELECT *FROM FLIGHT_CUSTOMER_TABLE, CUSTOMER,FLIGHT,ADDRESSWHERE CUSTOMER.ID=FLIGHT_CUSTOMER_TABLE.CUSTOMER_IDAND FLIGHT.ID=FLIGHT_CUSTOMER_TABLE.FLIGHT_IDAND ADDRESS.ID= CUSTOMER.ADDRESS_ID
25: Using_resource_references_in_EJB3.htmlo ENC = Enterprise Naming Contexto Versuche:o 1. jboss.xml auskommentieren + ejb-jar.xml bearbeiten: NUR
A session bean on looks up stuff in the ENCENCBean
http://docs.jboss.org/hornetq/2.2.5.Final/user-manual/en/html/using-jms.htmlhttp://docs.jboss.org/hornetq/2.2.5.Final/user-manual/en/html/using-jms.html -
8/3/2019 EJB Tutorial Kommentare
10/11
org.jboss.tutorial.resource_ref.bean.TestENC org.jboss.tutorial.resource_ref.bean.TestENCBean StatelessContainer
Dies deklariert, dass dieTestENCBean unter dem JNDI-Namen ENCBean zu lookup-en ist.Client:
TestENC bean = (TestENC)new InitialContext().lookup("ENCBean/remote");
o 2. jboss.xml bearbeiten. NUR ENCBean ENCTest
+ ejb-jar.xml bearbeiten: NUR A session bean on looks up stuff in theENC ENCBean org.jboss.tutorial.resource_ref.bean.TestENC org.jboss.tutorial.resource_ref.bean.TestENCBean
Stateless Container
o 3.publicclass TestENCBean implements TestENC bearbeiten. Keine
Eintrge ber Ressourcen in jboss.xml oder ejb-jar.xml: Gobaler lookup auf dieDefault-Datasource:
Object obj = initCtx.lookup("java:DefaultDS");
o 4. Alle anderen Versuche z.B. nur jboss.xml bearbeiten, dass eine Ressource z.B.die Datasource einen neuen Namen bekommt, sind fehlgeschlagen
o
26: Secondary_Tables_for_EJB3_Entities.htmlo @SecondaryTable(name = "EMBEDDED_ADDRESS", join =
{@JoinColumn(name = "ADDRESS_ID")}) funktioniert so nicht! Im
Quelltextstehts noch anders:@Entity@Table(name = "CUSTOMER")@SecondaryTable(name = "EMBEDDED_ADDRESS")// FIXME @JoinColumn(name = "ADDRESS_ID")
Da wusste der Autor wohl auch nicht so richtigSo gehts;@Entity@Table(name = "CUSTOMER")@SecondaryTable(name ="EMBEDDED_ADDRESS",pkJoinColumns={@PrimaryKeyJoinColumn(name="ADDRESS_ID",referencedColumnName="ID")})
publicclass Customer implements java.io.Serializable
SQL zum berprfen:
-
8/3/2019 EJB Tutorial Kommentare
11/11
SELECT * FROM CUSTOMER,EMBEDDED_ADDRESSWHERE CUSTOMER.ID=EMBEDDED_ADDRESS.ADDRESS_ID
27: Security_and_Transactions_in_EJB3.htmlo Wenn man mit den properties-Dateien spielen mchte, so werden die Security-
Einstelllungen der domain nicht sofort nach dem redeployen wirksam. Erstduch einen Neustart des JBoss kann dies garantiert werden! (Leidvollerfahren)