EJB Tutorial Kommentare

download EJB Tutorial Kommentare

of 11

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)