Beispiel: Stateless Session Bean (JBoss 4.0)
Inhalt:
Anlegen der Enterprise Application
Anlegen der GeometricModelBean
Anlegen des WebClient
Server einrichten
Anlegen des Application Clients
Ausführen des Application Clients
Export des Workspace
Re-Import
Beispiel für eine Stateless Session Bean, auf die per Webclient und mittels Application Client
zugegriffen wird.
Die Deployanleitung bezieht sich auf JBoss 4.0.3.
Hier gibt es das WebSphere-Projekt zum Download (dies ist ein Projektaustausch-Export, die Importanleitung
findet man am Ende dieses Dokuments): Stateless.ear
ACHTUNG: Nach dem Import XDoclet-Builder im EJB- und im Web-Projekt aktivieren ! (siehe Importanleitung)
Aufbau des Beispieles
a) Bean-Klasse mit Local und Remote-Interfaces
b) Webclient: JSP-Seite
c) WebClient: Servlet
d) App-Client
Anlegen der Application
Schritt 1: Über "File" -> "New" -> "Other..." gelangen wir in den Wizard zum Hinzufügen von neuen Komponenten.
wir wählen im Zweig "J2EE" ein "Enterprise Application Project".
Schritt 2: In dem erscheinenden Dialog geben wir dem Projekt einen Namen und wählen den JBoss 4.0-Server aus.
Auf "Next" klicken.
Schritt 3: Facets konfigurieren: hier müssen wir nur sicherstellen dass als "EAR version" "1.4" gewählt ist.
Schritt 4: Modulprojekte zufügen. Dazu auf den Button "New Module..." klicken. Wir wünschen uns ein EJB-Projekt, einen
Application Client und einen Webclient. Connectorprojekte werden wir im Rahmen dieses Praktikums nie anfassen.
Schritt 4: Zurück im Hauptdialog stellen wir sicher dass diese drei Module ausgewählt sind.
Man klickt auf "Finish" und hat folgende J2EE-Hierarchie angelegt:
Anlegen der StatelessBean
Schritt 1: In der J2EE-Hierarchie den Knoten "EJB Projects" \ "StatelessEJB" \ "StatelessEJB" \ "Session-Beans" wählen.
Rechtsklick, im Contextmenü den Punkt "New" -> "Other..." wählen.
Schritt 2: Eine Session-Bean zufügen:
Schritt 3: Wir vergeben einen Namespace und einen Bean-Namen.
Schritt 4: Hier können wir alles auf den Defaults belassen.
Schritt 5: Auch hier die Defaults:
Nach dem Klick auf "Finish" tut erstmal XDoclet seine Arbeit und erzeugt die Bean-Implementationsklassen für uns.
Die J2EE-Hierarchie sieht jetzt so aus:
Schritt 6: EJB-Referenzen vorbereiten:
Da wir auf die Bean vom ApplicationClient und vom WebClient aus zugreifen wollen müssen wir EJB-Referenzen erzeugen.
Dazu folgende XDoclet-Tags in den Klassenkommentar einfügen:
* @ejb.ejb-ref
* ejb-name="GeometricModel"
* view-type="local"
* name="ejb/GeometricModelLocal"
* @ejb.ejb-ref
* ejb-name="GeometricModel"
* view-type="remote"
* name="ejb/GeometricModel"
Schritt 7: Vorbereiten der Business-Methoden:
Die beiden Business-Methoden werfen eine eigene Exception. Diese wird dem Projekt so zugefügt:
Das Package "com.knauf.ejb.stateless" im Folder "StatelessEJB\ejbModule" im Projekt "StatelessEJB" auswählen. Rechtsklick,
"New" -> "Class". Eine Klasse namens "InvalidParameterException" zufügen, die von "java.lang.Exception abgeleitet ist.
Schritt 8: Hinzufügen der Business-Methoden:
Die Bean-Klasse "GeometricModelBean" wird bearbeitet und zwei Methoden "computeCuboidVolume" und "computeCuboidSurface" zugefügt.
Der Assistent hat uns bereits eine Methode "foo" deklariert, die wir überarbeiten.
Zu beachten: des XDoclet-Tag "@ejb.interface-method" wird so abgeändert dass der Viewtype auf "both" steht.
/**
*
* Berechen des Volumens eines Quaders.
*
* @param a
* Länge der Seite a, > 0
* @param b
* Länge der Seite b, > 0
* @param c
* Länge der Seite c, > 0
* @return Das Volumen des Quaders = a * b * c
* @exception InvalidParameterException
* Falls a oder b oder c <= 0 ist.
*
* <!-- begin-xdoclet-definition -->
*
* @ejb.interface-method view-type="both" <!-- end-xdoclet-definition -->
* @generated
*/
public double computeCuboidVolume(double a, double b, double c)
throws InvalidParameterException {
logger.info("computeCuboidVolume mit a = " + a + ", b = " + b
+ ", c = " + c);
if (a <= 0 || b <= 0 || c <= 0)
throw new InvalidParameterException("Seitenlänge <= 0");
return a * b * c;
}
Anlegen des Webclients
JSP anlegen
Den Ordner "Dynamic Web Projects" -> "StatelessWeb" -> "StatelessWeb" -> "WebContent" auswählen und per Rechtsklick eine
JSP zufügen.
Im ersten Schritt des Assistenten der JSP den Namen "GeometricModelTest.jsp" geben (die Fehler-Icons
im Screenshot liegen nur daran dass keine Internetverbindung bestand und deshalb xml-Dateien nicht validiert wurden.
In Schritt 2 verwenden wir das vorgeschlagene Template.
Jetzt noch auf "Finish" klicken und den JSP-Code einbauen (was zu Compilefehlern führt weil die EJB-Klassen vom Compiler
nicht gefunden werden). Beim JSP-Code die Unterschiede zu den anderen Beispielen beachten: wir verwenden hier direkt die
vom Bean-Assistenten generierte Hilfsklasse "GeometricModelUtil" um an die Home-Interfaces der Beans zu gelangen.
Hinzufügen der Referenz auf das EJB, damit der Compiler arbeiten kann: Auf "Dynamic Web Projects" -> "StatelessWeb" einen
Rechtsklick ausführen und in die "Properties" gehen. Im Punkt "Java JAR Dependencies" aktivieren wir die Referenz auf
"StatelessEJB.jar".
ACHTUNG: Das folgende gilt nur wenn kein Servlet definiert wird !
Jetzt müssen wir noch eine Referenz auf die EJB anlegen. Auf dem JBoss könnten wir sie zwar auch direkt über ihren JNDI-Namen
ansprechen, aber das wäre unsauber.
Wir öffnen die Datei "Dynamic Web Projects" -> "StatelessWeb" -> "StatelessWeb" -> "WebContent" -> "WEB-INF" -> "web.xml"
und fügen folgendes Stück nach dem Element "welcome-file-list" ein:
<ejb-ref>
<ejb-ref-name>ejb/GeometricModel</ejb-ref-name>
<ejb-ref-type>Session</ejb-ref-type>
<home>com.knauf.ejb.stateless.GeometricModelHome</home>
<remote>com.knauf.ejb.stateless.GeometricModel</remote>
<ejb-link>GeometricModel</ejb-link>
</ejb-ref>
<ejb-local-ref>
<ejb-ref-name>ejb/GeometricModelLocal</ejb-ref-name>
<ejb-ref-type>Session</ejb-ref-type>
<local-home>com.knauf.ejb.stateless.GeometricModelLocalHome</local-home>
<local>com.knauf.ejb.stateless.GeometricModelLocal</local>
<ejb-link>GeometricModel</ejb-link>
</ejb-local-ref>
Würden wir hier anderen Namen vergeben, könnten wir die EJB z.B. auch als "java:comp/env/ejb/EtwasKomplettAnderes" ansprechen.
Servlet anlegen:
Wir gehen auf "Dynamic Web Projects" -> "StatelessWeb" und erstellen mit Rechtsklick -> "New" -> "Servlet" ein neues Servlet.
Package und Name sollten so aussehen:
Im nächsten Schritt wird eine URL angegeben unter der das Servlet später angesprochen werden soll. Ich habe den Default
"/GeometricModelServlet" entfernt und durch "/servlet/GeometricModelServlet" ersetzt. Diese Angabe finden wir in "web.xml"
wieder.
In Schritt 3 belassen wir alles auf den Defaults.
Damit sind wir fertig. Zu beachten sind die XDoclet-Einträge im Header des Servlets. Dies führt zu einem neuen XDoclet-Task "webdoclet",
der die Dateien "web.xml" und "jboss-web.xml" befüllt. Das Ergebnis sieht so aus:
Dieser "webdoclet"-Task scheint übrigens erst nach dem Hinzufügen des Servlets zugeschlagen zu haben. Nur mit der JSP-Seite
hat die Anwendung und der Bean-Zugriff ebenfalls funktioniert, "web.xml" hätten wir aber per Hand editieren müssen.
Damit die EJB-Referenzen funktionieren müssen wir sie hier in den Klassenkopf des Servlets eintragen:
* @web.servlet
* name="GeometricModelServlet"
* display-name="GeometricModelServlet"
*
* @web.servlet-mapping
* url-pattern="/servlet/GeometricModelServlet "
* @web.ejb-ref
* name="ejb/GeometricModel"
* type="Session"
* home="com.knauf.ejb.stateless.GeometricModelHome"
* remote="com.knauf.ejb.stateless.GeometricModel"
* link="GeometricModel"
* @web.ejb-local-ref
* name="ejb/GeometricModelLocal"
* type="Session"
* home="com.knauf.ejb.stateless.GeometricModelLocalHome"
* local="com.knauf.ejb.stateless.GeometricModelLocal"
* link="GeometricModel"
Das Ergebnis dieser Deklaration finden wir in "web.xml" wieder.
Server einrichten
Das Webprojekt auswählen ("Dynamic Web Projects" -> "StatelessWeb"), Rechtsklick -> "Run As..." -> "Run on Server" wählen.
Im Assistenten wählen wir den JBoss-Server.
In Schritt 2 belassen wir die Defaults. In Schritt 3 sollte unsere Anwendung bereits ausgewählt sein.
Dass links das Application Client Project auftaucht ist ein Bug (siehe hier:
https://bugs.eclipse.org/bugs/show_bug.cgi?id=119584),
es ist sowieso nicht wählbar.
Wir klicken auf "Finish". Die Enterprise Application wird auf den JBoss deployed und der Server wird gestartet.
Falls das ohne Fehlermeldungen klappt erscheint ein integriertes Browserfenster mit einem Verzeichnislisting der URL
http://localhost:8080/StatelessWeb/.
Wir wählen hier unsere Seite "GeometricModelTest.jsp" aus und können Berechnungen ausführen.
Den neu angelegten Server erreichen wir über die Karteikarte "Servers" im unteren Bereich der Anwendung.
Nachdem wir die Anwendung jetzt zum ersten Mal deployed haben können wir sie in Zukunft nach einer Änderung aktualisieren
indem wir den Server auswählen und im Contextmenü "Publish" wählen. Kurz nach einem Publish sollte auf der Karteikarte
"Console", auf der die JBoss-Ausgabe landet, eine Ausgabe über ein Neu-Laden der Anwendung auftauchen.
Eine Anleitung wie das Logging für den JBoss zu konfigurieren ist findet sich hier.
Anlegen des Application Clients
In der J2EE-Hierarchie "Application Client Projects" \ "StatelessClient" auswählen. Rechtsklick, und dann
"New" -> "Class" wählen.
Wie im Webclient muss hier eine Abhängigkeit zum EJB-Projekt definiert werden (Rechtsklick auf "StatelessClient",
"Properties" wählen). Man wählt unter "J2EE Module Dependencies" \ "J2EE Modules" das Bean-JAR aus.
Jetzt den Code einfügen. Da wir uns im Gegensatz zum SunAppServer und WebSphere hier selbst um die Initialisierung des
Clients kümmern müssen, müssen wir die Verbindungsinfos zum JNDI (für das Bean-Lookup) selbst anlegen.
Dazu verwenden wir folgendes Codestück:
Properties props = new Properties();
props.setProperty(Context.INITIAL_CONTEXT_FACTORY, "org.jnp.interfaces.NamingContextFactory");
props.setProperty(Context.URL_PKG_PREFIXES, "org.jboss.naming.client");
props.setProperty(Context.PROVIDER_URL, "jnp://localhost:1099");
props.setProperty("j2ee.clientName", "StatelessClient");
InitialContext initialContext = new InitialContext(props);
Object homeref = initialContext.lookup(GeometricModelHome.COMP_NAME);
GeometricModelHome geometricModelHome = (GeometricModelHome) PortableRemoteObject.narrow(homeref, GeometricModelHome.class);
GeometricModel geometricModel = geometricModelHome.create();
Wichtig ist hier dass wir die Property j2ee.clientName
(scheint JBoss-spezifisch zu sein)
auf den Namen des Projekts (bzw. auf den Wert des Elements display-name
in "application-client.xml") setzen !
Die Lookup-Methoden in der vom WTP-Plugin erzeugten Hilfsklasse "GeometricModelUtil" können wir leider
nicht verwenden, da diese immer direkt den JNDI-Namen der Bean verwenden, statt über EJB-Referenzen zu gehen.
Nur die Konstante GeometricModelHome.COMP_NAME
können wir benutzen, diese hat
nämlich den Wert java:comp/env/ejb/GeometricModel
.
Die EJB-Referenzen müssen im Deployment-Deskriptor des Clients deklariert werden. Leider
kann uns XDoclet hier nicht mehr helfen, wir müssen also selbst Hand anlegen.
Dazu die Datei "application-client.xml" öffnen und folgendes einfügen:
<ejb-ref>
<ejb-ref-name>ejb/GeometricModel</ejb-ref-name>
<ejb-ref-type>Session</ejb-ref-type>
<home>com.knauf.ejb.stateless.GeometricModelHome</home>
<remote>com.knauf.ejb.stateless.GeometricModel</remote>
<ejb-link>GeometricModel</ejb-link>
</ejb-ref>
Jetzt noch die Main class in "Application Client Projects" -> "StatelessClient" ->
"appClientModule\META-INF\MANIFEST.MF" eintragen und nicht mal der J2EE-Verifier hat etwas zu meckern:
Manifest-Version: 1.0
Class-Path: StatelessEJB.jar
Main-Class: com.knauf.ejb.stateless.GeometricModelApplicationClient
Ausführen des Application Clients
Manueller Start:
Zum Start benötigen wir folgenden Aufruf:
java -cp C:\...\jboss-4.0.2\client\jbossall-client.jar;StatelessClient.jar com.knauf.ejb.stateless.GeometricModelApplicationClient
Zu beachten ist dass wir die Datei "jbossall-client.jar" aus dem Client-Verzeichnis der JBoss-Installation in den Classpath aufnehmen.
Ausführen aus Eclipse heraus:
Wir wählen das Application-Client-Projekt aus und gehen im Menü "Run" auf "Run As...". Der Dialog für die diversen Launch-Konfigurationen
öffnet sich. Wir wählen links den Punkt "Java Application" und fügen durch Klick auf "New" eine neue Konfiguration zu.
Die Konfiguration bekommt den Namen "StatelessClient", als MainClass wird natürlich "com.knauf.ejb.stateless.GeometricModelApplicationClient"
gewählt. Auf der Registerkarte "Classpath" finden wir auch die benötigten JBoss-Libraries wieder.
Nach dem Klick auf "Run" läuft unsere Anwendung los, und wir sollten auf der JBoss-Konsole ein paar Ausgaben über die Bean-Methoden-Aufrufe
sehen. Damit wir die Ausgabe unseres Clients sehen müssen wir die entsprechende Konsole auswählen (siehe Screenshot):
Export des Workspace
Um den kompletten Workspace so zu exportieren, dass er auf einem anderen Rechner wieder importiert
werden kann, im Menü "File" den Punkt "Export..." wählen. Als "export destination" wählen wir
"EAR file".
Im nächsten Schritt die zu exportierende EAR-Anwendung "Stateless" auswählen und eine Zieldatei für den Export
angeben. Ich würde empfehlen diese Datei genauso zu benennen wie die EAR-Anwendung da der Dateiname beim Import
als Vorschlag für die neu zu erstellen EAR-Anwendung verwendet wird.
Wichtig: den Haken bei "Export source files" setzen !
Fertig !
Re-Import:
Man öffnet Eclipse und wählt beim Start am sichersten ein leeres Verzeichnis als Arbeitsbereich.
Alternativ könnte man die bestehenden Projekte auch löschen und erspart sich damit die Konfiguration des
Arbeitsbereichs (Anlegen des Servers).
Zuallererst einmal legen wir den Server wieder an (da der Arbeitsbereich ja uninitialisiert ist).
Die Anleitung gibt es hier.
Im Menü "File" ruft man "Import..." auf. Man wählt wiederum die Quelle "EAR file".
Im nächsten Schritt wählt man die Quelldatei (unsere eben exportierte Zip-Datei), den Namen der Ziel-EAR-Anwendung
("Stateless"), und den eben angelegten Target-Server.
Unsere Anwendung verfügt über keine Hilfsprojekte, wir können den nächsten Schritt also ignorieren.
Im letzten Schritt wählen wir die gewünschten Module aus.
Nachbearbeitung: Leider geht die Einstellung darüber verloren dass der XDoclet-Builder
aktiviert war. Im Gegensatz zu WTP 0.7 müssen wir jetzt aber nichts mehr an der ".project"-Datei schrauben,
sondern können dies über schöne bunte Dialoge erledigen.
Wir gehen in die Properties des EJB-Projekts und wählen "Project Facets" aus.
Auf "Add/Remove Project Facets..." klicken. Wir setzen den Haken vor "EJBDoclet (XDoclet)":
Dass der Builder jetzt aktiviert ist können wir in den Properties des Projekts nachprüfen (vorher muss
der Properties-Dialog einmal mit OK geschlossen werden !):
Das gleiche müssen wir für das Web-Projekt wiederholen: hier muss eine "Project Facet" "WebDoclet (XDoclet)"
zugefügt werden:
Version 1.1.0.0, Stand 29.12.2005
Historie:
1.0.0.0 (08.09.2005): Erstellt
1.0.1.0 (27.10.2005): Screenshot für JAR-Dependency an WPT 1.0M8 angepaßt.
Import: Dokumentation der zu aktivierenden XDoclet-Builder.
1.0.1.1 (24.11.2005): Anleitung für Projekt-Erstellen war noch WTP 0.7.
1.0.2.0 (27.11.2005): Der Application Client verwendet EJB-Referenzen und jboss-client.xml
1.1.0.0 (29.12.2005): Angepaßt an WTP 1.0