Beschreibung

Werbung
TLGen
Beschreibung
EJB3 Backend Code-Generator
Version 2.5 (Deutsch)
Autoren:
Titus Livius Rosu
([email protected])
Titus Rosu
([email protected])
Liviu Rosu
([email protected])
Letzte Änderung: 27. April 2011
Table of Contents
Inhaltsverzeichnis
ABBILDUNGSVERZEICHNIS ............................................................................................................................... 3
TABELLENVERZEICHNIS .................................................................................................................................... 3
1.
ALLGEMEINE INFORMATION .................................................................................................................... 4
1.1 ZIELE ............................................................................................................................................................... 6
1.2 TLGEN´S ARCHITEKTUR-KONZEPT ......................................................................................................................... 7
1.2.1 Input für die Code-Generierung ............................................................................................................. 8
1.3 BESCHREIBUNG DER MÖGLICHKEITEN DURCH TLGEN ................................................................................................ 8
1.3.1 Code Generierung mit einem Domain Model (UML) ............................................................................. 9
1.3.2 Code Generierung mit einer schon vorhandenen Datenbank .............................................................. 10
2.
TLGEN CODE-GENERIERUNG UND DIE ANALYSE VON DATENBANKEN ................................................... 11
2.1 ANALYSE DES DOMAINMODELLS UND DER DATENBANK ........................................................................................... 12
2.2 DATEN KLASSEN - INTERFACES ............................................................................................................................ 16
2.3 SESSION BEAN ................................................................................................................................................. 17
2.3.1 Interfaces für eine Session Bean .......................................................................................................... 19
2.3.2 XML Persistente Datei ......................................................................................................................... 20
2.3.3 Interface Klassen zu Fachlogik Komponenten ..................................................................................... 21
2.3.4 Interceptors ......................................................................................................................................... 21
2.4 CLIENTS, BCI (BUSINESS COMMON INTERFACE)..................................................................................................... 22
2.4.1 Test Klassen ......................................................................................................................................... 23
2.4.1.1 Verwendung von Test Daten aus externen Dateien ...................................................................................... 24
2.5 MANAGER KLASSEN ......................................................................................................................................... 25
2.5.1 Manager Interfaces ............................................................................................................................. 27
2.6 ENTITY BEANS ................................................................................................................................................. 28
2.6.1 Relationen ........................................................................................................................................... 32
2.6.1.1 Relation „OneToMany“ .................................................................................................................................. 32
2.6.1.2 Relation „ManyToOne“ .................................................................................................................................. 33
2.6.1.3 Relation „OneToOne“ .................................................................................................................................... 34
2.6.1.4 Relation „ManyToMany“ ............................................................................................................................... 34
2.7 GENERIERUNG VON DATENBANK UND SQL SKRIPTE................................................................................................ 37
2.8 REGEL FÜR DIE GENERIERUNG VON NAMEN .......................................................................................................... 37
2.9 LOG DATEIEN BESCHREIBUNG............................................................................................................................. 38
2.10 MESSAGE DRIVEN BEAN.................................................................................................................................. 40
2.11 SERVICES ...................................................................................................................................................... 40
2.11.1 Timer Service ..................................................................................................................................... 40
2.11.2 Web Services...................................................................................................................................... 41
2.11.3 Callback Klasse .................................................................................................................................. 41
2.12 FREE KLASSE ................................................................................................................................................. 41
3.
VERGLEICH ZWISCHEN TLGEN UND ANDEREN CODE GENERATOREN ..................................................... 43
TLGen
2
StarData GmbH
Table of Contents
Abbildungsverzeichnis
ABBILDUNG 1: IT PROJEKT-ARCHITEKTUR............................................................................................................... 5
ABBILDUNG 2: TLGEN ARCHITEKTUR-KONZEPT ...................................................................................................... 8
ABBILDUNG 3: TLGEN-GENERIERUNGSPROZESS VOR EINER DATENBANK ........................................................... 11
ABBILDUNG 4: UML-KLASSENDIAGRAMM I .......................................................................................................... 13
ABBILDUNG 5: UML-KLASSENDIAGRAMM II ......................................................................................................... 13
ABBILDUNG 6: UML-KLASSENDIAGRAMM III ........................................................................................................ 14
ABBILDUNG 7: UML-KLASSENDIAGRAMM IV ........................................................................................................ 14
ABBILDUNG 8: „ONETOMANY“ ............................................................................................................................. 33
ABBILDUNG 9: „ONETOMANY“ DATENMODELL ................................................................................................... 33
ABBILDUNG 10: „MANYTOMANY“ DARSTELLUNG IM UML DOMAINMODELL ..................................................... 35
ABBILDUNG 11: „MANYTOMANY“ DB RELATION ................................................................................................. 35
Tabellenverzeichnis
TABELLE 1: JAVA-TYPEN ........................................................................................................................................ 16
TABELLE 2: ANNOTATIONEN ................................................................................................................................. 18
TABELLE 3: AUTOMATISCH GENERIERBARE DEFAULT METHODEN ...................................................................... 25
TABELLE 4: ANNOTATIONEN FÜR MANAGER KLASSEN ........................................................................................ 27
TABELLE 5: ANNOTATIONEN FÜR ENTITY BEANS (EJB3) ....................................................................................... 29
TABELLE 6: NAMEN-REGEL .................................................................................................................................... 38
TABELLE 7: ANNOTATIONEN FÜR MESSAGE DRIVEN BEAN .................................................................................. 40
TLGen
3
StarData GmbH
V 2.501
1. Allgemeine Information
„Wissen ist Macht“ hat der englische Philosoph Francis Bacon im sechzehnten Jahrhundert
gesagt. Um sich Wissen anzueignen, braucht man Daten.
Daten sind darstellbare Elemente einer Information, mit deren Hilfe Eigenschaften einer
Aktivität beschrieben und in Systemen verarbeitet werden. Heutzutage entsprechen diese
Systeme den Computern, die in einer digitalen Form Daten verarbeiten.
Durch die stetig ansteigende Computerleistung in Verbindung mit Datenbankensystemen
und Vernetzung (z.B. durch Internet) sind wir begraben unter einer Flut an Daten, die
Systeme regelrecht zusammenbrechen lassen.
Wir benötigen für den täglichen Tagesablauf eine Fülle an Informationen (z.B.
Banküberweisungen, Emailverkehr, CRM/ERP-Systeme), die wir immer öfter nicht mehr in
einer effizienten Form erhalten (z.B. Systemabstürze, Unterbrechungen, fehlende Daten).
Ein Hauptgrund dieser Problematik findet sich in den Verfahren mit dem die Daten gesucht
sowie abgespeichert werden.
Das heutige Standardverfahren für die Datenverwaltung der Informationen bevorzugt den
Einsatz von relationalen Datenbanken (z. b. Oracle, DB2 von IBM, MySQL, SQL Server von
Microsoft etc.) sowie von Applikation Servern bevorzugt (z. b. JBoss, WebLogic von Oracle,
WebSphere von IBM etc.).
Die zwei Komponenten - Datenbanken und Application Server -, werden in einer Persistenzschicht integriert, welche Teil eines Programms ist, das die Fachlogik darstellt, notwendig für
eine bestimmte Aktivität (siehe Abbildung 1).
Der Nutzer (User) verwendet ein Programm über die Bedienoberfläche (GUI oder Web), die
sich meist auf einem getrennten Computer, dem Client, befindet. Der Client holt sich die
Informationen, die er benötigt, von einem Server, wo sich die Fachlogik des Programms
sowie die Datenbank befinden. Nach heutigem technischem Stand wird die Steuerung der
Kommunikation zwischen Client und Server durch einen Application Server gesteuert, der
gleichzeitig die Daten innerhalb der Datenbank mit Hilfe von so genannten CRUDs (Create,
Read, Update, Delete) verwaltet.
Die Persistenzschicht ist ein essentiell wichtiger Teil eines jeden IT Programms und
verursacht den Hauptanteil der Programmentwicklungskosten zusammen mit Wartung und
Erweiterungen durch neue Features. Der Kostenwand wird durch den Einsatz von
relationalen Datenbanken weiter ausgebaut.
Zurzeit sind die wichtigsten Gründe für erhöhte Kosten im IT Sektor:

Falsche Modellierung von Daten-Modellen sowie die Anwendung von DatenModellen, die nicht genormt sind (wichtig ist die dritte Normalform)

Daten-Modelle, die Historisch gewachsen sind

Die Persistenzschicht ist nicht optimal gestaltet worden und benötigt einen zu großen
Aufwand an Wartung und Weiterentwicklung

Mischung von technischem mit fachlichem Code (siehe Anmerkung)
Anmerkung:
In der Softwareentwicklung sind drei Typen von Code zu unterscheiden:

Technischer Code: Code, der zu 100 % unabhängig von der Fachlogik ist.

Generierbarer Code: Ist gemischter Code, der aus technischem und fachlogischem
Code besteht (nur Datenstruktur). Dieser Code Typ lässt sich zu 100 % generieren
und somit die Entwicklung-, Wartung- sowie Weiterentwicklungs-Kosten von IT
Projekten enorm reduzieren.
TLGen
4
StarData GmbH
V 2.501
o

In Abb. 1 entspricht dieser Code Typ den Session Beans, der Persistence
Data (Objects/Interfaces), den Managern, der Entity Beans, BCI, JUnit (Test)
und den Interfaces der Business Tier. Das umfasst 40 – 80 % der
Entwicklungskosten eines IT Projekt (siehe 1.2.1).
Fachlogik-Code: Ist zu 100 % spezifisch für jedes einzelne IT Projekt. Zu diesem
Typ gehören z.B. die Gestaltung der Oberfläche (Präsentation Tier) oder die
Kommunikationsschnittstellen für Partnersysteme etc.
Abbildung 1: IT Projekt-Architektur
TLGen ist ein Generator für den gemischten Java Code auf Basis von EJB 3, eine Thematik,
die detailliert in Kapitel 1 erläutert wird (siehe auch www.tlgen.com).
In Kapitel 2 wird die Verwendung von TLGen mit der genauen Offenlegung seiner Features
in Kombination mit der Ordnerstruktur der Konfigurationsdatei, woraus man die
Projektarchitektur gestalten kann, beschrieben.
In Kapitel 3 werden Beispiele zur Code-Generierung mit Hilfe der Konfigurationsdatei
genannt.
TLGen
5
StarData GmbH
V 2.501
Kapitel 4 behandelt die Möglichkeiten, die TLGen ermöglicht, um z.B. die Datenmodelle zu
optimieren oder Kreise in Datenmodelle zu vermeiden. Gleichzeitig werden die Logdateien
beschrieben, die bei der Generierung entstehen.
Im Kapitel 5 wird die Installation und Verwendung von TLGen in IT Projekte beschrieben.
1.1 Ziele
TLGen ist ein Code-Generator auf Basis von EJB3 mit Java Annotationen. Ziel unserer
Arbeit war, die Kosten für die Backend-Softwareentwicklung durch eine komplette
Generierung von Code zu minimieren.
Aktuelle Code-Generatoren auf Basis des MDA Ansatzes (Hibernate, TopLink etc.)
benötigen nach der Generierung auch einen bedeutenden Arbeitsaufwand durch die
Entwickler, nachträgliches Customizing, so dass der angesetzte Zeitgewinn durch weiteren
Aufwand verfällt. Der Mix aus generiertem Code und den von Programmierern entwickelten
Code (manuelle Entwicklung) führen in der Realität zu einer Anzahl von Problemen
(unterschiedliche Logik, Layout, Auseinanderdriften von Modell und Code, Fehler etc.).
Dies ist der Grund, warum der Ansatz von TLGen eine klare Trennung zwischen dem
generierten und manuell entwickelten Code fordert. In der IT wurde des Öfteren bewiesen,
dass sich ein sehr großer Teil von Code vollständig generieren lässt. TLGen ermöglicht
diese Generierung mit Hilfe des Daten-Inputs in Form eines Domainmodells (neue Projekte)
oder einer schon existieren Datenbank (Refactoring Projekte von Legacy Systemen) in
Verbindung mit zwei Konfigurationsdateien (beinhalten die Steuerungsparameter für die
Generierung).
TLGen benötigt zwei Konfigurationsdateien: eine für allgemeine Definitionen, wie DatenTypen, Konvertierung, etc., die nur selten zu ändern ist (wird mit TLGen mitgeliefert) und
eine Projekt-Konfigurationsdatei, die wichtige Informationen beinhaltet, wie Namen, Regeln,
Umwandlungen, Projekt-Struktur (wichtig für Legacy-Projekte), Verknüpfung von Tabellen zu
bestimmten Session Beans, usw.
Zusätzlich bietet TLGen die Möglichkeit an eine Datenbank oder ein Domainmodell zu
analysieren und unterbreitet Vorschläge für deren Optimierung.
Ist die Entwicklungsphase eines IT-Projektes beendet, werden stetig weitere Features für
neue Praxis-Anforderungen implementiert und somit die benötigte Datenbank durch
Erweiterung angepasst (gemeint ist nur die Datenstruktur). Diese historisch wachsenden
Datenbanken führen eher selten zu einer Fortführung optimaler Datenstrukturen und
letztendlich zu hohen Wartungskosten in Verbindung mit dem Zwangsstart von Refactoring
Projekten.
Das Datenmodell sollte, mindestens in der dritten Normalform vorliegen (siehe z.B.
http://de.wikipedia.org/wiki/Normalisierung_%28Datenbank%29 ). Die Normalisierung ist ein
wichtiges Hilfsmittel, um die Konsistenz der Daten zu gewährleisten. Das erleichtert die
Wartung sowie die Upgrade-Möglichkeiten für zukünftige Anforderungen der Applikation,
ohne die Datensätze zu verändern.
Da es für viele Datenbanken keine grafische Darstellung der Datenstruktur gibt, um so die
Möglichkeit der Optimierung des Datenmodells zu gewährleisten, wird die Arbeit der
Erstellung eines neuen Modells erheblich erschwert. TLGen bietet jetzt die Möglichkeit an
aus einem existierenden Datenbankmodell die Grafik bzw. das Domainmodell zu generieren,
zusammen mit Optimierungsvorschlägen. Durch die schnelle Code-Generierung können
diese Änderungen sofort für die obligatorischen Projekt-Tests bereitstehen und somit einen
schnellen Überblick über das Entwicklungsvorhaben ermöglichen.
Diese grafische Darstellung als Domainmodell (UML) ist sehr wichtig für die Optimierung
einer alten Datenbank.
TLGen
6
StarData GmbH
V 2.501
Des Weiteren wird erst durch das neu-erstellte Domainmodell eine Generierung des
Backend‟s möglich, da jede Zeile aus einer Datenbanktabelle als Java Bean-Objekt im
generierten Code abgebildet wird (dabei spielt es keine Rollte, ob als Join/Mapping aus
mehreren Tabellen oder aus einer Zeile einer Tabelle).
Der generierte Backend-Code entspricht dem Software-Architekturkonzept, welches in Abb.
2 anschaulich erklärt wird.
1.2 TLGen´s Architektur-Konzept
In Abbildung 2 wird das Architektur-Konzept von TLGen dargestellt, zusammen mit den
Komponenten, welche TLGen generiert:

Test Klassen(JUnit),

Data Klassen/Interfaces

Sessions Beans

Manager Beans

Entity Beans

Message Driven Beans

Timer Services

Web Services

Callback Klassen

Free Klassen

Log Dateien (beschreiben im Detail die generierte Elemente)

Datenbank-Skripte (notwendig, um eine Datenbank zu erstellen).
Für das Ändern einer schon vorhandenen Datenbank werden nur die Differenz-Skripte
generiert, um so die existierenden Daten nicht zu löschen.
Für die Änderung einer existierenden Datenbank werden nur die Differenz Skripte generiert,
um so die vorhandenen Daten nicht zu löschen. Diese Skripte können direkt in dem
Generierungsprozess verwendet werden oder erst später, bei Bedarf (siehe 1.3 und 2).
TLGen
7
StarData GmbH
V 2.501
Abbildung 2: TLGen Architektur-Konzept
1.2.1 Input für die Code-Generierung
Damit TLGen den Code generieren kann, wird folgender Input benötigt:

Ein Datenstruktur-Modell, was entweder ein Domainmodell (siehe Abb. 2) sein
kann, designed in UML für den Start neuer IT-Projekte (siehe Kapitel 1.3.1) oder
ein Datenbankmodell (z. B. eine existierende Datenbank – Abb. 2) beim Einsatz
in Legacy-Projekten (siehe Kapitel 1.3.2), die einen Refactoring Prozess
benötigen.

Ein Default Konfigurationsdatei (im XML-Format), welche die Werte für
Definitionen beinhaltet, wie z.B. allgemeine Regeln für die Namen-Konventionen,
UML Domainmodell Regel, Standard-Methoden für die Datenbankzugriffe, eine
Tabelle mit Konvertierung zwischen den Variablen-Typen in Java Code und in der
Datenbank.

Ein Konfigurations-Datei (im XML-Format) mit unterschiedlichen Informationen,
die vom Projekt abhängen (siehe Kap. 3).
Oben genannte Input-Informationen werden in Projekten immer von den Designern oder
Datenmodellieren erstellt. Lediglich die Konfigurationsdatei ist neu für den Code, denn das
Daten- oder Datenbankmodell (DM oder DB) ist immer eine Notwendigkeit in der
Entwicklung von IT-Projekten.
1.3 Beschreibung der Möglichkeiten durch TLGen
Im fortlaufenden Kapitel werden alle detaillierten Möglichkeiten beschrieben, die TLGen für
die Codegenerierung sowie die Analyse von Datenbanken bietet. Die detaillierte Struktur der
Konfigurationsdateien wird in Kap. 4.4 erläutert.
TLGen
8
StarData GmbH
V 2.501
Wie schon im Kapitel 1.2 erwähnt, steuert TLGen den Generierungs-Prozess mit Hilfe von
zwei Konfigurations-Dateien, eine für Default-Werte, die in der Regel keinen großen
Änderungsbedarf besitzt sowie eine Konfigurations-Datei, die individuell für jedes Projekt ist.
TLGen bietet für die Generierung von Code folgende Möglichkeiten an:

Das Einbauen von Kommentaren innerhalb des generierten Codes (siehe Kap. 3.1)

Regel für die Namen-Generierung der Datenbanken sowie für den generierten Code
(siehe Kap. 3.3)

Der Einsatz aller Annotationen im generierten Code, die EJB3 anbietet

Informationen für die Generierung mit Hilfe von Apache Tool „ant“ und einer „ear“
Datei

Der generierte Code entspricht dem EJB 3-Standard und ist verwendbar auf allen
Applicationen Server, die momentan am Markt vertreten sind (WebLogic,
WebSphere, JBoss, GlasFish, IoNas, etc.)

Folgender Code wird generiert:
o
Session Beans mit allen Annotationen (siehe Kap. 2.3)
o
Manager Klassen für die Steuerung von Entity Beans mit allen möglichen Zugriffen für CRUD (Create, Read, Update, Delete). Beim Manager ist es auch
möglich eigene SQLs einzubinden (werden aus den Konfigurationsdateien
gelesen) (siehe Kap. 2.5).
o
Entity Beans, wo alle Relationen automatisch generiert werden (von
Domainmodell oder aus der Datenbank) - OneToOne, OneToMany,
ManyToOne, ManyToMany (siehe Kap. 2.6 und 2.7)
o
Clients Klassen für BCI (Business Common Interfaces); diese ermöglichen die
Verbindung zwischen Client und Server (Session Beans).
o
Test Klassen auf Basis von JUnit. Die Daten für Test Klassen können durch
TLGen generiert oder von einer XML Datei geladen werden. Auch die Struktur
von den XML-Daten-Dateien kann von TLGen generiert werden. TestKlassen sind in zwei Modi zu verwenden, indem die Daten direkt geprintet
oder über die Mechanismen von JUnit getestet werden.
o
Datenbank-Skripte
o
Klassen für die Interfaces für Fachlogik Code
o
Interceptoren
o
Daten Klassen/Interfaces
o
XML Datei für Persistenz (persistence.xml), eine für jede Session Bean
TLGen kann mit den „ant“ Apache Tool genutzt werden, da TLGen einen eigenen Tag
„generator“ besitzt.
1.3.1 Code Generierung mit einem Domain Model (UML)
Die Generierung mit Hilfe eines Domainmodells als Informations-Input findet seine
Anwendung bei neuen IT-Projekten. Ein IT-Architekt (oder ein Architektur-Team - die Wahl
hängt vom Projekt ab) designend zusammen mit der Fachabteilung ein Domainmodell, das
die Datenstruktur und dessen Verbindungen für das Programm darstellt. Auf dieser Basis
kann man letztendlich mit TLGen den kompletten Code generieren und diesen sofort testen.
TLGen
9
StarData GmbH
V 2.501
Für solch ein Projekt bietet TLGen zu den Eigenschaften aus Kapitel 1.3 zusätzliche
Möglichkeiten an:

Eine Analyse des Domainmodells nach falschen Namen (z. B. zu lang für eine
Datenbank), eventuelle Kreise in den Verbindungen zwischen Objekten (Tabellen)
und mögliche Verbesserungenvorschläge (siehe Kap. 2.1).

Innerhalb von einem Domainmodell können Klassen-Typen und Enume verwendet
werden. Daten und Klassen-Typen können in jeder beliebigen Art und Weise verschachtelt werden, so wie die benötigte Logik der Applikation.
1.3.2 Code Generierung mit einer schon vorhandenen Datenbank
Nachdem TLGen einen Zugang zur Datenbank erhalten hat, bezieht TLGen alle relevanten
Information für die Code-Genierung, wie z.B. Tabellen, Spalten, Relationen, Sequenzen etc.
TLGen ist kompatibel zu allen momentan Datenbanken.
Für ein Projekt, dass mit einer Datenbank als Input startet (z.B. Refactoring von LegacySystemen) bietet TLGen zu den in Kap. 1.3 aufgehführten Eigenschaften weitere Möglichkeiten an, wie:

Regel für die Verwendung von Tabellen, Spalten etc. für den generierten Code,
konform den existierenden Namen-Konventionen im Code

Generierung von Datenbank-Skripte für eine neue Datenbank oder nur Änderungsskripte, die dann nur die Differenzen beinhalten
TLGen
10
StarData GmbH
V 2.501
2. TLGen Code-Generierung und die Analyse von Datenbanken
TLGen ist ein einfaches Tools mit höchstem Grad an technischen Hintergrund für die
Generierung von Backend Code auf Basis von EJB3. Wie in den Kapiteln zuvor erklärt,
generiert TLGen den Code mit einem Domain- oder Datenbankmodell (siehe Abb. 3) und
bietet gleichzeitig Optimierungsmöglichkeiten nach eigener Analyse der Modelle an.
Abbildung 3: TLGen-Generierungsprozess vor einer Datenbank
In diesem Kapitel werden detailliert die generierten Objekte sowie zur Verfügung stehende
Steuerungsmöglichkeiten beschrieben.
Allgemeine Features, die zentral für die gesamte Generierung möglich sind (für Details siehe
Kap. 4.5):

Projekt-Name

Application Server, z.b. „JBoss“, “Weblogic” etc. Der Application Server ist wichtig für
die Verwendung des generierten Codes für „Clients“, weil jeder App.Server
verwendet für die Variable „datasource“ eigene Darstellung und für die Connection
zwischen Client und Server eigene Klassen, z.B. für JBoss folgende Klassen
verwendet:
initialcontextfactory="org.jnp.interfaces.NamingContextFactory"
initialcontextpkgprefix="org.jboss.naming:org.jnp.interfaces"
1. Listing

Datenbank-Namen mit Zugriff für die berechtigten User samt Passwörter zum
Auslesen der Informationen (Tabellen, Spalten, Sequences, etc., für Legacy Projekte
oder Ziele, wo die Tabellen generiert werden sollten)

Projekt-Steuerungs-Attribut. Ein Refactoring-Projekt durch eine schon vorhandene
Datenbank (wichtig bei vorhandener Legacy-IT) oder Entwicklung einer neuen
Applikation durch ein Domainmodell. Für die Generierung einer neuen Datenbank
kann diese vollständig neu erstellt oder nur die Änderungen übernommen werden
ohne schon vorhandene Daten zu löschen.

Notwendige Informationen für die Generierung von SQL Skripte wie Tablespace etc.

„ear“ Datei-Name

Die generierte Code-Formatierung kann frei gewählt werden (Standard JavaFormatierung z.B. mit geschweiften Klammern in derselben oder nächsten Zeile oder
TLGen
11
StarData GmbH
V 2.501
ob z.B. die Import-Deklarationen am Klassenanfang oder direkt im Code mit den
vollständigen Import-Pfaden angezeigt wird.).
import eu.stardata.core.hlp.dataif.CoLanguageDataIf;
import javax.persistence.OneToMany;
class
{
private CoLanguageDataIf …
…
}
2. Listing
oder ohne Import in Code:
class
{
@ javax.persistence.OneToMany(cascade = {
javax.persistence.CascadeType.PERSIST}, targetEntity =
eu.stardata.server.core.formular.entity.PageEntity.class)
private eu.stardata.server.core.doclist.entity.DocumentlistEntity …
…
}
3. Listing
2.1 Analyse des Domainmodells und der Datenbank
Die Relationen von Klassen eines Domainmodells oder von Datenbank-Tabellen können je
nach Anforderungen unterschiedlich komplex sein.
Betrachten wir als Beispiel Abbildung 4 eines UML-Klassendiagramms, wo beim Neuanlegen
der Klasse C mindestens ein B über zwei verschiedene Pfade gleichzeitig benötigt wird.
Doch, wenn noch kein B existiert, muss dieses erst neuangelegt werden. Dies ist in diesem
Fall aber nur möglich, falls ein C über eine Relation von Pfad A schon existiert. Das
Klassendiagramm ist logisch nicht inkorrekt (z.B. sei A ein Produkt, B ein Element des
Produkts und C ein Bestellauftrag). Aber die Klassen des Beispiel Domainmodells, jeweils
als Tabelle in einer Datenbank abgebildet, führen zum Problem, dass C B direkt benötigt (not
null) genauso wie A (not null) doch A benötigt und auch ein B (not null), dass zu diesem
Zeitpunkt schon existieren muss.
TLGen
12
StarData GmbH
V 2.501
Abbildung 4: UML-Klassendiagramm I
Anmerkung: Ein UML-Klassendiagramm, wo beim Neuanlegen der Klasse C B
über 2 verschiedene Pfade benötigt wird. Beim Neuanlegen von B kann dieses
dagegen noch nicht existieren, da C noch nicht über die Relation von Pfad A
existiert.
Kreise, durch Pfade in der Erreichbarkeit der Klasse „C“, sind hier folgende:
Die Klasse „C“ ist über die Klasse „B“ durch folgende Pfade erreichbar:


[B (NOT NULL)->A (NOT NULL)] ---> [C]
[B (NOT NULL)]
---> [C]
Genau in diesem Schema werden alle Pfade in der Erreichbarkeit einer Klasse (hier „C“),
über welche Klassen (hier „B“) diese Pfade verlaufen, in der Debug-Log Datei bei der
Generierung des Codes durch TLGen dargestellt. Fälle wie in Abbildung 4 werden mit einem
„Fatal Error“ in der Debug-LOG Datei und Error-LOG Datei ausgegeben. Dagegen werden
Kreise von Relationspfaden, die nicht über unterschiedliche Klassen in der Zielklasse enden,
mit einem „Warning“ angezeigt (vgl. Abbildung 5).
Abbildung 5: UML-Klassendiagramm II
Wie Abb. 1, aber in der Relation von [B(Null)] ---> [C] ist null erlaubt. Somit kann
B und C über den Relationen von A gleichzeitig angelegt werden.
Direkte Kreise, d.h. Zielklasse ist auch die Startklasse in einem Relationspfad, werden in den
LOG-Dateien als „Fatal Error“ deklariert (vgl. Abbildung 6), falls alle Klassen im
Relationspfad voneinander abhängig sind (hier: [A (NOT NULL)->C (NOT NULL) ->B (NOT NULL)] --->
[A]) und nur mit einem „Warning“, falls dies nicht zutrifft (vgl. Abbildung 7: [A (NOT NULL)->C
(NULL) ->B (NOT NULL)] ---> [A])
TLGen
13
StarData GmbH
V 2.501
Abbildung 6: UML-Klassendiagramm III
Ein direkter Relationspad, wo jede Startklasse auch Zielklasse ist und alle
voneinander abhängig sind.
Abbildung 7: UML-Klassendiagramm IV
Ein direkter Relationspad, wo jede Startklasse auch Zielklasse ist, aber nicht alle
voneinander abhängig sind.
Im Folgenden ist ein Knoten äquivalent mit einer Klasse des Domainmodells oder
einer Datenbanktabelle.
Die Debug-LOG Datei beinhaltet folgende Informationen, um Pfade zu analysieren:

„CHECK RELATIONS METHODS - Adjacency list”:
Die Liste zeigt alle Knoten (TARGET), die über verschiedene Relationspfade erreicht
werden können:
Node: 'TARGET':
[ungeordneter Relationspfad] ---> [TARGET] [alle passierten Vorknoten der Pfade aufsummiert]
Beispiel: [C,B] ---> [A]

[C(1),B(2)]
„CHECK RELATIONS METHODS - CIRCLE PATH (direct)”:
Die Liste zeigt alle Kreise der Knoten (TARGET), die über verschiedene
Relationspfade über den TARGET selber erreicht werden können:
Node: 'TARGET':
[geordneter Relationspfad beginnend mit TARGET] ---> [TARGET]
Beispiel: [A(NULL)->C (NOT NULL)->B (NOT NULL)] ---> [A]
TLGen
14
StarData GmbH
V 2.501

„CHECK RELATIONS METHODS – ALL PATHS”:
Die Liste zeigt alle Pfade der Knoten (TARGET), die über andere Knoten erreicht
werden können:
Node: 'TARGET':
[geordneter Relationspfad] ---> [TARGET]
Beispiel: [C (NOT NULL)->B (NOT NULL)] ---> [A]
Wenn neben dem Pfad ein „FATAL” steht, dann ist TARGET von sich selber
abhängig.

„CHECK RELATIONS METHODS - CIRCLE PATHS (not direct)”:
Die Liste zeigt alle Pfade der Knoten (TARGET), die von verschiedenen Knoten
(SOURCE) über unterschiedliche Relationspfade erreicht werden können:
'TARGET':
'SOURCE':
[geordneter Relationspfad mit SOURCE] ---> [TARGET]
Beispiel: -'C': [C (NOT NULL)->B (NOT NULL)] ---> [A]
Wenn neben dem Knoten SOURCE „FATAL” erscheint, dann sind mehrere Pfade,
die in TARGET enden, von SOURCE abhängig (siehe oben, z.B. [C->D]--->[A] und
[C->B]--->[A]). Wenn ein „Warning” erscheint, dann sind mehrere Pfade, die in
TARGET enden, von SOURCE abhängig, wobei diese über denselben Knoten in
TARGET (siehe oben, z.B. [C->D->B]--->[A] und [C->B]--->[A]) enden.
Die Error-LOG Datei beinhaltet folgende Informationen, um Pfade zu analysieren:

„Direct circles in relations”
o „Warning“, wenn es einen Relationspfad gibt, wo Start- und Endknoten
derselbe ist.
Beispiel: [A (NULL)->B (NOT NULL)] ---> [A])
o
„FATAL Error“, wenn es einen Relationspfad gibt, wo Start- und Endknoten
derselbe ist und voneinander abhängig sind.
Beispiel: [A (NOT NULL)->B (NOT NULL)] ---> [A]

„Relation Problems?”
o „Warning“, wenn man den Zielknoten über verschiedene Relationspfade
desselben Startknotens erreichen kann und diese voneinander abhängig sind,
aber in den Zielknoten immer über denselben Vorgängerknoten endet.
Beispiel: [C (NOT NULL)->B (NOT NULL)] ---> [A] und [C (NOT NULL)->D (NOT NULL)->B
(NOT NULL)] ---> [A])
o
„FATAL Error“, wenn man den Zielknoten über verschiedene Relationspfade
desselben Startknotens erreichen kann und diese voneinander abhängig sind.
Beispiel: [C (NOT NULL)->B (NOT NULL)] ---> [A] und [C (NOT NULL)->D (NOT NULL)] ---> [A]
TLGen
15
StarData GmbH
V 2.501
2.2 Daten Klassen - Interfaces
TLGen kann Daten, Klassen/Interfaces aus einem Domainmodell oder aus einer
vorhandenen Datenbank generieren. Es wandelt die Datenbank-Tabellen mit seinen Spalten
in Klassen/Interfaces mit ihren Variablen um. Die Daten-Typen von Spalten umwandelt es in
Java Daten-Typen wie in Tabelle 1 dargestellt. Für Sonderwünsche der Typ-Verwendung
kann in der Default Konfiguration Datei eigene Umwandlung definiert werden (siehe 4.4).
Tabelle 1: Java-Typen
Nr. Datenbank Type
Java (Code) Type
1
CHAR
char
2
NCHAR
char
3
DATE
java.util.Date
4
TIMESTAMP
java.util.Date
5
DECIMAL
double
6
BINARY_DOUBLE
double
7
BINARY_FLOAT
float
8
INTEGER
int
9
NUMBER
long
10
VARCHAR
java.lang.String
11
VARCHAR2
java.lang.String
12
NVARCHAR2
java.lang.String
13
LONG
java.lang.Long
14
RAW
java.lang.String
15
LONG RAW
byte[]
16
CLOB
java.lang.String
17
NCLOB
java.lang.String
18
BLOB
byte[]
19
TEXT
java.lang.String
20
LONGTEXT
java.lang.String
21
INT
int
22
BIGINT
long
23
DATETIME
java.util.Date
24
SMALLINT
short
In Konfigurationsdateien ist es möglich auch die Klassen/Interface Path mit „extends“ zu
definieren. Diese „extends“ sind Basis Klassen/Interfaces, die eventuelle Variablen
beinhalten, die die komplette Applikation beinhaltet und kann von TLGen Anwender
geschrieben werden. TLGen liefert auch diesen Code für Standard Anwendungen mit. Diese
Superklassen sind nicht unbedingt notwendig für das Programm.
TLGen
16
StarData GmbH
V 2.501
TLGen hat auch eigene Basis Klassen/Interfaces, die als Default verwendet werden, falls der
TLGen Anwender nicht eigene schreibt (siehe 4.4.2.1). In Konfigurationsdateien werden
auch das Path für Klassen „Typen“ und „Enums“ definiert, falls diese in der Applikation
verwendet werden.
TLGen generiert für die Relationen, die in der Datenbank- oder in dem Domainmodell
vorhanden sind entsprechende Variablen als Liste oder einfache Variablen wie für Interfaces:
public abstract List<CoPageDataIf> getPage();
public abstract void setPage(List<CoPageDataIf> arg);
4. Listing
und für Klassen:
private List<CoPageDataIf> m_page;
public List<CoPageDataIf> getPage() {
return m_page;
}
public void setPage(List<CoPageDataIf> arg) {
m_page = arg;
}
5. Listing
Für die Klassen/Interfaces, die seitens Domainmodells generiert sind, werden alle Attribute
übernommen, persistente und nicht persistente, aber in den SQL Skripten (die für die
Datenbank Generierung notwendig sind) werden nur die persistenten Variablen verwendet.
Für die Klassen/Interfaces, die von einer vorhandenen Datenbank generiert werden, können
neue Variable eingefügt werden, die nicht persistent sind.
2.3 Session Bean
Session Bean ist eine wichtige Klasse und die erste Klasse, welche von einem Client über
RMI aufgerufen wird. Sie hat innerhalb von EJB3 eine vordefinierte Form und kann mit
mehreren Annotationen verwendet werden (siehe Tabelle 2).
Mit Hilfe der Steuerung über die Konfigurationsdateien können für die Session Beans
folgende Features generiert werden:

Annotationen mit Parameter

Selbst geschriebene „extends“ Klassen oder die von TLGen Default Session Bean
Basis Klassen

Interceptoren (siehe 2.3.4)

Clients (Siehe 2.4)

Manager Klassen (siehe 2.5)

Entity Beans (siehe 2.6)

XML Persistente Datei (siehe 2.3.2)
TLGen
17
StarData GmbH
V 2.501

Definiert die Methoden, die von Client aufgerufen wird. Diese Methoden können von
den Manager Klassen übernommen werden.

Kann bestimmen, welcher Type von Transaktionen verwendet wird.

Interface-Klassen die, die Verbindung zwischen generiertem Code und Fachcode
ermöglichen.
Tabelle 2: Annotationen
Annotationen
Verwendung Kommentar
in TLGen 2.1
javax.ejb.Stateless
ja
Definiert eine Stateless Session Bean
javax.ejb.Stateful
ja
Definiert eine Stateful Session Bean
javax.ejb.EJB
ja
Definiert eine Lokale References z. B. Name
eines Manger Interface (siehe 2.5)
javax.ejb.Remote
ja
Bezeichnet eine Remote Verwendung von
Session Bean
javax.ejb.Local
ja
Ist für eine Lokale Verwendung
javax.ejb.ApplicationException
nein
javax.ejb.EJBs
ja
javax.ejb.Init
nein
javax.ejb.LocalHome
nein
Entspricht nicht der Philosophie von EJB3
javax.ejb.PostActivate
ja
Methode wird nach dem Aktivierung von
Session Bean aufgerufen
javax.ejb.PrePassivate
ja
Nur für Stateful Session Bean
javax.ejb.RemoteHome
nein
Entspricht nicht der Philosophie von EJB3
javax.ejb.Remove
ja
Call Methode mit den Annotation PreDestroy
(nur für Stateful Session Bean)
javax.ejb.Timeout
ja
Session Bean wird nach Ablauf von timeout
verworfen
javax.ejb.TransactionAttribute
ja
Transaction Type (REQUIRED, MANDATORY,
etc.)
javax.ejb.TransactionManagement
ja
Transaction management (CONTAINER or
BEAN)
Definiert eine von mehreren EJB Annotationen
Für eine Session Bean kann man eine oder mehrere Manager Klassen mit seiner Entity
Beans aufrufen.
Von einem Domainmodell kann für jedes Package eine Session Bean generiert werden und
innerhalb der Session Bean für jedes Element-Objekt ein Tandem vom Manager, Entity Bean
und Datenbank-Tabelle.
Für die Legacy Projekte (Refactoring), die auf Basis einer vorhandenen Datenbank
durchgeführt werden, soll in der Konfigurationsdatei eine Liste von Tabellen, die zu einer
Session Bean gehören, vorhanden sein.
Session Bean Code Beispiel:
TLGen
18
StarData GmbH
V 2.501
package eu.stardata.server.core.formular;
import eu.stardata.server.core.formular.bci.ExecBci;
import eu.stardata.server.core.formular.bci.TablecolBci;
……………………………………..
import javax.ejb.EJB;
@Stateless(name = FormularBci.JNDI_NAME, mappedName = "efp/"+FormularBci.JNDI_NAME+"/remote")
@Remote(FormularBci.class)
public class FormularSessionBean extends BaseSessionBean implements FormularBci
{
private static final long serialVersionUID = 196502766;
// Session annotations and fields for local manager
@EJB
private EntryBci m_EntryBci;
…………………………………….
/**
* Session method "createEntry()"
* @param arg
* @return
* @throws PersistenceException
*/
public CoEntryDataIf createEntry(CoEntryDataIf arg) throws PersistenceException
{
try
{
return m_EntryBci.create(arg);
} catch(Exception ex)
{
throw new PersistenceException(ex.getMessage(),ex,1);
}
}
6. Listing
2.3.1 Interfaces für eine Session Bean
Session Bean benötigt ein Interface mit allen definierten Methoden, die von Client aufgerufen
werden. Diese Interfaces für Session Bean verwenden zwei Annotationen:
@Remote für eine Remote-Verbindung vom Client sowie @Local für eine lokale
Verwendung. In diesem Interface sind auch drei vordefinierte Variablen, die für EJB3 sehr
wichtig sind:

String JNDI_NAME = Wert, ist der notwendige Name für den Client-Aufruf und
eindeutig für die gesamte Applikation. TLGen verwendet für diese Variable den Inhalt
des kompletten Session Bean Namens, z. B.
"eu.stardata.server.core.formular.FormularSessionBean"

String MANAGER_NAME = "managerFormular". Diese Variable ist wichtig für die
Verwendung der Manager Klasse (siehe Kapitel 2.5).

String EAR_NAME = "efp". Diese Variable bekommt den Wert aus der
Konfigurations-Datei und wird in der XML Persistenz Datei verwendet (siehe Kapitel
2.3.1).
Ein Beispiel für ein Session Bean Interface als „Remote“:
package eu.stardata.client.core.formular.bci;
import eu.stardata.core.form.dataif.CoRuletypeDataIf;
……………………………………………………………………..
TLGen
19
StarData GmbH
V 2.501
import eu.stardata.core.form.dataif.CoRulefieldDataIf;
import javax.ejb.Remote;
import java.lang.String;
import eu.stardata.core.form.dataif.CoFormularDataIf;
import eu.stardata.server.common.exception.PersistenceException;
import eu.stardata.core.form.dataif.CoExecDataIf;
@Remote
public interface FormularBci
{
// Client interface Fields
public final static String JNDI_NAME = "eu.stardata.server.core.formular.FormularSessionBean";
public final static String MANAGER_NAME = "managerFormular";
public final static String EAR_NAME = "efp";
// Session - Client interface methods
public void clearExec() throws PersistenceException;
public CoFieldDataIf createField(CoFieldDataIf arg) throws PersistenceException;
public CoFieldDataIf[] findAllField() throws PersistenceException;
………………………………………………
public CoElementDataIf createElement(CoElementDataIf arg) throws PersistenceException;
public void clearWebstyle() throws PersistenceException;
}
7. Listing
2.3.2 XML Persistente Datei
Ab EJB 3 ist nur eine XML Datei für das Deployment Description notwendig, alle anderen
Dateien der Vor-Versionen sind entweder abgeschafft oder werden als Annotation
verwendet. Zusätzlich gibt es noch eine XML Datei „orm.xml“ für das Mapping für Version 3
von EJB, doch diese wird aus Gründen der Performance mit TLGen nicht genutzt. TLGen
erlaubt das Mapping direkt im generierten Java Code und zwar in den Entity Beans (siehe
Kapitel 2.6 sowie 4.5.3.3)
In der Datei „persistence.xml“, die für jede Session Bean generiert wird, sind automatisch
folgende Informationen enthalten:

In Tag „persistence-unit“ die Parameter name  ManagerName Variable und
Transaction-type

In Tag „jta-data-source“ die Data Source im Format, das der jeweilige Applikation
Server benötigt (jede hat ein eigenes Format)

Eine vollständige Liste von allen in der Applikation vorhandenen Entity Beans mit
vollständig definierten Namen

In Tag „propertie“ allgemeine Informationen für den Application Server
Ein Beispiel für eine generierte „persistence.xml“:
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd" version="1.0">
<persistence-unit name = "managerFormular" transaction-type = "JTA">
<jta-data-source>java:/efpPool</jta-data-source>
<class>eu.stardata.server.core.user.entity.UserEntity</class>
<class>eu.stardata.server.core.hlp.entity.OperationEntity</class>
<class>eu.stardata.server.core.hlp.entity.FormatEntity</class>
<class>eu.stardata.server.core.hlp.entity.KeyEntity</class>
<class>eu.stardata.server.core.formular.entity.FieldEntity</class>
TLGen
20
StarData GmbH
V 2.501
<class>eu.stardata.server.core.hlp.entity.FieldtypeEntity</class>
………………………………………………..
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.Oracle10gDialect"/>
</properties>
</persistence-unit>
</persistence>
8. Listing
In der Datei „persistence.xml“ können einige Informationen definiert werden, die vom
Applikation Server benötigt werden (in einer „properties“ Tag).
Hinweis: Für den Applikation Server „JBoss“ Version 5 sollte die Oracle Datenbank in
Version 10 genutzt werden, da diese Oracle Version 11 noch nicht erkennt.
2.3.3 Interface Klassen zu Fachlogik Komponenten
Innerhalb eines Session Bean kann bzw. können eine oder mehrere Klassen definiert
werden, die zu oder von anderen Systemen gehören bzw. aufgerufen werden oder für die
Kodierung reiner Fachlogik benötigt werden. Wurden diese einmal generiert, lässt der
Generator es zu, diese dort abzuspeichern, um den dort manuell entwickelten Code nicht zu
löschen.
Nach unserer Erfahrung ist es weder produktiv noch notwendig generierten Code mit selbst
entwickelte zu mischen (merging). Daher ermöglicht TLGen eine vollständige Trennung
dieser Code-Arten.
2.3.4 Interceptors
Ein Interceptor ist eine einfache Java Klasse deren Methoden immer dann aufgerufen
werden, wenn die Methoden der Session Bean benützt werden. Die Interceptoren sind
Klassen, die eigentlich zum Beispiel unter anderem zur Überwachung einer Session Bean,
zur Übernahme der Informationen-Protokollierung oder Zeitmessen gedacht sind.
Diese Java Klassen können über die Konfigurationsdateien in den generierten Code
eingebettet werden. Es können entweder selbst geschriebene Klassen sein oder die von
TLGen Default Interceptoren zur Verfügung gestellten.
Ein einfaches Bespiel von einer Interceptor Klasse für die Zeitmessung:
public class TimeFormular
{
// Session annotations and fields for interceptor
/**
* Default Constructor
*/
public TimeFormular()
{
super();
}
// Session class methods
/**
* Interceptor method "timeTrace()"
* @param invocation
* @return
* @throws PersistenceException
*/
TLGen
21
StarData GmbH
V 2.501
@AroundInvoke
public java.lang.Object timeTrace(InvocationContext invocation) throws PersistenceException
{
long start = 0;
boolean toTime = true;
try
{
if(toTime)
{
start = System.currentTimeMillis();
}
return invocation.proceed();
} catch(Exception ex)
{
throw new PersistenceException(ex.getMessage(),ex,1);
}
finally
{
if(toTime)
{
// Example to time
long ende = System.currentTimeMillis();
String klasse = invocation.getTarget().toString();
String methode = invocation.getMethod().getName();
System.out.println(klasse + ":" + methode + " -> " + (ende - start) + "ms");
}
}
}
}
9. Listing
2.4 Clients, BCI (Business Common Interface)
Auf der Client Seite befindet sich das User Interface, mit dem dieser die Applikation nutzen
kann. Auf dem Server hingegen befindet sich die Logik der Applikation, mit dem benötigten
Code.
TLGen generiert vollständig die Klassen, die notwendig für die Kommunikation zwischen
Client und Server sind. Für den Client generiert TLGen auch die Test Klassen (auf Basis von
JUnit), die für die Tests der Applikation benötigt wird.
Als Beispiel ein generierter Aufruf vom Server, um einen Satz in eine Datenbank
abzuspeichern:
CoFormularDataIf clFormular = getFormularObject();
// make a factory client for call the session bean
FormularBci factory = FormularBciFactory.getFormularBci();
// call the session bean method over the client factory
clFormular = factory.createFormular(clFormular);
10. Listing
Dieser Serveraufruf ist in zwei Schritten durchzuführen: Zuerst wird die notwendige Factory
aufgerufen (diese entspricht in der Regel einer bestimmten Session Bean auf der Server
Seite) und letztendlich mit Hilfe der Factory die gewünschte Methode. Im oberen Beispiel ist
die Speicherung in der Datenbank eines Formular Objekts dargestellt.
TLGen generiert zwei Klassen/Interfaces, die diese Aufgabe erfüllen. In unserem Beispiel,
die Klasse FormularBciFactory.java und die Interface FormularBci.java, Teil des generierten
Code für die Factory:
/**
* getFormularBci()
*/
TLGen
22
StarData GmbH
V 2.501
public static synchronized FormularBci getFormularBci() throws PersistenceException {
return (FormularBci)getBciImplementation(FormularBci.class);
}
11. Listing
Als auch für die Interfaces:
@Remote
public interface FormularBci {
// Client interface Fields
public final static String JNDI_NAME = "eu.stardata.server.core.formular.FormularSessionBean";
public final static String MANAGER_NAME = "managerFormular";
public final static String EAR_NAME = "efp";
…………………………………………….
public CoFormularDataIf createFormular(CoFormularDataIf arg) throws PersistenceException;
…………………………………..
}
12. Listing
2.4.1 Test Klassen
TLGen generiert für die gewünschten Aufrufe die kompletten Test Klassen mit generierten
Test-Werten oder aus einer Daten-Datei die geladenen Test-Daten. Für welche Aufrufe die
Test Klassen (JUnit) zu generieren sind, soll in der Konfigurations-Datei eingetragen werden
(für weitere Details siehe Kapitel 4.4.8 und 4.5.3.6).
Test Klassen kann man testen und die Ergebnisse in einer Datei printen oder direkt auf den
Bildschirm ausgeben (z. B. in Eclipse) oder aber im JUnit, wo sie mit Hilfe von Asset
Methode zu Verfügung gestellt werden, ersehen. Listing 13 zeigt ein Beispiel für eine Test
Klasse:
public class FormularWriteReadTest extends TestCase {
private static final long serialVersionUID = 435512065;
// Test class data fields
private static CoFormularDataIf m_clFormular = null;
/**
* Default Constructor
*/
public FormularWriteReadTest() {
super();
// Insert your configuration data for application server
de.stardata.base.config.InitProgramm.put(de.stardata.base.config.ConfigKeyNames.INITIAL_CONTEXT,
"jnp://localhost:9099");
de.stardata.base.config.InitProgramm.put(de.stardata.base.config.ConfigKeyNames.INITIAL_CONTEXT
_FACTORY,"org.jnp.interfaces.NamingContextFactory");
de.stardata.base.config.InitProgramm.put(de.stardata.base.config.ConfigKeyNames.INITIAL_PKG_PRE
FIXES,"org.jboss.naming:org.jnp.interfaces");
}
// Test class methods
/**
* Test method "testCreateFormular()"
*/
public void testCreateFormular() {
try {
m_clFormular = new CoFormularData();
// initialize data for test class
m_clFormular.setCoreId(3);
……………………………………………………………………..
m_clFormular.setLanguage(writeLanguage());
m_clFormular.setMandant(writeMandant());
// make a factory client for call the session bean
TLGen
23
StarData GmbH
V 2.501
FormularBci factory = FormularBciFactory.getFormularBci();
// call the session bean method over the client factory
m_clFormular = factory.createFormular(m_clFormular);
// print the new primary key
System.out.println("New primary key is = " + m_clFormular.getFormularId());
} catch(PersistenceException ex) {
ex.printStackTrace();
}
}
13. Listing
Test Klassen Beispiel
2.4.1.1 Verwendung von Test Daten aus externen Dateien
Mit Hilfe der Konfigurations-Datei kann man eine XML Datei generieren, welche die DatenStruktur einer oder mehrerer Test-Objekte nachbildet. Diese XML kann mit den gewünschten
Daten erweitert und für Tests genutzt werden. Solch eine Datei wird in Listing 14 dargestellt:
<?xml version="1.0" encoding="UTF-8"?>
<TestMethod xsi:noNamespaceSchemaLocation = "C:/Project-TLGen2.1/source/generated/TestDataSchema.xsd" name = "testCreateFormular" xmlns:xsi =
"http://www.w3.org/2001/XMLSchema-instance" type = "void">
<Variable name = "FormularId" value = "2" type = "long"/>
<Variable name = "CoreId" value = "2" type = "long"/>
………………………………………………………………………………………………..
<Variable name = "Document_id" value = "2" type = "long"/>
……………………………………………………………………………………………….
<Method name = "writeMandant" type = "eu.stardata.core.cor.dataif.CoMandantDataIf">
<Variable name = "MandantId" value = "4" type = "long"/>
………………………………………………………………………………………………..
<Variable name = "Code" value = "-628" type = "java.lang.String"/>
</Method>
</TestMethod>
14. Listing
Die verwendete Schema-Datei “TestDataSchema.xsd” hat folgende Struktur:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!--W3C Schema generated by XMLSpy v2009 (http://www.altova.com)-->
<!--Please add namespace attributes, a targetNamespace attribute and import elements according to your
requirements-->
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
<xs:import namespace="http://www.w3.org/XML/1998/namespace"/>
<xs:element name="Variable">
<xs:complexType>
<xs:attribute name="name" use="required" type="xs:anySimpleType"/>
<xs:attribute name="type" type="xs:anySimpleType"/>
<xs:attribute name="value" type="xs:anySimpleType"/>
</xs:complexType>
</xs:element>
<xs:element name="Type">
<xs:complexType mixed="true">
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element ref="Variable"/>
<xs:element ref="Type"/>
<xs:element ref="Enum"/>
</xs:choice>
<xs:attribute name="name" use="required" type="xs:anySimpleType"/>
<xs:attribute name="type" type="xs:anySimpleType"/>
TLGen
24
StarData GmbH
V 2.501
</xs:complexType>
</xs:element>
<xs:element name="TestMethod">
<xs:complexType mixed="true">
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element ref="Variable"/>
<xs:element ref="Method"/>
<xs:element ref="Type"/>
<xs:element ref="Enum"/>
</xs:choice>
<xs:attribute name="name" use="required" type="xs:anySimpleType"/>
<xs:attribute name="type" type="xs:anySimpleType"/>
</xs:complexType>
</xs:element>
<xs:element name="Method">
<xs:complexType mixed="true">
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element ref="Type"/>
<xs:element ref="Enum"/>
<xs:element ref="Variable"/>
<xs:element ref="Method"/>
</xs:choice>
<xs:attribute name="name" use="required" type="xs:anySimpleType"/>
<xs:attribute name="type" type="xs:anySimpleType"/>
</xs:complexType>
</xs:element>
<xs:element name="Enum">
<xs:complexType>
<xs:attribute name="name" use="required" type="xs:anySimpleType"/>
<xs:attribute name="type" type="xs:anySimpleType"/>
<xs:attribute name="value" type="xs:anySimpleType"/>
</xs:complexType>
</xs:element>
</xs:schema>
15. Listing
2.5 Manager Klassen
Eine Manager Klasse ist eine lokale Stateless Session Bean, die für die Steuerung der
Persistenz (Entity Bean) genutzt wird.
Manager Klassen können Default Methoden für Datenbank-Administration für CRUD sein
oder aber auch Datenbank-Zugriffsmethoden, generiert auf Basis von selbst geschriebenen
SQL‟s. In Tabelle 3 sind die Default Methoden, welche TLGen automatisch generieren kann:
Tabelle 3: Automatisch generierbare Default Methoden
Nr.
Method Name
Parameter
Return
Funktionalität
1
create“Name“
Objekt
Objekt
Speichern eins neuen Objekts in der
Datenbank
2
update“Name“
Objekt
-
Aktualisieren eines Objekts in der
Datenbank
3
remove“Name“
Object
-
Löschen eines
Datenbank
4
flusch“Name“
Object
-
Beenden des Vorgang
5
close“Name“
-
-
Schließt eine Entity Object
6
clear“Name“
-
-
TLGen
25
Objekts
in
der
StarData GmbH
V 2.501
7
findByPrimaryKey“Name“
Object
PK
8
findAll“Name“
9
findBy“Name“
mit
Object
Lesen ein Objekt von DB mit den PK
-
Object[]
Lesen aller gespeicherter Objekte
Parameter
List
Object[]
Lesen aller Objekte für die Parameter
List
Ein Beispiel für generierten Code aus Tabelle 3, Zeile 9 ist in Listing 16 dargestellt:
public class ProductManager extends BaseManager implements ProductBciIf
{
private String m_getNameAndOffer = "select u from ProductEntity u
where u.name = :name and u.productOfferingId = :productOfferingId";
………………………………………………………………
/**
* Manager method "findByNameAndOffer()"
* @param name
* @param productOfferingId
* @return
* @throws PersistenceException
*/
public ProductDataIf[] findByNameAndOffer(String name, String productOfferingId) throws
PersistenceException {
try {
ProductDataIf[] listData = null;
List<?> list = m_manager.createQuery(m_getNameAndOffer).setParameter("name",
name).setParameter("productOfferingId",productOfferingId).getResultList();
if(list != null && list.size() > 0) {
listData = new ProductDataIf[list.size()];
int idx = 0;
for(Object entity : list) {
if(entity != null) {
listData[idx++] = ((ProductEntity)entity).callProduct();
}
}
}
return listData;
} catch(Exception ex) {
throw new PersistenceException(ex.getMessage(),ex,1);
}
}
………………………………………………………………..
}
16. Listing
Das Lesen, Speichern oder Löschen von Objekten kann direkt im Aufruf gesteuert werden,
ob nur das „Vater“ Objekt gelesen, gespeichert oder gelöscht wird oder aber zusammen mit
seinen „Kindern“ (solange die Beziehungen zwischen diesen „Null“ akzeptiert).
Für das selbst geschriebene SQL bietet TLGen eine Fülle von Modellen an, die sehr einfach
in der Konfigurations-Datei zu nutzen sind, mit der letztendlich TLGen den entsprechenden
Code generiert. In der Regel ist es nur sehr selten notwendig ein solches SQL zu schreiben,
weil durch automatisches Einbeziehen von Relationen werden alle benötigen Objekte
gelesen und abgespeichert.
Es folgt ein Ausschnitt einer generierten Manager Klasse:
package eu.stardata.server.core.formular.manager;
TLGen
26
StarData GmbH
V 2.501
import javax.persistence.EntityManager;
………………………………………………..
import javax.ejb.Local;
@Stateless(name = eu.stardata.server.core.formular.bci.FormularBci.JNDI_NAME)
@Local(eu.stardata.server.core.formular.bci.FormularBci.class)
public class FormularManager extends BaseManager implements
eu.stardata.server.core.formular.bci.FormularBci {
private static final long serialVersionUID = 644414680;
// Manager class data fields
@PersistenceContext(unitName = FormularBci.MANAGER_NAME)
public EntityManager m_manager = null;
private String m_getName = "select o from FormularEntity o where o.formular = :formular";
private String m_SQL_FIND_ALL = "select o from FormularEntity o";
…………………………………………………………………
/**
* Manager method "findByPrimaryKey()"
* @param arg
* @return
* @throws PersistenceException
*/
public CoFormularDataIf findByPrimaryKey(CoFormularDataIf arg) throws PersistenceException {
try
{
CoFormularDataIf classData = null;
FormularEntity entity = m_manager.find(FormularEntity.class, arg.getFormularId());
if(entity != null){
classData = entity.callFormular();
}
return classData;
} catch(Exception ex){
throw new PersistenceException(ex.getMessage(),ex,1);
}
}
……………………………………………….
}
17. Listing
Alle in den Manager Klassen verwendeten Methoden können von den dazugehörigen
Session Bean übernommen werden oder auch nicht. Dies kann über die KonfigurationsDatei gesteuert werden (Default bedeutet, dass alle übernommen werden).
In Tabelle 4 die Annotationen, die für eine Manager Klasse verwendet werden.
Tabelle 4: Annotationen für Manager Klassen
Annotationen
Vervendung
inTLGen
Kommentar
Stateless
ja
Bezeichnet eine Session Stateless Bean
Local
ja
Ist nur lokal zu verwenden
PersistenceContext
ja
Definiert den Namen des Managers
2.5.1 Manager Interfaces
Weil Manager Klassen eigentlich lokale Session Beans sind, benötigen sie ein eigenes
Interface. Diese werden auch automatisch von TLGen generiert.
TLGen
27
StarData GmbH
V 2.501
Ein Beispiel für ein Interface einer Manager Klasse:
18. Listing
import eu.stardata.core.form.dataif.CoFormularDataIf;
import java.lang.String;
import eu.stardata.server.common.exception.PersistenceException;
import eu.stardata.server.core.formular.bci.FormularBci;
import eu.stardata.server.core.formular.entity.FormularEntity;
public interface FormularBci {
// Manager interface data fields
public String JNDI_NAME = "eu.stardata.server.core.formular.bci.FormularBci";
public String EAR_NAME = "efp";
// Manager interface methods
public CoFormularDataIf findByPrimaryKey(CoFormularDataIf arg) throws PersistenceException;
………………………………………………………………………
public void close() throws PersistenceException;
}
2.6 Entity Beans
Die Entity Beans sind das Tor zur Datenbank, besser gesagt, sie sind die Schnittstellen für
eine relationale Datenbank. Eine Entity Bean sollte einer Tabelle in der Datenbank
entsprechen und so eine saubere sowie strukturierte Architektur für die Persistenzschicht
ermöglichen. Das ist sehr wichtig für die Wartung des Codes und für weitere Entwicklungen.
Entity Beans sind POJO‟s (Old Java Objects), d. h. sie sind normale Java Klassen und
anders als die Session Beans, brauchen sie keine Interfaces.
Jede Entity Bean muss einen Standardkonstruktor besitzen, weil es unter anderem Aufgabe
einer Manager Klasse ist, eine Instanz für die Entity Bean zu erzeugen.
TLGen generiert in einer Entity Bean die notwendigen Annotationen, Variablen, Default
Konstruktor, Mapping Methoden zwischen Daten Objekt Attributen, Tabellen-Spalten, einige
Hilfs-Methoden, die diese Mapping unterstützen und die Methoden für die Relationen.
Für eine Entity Bean werden auch mehrere Annotationen und Variablen generiert, wie in
Listing 19 dargestellt:
package eu.stardata.server.core.formular.entity;
import javax.persistence.GeneratedValue;
…………………………………………………………………..
import javax.persistence.Entity;
@Entity
@Table(name="CORE_FORMULAR")
@SequenceGenerator(name="SEQ_STORE_FORMULAR", sequenceName="CORE_FORMULAR_SEQ",
initialValue=1, allocationSize=20)
public class FormularEntity {
private static final long serialVersionUID = 802995295;
// Entity data field
private CoFormularDataIf m_formular = null;
// Fields from relations tables
private List<PageEntity> m_page = new ArrayList<PageEntity>();
private List<DocumentlistEntity> m_documentlist = new ArrayList<DocumentlistEntity>();
private LanguageEntity m_language = null;
………………………………………………………………………….
// constructors
/**
* Default Constructor
*/
TLGen
28
StarData GmbH
V 2.501
public FormularEntity() {
}
/**
* Constructor
* @param arg
*/
public FormularEntity(CoFormularDataIf arg) {
m_formular = arg;
fillFormular();
}
// Helper methods
/**
* Helper Method "makeFormular"
*/
public CoFormularDataIf makeFormular() {
if(m_formular == null) {
m_formular = new eu.stardata.core.form.data.CoFormularData();
}
return m_formular;
}
…………………………………………………………………………
}
19. Listing
In Tabelle 5 sind die Annotationen dargestellt, die für Entity Beans von EJB3 vorgesehen
sind:
Tabelle 5: Annotationen für Entity Beans (EJB3)
Annotationen
Vervendung
inTLGen
Kommentar
Entity
ja
Definiert eine Entity Bean
Table
ja
Table, die zu eine Entity gehören
Column
ja
Spalte einer Table (für Mapping)
SequenceGenerator
ja
Definiert die Art von Sequence Generator
GeneratedValue
ja
Generiert eine Sequence (für die automatische
Generierung von ID„s)
Id
ja
Definiert eine PK
ManyToMany
ja
Relation Typ (siehe 2.6.1.4 und 4.5.3.8)
ManyToOne
ja
Relation Typ (siehe 2.6.1.2 und 4.5.3.8)
OneToMany
ja
Relation Typ (siehe 2.6.1.1 und 4.5.3.8)
OneToOne
ja
Relation Typ (siehe 2.6.1.3 und 4.5.3.8)
Version
ja
Verwendet für die Versionskennzeichnung, wird für Locking
verwendet
PostLoad
ja
Hilfsmethoden, welche vor oder nach Processing
aufgerufen werden
PostPersist
ja
Hilfsmethoden, welche vor oder nach Processing
aufgerufen werden
PostRemove
ja
Hilfsmethoden, welche vor oder nach Processing
TLGen
29
StarData GmbH
V 2.501
aufgerufen werden
PostUpdate
ja
Hilfsmethoden, welche vor oder nach Processing
aufgerufen werden
PrePersist
ja
Hilfsmethoden, welche vor oder nach Processing
aufgerufen werden
PreRemove
ja
Hilfsmethoden, welche vor oder nach Processing
aufgerufen werden
PreUpdate
ja
Hilfsmethoden, welche vor oder nach Processing
aufgerufen werden
JoinColumn
ja
Verbindungsspalte für eine Relation
JoinColumns
ja
Mehrzahl von Verbindungs-Columns
JoinTable
ja
Verbindung DB Tabelle für eine ManyToMany Relation
Embeddable
ja
Verwendet für komplexe Primary Key
NamedQuery
ja
Definiert eine named SQL Query
NamedNativeQuery
ja
Definiert eine named Native Query
OrderBy
ja
Sortiert die Ergebnisse
Enumerated
nein
Vorgesehen für die nächste Version
EmbeddedId
nein
Vorgesehen für die nächste Version
Transient
nein
Vorgesehen für die nächste Version
TableGenerator
nein
Vorgesehen für die nächste Version
Temporal
nein
Vorgesehen für die nächste Version
Lob
ja
Verwendet für Blob und Clob (Große Daten)
SecondaryTable
nein
Vorgesehen für die nächste Version
Basic
ja
Wird zusammen mit Lob verwendet
PersistenceProperty
nein
Vorgesehen für die nächste Version
PersistenceUnit
nein
Vorgesehen für die nächste Version
UniqueConstraint
nein
Vorgesehen für die nächste Version
Inheritance
nein
Vorgesehen für die nächste Version
Innerhalb einer Entity Bean generiert TLGen eine Reihe von Hilfsmethoden, die für das
Mapping von Daten-Relationen notwendig sind. Diese Methoden sind:

fill„Name“(), hat keine Parameter und wird in Constructor aufgerufen. Diese ist
notwendig für das Speichern eines neuen Objektes in der Datenbank für eine
“ManyToOne” Relation

add„Name“(), hat keine Parameter und wird vom Manager aufgerufen. Diese ist
notwendig für das Speichern eines neuen Objekts in der Datenbank für eine
“OneToMany” Relation

call„Name“(), wird für alle Relationen beim Lesen eines Objektes aus der Datenbank
benutzt.
Listing 20 zeigt ein Beispiel-Code:
/**
* Helper Method "callFormular"
TLGen
30
StarData GmbH
V 2.501
*/
public CoFormularDataIf callFormular() {
// Relation ManyToOne, read data for "Formular" child, "Language"
if(getLanguage() != null) {
makeFormular().setLanguage(getLanguage().callLanguage());
}
// Relation ManyToOne, read data for "Formular" child, "Mandant"
if(getMandant() != null) {
makeFormular().setMandant(getMandant().callMandant());
}
// return the data object
return makeFormular();
}
20. Listing
In Listing 21 ist das Beispiel einer Mapping-Methode mit einem Sequence Generator für
Primary Key dargestellt:
// Methods from columns
@Id
@Column(name = "FORMULAR_ID")
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SEQ_STORE_FORMULAR")
public long getFormularId() {
return makeFormular().getFormularId();
}
public void setFormularId(long arg) {
makeFormular().setFormularId(arg);
}
21. Listing
TLGen generiert auch automatisch komplex verschachtelte Aufrufe für das Mapping.
Beispiel:
@Column(name = "authentificationFirstname", length = 255)
public String getAuthentificationFirstname() {
if(makeUser().getAuthentification() != null && makeUser().getAuthentification().getName() !=
null) {
return makeUser().getAuthentification().getName().getFirstname();
}
return null;
}
public void setAuthentificationFirstname(String arg) {
if(makeUser().getAuthentification() == null) {
makeUser().setAuthentification(new Authentification());
}
if(makeUser().getAuthentification().getName() == null) {
makeUser().getAuthentification().setName(new Name());
}
makeUser().getAuthentification().getName().setFirstname(arg);
}
22. Listing
TLGen
31
StarData GmbH
V 2.501
2.6.1 Relationen
Ein wichtiger Bestandteil von Entity Beans sind die Relationen zwischen verschiedenen
Objekten, die in einer Datenbank abgespeichert oder ausgelesen werden.
In diesem Kapitel werden die Verwendung von Relationen sowie der von TLGen generiertem
Code beschrieben.
2.6.1.1 Relation „OneToMany“
„OneToMany“ Relation wird verwendet, wenn ein Objekt mehrere Subobjekte (Kinder)
besitzt. In einer Datenbank wird dieses durch eine Tabelle, die eine „OneToMany“ Relation
zu einer anderen Tabelle hat, dargestellt. In Daten-Interface ist so eine Relation durch eine
Liste wie in Listing 23 erkennbar:
public interface CoFormularDataIf extends BaseDataIf
{
………………………………………………………………
public abstract List<CoPageDataIf> getPage();
public abstract void setPage(List<CoPageDataIf> arg);
………………………………………………………………
}
von “Formular” Objekt zu “Page” Object
{
………………………………………………………………
public abstract CoFormularDataIf getFormular();
public abstract void setFormular(CoFormularDataIf arg);
………………………………………………………………..
}
und von “Page” Objekt zu “Formular” Objekt.
23. Listing
und
in Entity Bean wie in Listing 24.
// Methods from relations tables
@OneToMany(cascade = {CascadeType.PERSIST,CascadeType.MERGE,CascadeType.REMOVE},
mappedBy = "formular",targetEntity = PageEntity.class)
public List<PageEntity> getPage() {
return m_page;
}
public void setPage(List<PageEntity> arg) {
m_page = arg;
}
24. Listing
Ob solch ein Objekt gespeichert werden muss oder nicht hängt von der Art der Relation ab,
„not null“ oder „null“. All seine Kinder werden automatisch gespeichert, wenn im Vater Objekt
die Kinderdaten vorhanden sind. Der Speicherungsprozess von Daten erfolgt automatisch
durch einen einzigen Aufruf von einer „create“ Methode (siehe Listing 13). Beim Lesen
werden zusammen mit dem Vater auch alle seine Kinder geholt, wenn diese vorhanden sind.
Die Tiefe von Relations-Ebenen kann gesteuert werden, d. h. es kann nur der Vater
gelesen/gespeichert werden oder die Ebenen können immer weiter um die Kinder erweitert
werden. Diese Ebenenerweiterungen werden dann möglich, wenn die Art der Relationen
„null“ ist. (Beispiel: ein „Formular“ hat mehrere „Pages“ und jede Page hat mehrere „Fields“
und so weiter)
TLGen
32
StarData GmbH
V 2.501
Eine UML-Darstellung für so eine Relation befindet sich in Abbildung 8. Zwischen „Formular“
Objekt und „Page“ Objekt existiert eine „null OneToMany“ Relation und zwischen „Page“
Objekt und „Fields“ Objekt eine „not null OneToMany“ Relation. Als Datenmodell wird diese
Relation in Abbildung 9 dargestellt.
Abbildung 8: „OneToMany“
2.6.1.2 Relation „ManyToOne“
Diese Relation ist eine symmetrische Relation zu „OneToMany“, d. h. ein Objekt kann in
mehrere andere Objekte verwendet werden. Auch bei dieser Art von Relation kann eine „not
null“ Verbindung existieren und dieser Link muss immer mit Daten versorgt werden, d. h. in
der Datenbank muss der Fremdschlüssel in den Kinder-Tabellen „not null“ sein (z.B. ein FK
=Fremdschlüssel) mit dem Typ „long“ soll immer größer als 0 sein und in der Tabelle, wo der
FK zeigt, muss ein richtiger Satz vorhanden sein).
Abbildung 9: „OneToMany“ Datenmodell
Die UML Darstellung ist gleich mit der Abbildung 8 und das Datenmodell wie Abbildung 9,
aber die Richtung ist umgekehrt als bei der Relation „OneToMany“, das gilt auch für die
Code-Darstellung in Listing 22.
Für den Entity Bean Code ist Listing 25 zu beachten:
@ManyToOne(optional = true,targetEntity = WebstyleEntity.class)
@JoinColumn(name = "WEBSTYLE_ID",insertable = true, updatable = true, nullable = true,
unique = false,referencedColumnName = "WEBSTYLE_ID")
public WebstyleEntity getWebstyle() {
return m_webstyle;
}
public void setWebstyle(WebstyleEntity arg) {
m_webstyle = arg;
}
TLGen
33
StarData GmbH
V 2.501
25. Listing
2.6.1.3 Relation „OneToOne“
Die Relation „OneToOne“ verbindet zwei Objekte so, dass eines ein einziges Kind besitzt.
Auch bei dieser Relation ist eine „null“-Verbindung möglich, d. h. der Fremdschlüssel kann
null sein, oder „not null“. In diesem Fall muss der Fremdschlüssel immer vorhanden sein und
zu einem vorhandenen Satz in der Datenbank die Verbindung anzeigen.
Auch bei dieser Verbindung gibt es einen Vater und ein Kind.
Code für diese Relation ist im Listing 26 für die Daten Interfaces und im Listing 27 für die
Entity Bean zu sehen.
public interface CoFieldDataIf extends BaseDataIf
{
…………………………………………………………
public abstract CoTableDataIf getTable();
public abstract void setTable(CoTableDataIf arg);
………………………………………………………….
{
26. Listing
public class FieldEntity
{
private TableEntity m_table = null;
…………………………………………………………
@OneToOne(cascade = {CascadeType.PERSIST,CascadeType.MERGE,CascadeType.REMOVE},
targetEntity = TableEntity.class,optional = true)
@JoinColumn(name = "TABLE_ID",insertable = false, updatable = false, nullable = true,
unique = false,referencedColumnName = "TABLE_ID")
public TableEntity getTable() {
return m_table;
}
public void setTable(TableEntity arg) {
m_table = arg;
}
…………………………………………………………..
}
27. Listing
2.6.1.4 Relation „ManyToMany“
Die Relation „ManyToMany“ ist die komplexe Form für das Verbinden mehrerer
Objekte/Tabellen. Auf der Code-Ebene hat jedes Objekt eine Liste mit den anderen Objekten
wie in der Listing 28:
public interface UserDataIf extends BaseDataIf
{
……………………………………………………..
// Methods from relations tables
public abstract List<UserRoleDataIf> getUserRole();
public abstract void setUserRole(List<UserRoleDataIf> arg);
……………………………………………………..
}
Von “User” Objekt, und von “UserRole” Objekt:
TLGen
34
StarData GmbH
V 2.501
public interface UserRoleDataIf extends BaseDataIf
{
……………………………………………………..
// Methods from relations tables
public abstract List<UserDataIf> getUser();
public abstract void setUser(List<UserDataIf> arg);
……………………………………………………..
}
28. Listing
Auf der Datenbank-Ebene ist für diese Relation eine dritte Tabelle notwendig, eine so
genannte Mapping Tabelle, wie in Abbildung 11. Die Darstellung in einem Domain Modell ist
in Abbildung 10 zu ersehen.
Abbildung 10: „ManyToMany“ Darstellung im UML Domainmodell
Aus einem Domain Modell generiert TLGen für „ManyToMany“-Relationen automatisch die
nötige Mapping Tabelle als SQL Skript.
Abbildung 11: „ManyToMany“ DB Relation
In den Entity Beans werden Annotationen mit den dazugehörigen Methoden, wie in unserem
Beispiel, sowohl in der „UserEntity“ Bean als auch in „UserRoleEntity“ Bean generiert (siehe
Listig 29):
@Entity
@Table(name="UserTable")
@SequenceGenerator(name="SEQ_STORE_USER", sequenceName="USERTABLE_SEQ", initialValue=1,
allocationSize=10)
public class UserEntity extends BaseData implements Serializable {
// Entity data field
private UserDataIf m_user = null;
……………………………………………………………………
TLGen
35
StarData GmbH
V 2.501
// Methods from relations tables
@ManyToMany(targetEntity = UserRoleEntity.class)
@JoinTable(name = "UserRole_UserTable",inverseJoinColumns = {@JoinColumn(name =
"UserRole_ID",insertable = true, updatable = true, nullable = false, unique = false)},
joinColumns = {@JoinColumn(name = "UserTable_ID",insertable = true, updatable = true,
nullable = false, unique = false)})
public List<UserRoleEntity> getUserRole() {
return m_userRole;
}
public void setUserRole(List<UserRoleEntity> arg) {
m_userRole = arg;
}……………………………………………………………………
}
Für “User” und
@Entity
@Table(name="UserRole")
@SequenceGenerator(name="SEQ_STORE_USERROLE", sequenceName="USERROLE_SEQ", initialValue=1,
allocationSize=10)
public class UserRoleEntity extends BaseData implements Serializable {
private static final long serialVersionUID = 413271821;
// Entity data field
private UserRoleDataIf m_userRole = null;
………………………………………………………………………………..
// Methods from relations tables
@ManyToMany(cascade = {CascadeType.PERSIST,CascadeType.MERGE,CascadeType.REMOVE},
mappedBy = "userRole",targetEntity = UserEntity.class)
public List<UserEntity> getUser() {
return m_user;
}
public void setUser(List<UserEntity> arg) {
m_user = arg;
}
……………………………………………………………………………..
}
Für “UserRole”
29. Listing
In der Praxis haben wir 3 Möglichkeiten Tabellen zwischen denen eine „ManyToMany“
Relation existiert, abzuspeichern, wie folgt:

Speichern beider Objekte gleichzeitig; das „User“ Objekt beinhaltet die Daten für
dessen „UserRole“ und in der Datenbank werden drei Sätze gespeichert, einer in der
„USERROLE“ Tabelle, der andere in die „USER“ Tabelle und der dritte Satz in die
Tabelle „USER_USERROLE“ mit beiden ID‟s (USER_ID und USERROLE_ID).

Speichern einer „UserRole“ von einem oder mehreren Objekten in der „USERROLE“
Tabelle

Speichern eines „User“ Objektes, der mit einem „USERROLE_ID“ einer vorhandenen
„USERROLE“ versorgt wird, in dem Datenbank Objekt einer „UserRole“. In diesem
Fall werden zwei Sätze in der Datenbank gespeichert, einer in die „USER“ Tabelle
und ein zweiter in der Tabelle „USER_USERROLE“ mit beiden ID‟s. Falls der
„USERROLE_ID“ zeigt, dass ein „USERROLE“ in dieser Tabelle nicht vorhanden ist,
wird eine Exception zurück zu den Client gesendet und eine Roll - Back Transaktion
folgt.
TLGen
36
StarData GmbH
V 2.501
2.7 Generierung von Datenbank und SQL Skripte
TLGen kann ein Datenbank SQL Skript aus einem Domainmodell, mit seinen Tabellen,
Spalten, Relationen, Indexes und Sequenzen generieren. Wenn der Datenbankzugriff (User
und Password) in der Konfiguration Datei vorhanden ist, verwendet TLGen das generierte
Skript, um die Datenbank zu generieren.
Dies ist auch möglich, wenn die Datenbank schon vorhanden ist. Dann werden nur die
Änderungen (es wird auch ein Änderung-Skript generiert) generiert, und somit werden die
schon vorhandenen Daten nicht gelöscht.
Skript-Beispiele werden in Listing 30 gezeigt:
----------- Drop all Tables ----------DROP TABLE Contract CASCADE CONSTRAINTS;
DROP TABLE Product CASCADE CONSTRAINTS;
…………………………………………………………
----------- Create Tables ----------CREATE TABLE Product (
Product_ID NUMBER(19,0) NOT NULL,
DB_VERSION NUMBER(16) NULL,
description VARCHAR2(255) NULL,
………………………………………………………
shortName VARCHAR2(255) NULL,
CustomerService_ID NUMBER(19,0) NULL,
PRIMARY KEY (Product_ID) USING INDEX TABLESPACE XINDEX
) Tablespace XDATA;
………………………………………………………
----- Foreign key -----ALTER TABLE Product ADD CONSTRAINT FK201A7DE FOREIGN KEY (CustomerService_ID) REFERENCES
CustomerService;
ALTER TABLE Contract ADD CONSTRAINT FKF96859 FOREIGN KEY (Customer_ID) REFERENCES
Customer;
ALTER TABLE Contract ADD CONSTRAINT FK31C7538 FOREIGN KEY (AccessControlContext_ID)
REFERENCES AccessControlContext;
ALTER TABLE Contract ADD CONSTRAINT FK7FE790 FOREIGN KEY (Offer_ID) REFERENCES Offer;
………………………………………………….
----------- Create Sequences ----------CREATE SEQUENCE Contract_SEQ START WITH 1 INCREMENT BY 1 CACHE 10 MINVALUE 1;
CREATE SEQUENCE Product_SEQ START WITH 1 INCREMENT BY 1 CACHE 10 MINVALUE 1;
30. Listing
Die sofortige Generierung einer Datenbank ist wichtig für den Datenbank OptimierungsProzess (neue und alte Projekte) siehe Kap. 2.1
2.8 Regel für die Generierung von Namen
TLGen verwendet im Code-Generierungs-Prozess zwei Arten von Regeln für die NamenGenerierung:

Die Domainmodell-Namen sind eigentlich Namen nach den Java Konventionen für
Datenbank-Namen. In diesem Fall verwendet die Generierung der Datenbank
Namen, schon vorhandene Namen aus dem Domainmodell.

Bei einer schon vorhandenen Datenbank (Legacy Projekte) sind in den meisten
Fällen Namen, die anders sind als die Java Namenskonventionen. Für diesen Fall
sind acht Namensumwandlungen möglich:
TLGen
37
StarData GmbH
V 2.501
o
Aus den Groß geschriebenen Namen, aus mehreren Teilen mit ein
„underscore“ verbunden, wird ein Name kleingeschrieben, ohne „underscore“,
bedeutet das die Default Einstellung, siehe Tab 6, Zeile 1
o
„underscore“ wird nicht mehr verwendet, d.h. der erste Buchstabe ist groß,
Zeile 2
o
„underscore“ wird nicht verwendet, der Rest ist gleich, Zeile 4 und 5
o
„underscore“ wird verwendet, der restliche Name bleibt gleich, Zeile 6
o
underscore“ wird verwendet, und der Rest verwendet die Java NamenKonvention, Zeile 7
o
keine Namen-Änderung.
Tabelle 6: Namen-Regel
Nr.
Datenbank Format
Java Format
1
CORE_FORMULAR
Formular
2
CORE_FORMULAR
CoreFormular
testCoreFormular
TestCoreFormular
CORE_FORMULAR
CoreFormular
testCoreFormular
TestCoreFormular
FORMULAR
Formular
CORE_FORMULAR
COREFORMULAR
testCoreFormular
TestCoreFormular
CORE_FORMULAR
CoreFormular
testCoreFormular
Testcoreformular
6
CORE_FORMULAR
COREFORMULAR
7
CORE_FORMULAR
Core_formular
8
CORE_FORMULAR
CORE_FORMULAR
3
4
5
Diese Regeln werden einmal für das gesamte Projekt gesetzt, aber wenn unterschiedliche
Regeln für die Namen innerhalb einer Session Bean mit seinen Komponenten erwünscht
sind, müssen diese gesetzt werden. Details siehe auch Kapitel 4.4.
Diese Regeln können auch von dem Domain Modell in Bezug auf der Datenbank verwenden
werden, aber die meisten Datenbanken machen keinen Unterschied zwischen Klein- und
Gross- Schreibung.
2.9 Log Dateien Beschreibung
TLGen erzeugt im Generierungs-Prozess mehrere Log-Dateien, in welchen alle Schritte
eingetragen werden. Durch diese Log-Dateien kann kontrolliert werden, ob das ProjektDesign den gewünschten Ergebnissen entspricht.
Die Verwendung von Log-Dateien ist einstellbar und der Name ist wählbar, d. h. es kann
bzw. können nur eine oder mehrere verwendet werden. Sind es mehrere, weil die
TLGen
38
StarData GmbH
V 2.501
Information in diesen Dateien sehr groß ist, wird die Verwendung dieser Dateien somit
erleichtert.
TLGen kann folgende Log-Dateien verwenden:

Eine Log-Datei für die Generierung allgemeiner Schritte (beschreibt nur wichtige
Schritte)

Eine Log-Datei für die Generierung von Session Beans

Eine Log-Datei für die Generierung von Entity Beans

Eine Log-Datei für die Generierung von Test Classen

Eine Log-Datei für die Generierung von Daten Classen/Interfaces

Eine Log-Datei für die Generierung von Manager Classen.
Es gibt eine Error Log-Datei, in der die Generierung Error, wie zu lange Namen, Fehler im
Domainmodell (z. B. Kreise in Relationen) eingetragen werden. Ein Beispiel für eine Error
Log-Datei befindet sich in Listing 31 (siehe auch Kap. 2.1):
Time Start : Sat Feb 05 13:29:11 CET 2011
0 Domain Error | Class-name is too lang[35] + 'AverageFlatDurationCalculationParam'
==== Direct circles in relations ==============================================
Warning: TARGET [Order] in a path starting with himself as SOURCE [Order]: [Order(NOT NULL)>Customer(NULL)->Asset(NOT NULL)->AssetItem(NOT NULL)] ---> [Order]
Warning: TARGET [Offer] in a path starting with himself as SOURCE [Offer]: [Offer(NOT NULL)>Customer(NULL)->Asset(NOT NULL)->AssetItem(NOT NULL)->Order(NOT NULL)->Contract(NOT NULL)] --->
[Offer]
………………………………………………..
==== Relation Problems? ==================================================
FATAL Error: [ServiceDescriptiontItem] needed by different mandatory relations starting from [AssetItemStatus]
[AssetItemStatus->AssetItem->Order->Contract->ServiceDescription] ---> [ServiceDescriptiontItem]
[AssetItemStatus->AssetItem->OrderItem] ---> [ServiceDescriptiontItem]
FATAL Error: [ServiceDescription] needed by different mandatory relations starting from [AssetItem]
[AssetItemStatus->AssetItem->Order->Contract] ---> [ServiceDescription]
[AssetItemStatus->AssetItem->Order->Contract->Offer] ---> [ServiceDescription]
Warning: [ProductRelation] can be reached over [AssetItem] in different relations:
[AssetItemStatus->AssetItem->OrderItem->ServiceDescriptiontItem->Product] ---> [ProductRelation]
[ServiceDescriptiontItem->AssetItem->OrderItem->Product] ---> [ProductRelation]
[OrderItem->ServiceDescriptiontItem->AssetItem->Product] ---> [ProductRelation]
31. Listing
TLGen
39
StarData GmbH
V 2.501
2.10 Message Driven Bean
In komplexen Anwendungen müssen die Aufgaben manchmal nicht sofort erledigt werden,
sondern erst zu einem späteren Zeitpunkt, nachdem der Anwendung eine Nachricht
zugekommen ist.
Für die Message Driver Bean läuft die Kommunikation zwischen Client und Server über JMS
(Java Message Service) ab. TLGen kann die Message Driver Bean mit sehr viel weniger
Aufwand generieren.
Die so generierte Message Driver Bean kann über die Callback Klasse (siehe 2.8.3) mit der
Applikation kommunizieren und so eine klare Trennung zwischen der technischen und der
fachlichen Schicht realisieren.
Mit Hilfe der Steuerung über die Konfigurationsdateien können für die Message Driver Bean
folgende Features generiert werden:

Annotationen mit Parameter (Tabelle 7)

Client Klassen

Message Driver Bean Klassen selber

Callback Klasse für die Verbindung mit der Fachlogik-Schicht
Tabelle 7: Annotationen für Message Driven Bean
Annotationen
Verwendung Kommentar
in TLGen 2.5
javax.annotation.Resource
ja
Definiert die Ressource Message Driven Bean
javax.ejb.MessageDriven
ja
Definiert eine Message Driven Bean
javax.ejb.ActivationConfigProperty
ja
Setzt die Properties für eine Message Driven
Bean
2.11 Services
Der Applikation Server für EJB 3 bietet zwei Services an, eine Time Service, mit deren Hilfe
ein bestimmter Prozess zu einer bestimmten Zeit mehrmals aufgerufen werden kann und ein
Web Service, die ein Aufruf einer Session Bean über das Inter/Intra-Net ermöglicht. TLGen
kann beide Services generieren.
2.11.1 Timer Service
Ein Timer Service kommt in einer Applikation zum Einsatz, wenn eine zeitgesteuerte
Verarbeitung nötig ist.
Der Methodenaufruf kann wahlweise erfolgen, einmalig oder aber in einem bestimmten
Zeitintervall dauerhaft.
TLGen
40
StarData GmbH
V 2.501
TLGen generiert ein Timer Service mit seinen Komponenten wie Client für Timer Service
Start, Timer Service selbst als auch eine Callback Klasse (siehe 2.8.3) für die
Implementierung der Fachlogik, notwendig für dieses Service.
Timer Service werden von TLGen in drei Varianten generiert:
1. Vollkommen automatisch; In diesem Fall sollten Start-, Stopp-Zeit und die
periodische Wiederholung automatisch nach eine Timer Service Initialisierung,
erfolgen.
2. Start- und Stopp-Zeit, gesteuert durch einen Client Aufruf
3. Automatische und manuelle Steuerungsmöglichkeiten
Der Timer Service kann mit einer Session Bean oder mit einer Message Driven Bean
verwendet werden.
2.11.2 Web Services
Eine Web Service ist ein beliebiger Service (z. B. eine Session Bean), der von einem entfernt
liegenden Client über ein World Wide Web verwendetes Protokoll aufgerufen werden kann.
Es gibt zwei Webservice-Arten, RPC(Remote Procedure Call) und DOCUMENT. RPC ist
eigentlich ein Aufruf von einer Methode (z. B. eine Methode einer Session Bean) über das
Web.
Der Unterschied zwischen einem Aufruf vom Client zu einer Session Bean (über Applikation
Server Techniken) und einem Client Aufruf einer WebServices liegt in der Aufrufart. Diese
basiert auf XML und ist standardisiert. Somit ist jeder Aufruf in der Lage sich mit einfachen
Mitteln an der Kommunikation zu beteiligen.
TLgen generiert für diesen Service den Client, den Webservice selber als auch eine Callback
Klasse (siehe 2.8.3), falls nötig.
2.11.3 Callback Klasse
Diese Art von Klasse befindet sich als Schnittstelle zwischen dem technischen Code,
komplett von TLGen generiert, und dem Fach-Code, welcher die Fachlogik der Applikation
beinhaltet.
Diese Klasse kann in drei Modi generiert werden und hat, abhängig von einem Parameter
„merge“, folgende Werte:

merge = 0, TLGen generiert diese Klasse immer wieder neu

merge = 1, diese Klasse wird generiert nur wenn sie nicht existiert

merge = 2, wird sie neu generiert und der manuell erstellte Code mit dem neu
generierten Code gemergt
2.12 Free Klasse
Diese Klassen sind für den Programmteil, welcher die Fachlogik beinhaltet, gedacht. Der
Inhalt dieser Klasse ist manuell zu implementieren. Findet der Generator diese Klassen,
abhängig vom Parameter „merge“, dann ergeben sich folgende Werte:
Folgende Attribute werden für diesen Tag verwendet:
TLGen
41
StarData GmbH
V 2.501

merge = 0, TLGen generiert diese Klasse immer wieder neu

merge = 1, diese Klasse wird generiert nur wenn sie nicht existiert

merge = 2, wird neu generiert und der manuell erstellte Code mit dem neu
generierten Code gemergt
TLGen
42
StarData GmbH
V 2.501
3. Vergleich zwischen TLGen und anderen Code Generatoren
EJB (Enterprise Java Beans) sind standardisierte Komponenten innerhalb eines Applikation
Servers, mit dem Ziel, komplexe, mehrschichtige sowie verteilte Software Systeme mit der
Programmiersprache Java zu vereinfachen.
Die erste Spezifikation von EJB wurde von IBM im Jahr 1997 durchgeführt und von Sun
Microsystems mit der Bezeichnung EJV 1.0 und 1.1 angenommen. Kurz danach erschienen
die ersten Applikation Server „WebSphere“ von IBM und „WebLogic“ von BEA auf dem
Markt.
Das EJB-Konzept sollte die Softwareentwicklung von komplexen verteilten Applikationen
stark vereinfachen. Das ist aber nur teilweise gelungen, da der persistente Teil (auf Basis
von Entity Beans) erhebliche Performance-Verluste verbuchte. Aus diesem Grund sind eine
Reihe von Applikationen als „Verbesserungs-Tools“ (z.B. „Hibernate“, „iBatis“, „TopLink“ etc)
entwickelt worden, hauptsächlich um diesen Zustand, zu korrigieren.
Version 2 von EJB verbessert diesen Zustand wesentlich, eine bessere Performance ist
vorhanden. Aber geblieben ist eine gewisse Schwierigkeit durch sehr komplexe und
aufwendig zu entwickelnde XML Dateien, notwendig für das Deployment von Applikation. Als
Hilfe dafür ist das Tool „XDoclet“ gedacht, welches mit Hilfe von eigenen Tags relativ einfach
diese komplexe XML Dateien generiert.
Ab Version 3.0 und 3.1 von EJB sind alle Probleme von EJB sehr gut gelöst worden. Eine
vernünftige Verwendung der Annotationen (neue Features von Java) lässt die komplette
Generierung des notwendigen Java Codes, nur auf Basis von Domainmodell oder
Datenmodell, zu. Die Generierungs-Steuerung (die nicht sehr umfangreich ist) übernimmt
eine Konfigurations-Datei.
Tools wie Hibernate sind für EJB 3 eigentlich nicht mehr notwendig, sie verkomplizieren
sogar die gesamte Applikation. Diese Applikationen bergen folgende Nachteile:

Die Applikation muss in der Running Zeit diese Tools in der Applikation einbeziehen:
o
das verkompliziert die Applikation
o
veranlasst eine Tool-Versions-Abhängigkeit sowie
o
Miteinbeziehung der Tool-Fehler

Verwendet eine extra Code-Schicht als von EJB3 vorgesehen ist

All diese Tools bringen nicht eine komplette neue Lösung in der Verwendung von
Datenbanken mit sich, sondern sind nur eine Extraschicht für einen Applikation
Server, um die Entwicklung mit allen diesen Nachteilen zu erleichtern. Eine reine
Nutzung von EJB3 ohne zusätzliche Tools (wie z.B. Hibernate, Toplink, etc.) ist im
direkten Vergleich zur Tool-Nutzung immer im Vorteil (siehe auch Anhang 1 - folgt in
Kürze).
Die Verwendung der Tools (wie z.B. Hibernate, TopLink, iBatis, etc.) mit einem EJB3
Applikation Server ist weder erforderlich noch empfehlenswert, es verkompliziert nur das ITProgramm ohne dabei Vorteile zu erbringen. So ein Tool ist nur für kleine Applikationen, die
keinen Applikation Server benötigt, zu gebrauchen.
In Gegensatz zu diesen Tools (Hibernate, TopLink, iBatis, etc.) bringt TLGen durch eine
komplette Generierung des notwendigen Java Codes eine wesentliche Vereinfachung in der
Verwendung von EJB3, so dass sich die Entwicklung nur auf die Fachlogik einer Applikation
konzentrieren kann. Die Verwendung von TLGen bringt folgende Vorteile:
TLGen
43
StarData GmbH
V 2.501

Komplette Code-Generierung: Test Klassen, Client Technische Klassen, Session
Beans, Manager Beans, Entity Beans, „persistence.xml“ Dateien, Daten
Klassen/Interfaces und Interceptor Klassen

TLGen beteiligt sich nicht bei der Applikation in Running Zeit, d. h. keine
Abhängigkeit von der TLGen Version

Der von TLGen generierte Code hat das gleiche Layout wie der Code, welcher ein
Programmierer selber schreiben könnte

Durch die sofortige Code-Generierung mit Test Klassen, können die Designer und
Architekten die Ergebnisse von Konzepten sofort ersehen und eventuell optimieren
(siehe Kap. 2.1)
TLGen
44
StarData GmbH
Herunterladen