Sie sind auf Seite 1von 11

EJB3 Tutorial fr JBOSS 5.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

<property name="jboss.home" value="${env.JBOSS_HOME}"/> <property name="jboss.server.config" value="default"/>

Dann wird wie auf EJB3_TUTORIAL_HOME.html beschrieben: For easy reference


throughout 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 as


the remote interface of Calculator bean you either annotate the bean class and specify what the remote interfaces are, or you annotate each remote interface the bean class implements with @javax.ejb.Remote. @Stateless @Remote(value=org.jboss.tutorial.stateless.bean.CalculatorRemote.class) public class CalculatorBean implements CalculatorRemote, CalculatorLocal {

Die Alternative (fett) ist also:

Im Projekt callbacks (beschrieben unter Callbacks_and_Callback_Handlers.html) ist en weiteres Beispiel:


@Stateless @Remote(CustomerDAO.class) () public class CustomerDAOBean implements CustomerDAO { ()

mit

public interface CustomerDAO { int create(String first, String last, String street, String city, String state, 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 den Client aus Eclipse direkt starten, so muss die jndi.properties im srcVerzeichnis 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 fr Ant 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:
fileset dir="."> <include name="META-INF/persistence.xml"/> </fileset> Blobs and clobs must only be accessed within a transaction. Blobs and clobs are also not serializable or detachable. Deswegen hat die EJB-Remote Interface-Methode long create(); auch

keinen Blob/Clob-Parameter. Man muss offenbar Daten roh bergeben und dann auf EJB-Seite ein Blob/Clob daraus basteln. Auch die Rckgabe

fuktioniert nur ber einen Stream:

ObjectInputStream ois = new ObjectInputStream(blob.getBlobby().getBinaryStream());

Der Vollstndigkeit halber knnte man noch zeigen, wie aus dem BlobEntity2-Objekt dann die 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) { throw new RuntimeException(e); }

und:
String s = entity.getClobby(); System.out.println(s);

Caching_EJB3_Entities.html:JBoss EJB3 uses Hibernate as the JPA implementation which


has support for a second-level cache.

Dazu in http://www.javalobby.org/java/forums/t48846.html: The second-level cache is


called 'second-level' because there is already a cache operating for you in Hibernate for the duration you have a session open. () As implied above, this 'second-level' cache exists as long as the session factory is alive. The second-level cache holds on to the 'data' for all properties and associations (and collections if requested) for individual entities that are marked to be cached. Unbedingt beachten: 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 eine ClassNotFoundException geworfen. Mal ein 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 JPAtypisches Idiom:
public List findByLastName(String last) Gibt eine Liste von Costomer-Objekten zurck. public void delete(List l) Und in der Tat: Wenn man das Caching ausstellt, sieht man, dass im zweiten Aufruf von customer = tester2.findByCustomerId(customer.getId()); eine zweites

erwartet eine solche Liste. Damit die einzelnen Customer-Objekte removed werden knnen, 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 public void preDestroyCallback() {

mal in Aktion sehen will, muss man nur mal un- oder redeployen!

Composite_Primary_Keys_for_Entities_in_EJB3.html: The @JoinTable must be defined on


both sides of the bi-directional relationship.

public Customer findCustomerById(CustomerPK cpk) throws Exception { // TODO Auto-generated method stub return manager.find(Customer.class, cpk); }

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:

und einem Aufruf im Client mit Funzt es immer noch. Ausgabe:

Customer c = test.findCustomerById(new CustomerPK(0L,"Bill")); System.out.println(c); 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 "<UNKNOWN jboss.j2ee:jar=jboss-ejb3-tutorialdependency.jar,name=HasXmlMBeanDependencyBean,service=EJB3>" is in error 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 das einfache 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 name Browse. 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 JTATransaction. Der EntityManager bleibt bestehen. In class StatelessSessionBean sieht 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 until you manually call EntityManager.flush(). Das wird hier allerdings nicht demonstriert. Stattdessen wird einer @Remove-Methode verwendet. Wie bekannt wirkt diese bei @Stateful SessionBeans, dass die Session beendet und aus dem peicher des AS entfernt wird. Damit ist klar, dass in diesem Moment auch die letzten ausstehenden EntityManager-Aktionen ausgefhrt werden mssen. o Hinweis: ShoppingCartBean.update2() und ShoppingCartBean.find() werden nie gerufen. Aber selbst, wenn man mal ShoppingCartBean.find() ruft, wird

deswegen auch ohne EXTENDED-PersistenceContext nicht fters ein neuer EntityManager injiziert (s.o.) Dependency_Injection.html o Interessanterweise hat das Calculator-Interface keine @Local-Annotation. JBoss sagt beim Deployen:
CalculatorBean/local - EJB3.x Default Local Business Interface CalculatorBean/localorg.jboss.tutorial.injection.bean.Calculator - EJB3.x Local Business Interface

genauso, als ob man an Interface Calculator @Local annotiert htte (habS ausprobiert). Dependency_Injection.html o Na das ist ja n bug:
@EJB private Calculator calculator; private Calculator set;

@EJB(beanName="CalculatorBean") public void setCalculator(Calculator c) { set = c; }

Der AS denkt, dass diese Setter-Methode fr das Field


private Calculator calculator; ist. Darin wird aber tatschlich die private Calculator set; injiziert. Folglich wird die private Calculator calculator; nicht injiziert. Beim 2. Aufruf von buy() krachts dann mit einer NPE! Richtig ist es so: @EJB private Calculator calculator; private Calculator set; @EJB(beanName="CalculatorBean") public void setSet(Calculator set) { this.set = set; }

o Noch etwas: o

@Resource(mappedName="DefaultDS") private javax.sql.DataSource ds;

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:

<interceptorclass>org.jboss.tutorial.interceptor.bean.DefaultInterceptor</interceptorclass> <interceptorclass>org.jboss.tutorial.interceptor.bean.AnotherInterceptor</interceptorclass>

o Ja, kann man machen. In der Konstellation dieses Projektes jedoch kommt weiter unten noch eine ejb-jar.xml-Deklaration zum ndern der AufrufReihenfolge der Interceptors dazu. Man muss nun entweder: AnotherInterceptor mit in die Liste aufnehmen oder Die Deklaration der Aufrufreihenfolge auskommentieren:
<!-<interceptor-order>

</interceptor-order> -->

o The @Interceptors annotation can take an array of classes, so you can bind more 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-Methode berhaupt 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 method gets 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 manchmal auftretende Exception sein, bei der JBoss sagt: I'm closing a JMS
connection 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-Vorgang ausgelst wurde. o Method-level interceptors are in addition to default and class-level
interceptors, meaning that when we call EmailSystemBean.sendBookingConfirmationMessage() we get intercepted by DefaultInterceptor (default) TracingInterceptor (class-level) OtherInterceptor (class-level) AccountsConfirmInterceptor (method-level)

Ok, es wre aber schon ok gewesen, explizit zu erwhnen, dass die Bean-interne Interceptor-Methode NICHT gerufen wird und durch den Method-level Interceptor ersetzt wurde.

Hinweis: In der xml-Variante ist der <res-ref-name> beliebig. Beweis: Folgende ejb-ref.xml deployt fehlerfrei:

<interceptor> <interceptorclass>org.jboss.tutorial.interceptor.bean.AccountsCancelInterceptor</interc eptor-class> <resource-ref> <res-ref-name>jms/ConnFactory_bla</res-ref-name>

Setup fr Projekt interceptorJava7JBoss6My o Die verwendeten Queues werden in der hornetq-jms.xml eingetragen unter <JBOSS_HOME>\server\default\deploy\hornetq z.B. so: <queue name="email"> <entry name="/queue/tutorial/email"/> </queue> Achtung: Die Datei queue-example-service.xml aus Projekt interceptor\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");

address> <expiry-address>jms.queue.ExpiryQueue</expiry-address>

Achtung: Die bereits vorhandenen Queues DLQ und ExpiryQueue kann man nicht verwenden. Sie sind in hornetq-configuration.xml als <dead-letter-address>jms.queue.DLQ</dead-letter-

vorkonfiguriert.

Eine Database Connection in Eclipse wre (mit Treiber unter


M:\00632PowertrainingJEE\jboss-6.1.0.Final\common\lib):

Die InMemory-HSQLDB kann jedoch nur von 1 Nutzer zur gleichen Zeit benutzt werden. 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

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 als eine SecurityDomain verwendet werden soll. Deswegen mssen die propertiesDateien 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 Datei diese Konfigurationen enthlt, muss er wiederum mit der jboss-service.xml darauf hingewiesen werden. 17: Quartz_scheduler_integration.html o Dem Build-Path des Projektes muss die quartz.jar aus <JBOSS_HOME>\common\lib hinzugefgt werden o Was bedeutet der String: propertyValue = "0/2 * * * * ?" Siehe http://quartz-scheduler.org/documentation/quartz2.x/tutorials/tutorial-lesson-06

Darin steht: Cron-Expressions are used to configure instances of CronTrigger. Cron-Expressions are strings that are actually made up of seven sub-expressions, that describe individual details of the schedule. These sub-expression are separated with white-space, and represent: Seconds Minutes Hours Day-of-Month Month Day-of-Week Year (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 you used '3/20' in the Minutes field, it would mean 'every 20th minute of the hour, starting at minute three' - or in other words it is the same as specifying '3,23,43' in the Minutes field. Note the subtlety that "/35" does *not mean "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-ofweek fields. It is used to specify "no specific value". This is useful when you need to specify something in one of the two fields, but not the other. See the examples below (and CronTrigger JavaDoc) for clarification. 18: JNDI_Bindings.html o In der META-INF/persistence.xml sind 2 JNDI Namen deklariert:

<properties> <property name="jboss.entity.manager.jndi.name" value="java:/jboss-ejb3-tutorial-jndibinding-EntityManager"/>

<property name="jboss.entity.manager.factory.jndi.name" value="java:/jboss-ejb3-tutorial-jndibinding-EntityManagerFactory"/> </properties> Muss man die EntityManagerFactory unbedingt mit deklarieren? In CustomerBean nmlich nur der EntityManager ge-lookup-t!

wird

Antwort: Nein muss nicht! Ist nur zu Demonstrationszwecken, falls man sich einen EntityManager ber eine EntityManagerFactory holen will. 20: Message_Driven_Beans.html o Man muss die META-INF/queue-example-service.xml einfach lschen, dann funktionierts. Darin wird die nicht mehr verwendete Klasse org.jboss.mq.server.jmx.Queue deklariert. Sie wird jetzt durch HornetQ ersetzt. Aber jene wiederum zu deklarieren ist nicht ntig. Alles, was man tun muss ist: Alle Deklarationen der Form
@Depends ("jboss.mq.destination:service=Queue,name=tutorial") lschen (hier: aus class ExampleMDB)

<queue name="tutorial"> <entry name="/queue/tutorial/example"/> </queue> <queue name="defaultedtutorial"> <entry name="/queue/tutorial/defaultedexample"/> </queue>

In der META-INF/queue-example-service.xml (oder den MDBs selbst) nachgucken, wie die JNDI-Namen der Queues heien. Dann diese in der hornetq-jms.xml unter <JBOSS_HOME>/ server\default\deploy\hornetq mit dazu eintragen:

Message_Driven_Beans_with_deployment_descriptor.html o Funzt nicht. ToDo: HornetQ-JMS Beispiel von http://docs.jboss.org/hornetq/2.2.5.Final/user-manual/en/html/using-jms.html zum Laufen bringen 24: EJB3_Entity_Relationships.html o Die Zeile
manager.persist(firstOne);

wird abgesetzt noch bevor das HashSet customers1 dem Flight one hinzugefgt wird. Dies soll wohl demonstrieren, dass in diesem Fall die customer nicht mit persistiert werden. Schreibt man diese Zeile direkt unter oder ber manager.persist(second); so werden sie mit persistiert. Im HSQL DatabaseManager: SELECT * FROM FLIGHT_CUSTOMER_TABLE, CUSTOMER,FLIGHT,ADDRESS WHERE CUSTOMER.ID=FLIGHT_CUSTOMER_TABLE.CUSTOMER_ID AND FLIGHT.ID=FLIGHT_CUSTOMER_TABLE.FLIGHT_ID AND ADDRESS.ID= CUSTOMER.ADDRESS_ID 25: Using_resource_references_in_EJB3.html o ENC = Enterprise Naming Context o Versuche: o 1. jboss.xml auskommentieren + ejb-jar.xml bearbeiten: NUR

<enterprise-beans> <session> <description>A session bean on looks up stuff in the ENC</description> <ejb-name>ENCBean</ejb-name>

<business-remote>org.jboss.tutorial.resource_ref.bean.TestENC</businessremote> <ejb-class>org.jboss.tutorial.resource_ref.bean.TestENCBean</ejb-class> <session-type>Stateless</session-type> <transaction-type>Container</transaction-type> </session> </enterprise-beans> Dies deklariert, dass die TestENCBean unter dem JNDI-Namen ENCBean zu lookup-en ist.

Client:
TestENC bean = (TestENC)new InitialContext().lookup("ENCBean/remote"); <enterprise-beans> <session> <ejb-name>ENCBean</ejb-name> <jndi-name>ENCTest</jndi-name> </session> </enterprise-beans>

o 2. jboss.xml bearbeiten. NUR

+ ejb-jar.xml bearbeiten: NUR

<enterprise-beans> <session> <description>A session bean on looks up stuff in the ENC</description> <ejb-name>ENCBean</ejb-name> <businessremote>org.jboss.tutorial.resource_ref.bean.TestENC</business-remote> <ejb-class>org.jboss.tutorial.resource_ref.bean.TestENCBean</ejbclass> <session-type>Stateless</session-type> <transaction-type>Container</transaction-type> </session> </enterprise-beans> o 3. public class TestENCBean implements TestENC bearbeiten. Keine

Eintrge ber Ressourcen in jboss.xml oder ejb-jar.xml: Gobaler lookup auf die Default-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.html o @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 richtig So gehts;


@Entity @Table(name = "CUSTOMER") @SecondaryTable(name = "EMBEDDED_ADDRESS",pkJoinColumns={@PrimaryKeyJoinColumn(name="ADDRESS_ID", referencedColumnName="ID")}) public class Customer implements java.io.Serializable

SQL zum berprfen:

SELECT * FROM CUSTOMER,EMBEDDED_ADDRESS WHERE CUSTOMER.ID=EMBEDDED_ADDRESS.ADDRESS_ID

27: Security_and_Transactions_in_EJB3.html o Wenn man mit den properties-Dateien spielen mchte, so werden die SecurityEinstelllungen der domain nicht sofort nach dem redeployen wirksam. Erst duch einen Neustart des JBoss kann dies garantiert werden! (Leidvoll erfahren)

Das könnte Ihnen auch gefallen