Konzeption und Implementierung des Sicherheitskonzepts in einem

Werbung
Technische Universität Berlin
Fakultät IV: Elektrotechnik und Informatik
INSTITUT FÜR WIRTSCHAFTSINFORMATIK
FACHGEBIET SYSTEMANALYSE UND EDV
Diplomarbeit
Wintersemester 2004/2005
Konzeption und Implementierung
des Sicherheitskonzepts in einem
Net Business Tool
Verfasser:
MatrikelNr:
Studiengang:
email:
letzte Änderung:
Bassem El-Ahmad
181794
Technische Informatik
[email protected]
3. Januar 2005
Gutachter:
Betreuer:
Prof. Dr. Krallman
Dipl.-Kfm. Marian Scherz
Die selbständige und eigenhändige Anfertigung versichere ich an Eides statt.
Berlin,den 3. Januar 2005
Unterschrift
Danksagung
Ich möchte mich bei allen bedanken, die mich während meines Studiums unterstützt
haben, besonders bei meinem Diplomarbeitsbetreuer Dipl.-Kfm. Marian Scherz, der
viel Geduld aufbringen mußte.
Mein größter Dank gilt meiner Mutter, die mir das Studium ermöglicht und mich
auch zu jeder Zeit unterstützt hat.
3
Inhalt
1. Einleitung
1.1. Gliederung der Arbeit . . . . . . . . . . . . . . . . . . . . . . . . . .
10
11
2. Einleitung zum Net Business Tool
2.1. Hintergrund zum Sicherheitskonzept . . . . . . . . . . . . . . . . . .
2.2. Zweck des Sicherheitskonzepts . . . . . . . . . . . . . . . . . . . . . .
2.3. Anforderungen an Benutzer des Admin Tools . . . . . . . . . . . . . .
12
13
13
13
3. Modellierung und Entwurf
3.1. Einführung . . . . . . . . . . . .
3.2. UML Modellierung . . . . . . . .
3.2.1. Anwendungsfalldiagramm
3.2.2. Klassendiagramm . . . .
3.2.3. Sequenzdiagramm . . . .
3.2.4. Aktivitätsdiagramm . . .
3.3. Datenbank Schema . . . . . . . .
.
.
.
.
.
.
.
15
15
16
17
18
20
21
21
.
.
.
.
.
.
.
.
23
23
23
25
26
28
29
30
32
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
4. Angewandte Technologien
4.1. Enterprise JavaBeans . . . . . . . . . . .
4.1.1. Der EJB-Server . . . . . . . . . .
4.1.2. Der EJB-Container . . . . . . . .
4.1.3. Das EJBHome-Interface . . . . .
4.1.4. Das EJBObjekt-Interface . . . . .
4.1.5. Enterprise JavaBeans Typen . . .
4.1.6. Session Beans . . . . . . . . . . .
4.1.7. Der Zugriff auf eine Session-Bean
4
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
4.2.
4.3.
4.4.
4.5.
4.1.8. Entity Beans . . . . . . . . . . .
Java Servlets . . . . . . . . . . . . . . .
Java Server Pages . . . . . . . . . . . . .
4.3.1. Elemente einer JSP-Seite . . . . .
4.3.2. Direktiven . . . . . . . . . . . . .
4.3.3. Aktionen . . . . . . . . . . . . . .
4.3.4. Scripting Elemente . . . . . . . .
4.3.5. Implizite Objekte einer JSP Seite
4.3.6. Gültigkeitsbereiche von Objekten
4.3.7. Beans . . . . . . . . . . . . . . .
4.3.8. Tag-Extensions . . . . . . . . . .
4.3.9. Zusammenfassung . . . . . . . . .
Code Generation mit XDoclet . . . . . .
4.4.1. Was ist XDoclet? . . . . . . . . .
4.4.2. XDoclet und J2EE . . . . . . . .
4.4.3. Beispiel EJB mit XDoclet . . . .
4.4.4. Fazit . . . . . . . . . . . . . . . .
JBoss Application Server . . . . . . . . .
4.5.1. Deployment unter JBoss . . . . .
5. Implementierung
5.1. UsersBean . . . . . . . . . . .
5.2. GroupsBean . . . . . . . . . .
5.3. PagesBean . . . . . . . . . . .
5.4. Anbindung an die Datenbank
5.5. Admin Tool Web-Interface . .
6. Admin Tool Benutzerhandbuch
6.1. Authentifizierung . . . . . .
6.2. User Verwaltung . . . . . .
6.2.1. List all user . . . . .
6.2.2. Create user . . . . .
6.2.3. Reset password . . .
6.2.4. Update User . . . . .
6.2.5. Delete user . . . . .
6.2.6. Show user groups . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
5
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
33
34
38
39
40
40
41
42
42
43
44
47
48
49
51
52
53
54
54
.
.
.
.
.
55
56
58
61
62
62
.
.
.
.
.
.
.
.
65
65
66
66
68
68
68
69
70
6.3. Groups verwalten . . . . . . .
6.3.1. List all groups . . . . .
6.3.2. Create group . . . . .
6.3.3. Add user to group . .
6.3.4. Delete group . . . . . .
6.3.5. Delete user from group
6.3.6. Add sub-group . . . .
6.3.7. Delete sub-group . . .
6.4. PLP Security . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
70
70
71
71
71
72
72
72
73
A. Anhang
75
A.1. GroupsBean.Java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75
A.2. UsersBean . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94
A.3. PagesBean . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117
Literaturverzeichnis
125
6
Abbildungsverzeichnis
3.1. Admin Tool UML Anwendungsfalldiagramm . . . . . . . . . . . . . .
3.2. Admin Tool Klassendiagramm . . . . . . . . . . . . . . . . . . . . . .
3.3. Die unterschiedlichen Datenbank Tabellen . . . . . . . . . . . . . . .
18
19
22
4.1.
4.2.
4.3.
4.4.
4.5.
4.6.
4.7.
4.8.
Die EJB-Architektur . . . . . . . . . . . . . . . . . . . . .
Die Beziehung Zwischen EJB-Server und EJB-Container .
Client-Schnittstelle einer EJB . . . . . . . . . . . . . . . .
EJB-Typen in EJB-Version 2.0 . . . . . . . . . . . . . . .
Zugriff auf eine Session-Bean . . . . . . . . . . . . . . . . .
Die verschiedenen Stufen bei der Ausführung eines Servlets
Die verschiedenen Stufen bei der Ausführung eines Servlets
XDoclet Ablauf . . . . . . . . . . . . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
24
25
26
30
33
36
39
50
5.1.
5.2.
5.3.
5.4.
5.5.
Die Hauptpackages
UsersBean . . . . .
GroupsBean . . . .
PagesBean . . . . .
Web infterface . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
55
56
59
61
64
6.1.
6.2.
6.3.
6.4.
6.5.
6.6.
6.7.
6.8.
Authentifizierung Prozess .
Login Page . . . . . . . . .
Hauptansicht . . . . . . . .
Liste aller verfuegbaren User
Create new user . . . . . . .
Update user . . . . . . . . .
Delete user . . . . . . . . .
List All Gropus . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
65
66
67
67
68
69
69
70
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
7
6.9. Add new group . .
6.10. Delete group . . . .
6.11. PLP Security Panel
6.12. PLP Managegroups
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
8
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
71
72
73
74
Tabellenverzeichnis
4.1. Implizite Objekte einer JSP-Seite . . . . . . . . . . . . . . . . . . . .
4.2. Gültigkeitsbereiche von Objekten einer JSP-Seite . . . . . . . . . . .
9
41
43
1. Einleitung
Diese Arbeit handelt von einem Admin Tool für die Realisierung eines Sicherheitskonzeptes für das NBT 1 . Zur Realisierung gehört unter anderem die Integration in
das vorhandene PLP2 Tool. Weiterhin wird eine Webanwendung mit JSP’s und EJB
ermöglicht. Mit Hilfe vom NBT Tool werden die Benutzer in Gruppen verwaltet und
ihnen bestimmte Rechte zugewiesen.
Es gibt drei Arten von Benutzern (Admin User, Group User und Guest User). Der Admin User verfügt über alle möglichen Rechte, wie z.B. anlegen, löschen und verändern
von Usern und Gruppen. Dagegen hat der Super User weniger Rechte als der Admin
User, er darf Veränderungen an den einzelnen Usern vornehmen, sie jedoch nicht
löschen. Zuletzt hat der Guest User nur eingeschränkte Möglichkeiten und darf nur
seine eigenen Informationen verändern.
Das Sicherheitstool stellt bestimmten Usern HTML Elemente im LRP Tool zur
Verfügung, dabei ist die Anzeige abhängig vom eingeloggten User in der zugehörigen
Gruppe. Demnach werden Elemente angezeigt bzw. versteckt.
Das Tool gliedert sich in die drei Hauptbereiche Usermanager, Groupmanager und
Pagemanager. Im Usermanager werden alle Funktionalitäten für die Verwaltung der
Benutzer implementiert. Der Gruppenmanager untergliedert sich in Groups und Subgroups, dabei werden im Bereich Groups die zugehörigen Rechte der Gruppe auf den
User übertragen bzw. ihm entzogen, wenn der User aus der Gruppe ausscheidet, dagegen ist die Subgroup eine Untergruppe von Groups, d.h. sie erbt alle Rechte der
Oberklasse Groups. Der Pagemanager wird für die Verwaltung der einzelnen Projekte
und HTML Elemente benötigt.
Zusätzlich wird eine PostgreSQL-Datenbank zur Verwaltung der Daten aufgebaut.
Dafür werden Tabellen für die Bereiche Gruppen, Users und Elemente angelegt.
1
2
Net Business Tool:http://venus.cs.tu-berlin.de/
PRESENTATION LAYER PRODUCER:http://venus.cs.tu-berlin.de/
10
1.1. Gliederung der Arbeit
11
1.1. Gliederung der Arbeit
Als erstes werden die Sicherheitsanforderungen and das NBT Admin Tool im Kapitel 2 vorgestellt. Dabei werden die Sicherheitsaspekte für Webapplikationen in den
Vordergrund gestellt, diskutiert und analysiert. Dazu werden Anforderungen und
Strategien sowie der Ablauf dargestellt.
In Kapitel 3 erfolgt eine Kurzbeschreibung der Modellierungssprache UML. Es werden bestimmte Modellierungsmethoden zur Konzeptbeschreibung verwendet. Die verschiedenen Usecases, Klassendiagramme sowie das Datenbankschema kommen durch
spezifische Beschreibung zur Geltung. Die einzelnen Diagramme dienen als Bausteine
zur Realisierung der Implementierungen.
Die angewandten Technologien (EJB, Servlets, JSP, JBOSS und XDoclet) werden in
Kapitel 4 beschrieben. Dazu gehört ein kleiner Exkurs in die Technologien, die wiederum auf die Problematik der Diplomarbeit abgestimmt werden. Zusätzlich werden
Definitionen und Grundkenntnisse in den einzelnen Technologien erläutert. Weiterhin
werden die Möglichkeiten und deren Anwendungsmöglichkeiten untereinander dargestellt und angewendet.
Kapitel 5 beshreibt die vollständige Implemtentierung der einzelnen Funktionalitäten,
wie z.B. UserBean, GroupBean und PagerBean. In UserBean werden Funktionalitäten zur Verwaltung und Erzeugung von Usern implementiert. Die GroupBean
Klasse ermöglicht das Einbinden erzeugter User durch UserBean in verschiedene
Gruppen zuzuordnen. Hingegen der Benutzerverwaltungen und Gruppenrechtzuweisungen beschreibt PagerBean die Verwaltung der einzelnen Projekte und HTML Elemente. Die Datenbankkonfiguration, die Interaktion zwischen Servlets und EJB’s, die
Interaktion zwischen JSP und Servlets und die Realisierung des Web-Interfaces zum
Admin Tool werden implementiert.
Ein Benutzerhandbuch in Kapitel 6 dient für die Schritt für Schritt Benutzung des
Admin Tools, das durch Grafikelemente die Navigation auf der Applikation erleichtert. Auszüge aus der User- und Gruppenverwaltung dienen als Demo.
2. Einleitung zum Net Business Tool
Das Net Business Tool (NBT) ist ein generisches, komponentenbasiertes, plattformund geräteunabhängiges Framework auf Basis offener Quelltexte (Open Source). Dieses Framework übernimmt die Aufgaben der Komponentenverwaltung und -verteilung.
Mit wenigen Operationen können mit dem NBT innerhalb weniger Minuten Webseiten erstellt werden. Der Webgenerator kann dabei an individuelle Anforderungen
angepasst werden (Customizing).
Ziel des NBT ist die Verschmelzung von Struktur- und Layout innerhalb des HTMLCodes so zu separieren, dass hierarchische Strukturen und logische Abhängigkeiten
zwischen den verschiedenen HTML-Objekten definiert werden können. Das NBT
verwaltet ein Projekt mit sämtlichen Bestandteilen einer zu erstellenden Website in
einer Datenbank.
Die Inhalte dieser Tabellen werden beim abschließenden Generierungslauf in XML
Befehle übersetzt. Grundgedanke der Software ist die Trennung von Layout und
eigentlichem Inhalt (Texte, Bilder, Multimedia, etc.). Das Erstellen von Stylesheets,
die im NBT über Bausteine direkt oder als Datei eingebunden werden, gibt eine
zusätzliche Möglichkeit, das Webdesign professionell zu gestalten1 .
Das NBT soll in Anwendungsbereichen wie Internet- und Intranet-Applikationen,
eBusiness sowie Geschäftsautomatisierung als plattformunabhängiges Werkzeug seine Funktionalität zur Verfügung stellen. Zur Umsetzung der Plattformunabhängigkeit
ist das NBT in Java geschrieben und benötigt zur Ausführung lediglich eine installierte Java VM und einen Browser, der Java uneingeschränkt unterstützt.
1
Net Business Tool:http://venus.cs.tu-berlin.de/
12
2.1. Hintergrund zum Sicherheitskonzept
13
2.1. Hintergrund zum Sicherheitskonzept
Immer mehr Anwendungen laufen auf einer Internet basierenden Technik, so auch
geschäftskritische Anwendungen. Das Internet stellt jedoch eine offene Plattform dar,
so dass der Sicherheitsgedanke fest mit der Anwendung verankert werden muss.
Spätestens beim Aufbau Internet basierender Geschäftsmodelle, zum Beispiel (eBusiness) oder beim Thema Fernwartung ist die Etablierung stabiler und verifizierbarer Sicherheitskonzepte unumgänglich. Nicht nur, dass der Gesetzgeber heute ein
Management der Sicherheit (Risikomanagement) fordert, der Fortbestand einer Unternehmung hängt ganz entscheidend von der Wahrung der Unternehmensgeheimnisse ab. Dies betrifft sowohl Benutzerdaten mit ihren Rechten als auch den Entwicklungsstand von zukünftigen Produkten und Dienstleistungen. Je nach Tätigkeitsfeld
sind verschiedene Informationen von unterschiedlicher Wichtigkeit und Bedeutung.
Grundlage für eine Webanwendung bzw. Security-Lösung ist eine Risikoanalyse, in
der mögliche Schwachstellen und Bedrohungen untersucht werden und wie mögliche
Angriffe darauf gestartet werden können. Nach der Bewertung, welchen Schaden diese
Angriffe anrichten können, werden geeignete Präventivmaßnahmen untersucht. Ausgehend von dieser Risikoanalyse, wird festgestellt, welche Sicherheitsmängel bestehen
und welche Gefahren daraus entstehen können.
2.2. Zweck des Sicherheitskonzepts
Sicherheitsaspekte spielen eine zentrale Rolle in Webapplikationen. Als Grundlage
für eBusiness-Strategien muss sichergestellt werden, dass Informationen nicht jedem
zugänglich sind, d.h. nicht jeder Benutzer ist befugt jede Information zu erhalten.
Daher müssen Einschränkungen vorgenommen werden um die Sicherheit und Privatsphäre jedes einzelnen zu schützen und zu garantieren.
2.3. Anforderungen an Benutzer des Admin Tools
Das Sicherheitskonzept innerhalb des Admin Tools muss die Verwaltung und Separierung der Informationen gewährleisten. Dabei werden bestimmte Zugriffsrechte
den Usern durch Gliederung in bestimmten Gruppen auferlegt. Nicht jeder User hat
2.3. Anforderungen an Benutzer des Admin Tools
14
damit die Möglichkeiten bestimmte Elemente sowie Projekte zusehen, d.h. der bestimmte User sieht nur für ihn zugelassene Elemente. Die einzelnen User können ihre
eigenen Daten ändern, aber sich nicht aus der Datenbank löschen. Hingegen diesen
Bestimmungen darf der Admin alle Operationen für einen User vornehmen und den
Benutzer somit aus der Datenbank löschen, verändern oder neu anlegen.
Die Gliederung der User in einzelne Gruppen ermöglicht ihnen bestimmte Funktionalitäten auszuführen. Es gibt drei Arten von Usergruppen (Admingroup, Supergroup,
Anonymousgroup). Die Admingruppe verfügt über alle Rechte im Tool. Dagegen
verfügt ein Supergroup User über mehr Rechte als ein Guest bzw. Anonymous User.
Jedoch können die User nur bestimmte Elemente bzw. Projekte sehen, die im Verbund mit ihnen stehen.
3. Modellierung und Entwurf
3.1. Einführung
Die Unified Modelling Language (UML) hat sich in den letzten Jahren als standardisierte Modellierungssprache fuer Softwareprodukte durchgesetzt. Die Darstellung und Modellierung erfolgt mit verschiedenen Diagrammen, die unterschiedliche
Aspekte des Systems beleuchten.1 Diese sind beispielsweise die gewuenschten Anwendungsfaelle (sogenannte use cases), Klassendiagramme (classdiagrams) oder Sequenzdiagramme (sequence diagrams). Letztere beschreiben die Kommunikation verschiedenener Klassen untereinander. Ein UML-Modell besteht aus mehreren dieser
Diagramme, die in ihrer Gesamtheit ein Softwareprodukt möglichst vollständig modellieren sollen.2
Die Erstellung solcher Dokumente geschieht meist mit Softwareentwicklungswerkzeugen (engl. CASE-Tools). Bekannte Vertreter sind hier Rational Rose3 und Together
ControlCenter4 . Diese Werkzeuge dienen meist nicht nur zur Erstellung der Diagramme, sondern helfen dem Softwareentwickler auch bei der Erstellung des Sourcecodes
und der Dokumentation.
Viele CASE-Tools bieten inzwischen das sogenannte Roundtrip-Engineering. Darunter versteht man die Möglichkeit, sowohl mit Diagrammen als auch mit dem eigentlichen Sourcecode zu arbeiten.5 Änderungen in einem der beiden Teile werden automatisch im anderen Teil nachgeführt. Dabei ist die Generierung von Diagrammen
aus bereits bestehendem Sourcecode ebenfalls möglich. Diese Werkzeuge entwickeln
sich zunehmend zu Werkzeugen für den gesamten Softwareentwicklungszyklus. So
1
Alhir (2003)
Eine recht umfangreiche Übersicht findet sich unter http://www.jeckle.de/unified.htm
3
http://www.rational.com
4
http://www.togethersoft.com
5
Balzert (2001)
2
15
3.2. UML Modellierung
16
gibt es Programme, die automatisch Tests durchführen können und aus Testlaeufen
Sequenzdiagramme erzeugen.
Selten wird ein Softwareprodukt nur von einer Person entworfen und programmiert.
Die Arbeit in Entwicklungsteams stellt somit den Regelfall dar. Softwareentwicklungswerkzeuge bieten auch hier einige Hilfswerkzeuge zur Teamarbeit an, die das
gemeinsame Arbeiten an Dokumenten ermöglichen. Dazu gehört neben der Verwaltung von Revisionen und Varianten auch das Softwarekonfigurationsmanagement.
Eine Vielzahl der Softwareentwicklungsprozesse arbeiten iterativ. Diese Iterationen
können dabei verschiedene Formen annehmen, auch eine Ueberlappung ist moeglich. Es lässt sich jedoch allgemein feststellen, dass die ständige Überarbeitung und
Korrektur der Entwurfsdokumente und Sourcecodes eine Vielzahl von verschiedenen
Versionen produziert. Betrachtet man zusätzlich die Möglichkeit aus vorhandenen
Programmen Diagramme generieren zu können (durch Reverse- Engineering oder
Testläufe), so nimmt die Anzahl der Diagramme weiter zu. Diese Diagramme beinhalten viele wertvolle Informationen über den Entwicklungsprozess.
3.2. UML Modellierung
1. Was ist die UML?
Unified Modelling Language ist eine Sprache zur Spezifikation, Visualisierung,
Konstruktion und Dokumentation von Modellen für Softwaresysteme, Geschäftsmodelle und andere Nicht-Softwaresysteme. Sie bietet den Entwicklern die
Möglichkeit, den Entwurf und die Entwicklung von Softwaremodellen auf einheitlicher Basis zu diskutieren. Die UML wird seit 1998 als Standard angesehen.6 Sie lag und liegt weiterhin bei der Object Management Group (OMG)
zur Standardisierung vor.
2. Wer steht hinter der UML?
Entwickelt wurde die UML von Grady Boch, Ivar Jacobsen und Jim Rumbaugh von RATIONAL ROSE SOFTWARE . Sie kombinierten die besten Ideen objektorientierter Entwicklungsmethoden und schufen daraus UML“. Vie”
le führende Unternehmen der Computerbranche (Microsoft, Oracle, Hewlett6
Objektorientierter Softwareentwurf mit UML Bannert:1999
3.2. UML Modellierung
17
Packard,...) wirkten aktiv an der Entwicklung mit und unterstützen die UML.
3. Warum ist die UML keine Methode?
Die UML ist keine Methode. Sie ist lediglich ein Satz von Notationen zur Formung einer allgemeinen Sprache zur Softwareentwicklung. Eine Methode beinhaltet Empfehlungen zur Vorgehensweise bei Entwicklungsprozessen. Um UML
erfolgreich zu nutzen, ist es notwendig eine passende Methode zu entwickeln,
die die UML unterstützt.7
Die Modellelemente der UML werden nach Diagrammtypen gegliedert:
• Anwendungsfalldiagramm
• Klassendiagramm
• Aktivitätsdiagramm
• Kollaborationsdiagramm
• Sequenzdiagramm
• Zustandsdiagramm
• Komponentendiagramm
• Einsatzdiagramm
3.2.1. Anwendungsfalldiagramm
• Definition:
Ein Anwendungsfalldiagramm besteht aus einer Menge von Anwendungsfällen und
stellt die Beziehungen zwischen Akteuren und Anwendungsfällen dar. Es zeigt das
äußerlich erkennbare Systemverhalten aus der Sicht eines Anwenders.
7
Alhir (2003)
3.2. UML Modellierung
18
Abbildung 3.1.: Admin Tool UML Anwendungsfalldiagramm
• Beschreibung:
Ein Anwendungsfalldiagramm beschreibt die Zusammenhänge zwischen verschiedenen Anwendungsfällen untereinander und zwischen Anwendungsfällen und den beteiligten Akteuren. Es zeigt die Struktur und Zusammenhänge von verschiedenen
Geschäftsvorfällen und wie mit ihnen verfahren wird. Die drei wichtigsten Akteure
im Admin Tool sind Guest, Super und Admin User. Abbildung 3.1 beschreibt die
Interaktionen zwischen den verschiedenen Anwendungsfällen.
3.2.2. Klassendiagramm
• Definition:
Eine Klasse ist eine Menge von Objekten, in der die Eigenschaften (Attribute), Operationen und die Semantik der Objekte definiert werden. Alle Objekte einer Klasse
entsprechen dieser Festlegung.
3.2. UML Modellierung
Abbildung 3.2.: Admin Tool Klassendiagramm
19
3.2. UML Modellierung
20
• Beschreibung:
Eine Klasse ist eine Zusammenfassung gleichartiger Objekte. Objekte sind die agierenden Grundelemente einer Anwendung. Die Gleichartigkeit bezieht sich auf Eigenschaften (Attribute) und/oder auf Fähigkeiten (Operationen/Methoden) der Objekte einer Klasse. Eine Klasse enthält gewissermaßen die Konstruktionsbeschreibung
für Objekte die mit ihr erzeugt werden. Das Verhalten der Objekte wird durch die
Möglichkeit eines Objektes Nachrichten zu empfangen und zu verstehen beschrieben. Dazu benötigt das Objekt bestimmte Operationen. Die Begriffe Operation und
Nachricht sollten nicht synonym verwendet werden. Zusätzlich zu Eigenschaften und
Fähigkeiten kann eine Klasse auch Definitionen von Zusicherungen, Merkmalen und
Stereotypen enthalten. Das NBT Admin Tool besteht aus verschiedenen Klassen, die
drei wichtigsten Klassen sind: UsersBean, GroupsBean und PagesBean. Abbilldung
3.2 beschreibt die Relatation zwischen den verschiedenen Klassen.
3.2.3. Sequenzdiagramm
• Definition:
Das Sequenzdiagramm beschreibt die zeitliche Abfolge von Interaktionen zwischen
einer Menge von Objekten innerhalb eines zeitlich begrenzten Kontextes.
• Beschreibung
Mittels des Sequenzdiagrammes beschreibt man die Interaktionen zwischen den Modellelementen ähnlich wie bei einem Kollaborationsdiagramm, jedoch steht beim Sequenzdiagramm der zeitliche Verlauf des Nachrichtenaustausches im Vordergrund.
Die Zeitlinie verläuft senkrecht von oben nach unten, die Objekte werden durch
senkrechte Lebenslinien beschrieben und die gesendeten Nachrichten waagerecht entsprechend ihres zeitlichen Auftretens eingetragen.
3.3. Datenbank Schema
21
3.2.4. Aktivitätsdiagramm
• Definition:
In einem Aktivitätsdiagramm werden die Objekte eines Programmes mittels der Aktivitäten, die sie während des Programmablaufes vollführen, beschrieben. Eine Aktivität ist ein einzelner Schritt innerhalb eines Programmablaufes, d.h. ein spezieller
Zustand eines Modellelementes, eine interne Aktion sowie eine oder mehrere von ihm
ausgehende Transitionen enthält. Gehen mehrere Transitionen von der Aktivität aus,
so müssen diese mittels Bedingungen voneinander zu entscheiden sein. Somit gilt ein
Aktivitätsdiagramm als Sonderform eines Zustandsdiagrammes, dessen Zustände der
Modellelemente in der Mehrzahl als Aktivitäten definiert sind.8
• Beschreibung:
In einem Programmablauf durchläuft ein Modellelement eine Vielzahl von Aktivitäten, d.h. Zuständen, die eine interne Aktion und mindestens eine daraus resultierende Transition enthält. Die ausgehende Transition impliziert den Abschluss der
Aktion und den Übergang des Modellelementes in einen neuen Zustand bzw. eine
neue Aktivität. Diese Aktivitäten können in ein Zustandsdiagramm integriert werden oder besser aber in einem eigenen Aktivitätsdiagramm visualisiert werden. Ein
Aktivitätsdiagramm ähnelt in gewisser Weise einem prozeduralem Flußdiagramm,
jedoch sind alle Aktivitäten eindeutig Objekten zugeordnet, d.h. sie sind entweder
einer Klasse, einer Operation oder einem Anwendungsfall eindeutig untergeordnet.
3.3. Datenbank Schema
Eine logische Beschreibung von Daten, die in einer Datenbank gespeichert sind. Das
Schema definiert nicht nur die Namen der einzelnen Daten, ihre Größe und andere
Charakteristiken, sondern identifiziert auch die Beziehung zwischen den Daten.9
Das DB-Schema wurde so geplant, daß man neue Users, Groups, HTML Elemente
und Pages hinzufügen kann, ohne daß man etwas am Quellcode der Komponenten
8
9
Sams (1999)
Turner (March 27, 2002)
3.3. Datenbank Schema
22
Abbildung 3.3.: Die unterschiedlichen Datenbank Tabellen
ändern muß. Die Datenbank wurde in einer Postgre-Datenbank10 realisiert.
Dazu gibt es eine Tabelle Users mit den Attributen (Uid, Username, Realname,
Email, Password), eine Tabelle Groups und deren Attributen (Gid, Groupname,
Groupdescription, Groupowner), eine Tabelle sub-groups mit den Attributen (Users,
Groups), eine Tabelle groups-user mit den Attributen (Gid, Uid), eine Tabelle elementgroups mit den Attributen (Gid, Pid, Eid). eine Tabelle projects-users mit den Attributen (Users, Projects). Für jeden Typ existiert dann eine eigene Tabelle mit den
angegebenen Attributen, in der die eigentlichen Daten gespeichert werden. Abbildung
3.3 stellt Alle NBT Admin Tool benötigen Tabellen dar.
10
http://www.postgresql.org/
4. Angewandte Technologien
4.1. Enterprise JavaBeans
Um Enterprise JavaBeans (EJB) effektiv verwenden zu können, muss man die EJBArchitektur verstehen (siehe Abbildung 4.1). Die Enterprise JavaBeans sind Hauptbestandteil der Java2 Enterprise Edition (J2EE). Sie stellen die Komponententechnologie für Applikationsserver mit J2EE dar. Im 1997 wurde die Technologie EJB
angekündigt. Im August 2001 wurde die Public Final-Version EJB 2.0 verfügbar, der
viele signifikante Erweiterungen und Verbessrungen gegenüber den Vorgängerversionen
enthält.
Sun Microsystems definiert EJB wie folgt:
Die Enterprise JavaBeans Architektur ist eine Komponenten-Architektur für die Entwicklung und Inbetriebnahme Komponenten-basierte Geschäftsanwendung. Applikationen, die unter Verwendung der EJB-Architektur geschrieben werden, sind skalierbar, transaktionsorientiert, und Mehr-benutzer-geeignet. Diese Applikation können
einmal geschrieben und dann auf jeder Serverplattform in Betrieb genommen werden,
die die EJB-Spezifikation unterstützen.
4.1.1. Der EJB-Server
Eigentlich müsste man von einem J2EE-Server sprechen. Die Strategie von Sun aber
bezieht EJB wesentlich stärker in das gesamte Portofolio von Java-basierten Programmierschnittstellen und Produkten ein, als es bislang der Fall war 1 .Der EJB-Server
stellt Systemdienste für Enterprise-Beans zur Verfügung und verwaltet die Container,
in denen die Beans ausgeführt werden. Also der EJB-Server ist eine Laufzeitumgebung für verschiedene Container.
1
(Denninger, 2000)
23
4.1. Enterprise JavaBeans
24
Abbildung 4.1.: Die EJB-Architektur
Vom EJB-Server wird die Basisfunktionalität bereitgestellt.
Dazu gehört:
• das Thread- und Prozessmanagement, damit mehrere Container parallel auf
dem Server ihre Dienste anbieten können
• die Unterstützung von Clustering und Lastverteilung
• die Ausfallsicherheit
• ein Namens- und Verzeichnisdienst, um Komponenten auffinden zu können
• eine Zugriffsmöglichkeit auf und das Pooling von Betriebssystemressourcen
Die Schnittstelle zwischen dem Server und den Containern ist dabei vom Hersteller
abhängig. Da ein Standard für dieses Protokoll fehlt, ist nicht sichergestellt, dass
der EJB-Container des Herstellers A im Server des Herstellers B betrieben werden
kann 2 . Der JBOSS- und der WebLogic Application Server sind ein Beispiel für einen
solchen Server.
2
(Denninger, 2000)
4.1. Enterprise JavaBeans
25
Abbildung 4.2.: Die Beziehung Zwischen EJB-Server und EJB-Container
4.1.2. Der EJB-Container
Der EJB-Container ist eine Laufzeitumgebung für Enterprise-Beans-Komponenten.
Enterprise- Beans wird als Oberbegriff für Session-Beans, Entity-Beans und Messagedriven-Beans (EJB 2.0) verwendet. Eine Enterprise-Bean ist von ihrem EJB-Container
abhängig. Genauso ist der EJB-Container auf den Server als Laufzeitumgebung und
Dienstanbieter angewiesen. Ein EJB-Server kann viele Container haben, die alle eine
oder mehrere Arten von Enterprise-Beans enthalten (siehe Abbildung 4.2).
Ein EJB-Container kümmert sich um den gesamten Lebenszyklus der EnterpriseBeans. Dazu gehört das Erzeugen, Lesen, Ändern und Löschen von Enterprise-Beans.
Das schließt nicht aus, Die Architektur von Enterprise JavaBeans dass möglichst oft
ein Pooling verwendet wird, um die Operationen für Erzeugen und Löschen einzusparen 3 . Obwohl Container einen wesentlichen Bestandteil der Enterprise-JavaBeansArchitektur ausmachen, müssen sich Enterprise-Bean-Entwickler und Anwendungs3
(Zimmermann, 2000)
4.1. Enterprise JavaBeans
26
Abbildung 4.3.: Client-Schnittstelle einer EJB
integratoren nicht mit den Containern befassen. In einem verteilten EJB-System
sind sie im Hintergrund tätig. Die Spezifikation (EJB 2.0) verpflichtet den EJBContainer dazu, einer Bean zur Laufzeit mindestens folgende Programmierschnittstellen zugänglich zu machen: Java 2 APIs, EJB 2.0, JNDI 1.2, JTA 1.0.1, JMS 1.0.2,
JDBC 2.0 und JavaMail 1.1. Dem Anbieter eines Java-Applikationsserver steht es frei
zusätzliche Dienste über Standard- Schnittstellen anzubieten.
4.1.3. Das EJBHome-Interface
Es steuert den Lebenszyklus der Bean. Im (EJB)Home-Interface sind die Methoden
definiert, die ein Client zum Erstellen, Suchen und Löschen von Instanzen einer Bean
verwendet (siehe Abbildung 4.3).
Als Bean-Provider muss man das Home-Interface definieren, aber jedoch nicht implementieren. Dies übernimmt der EJB-Container, indem er ein Home-Objekt erstellt,
das eine Referenz auf die Bean zurück gibt. Es ist üblich, dem Home-Interface denselben Namen zuzuweisen wie der Bean-Klasse und das Suffix Home anzuhängen.
Hat die Bean beispielsweise den Namen Users, sollte der Name des Home-Interfaces
4.1. Enterprise JavaBeans
27
für Users UsersHome lauten.
Alle Home-Interfaces erweitern das Interface javax.ejb.EJBHome, das wiederum das
java.rmi.Remote erweitert. Deshalb können alle Methoden des Home-Interfaces die
Ausnahme RemoteException auslösen 4 . Nachfolgend ist die vollständige Definition
vom EJBHome-Interface dargestellt:
package login.interfaces;
/**
* Home interface for Users.
* @xdoclet-generated at ${TODAY}
* @copyright The XDoclet Team
* @author XDoclet
* @version ${version}
*/
public interface UsersHome
extends javax.ejb.EJBHome
{
public static final String COMP_NAME="java:comp/env/ejb/Users";
public static final String JNDI_NAME="ejbs/Users";
public login.interfaces.Users create()
throws javax.ejb.CreateException,java.rmi.RemoteException;
}
EJBHome verfügt über zwei remove()-Methoden zum Entfernen von EnterpriseBean-Instanzen. Die erste remove()-Methode identifiziert die Instanz anhand eines
Handles und die zweite anhand eines Primärschlüssels getEJBMetaData( ) gibt
eine javax.ejb.EJBMetaData-Instanz zurück, die das Home-, das Remote- Interface, die Primärschlüsselklasse sowie die Information zurückgibt, ob es sich bei
der Bean um eine Session- oder Entity-Bean handelt 5 . Mit getHomeHandle()
kann ein Client sich einen so genannten HomeHandle zum Home-Interface geben
4
5
(Zimmermann, 2000)
(Monson-Haefel, 2000)
4.1. Enterprise JavaBeans
28
lassen und diesen auf nicht flüchtigem Speicher ablegen, da HomeHandle von java.io.Serializable abgeleitet ist. Der Handle einer Enterprise-Bean kann zum einem
übergeben werden, oder bei Entity-Beans auch deren Primärschlüssel, der in einem
regulären Java-Objekt repräsentiert sein muss 6 .
4.1.4. Das EJBObjekt-Interface
Der eigentliche Anwendungsdienst oder Persistenzdienst wird von den Methoden gebildet, die es außer Erstellen, Löschen und Auffinden noch gibt. Solche Methoden sind
im Remote-Interface zusammengefasst. Wenn der Client sich eine Referenz auf das
Remote-Interface holt, dann bekommt er in der Wirklichkeit eine Remote-Referenz
auf ein EJB-Objekt. Das EJB-Objekt implementiert das Remote-Interface, in dem es
Geschäftsmethoden an die Bean-Klasse weiter delegiert, es stellt seine eigenen Implementationen der in EJBObject definierten Methoden zur Verfügung 7 . Nachfolgend
ist der Quelltext für EJBObject-Interface dargestellt:
package login.interfaces;
public interface Users
extends javax.ejb.EJBObject
{
public boolean addUser( String username,String realname,
String email,String password )
throws java.lang.Exception, java.rmi.RemoteException;
.......
}
Die Methode getEJBHome() gibt eine Remote-Referenz auf das Home-Objekt der Bean zurück. Die Remote-Referenz wird als javax.ejb.EJBHome-Objekt zurückgegeben,
das dann auf das Home- Interface der jeweiligen Bean eingeengt werden kann. Diese Methode ist nützlich, wenn ein EJBObjekt den Sichtbarkeitsbereich des HomeObjekts, von dem es erzeugt wurde, verlassen hat. Wenn es sich bei der Bean um
6
7
(Zimmermann, 2000)
(Monson-Haefel, 2000)
4.1. Enterprise JavaBeans
29
eine Entity-Bean handelt, gibt die getPrimaryKey()-Methode den Primärschlüssel
für die Bean zurück. Die remove()-Methode löscht die Enterprise-Bean. Die Wirkung dieser Methode ist gleich wie bei der bereits besprochene Methode EJBHome.remove(). Die getHandle() Methode gibt einen beständigen Handle auf die
Bean-Instanz zurück. Weiterhin gibt es die Methode isIdentical() zum Vergleichen
von Enterprise-Beans 8 . Alle Methoden deklarieren das auslösen einer Ausnahme
(Exception) von Typ java.rmi.RemoteException, was erforderlich ist, wenn eine
Methode über RMI aufgerufen werden kann. Wie genau die oben genannten Methoden in der Realität verwendet werden, wird in den nächsten Kapiteln verdeutlicht.
4.1.5. Enterprise JavaBeans Typen
Abbildung 3.3 veranschaulicht die drei EJB-Arten aus Version 2.0. In der ersten
Version der EJBSpezifikation (1.0) war nur die Unterstützung von Session-Beans
vorgeschrieben. Session-Beans sind EJBs, die genau einem Client zugeordnet sind.
Diese Beans können einen internen Zustand haben, der über mehrere Aufrufe in
der selben Bean hinweg existiert. Dieser Zustand wird allerdings in der Regel nur im
Hauptspeicher gehalten oder temporär auf die Platte ausgelagert, überlebt einen Absturz oder Neustart des Servers nicht. Hingegen sind Entity-Beans, die erst seit der
Version 1.1 verpflichtend sind, persistent in einem Backend-System gespeichert, das
Methoden zum Erzeugen, Lesen, Schreiben und Löschen der Objekte bereitstellt. In
der Regel übernehmen diese Aufgabe Relationale Datenbanken. Bei BeanmanagedPersistence (BMP) muss der Entwickler selbst die Zugriffmethoden implementieren.
Der Entwickler kann bei der Container-managed-Persistence (CMP) aber abstrakt
vorgeben, welche Felder persistent sein sollen und die Mapping-Tools der EJB-Server
generieren die tatsächlichen Zugriffcode. Bislang wurden alle Methodenaufrufe von
EJBs synchron durchgeführt, das heißt der Client wartet bis ein Rückgabewert vom
Server geliefert wurde. Bei Message-driven-Beans (EJB 2.0) ist dies anders. Nun ist
auch das asynchrone auslösen von Aktionen durch den Java-Messaging Service JMS9
möglich. Das bedeutet, die Clients stellen eine Nachricht in eine Warteschlange, für
die der EJB-Server als Subscriber registriert ist. Jede EJB arbeitet nun anstehende Requests ab und ruft für jede Nachricht die onMessage()-Methode auf. Clients
warten nicht auf das Ende des Methodenaufrufs, können jedoch eine Rückmeldung
8
9
http://info.borland.com/devsupport/appserver/faq/ejbcpp/ejb_cpp.html
http://java.sun.com/products/jms/
4.1. Enterprise JavaBeans
30
Abbildung 4.4.: EJB-Typen in EJB-Version 2.0
erhalten, wenn eine Message-driven-Bean den Auftragbearbeitet hat. Die Messagedriven-Beans ähneln vom Verhalten her zustandslosen (stateless) Session-Beans. Sie
müssen allerdings nicht explizit mit create()-Methoden erzeugt werden und besitzen
weder ein Home- noch ein Komponenten-Interface. Im Gegensatz zu bisherigen JMSServern können auch mehrere EJBs gleichzeitig aktiv sein und eine große Anzahl
Requests parallel bearbeiten.
4.1.6. Session Beans
Session Beans werden dazu verwendet Anwendungslogik auf dem Server auszuführen.
Sie sind dafür geeignet, da für jeden Client durch den EJB- Server und den Container
ein eigenes Bean konstruiert wird und auch nur dieser eine Client Zugriff darauf hat.
Eine Session-Bean ist ein Geschäftsobjekt, weil sie die Logik eines Geschäftsprozesses
realisiert. Der Geschäftsprozess beschreibt alle Schritte, die notwendig sind, um eine
bestimmte Aufgabe zu erfüllen. Logisch wird eine Session-Bean als serverseitige Erweiterung des Clientprogramms betrachtet 10 . Sie kann Informationen für den Client
behalten.
Normalerweise wird die Bean entfernt, wenn der Client die Sitzung beendet. Im Gegensatz zu Entity-Beans repräsentieren Session-Beans keine gemeinsamen genutzten
Daten in der Datenbank 11 und somit sind sie nicht persistent. Session-Beans können
die Interaktionen zwischen Entity-Beans verwalten und beschreiben, wie diese zu10
11
Denninger (2000)
(Monson-Haefel, 2000)
4.1. Enterprise JavaBeans
31
sammenarbeiten, um eine bestimmte Aufgabe zu erfüllen.
Das Bean ist nicht persistent, d.h. sobald die Kommunikation zwischen Client und
Server beendet ist wird auch die Instanz durch den Container zerstört. Dies hat den
Nachteil, daß bei einer eventuellen Verbindungsunterbrechung, wie z.B. durch einen
Server- oder Client- Absturz sämtliche Informationen verloren gehen. Daten, wie
z.B. eine Transaktion die von dem Session Bean an eine Datenbank oder an ein Entity Bean delegiert werden, bleiben natürlich bestehen (es wird aber keine Rollback
Funktionalität angeboten), es geht lediglich die Instanz des Session Beans verloren.
Man kann die Session Beans weiter in statefull (zustandsbehaftete) und stateless (zustandslose) Beans unterteilen. Zustandslose Beans bekommen eine Anfrage
und geben eine Antwort, d.h. sie können sich nicht den Status einer vorausgegangenen Anfrage merken und dementsprechend reagieren. Sie werden also bei einfachen
Methodenaufrufen verwendet, wie z.B. bei Zahlungsvorgängen, bei denen eine Kreditkartennummer und der Betrag übermittelt wird, das Bean die Zahlungsfähigkeit
überprüft und dann eine positive oder negative Bestätigung zurückschickt.
Ein weiterer Anwendungsfall wäre eine komplexere Berechnung. Dem Bean werden mehrere Eingangsdaten übergeben, die sie dann auswertet und ein Ergebnis
zurückschickt. Bei zustandbehafteten Session Beans handelt es sich um kompliziertere Konstrukte, bei denen der Zustand der Konversation mit den Clients gespeichert
wird. Session Beans haben zusammenfassend folgende Eigenschaften:
• Repräsentiert nicht Daten in einer Datenbank.
• Kann gemeinsamgenutzte Daten in einer Datenbank verändern.
• Ein SessionBean ist immer nur einem Client zugeordnet (d.h. ein gleichzeitiger
Zugriff von mehreren Clients ist nicht möglich)
• Ist relativ kurzlebig.
• Unterstützt Transaktionen, ist jedoch kein Erfordernis.
• Verschwindet falls der EJB Server abstürzt (d.h. die Session Bean kann nicht
wiederhergestellt werden).
4.1. Enterprise JavaBeans
32
4.1.7. Der Zugriff auf eine Session-Bean
Der Client bekommt mit Hilfe des JNDI eine Referenz auf das Home-Interface. Beim
Aufruf der Methode lookup von Context wird ein Objekt vom Typ java.lang.Object
zurückgegeben. Ihr Code muss das zurückgegebene Objekt in den erwarteten Typ
umwandeln (siehe Abbildung 4.5). Für die richtige Konvertierung der Datentyp gibt
es die Methode narrow() von der Klasse javax.rmi.PortableRemoteObject. Nachdem
das Home-Interface bekannt ist, kann der Client eine neue Bean erzeugen (create)
und bekommt als Rückgabewert das Remote-Interface der Bean. Wenn es sich um
zustandslose Session-Bean handelt, verfügt das Home-Interface nur über eine create()-Methode, so dass diese vom Client aufgerufen werden muss, um die RemoteSchnittstelle zu beziehen.
Die vorgegebene create()-Methode einer zustandslosen Sesssion-Bean hat keine Parameter 12 . Mit dem Remote-Interface kann der Client mit der Bean fast so arbeiten,
als wäre sie ein lokales Objekt. Eine Java-Client-Applikation verwendet JNDI, um
eine Verbindung zu einem EJB-Server aufzubauen und ein bestimmtes Home-Objekt
zu finden. Nach dem Gebrauch der Bean muss der Client die Bean wieder löschen.
Der folgende Codefragment zeigt, wie das JNDI-API verwendet werden könnte, um
eine Referenz auf das Home-Objekt zu finden und zu bekommen:
//mit dem Naming-Service einen JNDI-Kontext abrufen
public void init() throws ServletException {
try {
Context context = new InitialContext();
value = (String) context.lookup("java:/comp/env/Title");
Object ref = context.lookup("java:/comp/env/ejbs/Users");
usershome =
(UsersHome) PortableRemoteObject.narrow(ref, UsersHome.class);
} catch (Exception e) {
throw new ServletException("Lookup of java:/comp/env/ failed");
}
}
12
http://info.borland.com/devsupport/appserver/faq/ejbcpp/ejb_cpp.html
4.1. Enterprise JavaBeans
33
Abbildung 4.5.: Zugriff auf eine Session-Bean
4.1.8. Entity Beans
Die Unterstützung von Entity-Beans wurde erst in EJB-1.1 als obligatorisch für
Server- und Container-Provider definiert. Im Gegensatz zu Session-Beans waren die
Entity-Beans in der EJB.1.0-Spezifikation noch optional 13 . Entity-Beans modellieren
Geschäftskonzepte, die als Substantive ausgedrückt werden können. Geschäftskonzepte
repräsentieren Daten, die kontrolliert und möglicherweise auch manipuliert werden
müssen. Entity-Beans repräsentieren also Objekte der realen Welt. Sie beschreiben
sowohl den Zustand als auch das Verhalten von diesen Objekten und ermöglichen
es Entwicklern, die Daten und die Geschäftsregeln, die zu bestimmten Konzepten
gehören, einzukapseln.
Entity-Beans repräsentieren Daten in der Datenbank. Es hat viele Vorteile, EntityBeans zu verwenden, anstatt direkt auf die Datenbank zuzugreifen. Die Verwendung
von Entity-Beans, um Daten in Objekt-Form zu bringen, stellt den Entwicklern einen
einfachen Mechanismus für den Zugriff auf die Daten und die Veränderung derselben
zu Verfügung. Es ist beispielsweise viel einfacher, den Titel eines Buch durch Aufruf
von buch.setTitel() zu ändern, als einen SQL-Befehl an die Datenbank zu schicken.
13
(Denninger, 2000)
4.2. Java Servlets
34
Außerdem erhöht man so die Chancen 14 , wiederverwendbare Software zu schreiben.
Eine einmal definierte Buch-Entity-Bean kann in vielen Bibliotheken auf konsistente
Weise wiederverwendet werden. Weil Entity-Beans es mehreren Clients ermöglichen,
parallel auf die gleichen Daten zuzugreifen, werden sie als zentrale Ressource betrachtet. jeder Client einer Entity-Bean arbeitet fast so, als würde er exklusiv auf sie
zugreifen. Die Datenbankprobleme, die durch den parallelen Zugriff entstehen, vermeidet der EJB-Container durch die teilweise Serialisierung der Zugriffe und durch
den Einsatz von Transaktionen (siehe Kapitel Transaktionen) 15 . Der paralleler Zugriff mehrere Clients auf eine Entity-Bean ist ein wesentlicher Unterschied zu SessionBeans, die jeweils für genau einen Client existieren.
Folgende Eigenschaften kennzeichnen Entity Beans:
• Repräsentiert Daten in einer Datenbank.
• Erlaubt gleichzeitigen (shared ) Datenzugriff von mehreren Clients auf ein Entity Bean
• Unterliegt immer der Transaktionsverwaltung.
• Kann langlebig sein (d. h. lebt solange die Daten in der Datenbank bleiben)
• Uberlebt EJB Serverabstürze (d. h. das Entity Bean kann nach einem Absturz
wiederhergestellt werden)
4.2. Java Servlets
Java Servlets bieten eine sehr mächtige Möglichkeit, Web-Applikationen zu bauen,
die leicht auf bereits vorhandene Systeme (z.B.: Datenbanken) zugreifen können. Was
ist nun ein Servlet? Die Java Servlet Specication Version 2.416
definiert Servlets wie folgt:
14
(Monson-Haefel, 2000)
(Denninger, 2000)
16
Java Servlet Specification Version 2.4: http://java.sun.com/products/servlet/
15
4.2. Java Servlets
35
Ein Servlet ist eine Web-Komponente (im Engl.: web component), die über einen
”
Kontainer (Servlet Engine17 ) gemanagt, dynamische Inhalte generiert. Servlets sind
kleine“ plattform-unabhängige Java Klassen, die nachdem sie in neutralen Byteco”
de kompiliert wurden, von einem Web-Server dynamisch geladen und zum Laufen
gebracht werden können. Servlets interagieren mit Web-Clients über ein RequestResponse-Schema (basierend auf das Hypertext Transfer Protocol), das vom Servlet
Kontainer implementiert wird“
Vereinfachend kann ein Servlet auch mit einem Applet 18 verglichen werden, das auf
der Server-Seite läuft und daher keine grafische Oberfläche besitzt. Folgende Vorteile
bietet der Einsatz von Java Servlets:
1. Plattform-Unabhängigkeit
2. Zugang zu allen Java API’s
3. Schneller als CGI Scripts19
4. Session-Management
Zur Ausführung des Servlets ist eine sogenannte Servlet Engine notwendig, die Anfragen an bestimmte Servlets weiterleitet. Die Servlet Engine ist entweder direkt im
Web-Server integriert (JavaSoft Java Web Server) oder eine eigene Server-Applikation
wie JBOSS20 oder Tomact Abbildung 2.8 zeigt, welche Methoden von der Servlet Engine während des Servlet’s Life Cycle aufgerufen werden.
Die init() Methode dient zur Initialisierung des Servlets, das geschieht entweder bei
der ersten Verwendung des Servlets oder schon vorher. Die service() Methode kann
mit der main() Methode einer Java Applikation verglichen werden. Für das abschließende Aufräumen der besetzten Resourcen wird die destroy() Methode verwendet.
Bei der Programmierung eines Servlets müssen diese Methoden entsprechend angepaßt werden, weiters muss das Servlet direkt oder indirekt das javax.servlet.Servlet
Interface implementieren. Der einfachere Weg ist das überschreiben von Methoden einer vorhandenen Servlet-Klasse, wie zum Beispiel der javax.servlet.http.HttpServlet
17
Eine Servlet Engine ist eine Server-Applikation, die Servlets ausführt.
Java Servlet Programming
19
Gewöhnliche CGI’s spalten beim Request jeweils einen neuen Prozess ab, Servlets hingegen sind
nur einfache Threads.
20
http://www.jboss.org
18
4.2. Java Servlets
36
Abbildung 4.6.: Die verschiedenen Stufen bei der Ausführung eines Servlets
Klasse. Listing 3.1 zeigt ein vom HttpServlet abgeleites Servlet, das nur die doGet()
Methode überschreibt, die dem HTTP Get entspricht.
Listing 3.1 Hello, ein vom HttpServlet abgeleitetes Java Servlet:
1 import javax.servlet.http.*;
2 import javax.servlet.*;
3 import java.io.*;
4 public class Hello extends HttpServlet {
5 public void doGet (HttpServletRequest request,
6 HttpServletResponse response)
7 throws ServletException, IOException {
8 // get an PrintWriter from the response object
9 PrintWriter out = response.getWriter();
10 // prepare the response’s content type
11 response.setContentType("text/html");
12 // get the IP address of the client
4.2. Java Servlets
13
14
15
16
17
37
String remoteAddress = request.getRemoteAddr();
// print to the output stream!
out.println("Hi Man from <b>" + remoteAddress + "</b>");
}
}
Vorausgesetzt der Server unterstützt Java Servlets, kann nun das Servlet via WebBrowser21 aufgerufen werden, dass im Gegenzug ein simples in unserem Fall sogar unvollständiges HTML-Dokument an den Client sendet. Akzeptiert das Servlet
den Aufruf, werden der doGet Methode zwei Objekte übergeben, eines der Klasse HttpServletRequest und eines der Klasse HttpServletResponse. Das erste Objekt
(request) kapselt die ,eingehende‘ , das andere Objekt (response) die ,ausgehende‘
Kommunikation und vereinfacht das Handling mit dem Hypertext Transfer Protokoll. Zum Beispiel wird in Listing 2.7, Zeile 11 der MIME22 -Type der HTTP-Antwort
festgelegt. Ein etwas sinnvollerer Anwendungsbereich von Servlets ist deren Einsatz
zur Kommunikation mit Datenbanken. Die benötigte Schnittstelle zu Datenbanken
wird durch das JDBC23 API realisiert, dass für alle bekannten Datenbanken Treiber
zur Verfügung stellt. Ein Verbindungsaufbau mit einer Postgresql Datenbank zeigt
das folgende Java Code-Stück aus der init() Methode eines Datenbank Servlets:
"");
Class.forName("org.postgresql.Driver").newInstance();
dbc = DriverManager.getConnection("jdbc:postgresql://localhost:5432/myDB?"
+"user=name&password=paswd");
Das erste Statement erzeugt ein Connection-Objekt, das die Verbindung zur Datenbank kapselt. Dazu wird ein passender JDBC-Driver für die Datenbank benötigt, in
unserem Fall heißt dieser örg.gjt.mm.mysql.DriverḊas zweite Statement stellt nun
eine konkrete Verbindung zur Datenbank her und diese bleibt während der Lebenszeit des Servlets aufrecht. Das Auslesen aller Datensätze einer Tabelle Produkte kann
zum Beispiel so geschehen:
21
Aufruf über URL, zum Beispiel http://localhost/servlets/Hello.
Multipurpose Internet Mail Extensions, siehe [Freed Borenstein, 1996].
23
Java DataBase Connectivity. Ein Java API zum Ausführen von SQL-Statements, stellt eine Reihe
von Klassen und Interfaces zur Manipulation von Datenbanken zur Verfügung.
22
4.3. Java Server Pages
38
1 Statement stmt = dbc.createStatement();
2 stmt.execute("select * from Produkte");
3 ResultSet rs = stmt.getResultSet();
Mit der Möglichkeit, SQL-Statements zu exekutieren (siehe Zeile 2), steht nun die
gesamte Funktionalität der Datenbank zur Verfügung. Der Einsatz von RMI24 würde
den Code des Servlets noch zusätzlich vereinfachen und die Komplexität des DatenbankHandlings auf eine zusätzliche Schicht verlagern.
Die Servlets-Technologie wird von einer immer größer werdenden Anzahl von Servern unterstützt und bietet eine gute Alternative zu CGI basierenden zeitkritischen
Applikationen.25 Zusätzliches Session-Management erlaubt nun endgültig die Interaktivität zu erhöhen. Mit Java hat man zudem den Vorteil, auf einer großen Menge
von Plattformen ohne Probleme lauffähige Applikationen erzeugen zu können und
von der Mächtigkeit der vorhandenen APIs zu profitieren. Zur Zeit ist die Java Servlet API Specification Version 2.4 unter http://java.sun.com/products/servlet
verfügbar.
4.3. Java Server Pages
JSP ist eine Technologie, die von der Firma SUN entwickelt wurde und die auf der
Java- Servlet-API basiert.Java Server Pages sind den Active Server Pages (ASP) von
Microsoft sehr ähnlich. Mit beiden Techniken kann man in eine normale HTMLSeite spezielle Kommandos integrieren, und damit zum Beispiel dynamische Inhalte
in die Seite integrieren26 . Ziel von Java Server Pages ist es, eine Trennung von Design und Applikationslogik zu erreichen. Da JSP auf Java basiert, ist außerdem eine
hohe Portabilität gewährleistet. Ein großer Vorteil von JSP ist, daß man innerhalb
einer JSP-Seite auf beliebige Java APIs zugreifen kann.Während Active Server Pages
nur mir den Microsoft Webservern verfügbar sind, kann man die Java Server Pages
mittlerweile mit allen gängigen Webservern benutzen27 .
Ein Webserver kann aber normalerweise nicht selbst die JSP-Seiten korrekt behandeln. Dazu benötigt man eine JSP-Engine. Diese wird dann gewöhnlich über
24
Remote Method Invocation, siehe http://java.sun.com/docs/books/tutorial/rmi
Kurniawann (2002)
26
Pure JSP – Java Server Pages: A Code-Intensive Premium Reference
27
Perry (2004)
25
4.3. Java Server Pages
39
Abbildung 4.7.: Die verschiedenen Stufen bei der Ausführung eines Servlets
ein zusätzliches Modul mit dem Webserver verbunden. Spezielle Anfragen an den
Webserver (meist alle Anfragen auf Dateien mit der Endung .JSP) werden dann an
die JSP-Engine weitergegeben. Die JSPEngine ist normalerweise als Servlet implementiert, welches in einer Servlet-Engine läuft.
Die JSP-Engine sorgt dafür, daß aus einer JSP-Seite ein Servlet generiert und dann
kompiliert wird. Ist dann eine aktuelle Klasse vorhanden, so wird die Anfrage an das
entsprechende Servlet weitergegeben. Treten beim generieren oder kompilieren des
Servlets Fehler auf, so werden diese als HTML-Seite zurückgegeben.
4.3.1. Elemente einer JSP-Seite
Die Basis einer JSP-Seite ist normalerweise eine beliebige HTML-Seite. In diese Templatedaten werden JSP-spezifische Elemente eingefügt.Es gibt drei unterschiedliche
Typen von Elementen:28 Direktiven, Aktionen und Scripting Elemente. Ein
zusätzliches Element ist der ’versteckte’ Kommentar. Da es eigentlich keine Funktion für die Seite hat, fällt dieses Element allerdings etwas aus der Reihe. Es wird
dazu benutzt um Kommentar in einer JSP-Seite einzufügen, der nicht in die Ausgabe geschrieben wird. Der gleiche Effekt ist allerdings auch mit Scripting Elementen
28
KOLB (2000)
4.3. Java Server Pages
40
möglich.
Dieser Text wird in den Ausgabestrom geschrieben.
<!-- Auch dieser HTML-Kommentar wird ausgegeben ! -->
<%-- Dieser Kommentar wird nicht ausgegeben ! --%>
<% /* Dieser Kommentar ist in der Programmiersprache der Seite und
wird auch nicht ausgegeben ! */ %>
Grundsätzlich können alle speziellen Elemente einer JSP-Seite auch XML-konform
geschrieben werden. Aktionen werden sowieso schon in einer an XML angelehnten
Form geschrieben. Für Direktiven und Scripting Elemente gibt es entsprechende Alternativen. Im folgenden wird noch einmal auf die Funktionen und Schreibweise der
drei Hauptelemente eingegangen.29
4.3.2. Direktiven
Mit einer Direktiven lassen sich bestimmte Informationen an die JSP-Engine übergeben.
Es gibt die drei Direktiven include, taglib und page. Mit der include-Direktiven lassen sich statische Seiten einbinden. Die taglib-Direktive definiert die Zuordnung von
Präfixen zu Benutzertags. Auf diese Direktive und die Benutzertags wird später noch
genauer eingegangen. Die page-Direktive wird benutzt, um Eigenschaften der gesamten JSP-Seite zu setzten. So kann man zum Beispiel den Typ des Inhaltes definieren
oder die Puffergröße setzten. Theoretisch kann man damit auch die Programmiersprache der Seite bestimmen. Diese muß dann natürlich auch von der JSP-Engine
unterstützt werden.
<%@ page language="java" import="package.*" buffer="none" %>
<%@ taglib uri="tagLibURI" prefix="myTagLib" %>
<%@ include file="header.html" %>
4.3.3. Aktionen
Aktionen dienen zur Beeinflussung des Ausgabestromes. Es gibt eine Reihe von Standardaktionen, die in einer JSP Seite benutzt werden können. Dazu zählen zum Bei29
Goodwill (2000)
4.3. Java Server Pages
Name
request
response
pageContext
session
application
out
config
page
exception
Klasse
javax.servlet.ServletRequest
javax.servlet.ServletResponse
javax.servlet.jsp.PageContext
javax.servlet.http.HttpSession
javax.servlet.ServletContext
javax.servlet.jsp.JspWriter
javax.servlet.ServletConfig
java.lang.Object
java.lang.Throwable
41
Zweck
Repräsentation der Anfrage
der Antwort auf die Anfrage
Der Kontext der Seite
Das Session Objekt
Der Kontext der Anwendung
Ausgabestrom für die Antwort
Enthält Einstellungen der Seite
Instanz der Seitenimplementierung
Die aufgetretene Ausnahme,
Tabelle 4.1.: Implizite Objekte einer JSP-Seite
spiel das Einbinden von dynamischen Seiten oder der Zugriff auf Beans30 . Auch benutzerdefinierte Tags zählen zu den Aktionen.
Einbinden eines Beans und setzen von Eigenschaften.
<jsp:useBean id="myBean" class="package.class"/>
<jsp:setProperty name="myBean" property="property1"
value="propertyValue"/>
Ausgabe einer Eigenschaft...
<jsp:getProperty name="myBean" property="property2">
4.3.4. Scripting Elemente
Scripting Elemente sind Codefragmente, die direkt in die JSP-Seite geschrieben werden. Es gibt drei verschiedene Typen von Scripting Elementen: Deklarationen,
Scriptlets und Ausdrücke. Alle müssen in speziellen Zeichen verschachtelt sein.
<%! Deklaration %>
<% Scriptlet %>
<%= Ausdruck %>
Mit Deklarationen kann man für eine Seite Variablen und Methoden definieren. Diese
können dann später in Scriptlets oder Ausdrücken verwendet werden. Ein Scriptlet
30
Beans sind wiederverwertbare Java-Komponenten. Sie bestehen aus einer Java-Klasse, die einen parameterlosen Konstruktor enthält und meist Daten durch get- und set-Methoden zugänglich macht.
4.3. Java Server Pages
42
besteht aus beliebigem Code. Dieser wird ausgeführt, sobald die Ausgabe der Seite
die Position des Tags erreicht hat. Ausdrücke werden zur Laufzeit ausgewertet und
das Ergebnis wird direkt in den Ausgabestrom geschrieben. Sie können auch als dynamische Parameter für Attribute von Aktionen benutzt werden, sofern dies für das
Attribut erlaubt ist. Beispiel:
<html>
<body>
<%! String color="black"; %>
Wir produzieren eine Zufallsfarbe !<br>
<% color="#";
while (color.length() < 7) {
int i = (int) (Math.random() * 15);
if (i > 9) color += (char) (i + 87);
else color += (char) (i + 48);
%>
<font color="<%= color %>">Der Text ist farbig !</font><br>
</body>
</html>
4.3.5. Implizite Objekte einer JSP Seite
Es gibt eine Reihe von Objektinstanzen, die innerhalb einer JSP-Seite verfügbar
sind. Man kann direkt auf sie zugreifen, da sie von der JSP-Engine erzeugt werden.
In Tabelle 4.1 sind alle Impliziten Objekte einer JSP-Seite aufgelistet. Einige dieser
Objekte, wie zum Beispiel exception sind allerdings nur in speziellen Fällen verfügbar.
4.3.6. Gültigkeitsbereiche von Objekten
Alle impliziten Objekte einer JSP-Seite sind Gültigkeitsbereichen zugeordnet. Das
bedeutet eine Instanz ist nur in einem bestimmten Bereich verfügbar. Auch eigene
Objekte können solchen Bereichen zugeordnet, und so zum Beispiel auf mehreren
Seiten genutzt werden. Eine Übersicht aller Gültigkeitsbereiche ist in Tabelle 4.2
verfügbar.
4.3. Java Server Pages
page
request
session
application
43
Objekte die dieses Gültigkeitsbereiches sind nur von der Seite aus
erreichbar, auf der sie erzeugt wurden. Sie sind im pageContext
Objekt abgelegt. (Implizite Objekte: page, response, pageContext,
out, config)
Objekte die dieses Gültigkeitsbereiches sind im request Objekt abgelegt. Sie sind auf allen Seiten verfügbar, die bei der Bearbeitung
der selben Anfrage beteiligt sind. Das kann zum Beispiel bei einem
forward der Fall sein. (Implizite Objekte: request)
Objekte, dieses Gültigkeitsbereiches sind nur verfügbar, wenn die
Seite eine Session benötigt. Nur in diesem Fall ist das session Objekt
vorhanden, in dem die Objekte abgelegt werden. (Implizite Objekte:
session)
Alle Objekte, die im ServletContext (application Objekt) verfügbar
sind, besitzen diesen Gültigkeitsbereich. Sie sind von allen Seiten
aus erreichbar.(Implizite Objekte: application)
Tabelle 4.2.: Gültigkeitsbereiche von Objekten einer JSP-Seite
4.3.7. Beans
Man kann in einer JSP-Seite auch Java-Beans einbinden. Dies geschieht über eine
spezielle Aktion: jsp:useBean
<jsp:useBean id="instanceName" class="package.class" scope="scope"/>
Mit anderen Aktionen kann man nun entweder Eigenschaften des Beans setzten oder
auslesen.
Setzten eines konstanten Wertes, oder eines Ausdrucks:
<jsp:setProperty name="instanceName" property="property" value="value"/>
Setzen von Werten aus den Request-Parametern:
<jsp:setProperty name="instanceName" property="property" param="param"/>
Ausgabe einer Eigenschaft:
<jsp:getProperty name="instanceName" property="property" />
Beans sind eine gute Möglichkeit, um dynamische Inhalte in eine JSP-Seite einzubinden. Dabei bleibt der Code vollständig getrennt vom Layout. In vielen Fällen können
Beans deshalb auch komplett wiederverwertet werden. Beans sind meist recht einfach
zu erstellen, da keine großen Anforderungen an sie gestellt werden. Der Nachteil von
4.3. Java Server Pages
44
Beans ist, daß man nicht ohne weiteres Zugriff auf die impliziten Objekte der JSPSeite hat. Alle Einstellungen und Objekte, die dem Bean verfügbar gemacht werden
sollen, müssen über die Aktion setProperty übergeben werden.
4.3.8. Tag-Extensions
Da die Bibliothek, die während der Diplomarbeit entwickelt wurde, auf Tag-Extensions
basiert, wird hier etwas ausführlicher darauf eingegangen. Mit JSP-Tag-Extensions
ist es möglich eigene Tags zu definieren. Diese können dann mit spezieller Logik versehen werden. Es besteht aber auch die Möglichkeit, Tags aus fertigen Bibliotheken
zu benutzen. Zu jeder Bibliothek gehört eine Beschreibungsdatei, der Tag-LibraryDescriptor (TLD). Dort stehen Informationen zur Bibliothek und deren Tags. Unter
anderem geschieht dort auch die Zuordnung von Tagname zu Tagklasse. Aber nicht
nur ein Tag einer Bibliothek, sondern auch jedes andere, eigene Tag muß in einem
TLD deklariert werden, um es in einer JSP-Seite nutzen zu können. Zusätzlich muß
man noch mit einer Direktive den entsprechenden Tag-Library-Descriptor bekannt
machen:Einbinden einer Tag-Library
<%@ taglib uri="tagLibURI" prefix="myTagLib" %>
In einer JSP-Seite kann man dann auf alle Tags in einer solchen Bibliothek mit dem
gleichen, in der Direktive angegebenen Präfix zugreifen. Die Tags können theoretisch
beliebig verschachtelt werden. Auch ist es möglich innerhalb der Tags beliebigen
HTML-Code, Scripting-Elemente oder Aktionen zu verwenden:
<myTagLib:myTag1 attribute1="value">
Hallo Welt !<br><jsp:
<myTagLib:myTag2 attribute1="value1"/>
</myTagLib:myTag1>
Tags in einer JSP-Seite
Ob solche Verschachtelungen allerdings sinnvoll, bzw. überhaupt möglich sind, hängt
von der Logik der Tags ab. Es kann zum Beispiel sein, daß ein bestimmtes Tag immer
im Body31 eines anderen Tags stehen muß. Genauso kann es aber auch sein, daß ein
31
Der Body eines Tags ist das, was zwischen Start-Tag und End-Tag steht.
4.3. Java Server Pages
45
Tag den Inhalt des Bodys stets ignoriert. Wenn eine JSP-Seite von der JSP-Engine
kompiliert wird, dann prüft diese, ob die Tags syntaktisch korrekt verwendet wurden.
Die Informationen, die dazu nötig sind, bekommt sie aus dem Tag-Library-Descriptor.
Dieser ist in einem XML-Dialekt geschrieben. Die Datei endet üblicherweise mit ’.tld’.
Die Struktur ist wie folgt:
<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE taglib PUBLIC
"-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.1//EN"
"http://java.sun.com/j2ee/dtds/web-jsptaglibrary_1_1.dtd">
<taglib>
<tlibversion>1.0</tlibversion>
<jspversion>1.1</jspversion>
<shortname>aShortName</shortname>
<uri>theTaglibURI</uri>
<info>Infos zu der Bibliothek</info>
<tag>
<name>myTag</name>
<tagclass>package.class</tagclass>
<info>Infos zu dem Tag</info>
<attribute>
<name>attribute1</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<name>attribute2</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
</tag>
</taglib>
4.3. Java Server Pages
46
Die Klasse, die zu einem Tag gehört ist der sogenannte Tag-Handler. Jeder TagHandler muß das Interface Tag32 implementieren. Tags die Attribute definieren,
müssen zusätzlich für jedes Attribut eine get- und eine set- Methode implementieren. Es gibt zwei Verschiedene Arten von Tag-Handlern. Einmal Tag-Handler, die
auf den Inhalt des Bodys zugreifen müssen, und dann solche, die es nicht müssen.
Das Interface BodyTag erweitert das Tag Interface, um den Zugriff auf den Body
zu ermöglichen. Mit den Tag-Extensions hat man gegenüber Beans ein paar Vorteile. Diverse Methoden der Tag-Handler Interfaces bieten die Möglichkeit, durch
Rückgabewerte die Ausgabe zu beeinflussen. Dadurch kann man zum Beispiel den
Body des Tags mehrfach, oder auch gar nicht ausgeben. Auch ist es möglich, den gesamten Inhalt zu bearbeiten, bevor er in den Ausgabestrom geschrieben wird. Damit
lassen sich mit Tags Schleifenkonstrukte (for, while,...) oder bedingte Ausgaben (if,
switch,...) erzeugen.
Die Tag-Handler werden von der JSP-Engine erzeugt. Diese ruft dann die Methoden
des Tag- Handler Interfaces und die set-Methoden der belegten Attribute nach einem
bestimmten Schema auf.
Der Ablauf bei einem normalen Tag ist wie folgt:
ATag t = new ATag();
t.setPageContext(...);
t.setParent(...);
t.setAttribute1(value1);
t.setAttribute2(value2);
t.doStartTag();
t.doEndTag();
t.release();
Für Tags, die BodyTag implementieren ist der Ablauf folgendermaßen:
// bis hier wie bei einem normalen Tag
t.doStartTag();
32
Die Klassen, auf die sich im folgenden bezogen wird gehören zum Package javax.servlet.jsp.tagext
der Servlet API. http://java.sun.com/products/servlet/2.2/javadoc/index.html
4.3. Java Server Pages
47
out = pageContext.pushBody();
t.setBodyContent(out);
t.doInitBody();
t.doAfterBody();
// solange wie doAfterBody den Status EVAL_BODY_TAG zurückgibt
// wird die Body Auswertung erneut ausgeführt.
...
t.doAfterBody();
t.doEndTag();
t.pageContext.popBody();
t.release();
Die Klassen TagSupport und BodyTagSupport sind zwei Basisimplementierungen für
Tag-Handler. Diese erleichtern die Programmierung, da man nur noch die Methoden
implementieren muß, in denen spezielle Logik nötig ist. In allen Tags sind auch die impliziten Objekte der JSP-Seite zugänglich. Allerdings ist nur das pageContext Objekt
direkt verfügbar. Alle anderen lassen sich über Methoden dieses Objekts erreichen.
Tags, die in einem anderen verschachtelt sind, haben Zugriff auf die entsprechende
Tag- Handler-Instanz des übergeordneten Tags - dem Parent.
4.3.9. Zusammenfassung
Da als Basis für JSP die Programmiersprache Java verwendet wird, ist eine hohe
Portabilität gewährleistet. Für die gängigsten Betriebssysteme bekommt man schon
eine Java Runtime Engine (JRE). Da es auch verschiedene JSP-Engines gibt, die
komplett unter Java geschrieben sind kann somit auch JSP mit diesen Systemen verwendet werden.Java ist außerdem einfach zu erlernen und bietet eine umfangreiche
Klassenbibliothek, auf die uneingeschränkt zugegriffen werden kann.
Java Anwendungen mit grafischer Oberfläche sind oft recht langsam. Dies liegt häufig
an den AWT33 Klassen. Da die JSP-Engine komplett serverseitig läuft, benötigt man
diese Klassen im Normalfall nicht. Somit sind JSP-Seiten meist auch ausreichend
schnell.Nutzt man Beans und Taglibraries, so bekommt man eine Trennung von Design und Logik.
33
Abstract Window Toolkit. Eine API, die für das erstellen von Oberflächen gedacht ist. In den Java
Version bis 1.2 recht langsam.
4.4. Code Generation mit XDoclet
48
So kann man gut änderbare und skalierbare Webanwendungen erstellen. Außerdem
wird der Code besser wiederverwendbar. Ein Nachteil von JSP ist allerdings, daß man
viele Daten in der Session ablegen muß und die Logik stellenweise ungünstig verteilt
ist. Als Beispiel könnte man eine JSP-Seite nehmen, die Daten lädt und in einem
Formular bereitstellt. Nach dem Abschicken der Formulardaten müssen diese auf der
Folgeseite ausgewertet werden. Jegliche Zustände müssen dabei in der Session abgelegt werden, damit sie auf beiden Seiten verfügbar sind. Die Logik ist auf mindestens
Zwei Seiten verteilt. Sinnvoller wäre, daß standardmäßig die Logikkomponente der
ersten Seite auch die Formulardaten auswertet. Die Komponente hätte alle Zustände
zur Verfügung und könnte dann, je nach Daten entscheiden, welche Seite dem Benutzer angezeigt wird. Alles in allem ist JSP aber eine gute Möglichkeit dynamische
Webseiten zu erzeugen. Das zeigt sich auch daran, daß diverse Application-Server
und auch Content-Management- Systeme auf JSP aufsetzten, oder es zumindest unterstützen.
4.4. Code Generation mit XDoclet
Wenn man einmal die ganzen Klassen und Deployment Descriptoren für eine EJB
von Hand geschrieben hat, wird man ermüdet feststellen, dass es hier eigentlich unheimlich viele redundante Vorgänge gibt. Da wäre doch ein Tool nützlich, das diesen
Code nach den gewünschten Vorgaben generiert. Solche Tools gibt es natürlich: Viele
kosten Geld und sind Bestandteil von Entwicklungsumgebungen basieren auf Eigenentwicklungen und Datenbanken. Es gibt aber auch ein kostenloses XML-basierendes
Tool: XDoclet.
XDoclet braucht normalerweise nur eine Datei, nämlich die EJB Implementation,
und generiert daraus alle weiteren notewendigen Dateien, um eine EJB zu deployen,
also:
1. EJB und produktspezifische (JBoss, WebLogic, WebSphere, Orion) deployment
descriptoren
2. Home und Remote Interfaces
3. Primary Key Class für die Entity Bean
4. Bulk Data Object (Value Object)
4.4. Code Generation mit XDoclet
49
5. EJB Wrapper Klassen
Wo nötig, kann man auch die Erstellung einiger dieser Datein unterbinden, man
kann den generierten Code verändern lassen und zusätzlichen Code/Descriptions als
vordefinierte ’Merge Points’ hinzufügen.
XDoclet ist eine Weiterentwicklung des Original-EJBDoclet-Tools von Rickard Oberg.
Die Idee dahinter ist simpel: Statt mit allen EJB-Dateien zu jonglieren, wird die ganze Komponente aus der Bean-Klasse erzeugt. Wie das geht? In Java gibt es doch die
Javadoc-Tags. Wir setzten nun einfach spezielle @ -Tags in die normalem JavadocKommentare hinein, und lassen das Doclet-Tool diese Tags auslesen. Das Tool generiert die entsprechenden XML-Descriptoren und Interfaces für diese EJB. XDoclet
führt die Idee von EJBDoclet noch weiter, indem das Framework noch viel mehr als
nur EJB unterstützt: Man kann auch Web Services, Web Application Descriptoren
und sogar Eigenentwicklungen damit schreiben lassen.
4.4.1. Was ist XDoclet?
XDoclet ist eine OpenSource Engine für die Generierung von Code. Sie liest Java Quelldateien ein und wertet die darin enthaltenen Metainformationen aus. Die
XDoclet Informationen werden in Form von JavaDoc Tags direkt im Quellcode angegeben. Mit Hilfe von Code-Schablonen und den ermittelten Metainformationen erzeugt die Engine die gewünschten Ausgabedateien. Mögliche Zielformate sind unter
anderem XML (z. B. Deployment Deskriptoren), Java Quelldateien oder Implementierungen der J2EE Patterns.34
Der Funktionsumfang von XDoclet kann über Module erweitert werden. Module enthalten die entsprechenden Generierungs-Schablonen für eine bestimmte Technologie.
Folgende Module sind bereits in XDoclet integriert:
• EJB
• Web
34
Sullins und Whipple (May 2003)
4.4. Code Generation mit XDoclet
Abbildung 4.8.: XDoclet Ablauf
50
4.4. Code Generation mit XDoclet
51
• Hibernate
• Mockobjects
• JDO
• JMX
Die Anpassung bzw. die Erstellung eigener Module ist m?glich.
Für die Ausführung der Engine wird in der aktuellen Version das ebenfalls als OpenSource verfügbare Buildwerkzeug Apache Ant benötigt. Die einzelnen Module stellen
Ant Tasks zur Verfügung, mit deren Hilfe der eigentliche Generierungslauf ausgeführt
wird.
4.4.2. XDoclet und J2EE
XDoclet bietet eine gute Unterstützung der J2EE Technologien. Neben der manuellen Erstellung bzw. Erweiterung der Deployment Deskriptoren entfallen z. B. auch
zeitaufwendige T?tigkeiten wie die Erstellung von Home- und Remoteinterfaces bei
der EJB Entwicklung. Es genügt, die Bean Klasse um Metainformationen in Form
von Tags zu erweitern.35
Dies hat zum einen zur Folge, daß innerhalb des Projektes keine veralteten Deployment Deskriptoren mehr enthalten sind, zum anderen erhält der Entwickler eine bessere Ubersicht über das Projekt, da die Informationen nicht mehr auf mehrere Dateien
verteilt, sondern zentral in einer Datei gepflegt werden. Mit Hilfe von XDoclet lassen
sich neben Standard Deployment Deskriptoren auch containerabhängige Deskriptoren erzeugen. Unterstützt werden zur Zeit unter anderem:
• JBoss
• Tomcat
• Bea Weblogic
• IBM Websphere
35
Sullins und Whipple (May 2003)
4.4. Code Generation mit XDoclet
52
Zusätzlich wird die Implementierung einiger J2EE Patterns erleichtert. Durch Deklaration in der Java Datei sowie in der Build Datei lassen sich so z. B. ValueObjects,
Struts Formulare oder Schlüsselgenerierungs Session Beans erzeugen.
4.4.3. Beispiel EJB mit XDoclet
Abschließend wird anhand eines Beispiels der Einsatz von XDoclet während der EJB
Entwicklung gezeigt.
Ausgangspunkt der Entwicklung ist die Bean Klasse, die wir, entgegen der eigentlichen Vorgehensweise bei Session Beans, als abstrakte Klasse implementieren. XDoclet
erstellt bei der Generierung eine abgeleitete Klasse, die die fehlenden Callback Methoden (setSessionContext, etc.) implentiert. Diese Klasse wird dann auch automatisch
in den Deployment Deskriptor eingetragen.
In die Dokumentation der Klassen werden allgemeine Metainformationen wie BeanName und Typ des Beans aufgenommen. In der Dokumentation der Business-Methode
wird definiert, daß die Methode auch im Interface aufgeführt sein soll. Damit ist die
Bean Implementierung abgeschlossen.
Zur Generierung wird das XDoclet Modul ejbdoclet benutzt. Dieses muß hierzu in
der Build Datei angegeben und aufgerufen werden. Im Beispiel enthält der Aufruf von ejbdoclet die Anweisung, daß sämtliche auf Bean.java endende Dateien im
Source Verzeichnis in die Verarbeitung eingeschlossen werden sollen. Durch das session Element wird ejbdoclet angewiesen, Session Beans zu berücksichtigen und die
entsprechenden Tags auszuwerten. Das Attribut acceptAbstractClasses erlaubt den
oben bereits erwähnten Einsatz von abstrakten Klassen bei Session Beans. Im weiteren wird definiert, daß Remote- und Homeinterfaces erstellt werden sollen. Zusätzlich
wird ein Standard Deployment Deskriptor sowie ein JBoss Deployment Deskriptor
erzeugt.
Die so erstellten Java Klassen können nun compiliert und in ein JAR Archiv gepackt
werden. Dieses kann anschlieäend in den Server deployed werden.
<target name="xdoclet-generate" depends="init">
<taskdef name="ejbdoclet"
4.4. Code Generation mit XDoclet
53
classname="xdoclet.modules.ejb.EjbDocletTask">
<classpath refid="compile.classpath"/>
</taskdef>
<ejbdoclet destdir="${build.src.dir}"
excludedtags="@version,@author"
mergedir="${meta.dir}/ejb-jar/META-INF/">
<fileset dir="${src.dir}">
<include name="**/*Bean.java"/>
</fileset>
<session acceptAbstractClasses="true"/>
<remoteinterface/>
<homeinterface/>
<deploymentdescriptor destdir="${build.dir}/META-INF"/>
<jboss version="3.0" xmlencoding="UTF-8"
destdir="${build.dir}/META-INF"
validateXml="false"/>
</ejbdoclet>
</target>
4.4.4. Fazit
XDoclet ist sicher kein Model Driven Architecure (MDA) Tool im eigentlichen Sinne,
es handelt sich vielmehr um ein hilfreiches Werkzeug, mit dessen Hilfe die Entwicklung besonders von J2EE Anwendungen vereinfacht wird. Der Entwickler kann sich
wieder auf die eigentlichen Aufgaben konzentrieren und muß sich nicht mehr mit
aufwendiger, fehleranfälliger Cut- and Paste Arbeit aufhalten.36
36
http://www.xdoclet.org
4.5. JBoss Application Server
54
4.5. JBoss Application Server
JBoss ist ein vollständig in Java implementierter Open-Source Application Server.
Er unterstützt Enterprise JavaBeans 2.0 und arbeitet sowohl mit Jetty als auch mit
Tomcat als Web Engine zusammen.37
4.5.1. Deployment unter JBoss
JBoss unterstützt das sogenannte Hot Deployment. Um eine EJB einzusetzen,genügt
es, die dazugehörige Jar-Datei in das Deploy-Verzeichnis des Application Servers zu
kopieren (JBOSS/server/default/deploy). JBoss erkennt, dass die Datei verändert
wurde und lädt die enthaltenen EJBs. Im Verzeichnis JBOSS/server befnden
sich mehrere Profile des Application Servers. Beim Start wird durch den Parameter -configure=X das zu ladende Profile X festgelegt. Das Standardprofile ist
JBOSS/server/default. Ein neues Profile lässt sich einfach durch das Kopieren
eines bestehenden erstellen. Jedes Profile besitzt ein eigenes Deploy-Verzeichnis. Bevor die Komponente Usermanagement eingesetzt werden kann, muss sie zunächst
kompiliert, zusammen mit den Deployment-Deskriptoren in ein Jar-Archiv gepackt
und in das Deployment-Verzeichnis des JBoss kopiert werden
Neben deploy werden die Funktionen compile und clean zur Verfügung gestellt.
Deploy erstellt aus den kompilierten Klassen ein Jar-Archiv und kopiert es in das
standard Deploy-Verzeichnis des Application Servers. Der Pfad zu einer Installation von JBoss wird dem Skript mit der Variablen jboss.path übergeben. Falls es
notwendig ist, wird von deploy die Funktion compile aufgerufen, wodurch zunächst
sämtliche Klassen kompiliert werden. Mit clean können alle erzeugten Klassen und
Archive wieder gelöscht werden.
37
http://www.jboss.org
5. Implementierung
In diesem Kapital werden die Hauptpackages dargestellt. Weiter wird die JSP Webinferface erklärt. Die Implementierung der Hauptpackages untergliedert sich in drei
Unterpackages (package login.ejb, package login.interfaces, package login.web), die
im Zusammenhang miteinander stehen. Im Package login.ejb befinden sich alle EJB’s
zur Realisierung der einzelnen Klassen usersBean, pagesBean und groupsBean. Das
Interface wird durch XDoclet automatisch erzeugt. Das Interface beinhaltet somit
das remote- und home-interface. Hingegen benutzt das login.web package die anderen
beiden Packages (Abbildung 5.1). In diesem Package befinden sich unter anderem die
Servlets und die JSP-Seiten.
Hinweis: Die vollständige Implementierung der einzelnen Methoden, Klassen und
Packages sind im Anhang zu finden.
Abbildung 5.1.: Die Hauptpackages
55
5.1. UsersBean
56
5.1. UsersBean
Alle notwendigen Funktionalitäten über den User werden in der Klasse UsersBean implementiert. Darin befinden sich die Methoden wie die Auflistung aller User,
Löschen einzelner User, Hinzufügen einzelner User in eine bestehende Gruppe und
Verändern der Daten eines Users.
Abbildung 5.2.: UsersBean
Login: Die folgende Methode login erhält den Namen und das Passwort des Users.
Ist der User vorhanden und tippt der User sein Passwort korrekt ein, so wird er durch
diese Methode erkannt und die Zulassung zum System erfolgt. Sollte der User falsche
Eingaben vornehmen, wird eine Exception ausgelöst.
public Integer login(String userName, String password) {
...
}
5.1. UsersBean
57
Add User: Durch die addUser Methode wird der User in die Datenbank hinzugefügt.
Existiert der User bereits, wird eine Exception ausgelöst und die Daten des Users
werden verworfen. Diese Aktion wird durch eine Hilfsmethode isUserFree durchgeführt. Der User erfährt somit, dass jemand mit dem von ihm gewählten Usernamen
schon existiert. Existieren jedoch die Daten nicht, so wird der User in die Datenbank
aufgenommen.
public boolean addUser(String username,
String realname, String email, String password)
throws Exception {
....
}
Delete User: In der folgenden Methode wird ein User aus der vorhandenen Liste
der User gelöscht. Dafür wird die ID des Users benötigt. Ist der User zum Löschen
markiert, wird er nach Ausführen aus der Datenbank sowie aus den Gruppen, in
denen er sich befindet, gelöscht. Als Ausgabe erhält man, dass der User erfolgreich
vom System entfernt wurde.
public String deleteUser(Integer uid) throws Exception {
...
}
Update User: Mit Hilfe dieser Methode updateUser können die Daten der jeweiligen
User aktualisiert werden. Die Methode braucht zur Aktualisierung der Daten das
Usernamen, Realnamen, Emailadresse und den Passwort des Users.
public void updateUser(String username,
String realname, String email,
String password)
throws Exception, RemoteException {
...
}
5.2. GroupsBean
58
Get Users: Durch die Implementierung der Methode getUser wird das Auslesen
eines bzw. mehrerer User ermöglicht. Die Ausgabe erfolgt durch ein String Array
pro User. Dieses Array liefert als Ausgabe den UserId, Usernamen, Realnamen und
Emailadresse.
public String[] getUser(String username)
throws Exception, RemoteException {
...
}
Reset Password: Durch diese Option hat der User die Möglichkeit, eine Anfrage
beim Admin für die Zurücksetzung seines Passwortes zu machen. Dafür benötigt der
Admin lediglich den Usernamen des Users, um das Passwort auf einen Defaultwert
zurückzusetzen.
public void setpassword(String username,
String admin, String password)
throws Exception, RemoteException {
...
}
5.2. GroupsBean
In der Klasse GroupsBean befinden sich alle Methoden für die Verwaltung von
Gruppen. Darunter befinden sich Methoden, wie z.B. Erstellen einer neuen Gruppe, Löschen einer vorhanden Gruppe sowie das Hinzufügen bzw. Löschen eines User
in bzw. aus eine(r) vorhandene(n) Gruppe. Zusätzlich werden in dieser Klasse den
Gruppen auch Elemente und Projekte zu geordnet.
Add Group: Durch diese Methode wird eine neue Gruppe im System erstellt. Als
Pflichteingabefelder sind Gruppenname und Gruppenbeschreibung einzugeben. Falls
die Gruppe vorhanden ist, wird eine Exception ausgelöst und die eingegebenen Daten
werden verworfen.
5.2. GroupsBean
59
Abbildung 5.3.: GroupsBean
public boolean addGroup(String groupname,
String gdescription)
throws Exception {
...
}
Delete Group: Die Methode deleteGroup löscht eine vorhandene Gruppe aus dem
System. Durch das Entfernen der Gruppe verliert die Gruppe ihre Gültigkeit, jedoch
existieren die User weiterhin im System. Zum Löschen der Gruppe benötigt man
lediglich die ID der Gruppe. Als Rückgabewert wird ein String ausgegeben.
public String deleteGroup(Integer gid)
throws Exception {
...
}
Add user to group: Es besteht die Möglichkeit einer vorhandenen Gruppe einen
bzw. mehrere User hinzuzufügen. Dies wird durch die Methode addUserToGroup
5.2. GroupsBean
60
ermöglicht. Als Eingabewerte für die Methode sind Gruppenname und Username
erforderlich.
public boolean addUserToGroup(String gname,
String uname) throws Exception {
...
}
Deletes a user from a group: Das Löschen eines Users aus einer vorhandenen
Gruppe bedeutet nicht das Löschen des Users aus dem System. In der Methode
removeUserFromGroup wird der User aus der Gruppe entfernt, somit verliert der
User seine Gruppenangehörigkeit. Die Gruppe und der User existieren weiterhin.
public void removeUserFromGroup(String gname,
String uname) throws Exception{
...
}
Add element to group: Die Methode addElementToGroup weist einer vorhandenen Gruppe ein neues HTML-Element bzw. ein neue Page zu. Dazu benötigt die
Methode die Page ID bzw. Element ID und den Gruppennamen. Ist ein neues Element
bzw. Page einer Gruppe hinzugefügt worden, so erhalten alle User die Berechtigungen
zu den Elementen.
public void addElementToGroup(Integer eid,
Integer pid,String gname) throws Exception{
...
}
Delete element from group: Im Gegensatz zu addElementToGroup besteht auch
eine Methode removeElementFromGroup, um Elemente und Pages aus einer Gruppe
wieder zu Entfernen. Nach dem entfernen der Elemente verlieren die Gruppenmitglieder die Berechtigung gegenüber den Elementen.
public void removeElementFromGroup(Integer eid,
5.3. PagesBean
61
Integer pid, String gname) throws Exception {
...
}
Get Group: Die Darstellung und Anzeige aller vorhandenen Gruppen wird durch
eine Vektormethode getAllGroups realisiert. Diese Methode ist eine einfache Implementierung zur Darstellung der Gruppen mit Ihren ID’s, Gruppenname sowie der
Gruppenbeschreibung.
public Vector getAllGroups()
throws Exception ,RemoteException {
...
}
5.3. PagesBean
Die Klasse PagesBean besteht aus einigen private-Methoden und der isVisible-Methode.
Dabei wird in den private-Methoden, die nach aussen nicht sichtbar sind, ein Vergleich zwischen den Gruppen und den Usern durchgeführt, ob sie im Zusammenhang
miteinander stehen. Ist dies der Fall, so hat die Gruppe, und somit auch der User,
die Berechtigung dieses HTML-Element zu sehen.
Abbildung 5.4.: PagesBean
isVisible: Die größte Bedeutung kommt der isVisible Methode in der Klasse PagerBean zu. Diese Methode , gibt die Berechtigung bzw. Zusammengehörigkeit der
Gruppen und User frei, und ermöglicht somit Elemente oder Pages zusehen.
5.4. Anbindung an die Datenbank
62
public Boolean isVisible(Integer userID,
Integer projectID,Integer pageID,
Integer elementID,Vector pageHierarchy) {
...
}
5.4. Anbindung an die Datenbank
Die Anbindung der PostgreSQL-Datenbank wird durch ein EJB configBean“ rea”
lisiert. Dabei wird eine Verbindung durch die Methode getDBConnectionData aufgebaut. Diese Methode braucht zusätzlich den Treiber für die Datenbank. Als Parameter benötigt die Methode noch zusätzliche Angaben wie den Usernamen für die
Datenbank, Passwort, Port und den Datenbanknamen.
public Map getDBConnectionData (){
Map map = new HashMap();
map.put("driver", "org.postgresql.Driver");
map.put("url", "jdbc:postgresql://localhost:5432/admin");
map.put("username", "test");
map.put("password", "test");
return map;
}
5.5. Admin Tool Web-Interface
Das Web-Interface dient zur Realisierung der Funktionalitäten und ist eine JSPSeite, die eine Verbindung zwischen dem Benutzer und dem System darstellt. Im
Package web.root werden die einzelnen Servlets und JSP-Seiten abgelegt. Weitere
Klassen innerhalb des Web-Interfaces sind validateUser, validateGroup und treeTag.
Um auf die EJB’s zugreifen zu können, benötigen wir die Klasse validateUser, um eine
5.5. Admin Tool Web-Interface
63
Verbindung zwischen den EJB’s und den JSP-Seiten zu ermöglichen. Äquivalent gilt
diese Implementierung für den validateGroup, der dann die Verbindung zwischen den
EJB’s und den JSP-Seiten gruppenseitig herstellt. Ein Auszug aus dem validateUsers
sieht wie folgt aus:
public boolean addUser(String username, String realname, String email,
String password) {
try {
Context context = new InitialContext();
String value = (String) context.lookup("java:/comp/env/Title");
Object ref = context.lookup("java:/comp/env/ejbs/Users");
UsersHome usershome = (UsersHome) PortableRemoteObject.narrow(ref,
UsersHome.class);
Users bean = usershome.create();
bean.addUser(username, realname, email, password);
return true;
} catch (Exception exp) {
return false;
}
}
Die Klasse treeTag dient zur dynamischen Darstellung der einzelnen Links. Durch
Ausführen dieser Klasse wird die Navigation der einzelnen Funktionalitäten sichergestellt. Diese Klasse ermöglicht weiterhin das Expandieren bzw. den Kollaps der
Baumstruktur.
5.5. Admin Tool Web-Interface
Abbildung 5.5.: Web infterface
64
6. Admin Tool Benutzerhandbuch
Das folgende Kapitel beschreibt eine Schritt für Schritt Einführung in das Admin
Tool. In diesem Abschnitt werden die einzelnen Schritte über das Einloggen bis hin
zum Benutzen des Admin Tools im Detail beschrieben.1
6.1. Authentifizierung
Abbildung 6.1.: Authentifizierung Prozess
Der Zugang zum Admin Tool erfolgt über eine Authentifizierungsseite. Nur authentifizierten Usern ist der Zugang in das Admin Tool gestattet. Jeder User muss sich
mit seinem gültigen Usernamen und Passwort auf der Authentifizieungsseite anmelden (siehe Abbildung 6.2). Versucht ein nichtauthentifizierter User den Zugang zu
erzwingen, wird er vom Admin Tool abgewiesen und erhält eine Fehlermeldung anhand einer HTML Error Page (siehe Abbildung 6.1).
Nach dem Einloggen gliedert sich die Webapplikation in drei Bereiche. Im linken
Bereich der Applikation sieht man die User und Gruppen Verwaltung. Im rechten
1
NBT Admin Tool: http://www.venus.cs.tu-berlin.de/adminproject/login.jsp
65
6.2. User Verwaltung
66
Abbildung 6.2.: Login Page
Frame, dem so genannten Hauptframe, sieht man die Übersicht der einzelnen Funktionen bzw. Darstellung der einzelnen Links (Abbildung 6.3).
6.2. User Verwaltung
Im Untermenü User Verwaltung befinden sich weitere Untermenüs, die alle Benutzer
anzeigen, neue User anlegen, Passwörter zurücksetzen bzw. Anzeigen von vorhandenen Gruppen.
6.2.1. List all user
In der User List erhält man alle im System vorhandenen User mit ihren Usernamen,
Realnamen und Emailadressen sowie eine Checkbox, um bestimmte Operationen auf
den User auszuführen, wie z.B. Einfügen eines ausgewählten Users in eine Gruppe.
6.2. User Verwaltung
67
Abbildung 6.3.: Hauptansicht
Abbildung 6.4.: Liste aller verfuegbaren User
6.2. User Verwaltung
68
6.2.2. Create user
Unter diesem Link besteht die Möglichkeit einen neuen User anzulegen. Dafür werden
Informationen über den Usernamen, Realnamen und die Emailadresse benötigt. Falls
der User sich in der Datenbank befindet bzw. sein Username schon existiert, wird der
User vom System abgewiesen und die eingegebenen Daten werden verworfen.
Abbildung 6.5.: Create new user
6.2.3. Reset password
Falls der User sein Passwort vergisst, kann der Admin dessen Passwort auf Wunsch
wieder zurücksetzen. Dieses Feature wird in Zukunft dann über eine Email abgewickelt und der User erhält sein zurückgesetztes Passwort per Mail.
6.2.4. Update User
Diese Funktionalität ist für den Admin sowie für den Anonymous User verfügbar,
d.h. sogar der Anonymous User hat das Recht, Veränderungen an seinen eigenen
Daten vorzunehmen.
6.2. User Verwaltung
69
Abbildung 6.6.: Update user
6.2.5. Delete user
Delete user dient zum Löschen eines Users aus der Datenbank. Ist der User aus
der Datenbank verworfen, gehen alle Daten über den User verloren sowie dessen
Zugehörigkeiten in den einzelnen Gruppen.
Abbildung 6.7.: Delete user
6.3. Groups verwalten
70
6.2.6. Show user groups
Mit dieser Funktion wird eine detaillierte Ausgabe über einen ausgewählten User in
den eingetragenen Gruppen dargestellt. Es werden nur die Gruppen dargestellt, in
denen sich der User auch tatsächlich befindet.
6.3. Groups verwalten
Unter dem Hauptmenüpunkt Gruppenverwaltungen verbergen sich Funktionalitäten
wie Anzeigen aller Gruppen, Erzeugen von neuen Gruppen sowie das Hinzufügen,Löschen
und die Verwaltung der Subgruppen, die eine Teilmenge der Hauptgruppen sind.
6.3.1. List all groups
Im ersten Untermenü von der Gruppenverwaltung befindet sich list all groups. Hierbei
werden alle Gruppen aufgelistet, die im System vorhanden sind. Diese Gruppen sind
eindeutig über ID’s gekennzeichnet. Weiterhin erhält man eine Kurzbeschreibung zu
den einzelnen Gruppen.
Abbildung 6.8.: List All Gropus
6.3. Groups verwalten
71
6.3.2. Create group
Create Group dient zur Erzeugung einer neuen Gruppe. Dabei wird ein eindeutiger ID der Gruppe durch das System zugeordnet. Weiterhin hat der Eintragende
die Möglichkeit den Gruppennamen sowie eine Kurzbeschreibung über den erfolgten
Eintrag einzugeben.
Abbildung 6.9.: Add new group
6.3.3. Add user to group
Ein neuer bzw. bestehender User wird zu einer vorhandenen Gruppe hinzugefügt,
somit erhält der User bestimmte Rechte, die der Gruppe auferlegt sind, und erhält
dadurch die Verknüpfung zu den Projekten und den HTML Elementen.
6.3.4. Delete group
Mit ein paar klick’s löscht man eine vorhandene Gruppe aus der Liste. Dafür wählt
man die Checkbox und geht dann auf Delete. Hierbei wird die Gruppe gelöscht,
jedoch nicht die einzelnen User, d.h. die User verlieren nur die Zugehörigkeiten zur
gelöschten Gruppe und nicht mehr.
6.3. Groups verwalten
72
Abbildung 6.10.: Delete group
6.3.5. Delete user from group
Löscht man einen User aus der Gruppe, so verliert der User die Verknüpfung zu den
einzelnen Projekten sowie zu den HTML Elementen, da der User nicht mehr in der
Gruppe existiert. Dies bedeutet jedoch nicht, dass der User komplett vom System
gelöscht wurde, sondern nur den Verlost der Berechtigung für die jeweilige Gruppe.
6.3.6. Add sub-group
In dem Untermenü add sub-group wird eine neue Gruppe einer bestehenden Maingruppe erzeugt. In diesem Falle erbt die Untergruppe alle Berechtigungen und Funktionalitäten der Maingruppe. Zu dem werden auch alle User aus der Maingruppe ein
Teil der neuen Subgruppe.
6.3.7. Delete sub-group
Mit dem Entfernen einer Subgruppe werden alle Funktionalitäten und Berechtigungen sowie die eingetragenen User gelöscht. Durch diesen Löschvorgang wird die Maingruppe, aus der die Subgruppe einmal erzeugt wurde, nicht angetastet, d.h. die Maingruppe verliert weder ihre Berechtigungen, Funktionalitäten noch die eingetragenen
6.4. PLP Security
73
User.
6.4. PLP Security
Abbildung 6.11.: PLP Security Panel
Das Admin Tool wird durch ein Gui-Interface in PLP ergänzt. Damit man die Security (Abbildung 6.11) Funktionalitäten ausnutzen kann muss, man sich auf dem PLP
als Administrator einloggen. Daher ist ein zusätzliches Login Fenster für das PLP
vorhanden, um bestimmte Elemente den verschiedenen Usern, die in unterschiedlichen Gruppen zugeordnet sind, anzuzeigen.
6.4. PLP Security
74
Die einzelnen Elemente und Pages werden durch den Menüpunt Managegroups (Abbildung 6.12) behandelt. Dabei werden bestimmte Projekte und HTML Elemente zu
bestimmten Gruppen hinzugefügt. Jede Gruppe erhält somit eine bestimmte Auswahl an HTML Elementen und Projekten, die ihr zugewiesen werden.
Abbildung 6.12.: PLP Managegroups
A. Anhang
A.1. GroupsBean.Java
/* $Id: GroupsBean.java,v 1.10 2004/12/13 06:42:15 bassem Exp $ */
package login.ejb;
import
import
import
import
import
import
import
import
import
import
java.lang.reflect.InvocationTargetException;
java.lang.reflect.Method;
java.rmi.RemoteException;
java.sql.Connection;
java.sql.DriverManager;
java.sql.ResultSet;
java.sql.SQLException;
java.sql.Statement;
java.util.Map;
java.util.Vector;
import
import
import
import
import
import
import
import
import
javax.ejb.CreateException;
javax.ejb.EJBException;
javax.ejb.EJBHome;
javax.ejb.EJBObject;
javax.ejb.SessionBean;
javax.ejb.SessionContext;
javax.naming.Context;
javax.naming.InitialContext;
javax.naming.NamingException;
75
A.1. GroupsBean.Java
76
import javax.rmi.PortableRemoteObject;
/**
* @author <a href="mailto:[email protected]">Bassem El-Ahmad</a>
*
* @ejb.bean
name = "Groups"
* display-name = "GroupsBean EJB"
* description = "EJB inorder to manged the Groups"
* view-type = "remote"
* jndi-name = "ejbs/Groups"
*/
public class GroupsBean implements SessionBean {
/**
* The Java-Mysql Connection
*
* @uml.property name="stmt"
* @uml.associationEnd multiplicity="(0 -1)" elementType="java.lang.String"
*/
private Statement stmt = null;
/**
* database connection result
*
* @uml.property name="rs"
* @uml.associationEnd multiplicity="(0 -1)" elementType="java.lang.String"
*/
private ResultSet rs = null;
private String admin;
private String all;
private String page;
A.1. GroupsBean.Java
77
private boolean loggedIn;
public GroupsBean() {
super();
}
public Connection getConnection() {
Map map = null;
try {
Context context = new InitialContext();
Object ref = context.lookup("funcEJBS/Config");
EJBHome homeObject = (EJBHome) PortableRemoteObject.narrow(ref,
EJBHome.class);
Method createMethod = homeObject.getEJBMetaData()
.getHomeInterfaceClass()
.getMethod("create", new Class[] {});
EJBObject ejbObject = (EJBObject) createMethod.invoke(homeObject,
new Object[] {});
Method method = homeObject.getEJBMetaData()
.getRemoteInterfaceClass().getMethod("getDBConnectionData",
new Class[] {});
map = (Map) method.invoke(ejbObject, new Object[] {});
Class.forName((String) map.get("driver")).newInstance();
Connection conn = DriverManager.getConnection((String) map
.get("url"), (String) map.get("username"), (String) map
.get("password"));
return conn;
} catch (NamingException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (RemoteException e) {
e.printStackTrace();
A.1. GroupsBean.Java
78
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
/**
* Adds a group
*
* @param group The Group
* @param user The user who wants to add the Group
* @throws Exception if group allready exists
* @ejb.interface-method view-type = "remote"
*/
public boolean addGroup(String groupname,String gdescription) throws Exception
String insert;
try {
Connection conn = getConnection();
if (this.groupFree(groupname)) {
stmt = conn.createStatement();
A.1. GroupsBean.Java
79
insert = ("insert into groups(gname,gdescription) values(’"
+ groupname.trim()
+ "’,’"
+ gdescription.trim() + "’)");
stmt.execute(insert);
return true;
} else{
throw new Exception(groupname + " is allready in Database!");
}
}
catch (SQLException ex) {
System.out.println("SQLException: " + ex.getMessage());
System.out.println("SQLState: " + ex.getSQLState());
System.out.println("VendorError: " + ex.getErrorCode());
}
finally {
if (rs != null) {
try {
rs.close();
} catch (SQLException sqlEx) {
rs = null;
}
}
if (stmt != null) {
try {
stmt.close();
} catch (SQLException sqlEx) {
stmt = null;
}
}
}
A.1. GroupsBean.Java
80
return false;
}
/**
* Deletes a group
* @param gid The Group ID
* @ejb.interface-method view-type = "remote"
*/
public String deleteGroup(Integer gid)throws Exception {
String result = "Group Deleted";
Connection conn = null;
try
{
conn = getConnection();
stmt = conn.createStatement();
stmt.executeUpdate("DELETE FROM groups_users WHERE gid = "+gid.intVal
stmt = conn.createStatement();
stmt.executeUpdate("delete from groups where gid ="+gid.intValue());
}catch(Exception e){
e.printStackTrace();
result = e.getMessage();
}
finally{
try{
conn.close();
A.1. GroupsBean.Java
81
}catch(SQLException ex){
}
}
return result;
}
/**
* Adds a user to a group
*
* @param group The name of the Group
* @param user The user who is to be added to the group
* @param admin The admin who wants to add to the group
* @throws Exception If user is not allowed to add users to the group
* @ejb.interface-method view-type = "remote"
*/
public boolean addUserToGroup(String gname, String uname) throws Exception {
String insert = null;
try {
Connection conn = getConnection();
if (!(groupFree(gname))) {
if (this.getUid(uname) == 0)
throw new Exception("Failed to add " + uname
+ " to group " + gname + "!");
stmt = conn.createStatement();
insert = ("insert into groups_users values (’"
+ this.getGid(gname) + "’,’"
+ this.getUid(uname) + "’)");
stmt.executeUpdate(insert);
return true;
A.1. GroupsBean.Java
82
} else
throw new Exception("Group " + gname + " does not exist");
} catch (Exception e) {
throw new Exception(e.getMessage());
}
}
/**
* Deletes a user from a group
*
* @param group The name of the Group
* @param user The user who is to be deleted from the group
* @param admin The admin who wants to delete the user
* @throws Exception If user is not allowed to delete users from group
* @ejb.interface-method view-type = "remote"
*/
public void removeUserFromGroup(String gname, String uname) throws Exception{
try {
Connection conn = getConnection();
String delete = null;
stmt = conn.createStatement();
delete = ("DELETE FROM groups_users WHERE uid = ’"
+ this.getUid(uname) + " and gid = ’"
+ this.getGid(gname) + "’)");
A.1. GroupsBean.Java
83
stmt.executeUpdate(delete);
} catch (Exception e) {
throw new Exception(e.getMessage());
}
}
/**
* Adds a element to a group
*
* @param gname The name of the Group
* @param eid Element ID
* @param pid The Project ID
* @throws Exception If user is not allowed to add users to the group
* @ejb.interface-method view-type = "remote"
*/
public void addElementToGroup(Integer eid,Integer pid, String gname) throws Ex
String insert;
try {
Connection conn = getConnection();
stmt = conn.createStatement();
insert = ("insert into element_groups values("
+ this.getGid(gname) + ","
+ eid.intValue()+"," +
pid.intValue()+ ")");
stmt.executeUpdate(insert);
} catch (Exception e) {
throw new Exception(e.getMessage());
}
}
A.1. GroupsBean.Java
84
/**
* Delete element from group
*
* @param gname The name of the Group
* @param eid Element ID
* @param pid The Project ID
* @throws Exception If user is not allowed to add users to the group
* @ejb.interface-method view-type = "remote"
*/
public void removeElementFromGroup(Integer eid,Integer pid, String gname) throws E
String insert;
try {
Connection conn = getConnection();
stmt = conn.createStatement();
insert = ("delete from element_groups where eid="+eid.intValue()+" AND pid="+
pid.intValue()+" AND gid="+getGid(gname));
stmt.executeUpdate(insert);
} catch (Exception e) {
throw new Exception(e.getMessage());
}
}
/**
* Returns a Vector of all groups
*
* @return A vector of groups (only with Groupnames)
A.1. GroupsBean.Java
85
* @throws Exception If user is not allowed to
* @ejb.interface-method view-type = "remote"
*/
public Vector getAllGroups() throws Exception ,RemoteException {
String select = null;
Vector allgroups = new Vector();
Connection conn = getConnection();
if (conn != null) {
try {
stmt = conn.createStatement();
select = "select gid,gname,gdescription,gowner from groups";
rs = stmt.executeQuery(select);
row[0]
row[1]
row[2]
row[3]
=
=
=
=
while (rs.next()) {
String[] row = new String[4];
rs.getString("gid");
rs.getString("gname");
rs.getString("gdescription");
rs.getString("gowner");
allgroups.add(row);
}
}
catch (SQLException ex) {
System.out.println("SQLException: " + ex.getMessage());
System.out.println("SQLState: " + ex.getSQLState());
System.out.println("VendorError: " + ex.getErrorCode());
}
A.1. GroupsBean.Java
finally {
if (rs != null) {
try {
rs.close();
} catch (SQLException sqlEx) {
rs = null;
}
}
if (stmt != null) {
try {
stmt.close();
} catch (SQLException sqlEx) {
stmt = null;
}
}
}
}
return allgroups;
}
/**
* Returns a Vector of all group names
*
* @return A vector of groups (only with Groupnames)
* @throws Exception If user is not allowed to
* @ejb.interface-method view-type = "remote"
*/
public Vector getGroupName() {
Vector groups = new Vector();
Connection conn = getConnection();
if (conn != null) {
try {
86
A.1. GroupsBean.Java
87
stmt = conn.createStatement();
rs = stmt.executeQuery("SELECT gname FROM groups");
while (rs.next()){
String group = new String(rs.getString("gname"));
groups.add(group);
}
}
catch (SQLException ex) {
System.out.println("SQLException: " + ex.getMessage());
System.out.println("SQLState: " + ex.getSQLState());
System.out.println("VendorError: " + ex.getErrorCode());
}
finally {
if (rs != null) {
try {
rs.close();
} catch (SQLException sqlEx) {
rs = null;
}
}
if (stmt != null) {
try {
stmt.close();
} catch (SQLException sqlEx) {
stmt = null;
}
}
}
}
return groups;
}
/**
A.1. GroupsBean.Java
* Returns a Vector of all group names
*
* @return A vector of groups (only with Groupnames)
* @throws Exception If user is not allowed to
* @ejb.interface-method view-type = "remote"
*/
public Vector getGroupNamesOfElement(Integer eid, Integer pid) {
Vector groups = new Vector();
Vector gids = new Vector();
Connection conn = getConnection();
if (conn != null) {
try {
stmt = conn.createStatement();
rs = stmt.executeQuery("SELECT gid FROM element_groups where eid="+
eid.intValue()+" AND pid="+pid.intValue());
while (rs.next()){
gids.add(new Integer(rs.getInt("gid")));
}
rs = stmt.executeQuery("SELECT gid, gname FROM groups");
while(rs.next()){
Integer i = new Integer(rs.getInt("gid"));
if(gids.contains(i)) groups.add(rs.getString("gname"));
}
}
catch (SQLException ex) {
System.out.println("SQLException: " + ex.getMessage());
System.out.println("SQLState: " + ex.getSQLState());
System.out.println("VendorError: " + ex.getErrorCode());
}
finally {
88
A.1. GroupsBean.Java
if (rs != null) {
try {
rs.close();
} catch (SQLException sqlEx) {
rs = null;
}
}
if (stmt != null) {
try {
stmt.close();
} catch (SQLException sqlEx) {
stmt = null;
}
}
}
}
return groups;
}
/**
*
* @param gid
* @param uid
* @return
* @ejb.interface-method view-type = "remote"
*/
public Vector getGroupNamesOfUser(Integer gid, Integer uid) {
Vector usergroups = new Vector();
Vector gids = new Vector();
Connection conn = getConnection();
if (conn != null) {
try {
stmt = conn.createStatement();
rs = stmt.executeQuery("SELECT gid FROM groups_users where uid="+
uid.intValue()+" AND gid="+gid.intValue());
89
A.1. GroupsBean.Java
while (rs.next()){
gids.add(new Integer(rs.getInt("gid")));
}
rs = stmt.executeQuery("SELECT gid, gname FROM groups");
while(rs.next()){
Integer i = new Integer(rs.getInt("gid"));
if(gids.contains(i)) usergroups.add(rs.getString("gname"));
}
}
catch (SQLException ex) {
System.out.println("SQLException: " + ex.getMessage());
System.out.println("SQLState: " + ex.getSQLState());
System.out.println("VendorError: " + ex.getErrorCode());
}
finally {
if (rs != null) {
try {
rs.close();
} catch (SQLException sqlEx) {
rs = null;
}
}
if (stmt != null) {
try {
stmt.close();
} catch (SQLException sqlEx) {
stmt = null;
}
}
}
}
90
A.1. GroupsBean.Java
91
return usergroups;
}
/**
* Returns the Id of a given group
*
* @param user
*
The groups name
* @return The Group id
*/
private int getGid(String group) throws Exception, RemoteException {
String select;
try {
Connection conn = getConnection();
stmt = conn.createStatement();
select = ("select gid from groups where gname =’" + group.trim() + "’"
rs = stmt.executeQuery(select);
if (rs.next()) {
return rs.getInt("gid");
} else
return 0;
} catch (Exception e) {
System.out.println(e.getMessage());
return 0;
}
}
/**
* Returns the Id of a given User
A.1. GroupsBean.Java
92
* @param user The user
* @return The Uid
*/
public int getUid(String uname) throws Exception, RemoteException {
String select;
try {
Connection conn = getConnection();
stmt = conn.createStatement();
select = ("select uid from users where username = ’" + uname + "’");
rs = stmt.executeQuery(select);
if (rs.next()) {
return rs.getInt("uid");
} else
return 0;
} catch (Exception e) {
System.out.println(e.getMessage());
return 0;
}
}
/**
* Checks if the Groupname is already used
* @param gName The name of the Group)
* @return true, if Groupname is unused, false else
*
*/
private boolean groupFree(String gname) throws Exception, RemoteException {
String select;
try {
Connection conn = getConnection();
A.1. GroupsBean.Java
93
stmt = conn.createStatement();
select = ("select * from groups where gname = ’" + gname.trim() + "’")
rs = stmt.executeQuery(select);
if (rs.next())
return false;
else
return true;
} catch (Exception e) {
System.out.println(e.getMessage());
return false;
}
}
/**
* Default create method
*
* @throws CreateException
* @ejb.create-method
*/
public void ejbCreate() throws CreateException {
}
/* (non-Javadoc)
* @see javax.ejb.SessionBean#ejbActivate()
*/
public void ejbActivate() throws EJBException, RemoteException {
// TODO Auto-generated method stub
}
/* (non-Javadoc)
* @see javax.ejb.SessionBean#ejbPassivate()
*/
A.2. UsersBean
94
public void ejbPassivate() throws EJBException, RemoteException {
// TODO Auto-generated method stub
}
/* (non-Javadoc)
* @see javax.ejb.SessionBean#ejbRemove()
*/
public void ejbRemove() throws EJBException, RemoteException {
// TODO Auto-generated method stub
}
/* (non-Javadoc)
* @see javax.ejb.SessionBean#setSessionContext(javax.ejb.SessionContext)
*/
public void setSessionContext(SessionContext arg0) throws EJBException,
RemoteException {
// TODO Auto-generated method stub
}
}
A.2. UsersBean
/* $Id: UsersBean.java,v 1.10 2004/12/05 18:41:19 bassem Exp $ */
package login.ejb;
import
import
import
import
java.lang.reflect.InvocationTargetException;
java.lang.reflect.Method;
java.rmi.RemoteException;
java.sql.Connection;
A.2. UsersBean
import
import
import
import
import
import
java.sql.DriverManager;
java.sql.ResultSet;
java.sql.SQLException;
java.sql.Statement;
java.util.Map;
java.util.Vector;
import
import
import
import
import
import
import
import
import
import
javax.ejb.CreateException;
javax.ejb.EJBException;
javax.ejb.EJBHome;
javax.ejb.EJBObject;
javax.ejb.SessionBean;
javax.ejb.SessionContext;
javax.naming.Context;
javax.naming.InitialContext;
javax.naming.NamingException;
javax.rmi.PortableRemoteObject;
95
/**
* @author <a href="mailto:[email protected]">Bassem El-Ahmad </a>
*
* @ejb.bean name = "Users"
* display-name = "UsersBean EJB"
* description = "EJB inorder to manged the Users"
* view-type = "remote"
* jndi-name = "ejbs/Users"
*/
public class UsersBean implements SessionBean {
/** A commando for the database */
private Statement stmt = null;
A.2. UsersBean
96
/** database connection result */
private ResultSet rs = null;
/**
* Is the user logged in
*
* @uml.property name="loggedIn"
*/
private boolean loggedIn;
/**
*
* @uml.property name="pass"
*/
private String pass;
public UsersBean() {
super();
}
public Connection getConnection() {
Map map = null;
try {
Context context = new InitialContext();
Object ref = context.lookup("funcEJBS/Config");
EJBHome homeObject = (EJBHome) PortableRemoteObject.narrow(ref,
EJBHome.class);
Method createMethod = homeObject.getEJBMetaData()
.getHomeInterfaceClass()
.getMethod("create", new Class[] {});
EJBObject ejbObject = (EJBObject) createMethod.invoke(homeObject,
A.2. UsersBean
}
}
}
}
}
}
}
}
}
}
new Object[] {});
Method method = homeObject.getEJBMetaData()
.getRemoteInterfaceClass().getMethod("getDBConnectionData",
new Class[] {});
map = (Map) method.invoke(ejbObject, new Object[] {});
Class.forName((String) map.get("driver")).newInstance();
Connection conn = DriverManager.getConnection((String) map
.get("url"), (String) map.get("username"), (String) map
.get("password"));
return conn;
catch (NamingException e) {
e.printStackTrace();
catch (SecurityException e) {
e.printStackTrace();
catch (RemoteException e) {
e.printStackTrace();
catch (NoSuchMethodException e) {
e.printStackTrace();
catch (IllegalArgumentException e) {
e.printStackTrace();
catch (IllegalAccessException e) {
e.printStackTrace();
catch (InvocationTargetException e) {
e.printStackTrace();
catch (InstantiationException e) {
e.printStackTrace();
catch (ClassNotFoundException e) {
e.printStackTrace();
catch (SQLException e) {
e.printStackTrace();
}
return null;
}
97
A.2. UsersBean
98
/**
* Adds a user
*
* @param user The username
* @param admin The admin who adds the user
* @throws Exception If user is not allowed to add an user or if user allready exi
*
* @ejb.interface-method view-type = "remote"
*/
public boolean addUser(String username, String realname, String email, String
String insert;
try {
Connection conn = getConnection();
if (this.userFree(username)) {
stmt = conn.createStatement();
insert = ("insert into users(username, realname, email, password)
+ username.trim()
+ "’,’"
+ realname.trim()
+ "’,’"
+ email.trim()
+ "’,’"
+ password.trim() + "’)");
stmt.execute(insert);
return true;
} else{
throw new Exception(username + " is allready in Database!");
}
}
catch (SQLException ex) {
System.out.println("SQLException: " + ex.getMessage());
A.2. UsersBean
99
System.out.println("SQLState: " + ex.getSQLState());
System.out.println("VendorError: " + ex.getErrorCode());
}
finally {
if (rs != null) {
try {
rs.close();
} catch (SQLException sqlEx) {
rs = null;
}
}
if (stmt != null) {
try {
stmt.close();
} catch (SQLException sqlEx) {
stmt = null;
}
}
}
return false;
}
/**
Deletes a User
@param user the user who is going to be deleted
@param admin the admin who wants to delete the user (can be the user)
@throws Exception If user is not allowed to delete user
*
*
*
*
*
* @ejb.interface-method view-type = "remote"
*/
public String deleteUser(Integer uid) throws Exception {
String result = "User Deleted";
A.2. UsersBean
100
String delete = null;
String select = null;
String toDelete = null;
try {
Connection conn = getConnection();
//User is deleted from the groups_users table
stmt = conn.createStatement();
stmt.executeUpdate("delete from groups_users where uid ="+uid.intV
//User is deleted from the user table
stmt = conn.createStatement();
stmt.executeUpdate("delete from users where uid ="+uid.intValue())
//All groups owned by user are deleted
stmt = conn.createStatement();
stmt.executeUpdate("select * from groups where gowner ="+uid.intVa
}
catch (SQLException ex) {
System.out.println("SQLException: " + ex.getMessage());
System.out.println("SQLState: " + ex.getSQLState());
System.out.println("VendorError: " + ex.getErrorCode());
}
finally {
if (rs != null) {
try {
rs.close();
} catch (SQLException sqlEx) {
rs = null;
}
}
if (stmt != null) {
try {
stmt.close();
} catch (SQLException sqlEx) {
A.2. UsersBean
101
stmt = null;
}
}
}
return result;
}
/**
* Updates data of a specific user
*
* @param username The (old) name of the user who is going to be updated
* @param user The new user data
* @param admin The admin who wants to change the Data
* @throws Exception If user is not allowed to update user or if new username allr
*
* @ejb.interface-method view-type = "remote"
*/
public void updateUser(String username, String realname, String email,
String password) throws Exception, RemoteException {
String update = null;
try {
Connection conn = getConnection();
if ((!(username.equals(username))) && this.userFree(username)) {
stmt = conn.createStatement();
update = "update users set username = ’" + username
+ "’, realname = ’" + realname + "’, email = ’" + email
+ "’ where uid = " + this.getUid(username) + ";";
stmt.executeUpdate(update);
} else
throw new Exception("Username " + username
+ " is allready in use");
}
catch (SQLException ex) {
A.2. UsersBean
102
System.out.println("SQLException: " + ex.getMessage());
System.out.println("SQLState: " + ex.getSQLState());
System.out.println("VendorError: " + ex.getErrorCode());
}
finally {
if (rs != null) {
try {
rs.close();
} catch (SQLException sqlEx) {
rs = null;
}
}
if (stmt != null) {
try {
stmt.close();
} catch (SQLException sqlEx) {
stmt = null;
}
}
}
}
/**
Returns a User
@param user The user
@param admin The admin who wants the userdata (can be the user)
@return A User
@throws Exception If user is not allowed to get the user
*
*
*
*
*
*
* @ejb.interface-method view-type = "remote"
*/
public String[] getUser(String username) throws Exception, RemoteException {
String select = null;
A.2. UsersBean
103
String[] returnUser = null;
String str = null;
Statement stmt = null;
ResultSet rs = null;
String iproj = null;
try {
Connection conn = getConnection();
stmt = conn.createStatement();
select = "select username,realname,email from users where username = ’
rs = stmt.executeQuery(select);
if (rs.next()) {
returnUser = new String[3];
returnUser[0] = rs.getString("username");
returnUser[1] = rs.getString("realname");
returnUser[2] = rs.getString("email");
} else
throw new Exception("User " + username + "does not exist");
}
catch (SQLException ex) {
System.out.println("SQLException: " + ex.getMessage());
System.out.println("SQLState: " + ex.getSQLState());
System.out.println("VendorError: " + ex.getErrorCode());
}
finally {
if (rs != null) {
try {
rs.close();
} catch (SQLException sqlEx) {
rs = null;
}
A.2. UsersBean
}
if (stmt != null) {
try {
stmt.close();
} catch (SQLException sqlEx) {
stmt = null;
}
}
}
return returnUser;
}
/**
* Returns a Vector of Users
*
* @return A vector of User objects (but only with the Usernames)
* @throws Exception If user is not allowed to
*
* @ejb.interface-method view-type = "remote"
*/
public Vector getAllUser() throws Exception, RemoteException {
String select = null;
Vector allUser = new Vector();
Connection conn = getConnection();
if (conn != null) {
try {
Statement stmt = conn.createStatement();
select = "select uid,username,realname,email from users";
104
A.2. UsersBean
rs = stmt.executeQuery(select);
while (rs.next()) {
String[] row = new String[4];
row[0] = rs.getString("uid");
row[1] = rs.getString("username");
row[2] = rs.getString("realname");
row[3] = rs.getString("email");
allUser.add(row);
}
}
catch (SQLException ex) {
System.out.println("SQLException: " + ex.getMessage());
System.out.println("SQLState: " + ex.getSQLState());
System.out.println("VendorError: " + ex.getErrorCode());
}
finally {
if (rs != null) {
try {
rs.close();
} catch (SQLException sqlEx) {
rs = null;
}
}
if (stmt != null) {
try {
stmt.close();
} catch (SQLException sqlEx) {
stmt = null;
}
}
}
}
return allUser;
105
A.2. UsersBean
106
}
/**
Checks if a user exists and uses the correct password
@param User The user
@param password The password
@return The user who is logged in
@throws Exception If user is unable to login
*
*
*
*
*
*
* @ejb.interface-method view-type = "remote"
*/
public Integer login(String userName, String password) {
Integer result = new Integer(-1);
try {
Connection conn = getConnection();
stmt = conn.createStatement();
String sql = "SELECT uid FROM users" + " WHERE username=’"
+ userName + "’" + " AND password=’" + password + "’";
ResultSet rs = stmt.executeQuery(sql);
if (rs.next()) {
result = new Integer(rs.getInt("uid"));
rs.close();
stmt.close();
conn.close();
}
}
catch (SQLException ex) {
System.out.println("SQLException: " + ex.getMessage());
A.2. UsersBean
107
System.out.println("SQLState: " + ex.getSQLState());
System.out.println("VendorError: " + ex.getErrorCode());
}
finally {
if (rs != null) {
try {
rs.close();
} catch (SQLException sqlEx) {
rs = null;
}
}
if (stmt != null) {
try {
stmt.close();
} catch (SQLException sqlEx) {
stmt = null;
}
}
}
return result;
}
/**
Checks if a user exists in group
@param Username The user
@param Groupname The groupname
@return True if the user part the group else return false
@throws Exception If user is unable to login
*
*
*
*
*
*
* @ejb.interface-method view-type = "remote"
*/
public boolean isUserinGroup(String username, String groupname) throws Excepti
A.2. UsersBean
108
RemoteException {
String sql = "select * from gruops, users where gruops.gname = \’"
+ groupname + "\’ ";
sql += " and group.gid = users.gid ";
sql += ("and user.username = \’" + username + "\’ ");
System.out.println(sql);
boolean ret = false;
ResultSet r = null;
try {
Connection conn = getConnection();
Statement select = conn.createStatement();
sql = new String(sql.getBytes("SJIS"), "8859_1");
r = select.executeQuery(sql);
ret = r.first();
select.close();
conn.close();
}
catch (SQLException ex) {
System.out.println("SQLException: " + ex.getMessage());
System.out.println("SQLState: " + ex.getSQLState());
System.out.println("VendorError: " + ex.getErrorCode());
}
finally {
if (rs != null) {
try {
rs.close();
} catch (SQLException sqlEx) {
rs = null;
}
}
if (stmt != null) {
try {
stmt.close();
A.2. UsersBean
109
} catch (SQLException sqlEx) {
stmt = null;
}
}
}
return ret;
}
/**
Allows the admin to change an Users password
@param user The user whos password is going to be change
@param admin the admin
@param password The new password
@throws Exception If user is not allowed to set password
*
*
*
*
*
*
* @ejb.interface-method view-type = "remote"
*/
public void setpassword(String username, String admin, String password)
throws Exception, RemoteException {
String update = null;
try {
Connection conn = getConnection();
if (this.checkAdmin(admin)) {
stmt = conn.createStatement();
update = "update users set password = sha1(\"" + password
+ "\") where uid = " + this.getUid(username) + ";";
stmt.executeUpdate(update);
} else
throw new Exception(
"You are not allowed to change the password of user "
+ username);
}
catch (SQLException ex) {
A.2. UsersBean
110
System.out.println("SQLException: " + ex.getMessage());
System.out.println("SQLState: " + ex.getSQLState());
System.out.println("VendorError: " + ex.getErrorCode());
}
finally {
if (rs != null) {
try {
rs.close();
} catch (SQLException sqlEx) {
rs = null;
}
}
if (stmt != null) {
try {
stmt.close();
} catch (SQLException sqlEx) {
stmt = null;
}
}
}
}
/**
Allows an user to change his password
@param user The user who wants to change his passwod
@param password The new password
@throws Exception If user is not allowed to set password
*
*
*
*
*
* * @ejb.interface-method view-type = "remote"
*/
public void userSetpassword(String username, String password) throws Exception
RemoteException {
String update = null;
try {
Connection conn = getConnection();
A.2. UsersBean
111
stmt = conn.createStatement();
update = "update users set password = sha1(\"" + password
+ "\") where uid = " + this.getUid(username) + ";";
stmt.executeUpdate(update);
}
catch (SQLException ex) {
System.out.println("SQLException: " + ex.getMessage());
System.out.println("SQLState: " + ex.getSQLState());
System.out.println("VendorError: " + ex.getErrorCode());
}
finally {
if (rs != null) {
try {
rs.close();
} catch (SQLException sqlEx) {
rs = null;
}
}
if (stmt != null) {
try {
stmt.close();
} catch (SQLException sqlEx) {
stmt = null;
}
}
}
}
/**
* Returns the Id of a given User
* @param user The user
* @return The Uid
*
A.2. UsersBean
112
* @ejb.interface-method view-type = "remote"
*/
public int getUid(String username) {
int re_uid = -1;
try {
Connection conn = getConnection();
Statement select = conn.createStatement();
String sql = "select * from users where " + "users.username = \""
+ username + "\"";
sql = new String(sql.getBytes("SJIS"), "8859_1");
ResultSet res = select.executeQuery(sql);
if (res.first()) {
re_uid = res.getInt("uid");
}
select.close();
conn.close();
} catch (Exception err) {
System.out.println("Error in SQL query: " + err);
}
return re_uid;
}
/**
* Checks if the username is already used
* @param username The name of the User
* @return true, if username is unused, false else
*/
private boolean userFree(String username) throws Exception, RemoteException {
A.2. UsersBean
113
String select;
try {
Connection conn = getConnection();
stmt = conn.createStatement();
select = ("select * from users where username = ’" + username.trim() +
rs = stmt.executeQuery(select);
if (rs.next())
return false;
else
return true;
} catch (Exception e) {
System.out.println(e.getMessage());
return false;
}
}
/**
*
* @uml.property name="loggedIn"
*/
public void setLoggedIn(boolean status) {
this.loggedIn = status;
}
/**
*
* @uml.property name="pass"
*/
public void setPassword(String pass) {
final String password = null;
this.pass = password;
A.2. UsersBean
114
}
/**
* Allows an Admin to set a new admin
*
* @param newAdmin The new admin
* @param admin The admin who wants to set the new Admin
* @throws Exception If user is not allowed to set a new admin
*/
public void setAdmin(String newAdmin, String admin) throws Exception,
RemoteException {
String update = null;
try {
Connection conn = getConnection();
if ( checkAdmin(admin)) {
if (!(this.userFree(newAdmin))) {
stmt = conn.createStatement();
update = "update users set adminflag = \"" + ’a’
+ "\" where uid = " + this.getUid(newAdmin) + ";";
stmt.executeUpdate(update);
} else
throw new Exception(newAdmin + " does not exist!");
} else
throw new Exception("You are not allowed to set new Admins");
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
/**
* Checks if a user is a global admin
* @param admin The (potential) admin
A.2. UsersBean
115
* @return true if user is admin, false else
*/
private boolean checkAdmin(String admin) throws Exception, RemoteException {
String select = null;
try {
Connection conn = getConnection();
stmt = conn.createStatement();
select =
("SELECT * FROM users WHERE username = ’" + admin + "’ AND adminflag =
rs = stmt.executeQuery(select);
if (rs.next())
return true;
else
return false;
} catch (Exception e) {
System.out.println(e.getMessage());
return false;
}
}
/**
* Default create method
*
* @throws CreateException
* @ejb.create-method
*
*/
public void ejbCreate() throws CreateException {
A.2. UsersBean
116
}
/**
* (non-Javadoc)
*
* @see javax.ejb.SessionBean.ejbActivate()
*/
public void ejbActivate() throws EJBException, RemoteException {
// TODO Auto-generated method stub
}
/**
* (non-Javadoc)
*
* @see javax.ejb.SessionBean.ejbPassivate()
*/
public void ejbPassivate() throws EJBException, RemoteException {
// TODO Auto-generated method stub
}
/**
* (non-Javadoc)
*
* @see javax.ejb.SessionBean.ejbRemove()
*/
public void ejbRemove() throws EJBException, RemoteException {
// TODO Auto-generated method stub
}
A.3. PagesBean
117
/**
* (non-Javadoc)
*
* @see javax.ejb.SessionBean.setSessionContext(javax.ejb.SessionContext)
*/
public void setSessionContext(SessionContext arg0) throws EJBException,
RemoteException {
// TODO Auto-generated method stub
}
}
A.3. PagesBean
/* $Id: PagesBean.java,v 1.10 2004/12/10 20:02:35 bassem Exp $ */
package login.ejb;
import
import
import
import
import
import
import
import
import
import
import
import
java.io.UnsupportedEncodingException;
java.lang.reflect.InvocationTargetException;
java.lang.reflect.Method;
java.rmi.RemoteException;
java.sql.Connection;
java.sql.DriverManager;
java.sql.ResultSet;
java.sql.SQLException;
java.sql.Statement;
java.util.Iterator;
java.util.Map;
java.util.Vector;
import javax.ejb.CreateException;
A.3. PagesBean
import
import
import
import
import
import
import
import
import
118
javax.ejb.EJBException;
javax.ejb.EJBHome;
javax.ejb.EJBObject;
javax.ejb.SessionBean;
javax.ejb.SessionContext;
javax.naming.Context;
javax.naming.InitialContext;
javax.naming.NamingException;
javax.rmi.PortableRemoteObject;
/**
* @author <a href="mailto:[email protected]">Bassem El-Ahmad</a>
*
* @ejb.bean
name = "Pages"
* display-name = "PagesBean EJB"
* description = "EJB in order to managed the Page"
* view-type = "remote"
* jndi-name = "ejbs/Pages"
*/
public class PagesBean implements SessionBean {
private Connection conn;
public PagesBean() {
super();
// TODO Auto-generated constructor stub
}
public Connection getConnection() {
Map map = null;
try {
Context context = new InitialContext();
Object ref = context.lookup("funcEJBS/Config");
A.3. PagesBean
EJBHome homeObject = (EJBHome) PortableRemoteObject.narrow(ref,
EJBHome.class);
Method createMethod = homeObject.getEJBMetaData()
.getHomeInterfaceClass()
.getMethod("create", new Class[] {});
EJBObject ejbObject = (EJBObject) createMethod.invoke(homeObject,
new Object[] {});
Method method = homeObject.getEJBMetaData()
.getRemoteInterfaceClass().getMethod("getDBConnectionData",
new Class[] {});
map = (Map) method.invoke(ejbObject, new Object[] {});
Class.forName((String) map.get("driver")).newInstance();
Connection conn = DriverManager.getConnection((String) map
.get("url"), (String) map.get("username"), (String) map
.get("password"));
return conn;
} catch (NamingException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (RemoteException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
119
A.3. PagesBean
120
e.printStackTrace();
}
return null;
}
/**
* detects whether a HTML element is visible or not
* @throws Exception if group allready exists
* @ejb.interface-method view-type = "remote"
*/
public Boolean isVisible(Integer userID,Integer projectID,Integer pageID,
Integer elementID,Vector pageHierarchy){
Vector userGroups = getGroupsForUser(userID.intValue());
Vector elementGroups = getGroupNamesOfElement(elementID,projectID);
if(elementGroups.size() == 0){
elementGroups = getGroupNamesOfElement(pageID,projectID);
}
if(elementGroups.size() == 0){
for(int i = 0; i < pageHierarchy.size() && elementGroups.size() == 0 ; i++){
Integer tmp = (Integer)pageHierarchy.elementAt(i);
elementGroups = getGroupNamesOfElement(tmp,projectID);
}
}
return new Boolean(compareGroups(userGroups,elementGroups));
}
private boolean compareGroups(Vector userGroups ,Vector elementGroups){
A.3. PagesBean
121
boolean result = false;
for (int i = 0; i < userGroups.size(); i++) {
if(elementGroups.contains(userGroups.get(i))){
result = true;
break;
}
}
return result;
}
private Vector getGroupsForUser(int uid){
Vector result = new Vector();
String sql = "select gid from groups_users where uid="+uid;
boolean ret = false;
ResultSet rs = null;
//Connection conn = null;
try {
//conn = getConnection();
Statement select = conn.createStatement();
rs = select.executeQuery(sql);
while(rs.next()){
result.add(new Integer(rs.getInt("gid")));
}
//iyad:temp loesung jeder User ist auch in der Gruppe
//anonymous mitglied, bessere Loesung mit SubGruppen
rs = select.executeQuery("select gid from groups where gname=’anonymous’");
if(rs.next()){
result.add(new Integer(rs.getInt("gid")));
}
} catch (Exception err) {
System.out.println(err.getMessage());
}
finally{
//try{
// conn.close();
A.3. PagesBean
122
//}catch(SQLException ex){
//}
}
return result;
}
private Vector getGroupNamesOfElement(Integer eid, Integer pid) {
Vector groups = new Vector();
Vector gids = new Vector();
ResultSet rs = null;
//Connection conn = getConnection();
if (conn != null) {
try {
Statement stmt = conn.createStatement();
rs = stmt.executeQuery("SELECT gid FROM element_groups where eid="+
eid.intValue()+" AND pid="+pid.intValue());
while (rs.next()){
gids.add(new Integer(rs.getInt("gid")));
}
rs = stmt.executeQuery("SELECT gid, gname FROM groups");
while(rs.next()){
Integer i = new Integer(rs.getInt("gid"));
if(gids.contains(i)) groups.add(i);
}
}
catch (SQLException ex) {
System.out.println("SQLException: " + ex.getMessage());
System.out.println("SQLState: " + ex.getSQLState());
System.out.println("VendorError: " + ex.getErrorCode());
}
A.3. PagesBean
123
finally {
//try {
//conn.close();
//} catch (SQLException sqlEx) {
//}
}
}
return groups;
}
/**
* Default create method
*
* @throws CreateException
* @ejb.create-method
*/
public void ejbCreate() throws CreateException {
conn = getConnection();
System.out.println("dbConection created for PagesBean");
}
/* (non-Javadoc)
* @see javax.ejb.SessionBean.ejbActivate()
*/
public void ejbActivate() throws EJBException, RemoteException {
// TODO Auto-generated method stub
}
/* (non-Javadoc)
* @see javax.ejb.SessionBean.ejbPassivate()
*/
A.3. PagesBean
124
public void ejbPassivate() throws EJBException, RemoteException {
// TODO Auto-generated method stub
}
/* (non-Javadoc)
* @see javax.ejb.SessionBean.ejbRemove()
*/
public void ejbRemove() throws EJBException, RemoteException {
if(conn != null){
try{
conn.close();
}catch(Exception ex){
System.out.println("Exception while closing the database connection in "
+"PagesBean");
System.out.println(ex.getMessage());
}
}
System.out.println("PagesBean removed");
}
/* (non-Javadoc)
* @see javax.ejb.SessionBean.setSessionContext(javax.ejb.SessionContext)
*/
public void setSessionContext(SessionContext arg0) throws EJBException,
RemoteException {
// TODO Auto-generated method stub
}
}
Literaturverzeichnis
[JMS ] :
Java Message Service.
http://java.sun.com/products/jms/
[RMI ] :
The Java Remote Method Invocation.
http://java.sun.com/docs/books/tutorial/rmi
[JBoss ] :
JBoss Developer Zone.
http://www.jboss.org
[NBT ] :
Net Business Tool.
http://venus.cs.tu-berlin.de/
[PostgreSQL ] :
PostgreSQL.
http://www.postgresql.org/
[Rational ] :
Rational.
http://www.rational.com
[UML-Uebersicht ] :
Eine recht umfangreiche UML Uebersicht.
http://www.jeckle.de/unified.htm
[Servlet-Specification ]
:
125
Literaturverzeichnis
Servlet Specification Version 2.4.
http://java.sun.com/products/servlet/
[Together-Technologies ] :
Together technologies.
http://www.togethersoft.com
[XDoclet ] :
What is XDoclet.
http://xdoclet.sourceforge.net/xdoclet/index.html
[Alhir 2003] Alhir, Sinan S. (Hrsg.):
Learning UML.
O’Reilly, 2003
[Balzert 2001] Balzert, Heide (Hrsg.):
UML kompakt.
Spektrum, 2001
[Bannert 1999] Bannert, Weitzel M. (Hrsg.):
Objektorientierter Softwareentwurf mit UML.
Addison-Wesley, 1999
[Denninger 2000] Denninger, S. (Hrsg.):
Enterprise JavaBeans.
Addison-Wesley, 2000
[Goodwill 2000] Goodwill, James (Hrsg.):
Pure JSP – Java Server Pages: A Code-Intensive Premium Reference.
Sams, 2000
[Jason Hunter 1998] Jason Hunter, William C. (Hrsg.):
Java Servlet Programming.
OReilly, 1998
[KOLB 2000] KOLB, DUANE K. FIELDS MARK A. (Hrsg.):
Web Development with JavaServer Pages.
Manning Publications Co, 2000
126
Literaturverzeichnis
127
[Kurniawann 2002] Kurniawann, Budi (Hrsg.):
Java for the Web with Servlets, JSP, and EJB: A Developer’s Guide to J2EE
Solutions.
New Riders Publishing, 2002
[Monson-Haefel 2000] Monson-Haefel, R. (Hrsg.):
2. Auflage Enterprise JavaBeans.
OReilly, 2000
[Perry 2004] Perry, Bruce W. (Hrsg.):
Java Servlet and JSP Cookbook.
O’Reilly, 2004
[Sams 1999] Sams (Hrsg.):
Sams Teach Yourself UML in 24 Hours.
Macmillan Computer Publishing, 1999
[Sullins und Whipple May 2003]
Sullins, Benjamin G. (Hrsg.) ; Whipple,
Mark B. (Hrsg.):
EJB Cookbook.
Manning Publications Co, May 2003
[Turner March 27, 2002] Turner, James (Hrsg.):
MySQL and JSP Web Applications:ata-Driven Programming Using Tomcat and
MySQL.
Sams Publishing, March 27, 2002
[Zimmermann 2000] Zimmermann, J. (Hrsg.):
Verteilte Komponenten und Datenbankanbindung.
Addison-Wesley, 2000
Herunterladen