Client/Server-Programmierung WS2007/08 EJB/JSP: Schritt

Werbung
Client/Server-Programmierung
WS2007/08
EJB/JSP: Schritt-für-Schritt Anleitung
Version 1.1, 26.09.07
Eingesetzte Software:
- Apache Tomcat 5.5.9 bzw. 5.5.12
- OpenEJB 0.9.2
(http://tomcat.apache.org/download-55.cgi#5.5.12)
(http://openejb.codehaus.org/Download)
Hinweis:
Bevor mit dem EJB-Container OpenEJB im Labor H-A 4111 das erste Mal gearbeitet werden
kann, ist das Installationsskript /opt/dist/tools/openejb_install.sh auszuführen und die
Umgebungsvariable OPENEJB_HOME auf $HOME/Soft/openejb-0.9.2 zu setzen, siehe
Abschnitt 8.3.3 des Vorlesungsskripts.
EJB
Im folgenden Beispiel wird von der Implementierung eines einfachen Hello-World-Programms
ausgegangen und der Vorgang bis zum Deployment als stateless Session-Bean beschrieben. Des
Weiteren erfolgen Hinweise zu Änderungen, welche im Rahmen des Praktikums notwendig werden.
Zunächst sind zwei Verzeichnisse zu erstellen. Das eine heisst META-INF und beinhaltet zwei XMLDateien des Deployment-Deskriptors. Die Datei ejb-jar.xml sieht folgendermassen aus (weitere
Informationen unter http://www.vipan.com/htdocs/ejb-jar.xml.html):
<?xml version="1.0" encoding="UTF-8"?>
<ejb-jar>
<enterprise-beans>
<session>
<ejb-name>Hello</ejb-name>
<home>org.Hello.HelloHome</home>
<remote>org.Hello.HelloObject</remote>
<ejb-class>org.Hello.HelloBean</ejb-class>
<session-type>Stateless</session-type>
<transaction-type>Container</transaction-type>
</session>
</enterprise-beans>
<assembly-descriptor>
<container-transaction>
<method>
<ejb-name>Hello</ejb-name>
<method-name>*</method-name>
</method>
<trans-attribute>Required</trans-attribute>
</container-transaction>
</assembly-descriptor>
</ejb-jar>
Seite 1 von 7
Die wichtigsten verwendeten Tags sind dabei:
<ejb-name>
Name der EJB, über den andere J2EE-Komponenten die EJB referenzieren können und der als
ID im Deployment-Deskriptor verwendet wird.
<home>
Name der Datei des Home-Interfaces mit Angabe des Pfades im Package.
<remote>
Name der Datei des Remote-Interfaces mit Angabe des Pfades im Package.
<ejb-class>
Name der Datei der Bean-Implementierung mit Angabe des Pfades im Package.
<session-type>
Stateless oder Stateful, je nachdem, welcher Bean-Typ entstehen soll.
<method-name>
Namen der öffentlichen Methoden der Bean, welche bereit gestellt werden. Mit * stehen alle
Methoden der Bean zur Verfügung.
Die Datei openejb-jar.xml ist spezifisch für den OpenEJB-Container. Man kann sie manuell
erzeugen oder beim Deployment mit der Option -a automatisch generieren lassen. Sie ist folgendermassen aufgebaut (weitere Informationen unter http://www.openejb.org/faq_openejb-jar.html):
<?xml version="1.0" encoding="UTF-8"?>
<openejb-jar xmlns="http://www.openejb.org/openejb-jar/1.1">
<ejb-deployment ejb-name="Hello" deployment-id="Hello"
container-id="Default Stateless Container"/>
</openejb-jar>
Die wichtigsten verwendeten Tags sind dabei:
<ejb-name>
Name der Bean in der Datei ejb-jar.xml.
<deployment-id>
Name, der für den Lookup im JNDI-Namespace verwendet werden soll.
<container-id>
Name des Containers aus der Datei openejb.conf, in dem diese Bean ausgeführt werden
soll. Wir verwenden Default Stateless Container bzw. Default Stateful
Container.
Das zweite Verzeichnis beinhaltet das Package mit den Java-Dateien der Bean, in unserem Fall haben
wir ein Verzeichnis org mit Unterverzeichnis Hello (im Folgenden als org/Hello bezeichnet).
Dort werden drei Dateien generiert. Die Datei HelloHome.java beinhaltet das Home-Interface:
package org.Hello;
import java.rmi.*;
import javax.ejb.*;
import java.util.*;
public interface HelloHome extends EJBHome
{
public HelloObject create() throws RemoteException, CreateException;
}
Seite 2 von 7
Die Datei HelloObject.java enthält das Remote-Interface:
package org.Hello;
import java.rmi.*;
import javax.ejb.*;
import java.util.*;
public interface HelloObject extends EJBObject
{
public String sayHello() throws RemoteException;
}
Die Datei HelloBean.java beinhaltet schließlich die Implementierung der eigentlichen EJB, welche
auf dem Server im EJB-Container OpenEJB ausgeführt werden soll:
package org.Hello;
import java.rmi.RemoteException;
import javax.ejb.*;
public class HelloBean implements SessionBean
{
private SessionContext sessionContext;
public void ejbCreate()
{}
public void ejbRemove()
{}
public void ejbActivate()
{}
public void ejbPassivate()
{}
public void setSessionContext(SessionContext sessionContext)
{
this.sessionContext = sessionContext;
}
public String sayHello() throws java.rmi.RemoteException
{
return "Hallo? Jemand da?";
}
}
Nun erfolgt eine Kompilierung der Java-Dateien mittels
javac -classpath $OPENEJB_HOME/lib/ejb-1.0.jar org/Hello/*.java
Seite 3 von 7
Im nächsten Schritt erfolgt die Paketierung der Bean. Dies geschieht mit
jar cvf myHelloEjb.jar org META-INF
Das entstandene Paket mit dem Namen myHelloEjb.jar müssen Sie nun dem OpenEJB-Container
bekannt machen. Dazu stoppen Sie zunächst den Container sofern er aktiv ist, indem Sie in sein HomeVerzeichnis ($OPENEJB_HOME) wechseln und
./openejb.sh stop –p <Port>
ausführen. Das Deployment erfolgt dann mit
./openejb.sh deploy -a -c -f <vollständiger Pfadname der jar-Datei>
Wenn Sie den EJB-Container auf dem Ihnen zugewiesenen Port mit
./openejb.sh start -p <Port>
neu starten, steht Ihnen der Dienst der EJB zur Verfügung.
Um den Dienst nun nutzen zu können, benötigen Sie eine Java-Applikation HelloWorld.java als
Client. Es wird zunächst über JNDI eine Referenz auf das Home-Objekt erzeugt und durch
Verwendung der create-Methode ein EJB-Objekt angelegt. Auf dieses kann dann genauso
zugegriffen werden wie auf ein lokales Objekt:
import org.Hello.*;
import javax.rmi.*;
import javax.naming.*;
import java.util.*;
public class HelloWorld
{
public static void main(String args[])
{
try
{
Properties p = new Properties();
p.put("java.naming.factory.initial",
"org.openejb.client.RemoteInitialContextFactory");
p.put("java.naming.provider.url", "127.0.0.1:4201");
p.put("java.naming.security.principal", "Benutzername");
p.put("java.naming.security.credentials", "Kennwort");
InitialContext ctx = new InitialContext(p);
Object obj = ctx.lookup("/Hello");
HelloHome ejbHome = (HelloHome)PortableRemoteObject.narrow(
obj,HelloHome.class);
HelloObject ejbObject = ejbHome.create();
String message = ejbObject.sayHello();
System.out.println(message);
ejbObject.remove();
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
Seite 4 von 7
Beachten Sie, daß Sie beim Setzen der Ressource java.naming.provider.url den Port und ggf.
auch die IP-Adresse bzw. den Rechnernamen des OpenEJB-Containers anpassen müssen!
Um den Client zu kompilieren, benötigt er neben dem Archiv ejb-1.0.jar die Interface-Klassen der
Bean (HelloHome.class und HelloObject.class) in seinem Classpath. Kopieren Sie diese
beide Klassen in ein relatives Unterverzeichnis org/Hello zu der Client-Applikation
HelloWorld.java. Die Kompilierung wird dann folgendermassen durchgeführt:
javac -classpath $OPENEJB_HOME/lib/ejb-1.0.jar:. HelloWorld.java
Da der Client von der Implementierung des EJB-Containers abhängt, müssen Sie beim Start des
Clients die Archive openejb-0.9.2.jar und die openejb_client-0.9.2.jar mit im Classpath
führen. Der Client wird daher folgendermaßen ausgeführt (die Zeilenumbrüche sind nur des Drucks
wegen vorhanden und dürfen nicht eingegeben werden!):
java -classpath $OPENEJB_HOME/lib/ejb-1.0.jar:
$OPENEJB_HOME/dist/openejb-0.9.2.jar:
$OPENEJB_HOME/dist/openejb_client-0.9.2.jar:.
HelloWorld
JSP & EJB
Wie eine Bean mit Tomcat als Bean-Container angesprochen wird, ist bereits auf dem Übungsblatt
erläutert. Im Rahmen des Tutorials wird nun dargelegt, wie man mittels eines client-seitigen InternetBrowsers über JSP auf einem Web-Server auf eine EJB zugreift. Die client-seitige Java-Applikation
wird dadurch ersetzt. Die JSP-Seiten bauen eine Verbindung zu dem EJB-Container OpenEJB als
Applikationsserver auf, der wiederum mit einer Datenbank, z.B. MySQL, kommunizieren kann. Auf
diese Weise ergibt sich eine klassische 4-Tier-Architektur (siehe http://lamscase.epfl.ch/
PetStore/HP/j2eemodel/tieres.htm):
Seite 5 von 7
Als erste Voraussetzung müssen die jar-Dateien
•
•
•
ejb-1.0.jar aus dem lib-Verzeichnis
openejb_client-0.9.2.jar aus dem dist-Verzeichnis
openejb-0.9.2.jar aus dem dist-Verzeichnis
des OpenEJB-Containers in das Verzeichnis shared/lib des Tomcat kopiert werden. Nun ist
Tomcat in der Lage, mit dem EJB-Container zusammenzuarbeiten.
Für den Zugriff auf die konkrete HelloWorld-EJB von einer JSP aus müssen die Interface-Klassen
(HelloHome.class und HelloObject.class) nach shared/classes/org/Hello des Tomcat
kopiert werden. Für die Börsenanwendung sind natürlich ebenso die passenden Interface-Klassen zu
kopieren. Beachten Sie, dass bei jeder Änderung von class- oder jar-Dateien der Tomcat-Server neu
gestartet werden sollte!
Nach dem Deployment der HelloWorld-EJB und dem Start des OpenEJB-Containers kann nun die
HelloWorld-EJB über die folgende JSP-Datei angesprochen werden. Diese muß im Verzeichnis
webapps/ROOT von Tomcat angelegt werden und die Endung .jsp besitzen (wieder müssen ggf.
Host und Port der java.naming.provider.url angepaßt werden):
<!doctype html public "-//w3c//dtd html 4.0 transitional//en"
"http://www.w3.org/TR/REC-html40/strict.dtd">
<%@ page import="org.Hello.*,
javax.rmi.*,
javax.naming.*,
java.util.*
"%>
<html>
<body>
<%
Properties p = new Properties();
p.put("java.naming.factory.initial",
"org.openejb.client.RemoteInitialContextFactory");
p.put("java.naming.provider.url", "127.0.0.1:4201");
p.put("java.naming.security.principal", "Benutzername");
p.put("java.naming.security.credentials", "Kennwort");
InitialContext ctx = new InitialContext(p);
Object obj = ctx.lookup("/Hello");
HelloHome ejbHome = (HelloHome)PortableRemoteObject.narrow(
obj,HelloHome.class);
HelloObject ejbObject = ejbHome.create();
out.println(ejbObject.sayHello());
ejbObject.remove();
%>
</body>
</html>
Der Start der Anwendung erfolgt nun über den Internet-Browser. Da die Referenz ejbObject nur für
eine JSP-Datei gilt, muss diese Referenz bei Einsatz einer stateful Session-Bean, wie es bei dem
ToyDax-Beispiel notwendig ist, als Session-Attribut in Tomcat gehalten werden. Dies geschieht über
das Anlegen des Attributs, sofern es in der Tomcat-Session noch nicht vorhanden ist. Ist es bereits
vorhanden, so wird die dort gespeicherte Referenz weiter verwendet:
Seite 6 von 7
try
{
ToyDaxObject ejbObject;
// Versuch, Session-Objekt holen
ejbObject = (ToyDaxObject)session.getAttribute("ToyDaxSession");
if (ejbObject == null)
{
// wenn Session-Objekt nicht existiert -> anlegen!
Properties p = new Properties();
p.put("java.naming.factory.initial",
"org.openejb.client.RemoteInitialContextFactory");
p.put("java.naming.provider.url", "127.0.0.1:4201");
p.put("java.naming.security.principal", "Benutzername");
p.put("java.naming.security.credentials", "Kennwort");
InitialContext ctx = new InitialContext(p);
Object obj = ctx.lookup("/ToyDax");
ToyDaxHome ejbHome = (ToyDaxHome)PortableRemoteObject.narrow(
obj,ToyDaxHome.class);
ejbObject = ejbHome.create();
session.setAttribute("ToyDaxSession", ejbObject);
}
// Aufrufen und Auswerten der Methode aus der EJB
... = ejbObject.Buy(..., ...);
...
}
catch (Exception e)
{
out.println ("FEHLER: "+e);
}
Seite 7 von 7
Herunterladen