»  New
  »  Starten des Tomcat
Um die Flex Anwendung auf dem Tomcat zu starten, muss die Datei startup.bat unter tomcat/bin ausgeführt werden.
Unter:
http://localhost:8080/ RemoteObject_Hibernate/ RemoteObject_Hibernate.mxml
kann die Anwendung angesprochen werden (entferne die Leerzeichen wenn Du die URL kopierst).
  »  JUnit für Hibernate
Im workspace für Eclipse befindet sich ein Unit-Test um die Hibernate Funktionalität ohne Flex-Anwendung zu testen. Dieser Test läuft nur mit gestarteter Hypersonic Datenbank. Dafür muss der Tomcat gestartet werden. Der JUnit-Test überschreibt die Werte in der Datenbank.
Wird die Flex Anwendung nach einem Unit-Test aufgerufen, sind weder Studenten noch Kurse zu sehen. Um die default Werte wieder herzustellen, muss die Datei tomcat/db/_fleksraydb.script nach tomcat/db/fleksraydb.script kopiert werden.
   

  »  Flex LiveCycle DataManagement Service und Hibernate im Zusammenspiel

Hibernate und Adobe Flex Frontends lassen sich in einfacher Weise mit dem DataManagement Service verbinden. Damit lassen sich in Java entwickelte Klassen eins zu eins in eine Flex Anwendung übernehmen. Alle Änderungen an Objekten im Flex Client werden direkt auf die Java Objekte übertragen.
Wird der DataManagement Service in Verbindung mit Hibernate verwendet, ist es nicht einmal nötig DataAccess Klassen zu entwickeln. Alle Create-, Update- und Delete-Operationen werden direkt auf die Java Objekte angewendet (hinter den Kulissen führt die Klasse flex.data.adapters.JavaAdapter des DataManagement Service die CRUD Operationen aus).
Diese Vorgehensweise vereinfacht den Entwicklungsaufwand enorm. Die Programmierung von DAO's entfällt.
Die Verwendung des DataManagement Service bringt aber auch Nachteile mit sich. Der Service verwendet das Real Time Messaging Protokoll, das im Normalfall Port: 2038 verwendet.
Der Einsatz beschränkt sich deshalb mehr oder weniger auf Intranet Anwendungen. Soll Hibernate in klassischen Internet Applikationen eingesetzt werden, kommt man nicht umhin, Data Access Klassen zu implementieren und deren Interface per WebService im Netz zur Verfügung zu stellen.

Hibernate mit Flex DataManagement Service

Die Studenten-Kurse Anwendung unter Verwendung von Hibernate


Studenten und Seminare, eine m:n Beziehung
Im folgenden Beispiel wird eine Anwendung entwickelt, mit der es möglich ist Studenten und Seminare zu verwalten. Für diese Entities werden zwei entsprechende Klassen, sowohl in Java, als auch in ActionScript erstellt. Für die Persistenz der Objekte ist Hibernate zuständig. Als Datenbank kommt Hypersonic SQL zum Einsatz. Als Webapplication Server wird Tomcat verwendet.
Mit der Flex Anwendung ist es möglich, Create, Update und Delete Operationen für Studenten und Seminare auszuführen.
Der Einfachheit halber wird auf die Funktionalität verzichtet, Studenten bestimmte Seminare zu zuweisen. In der der Hypersonic Datenbank sind jedoch bereits einige Zuweisungen angelegt. Mit der hier entwickelten Applikation können die Seminare nur angezeigt werden, die von einem bestimmten Studenten belegt werden.

Flex Hibernate

Anzeige der Kurse für die ausgewählte Studentin


Da die komplette Anwendung recht umfangreich ist, wird im Artikel nur auf Ausschnitte des Source Code eingegangen. Die kompletten Quellen finden sich in der Box: Source Code im linken Seitenbereich oben.
25, Oktober 2007

  »  Die Java Klassen und die Hibernate Config-Files

Die Java Klassen
Für die Entities Student und Course werden zwei Java Beans angelegt, deren Aufbau recht simpel ist.

Die Klasse Student besitzt die Eigenschaften und entsprechenden set- und get-Methoden:
studentNumber; studentFirstName; studentLastName
Die Klasse Course besitzt die Eigenschaften und entsprechenden set- und get-Methoden:
courseNumber; courseName; description

Die Java Klasse Student besitzt ein HashSet namens courses. Dieses Set enthält die Kurse, für die sich der Student eingetragen hat.
Ebenso besitzt die Klasse Course ein HashSet students, das alle Studenten enthält, die diesen Kurs belegen.
Im Beispiel handelt es sich also um eine m:n Beziehung.
Ein Student belegt mehrere Kurse.
Ein Kurs wird von mehreren Studenten belegt.

Die Hibernate Config-Files
Die hibernate.cfg.xml enthält allgemeine Einstellungen zur Datenbank-Connection, zum SQL-Dialect usw. auf die hier nicht weiter eingegangen werden soll.
In der StudentCourse.hbm.xml werden die Klassen Student und Course gemappt. Diese Datei wird im folgendem genauer erklärt.
Das Hibernate Mapping File für die Studenten- und die Course Klasse enthält das Root-Tag <hibernate-mapping>. Innerhalb dieses Tags werden die Java Klassen auf die entsprechende Tabelle der SQL Datenbank gemappt.
Bei komplexen Anwendungen erhält jede Javaklasse/Sql-Tabelle ein eigenes Mapping-File. Hier im Beispiel werden die Klassen Student und Course der selben Datei eingetragen. Auf das Mapping der Klasse Student soll etwas genauer eingegangen werden. Das Mapping für die Klasse Course ist ähnlich.

 Die gemappte Student Klasse
  			
            <class name="Student" table="Student">
                 <id name="studentNumber" column="student_number">
                      <generator class="native">
                 </id>
                 
                 <property name="studentFirstName"/>
                 <property name="studentName"/>
  			     
                 <set name="courses" 
                      table="Course_Student" 
                      inverse="true" 
                      lazy="true" 
                      cascade="save-update">
                           
                          <key column="student_number"/>
                          <many-to-many class="Course" column="course_number"/>
                 </set>
            </class>  

            <query name="students.all">From Student</query>			
            

Im öffnendem <class> Tag wird der Name der Klasse und die entsprechende SQL-Tabelle angegeben.
Im Tag <id> wird der Primary-Key vereinbart. Im Fall der Klasse Student ist das die Eigenschaft studentNumber, die der Spalte student_number der Tabelle Student in der Hypersonic Datenbank entsprechen soll.
Dann werden die Eigenschaften studentFirstName und studentName deklariert. Solange der Name der Eigenschaft mit dem Namen der Tabellenspalte übereinstimmt, müssen hier keine weiteren Einstellungen vorgenommen werden (Hibernate bietet eine Fülle von Möglichkeiten um die Eigenschaften der Properties feiner zu spezifizieren, darauf soll an dieser Stelle jedoch verzichtet werden).

Im Tag <set> wird ein Collection deklariert, die die Kurse enthält, für die sich der Student eingeschrieben hat. Der Name des Set muß dem Namen des Property in der Klasse Student entsprechen. Als table wird die Tabelle angegeben, die die Beziehung zwischen der Klasse Course und der Klasse Student managed.

Die Tabelle Course_Student enthält lediglich die zwei Spalten student_number und course_number, welche die primary keys der Tabellen Student und Course repräsentieren. Im Tag <many-to-many> wird Hibernate die Art der Beziehung, die Klasse zu der die Beziehung aufgebaut werden soll und der primary key eben dieser Klasse mitgeteilt.
Wird die Eigenschaft lazy auf true gesetzt, wird die Student Klasse per default mit einem leeren courses-Set instantiiert. Die Eigenschaft cascade gibt an, wann das Set gefüllt werden soll.

Am Ende wird ein HQL-Query Statment definiert, das in der Flex Anwendung dazu dient, eine Collection mit Studenten Objekten zu füllen. Dazu mehr in der Box: Die Flex Applikation weiter unten.
Das Mapping für die Klasse Course ist nahezu identisch aufgebaut.
25, August 2007

  »  Die Config-Files für den DataManagement Service

Konfiguration des RMTP-Channels und der Destinations
Wie alle Konfigurationdateien für den Adobe LiveCycle Service sind auch die Config-Files für den DataManagement Service unterhalb des [CONTEXT-ROOT]/WEB-INF/flex Verzeichnisses zu finden. Die beiden relevanten Dateien, für die hier vorgestellte Applikation, sind services-config.xml und data-management-config.xml.
In der services-config.xml muss folgender Eintrag (meist schon per default) vorhanden sein.

 Die Definition des RTMP-channels
            
            <channel-definition id="my-rtmp" class="mx.messaging.channels.RTMPChannel">
                        <endpoint uri="rtmp://{server.name}:2038" 
                             class="flex.messaging.endpoints.RTMPEndpoint"/>
                        <properties>
                             <idle-timeout-minutes>20</idle-timeout-minutes>
                             <client-to-server-maxbps>100K</client-to-server-maxbps>
                             <server-to-client-maxbps>100K</server-to-client-maxbps> 
                        </properties>
           </channel-definition>


In der data-management-config.xml Datei werden für die entwickelten Java Klassen so genannte destinations deklariert. Im <destination> Tag wird eine frei wählbare ID vergeben. Diese ID wird später in der Flex Anwendung benötigt, um den DataService für die entsprechende Klasse anzusprechen. Innerhalb der Destination werden folgende Angaben gemacht:
<adapter> Hier wird eine Refererenz auf den Adapter angegeben, der die Verbindung zu den Java Objekten aufnehmen soll. In unserem Fall ist das die Adapter Klasse flex.data.adapters.ASObjectAdapter.

Dann folgen eine Reihe von Eigenschaften, die das Zusammenspiel der entwickelten Java Klassen, Hibernate und dem DataManagement Service regeln. Im folgenden wird nur auf die für unsere Anwendung relevanten Properties eingegangen.

<source> Hier wird die Klasse des Hibernate Assemblers eingetragen, eine Klasse des Flex LiveCycle Service, die die Schnittstelle zu Hibernate darstellt.
<scope> Einstellung des "Sichtbarkeitsbereiches" der Student Klasse. Möglich sind: application, session und request.
<identity> Angabe des primary key der Student Klasse.
<hibernate-entity> Angabe des kompletten Klassepfades zur Student Klasse.
<fill-method> Name der Fill-Methode und Angabe der Collection Klasse, die später die Studenten Objekte in der Flex Anwendung aufnehmen soll.
<fill-configuration> Hier ist der Eintrag <allow-hql-queries>true</allow-hql-queries> wichtig. Dieser erlaubt in der Flex Applikation HQL-Queries aufzurufen, die in der StudentCourse.hbm.xml definiert wurden.

 Die Definition der Student destination in der data-management-config.xml


      <destination id="hibernate-student">
            <adapter ref="java-dao" />
            <properties>
                 <use-transactions>true</use-transactions>
                 <source>flex.data.assemblers.HibernateAssembler</source>
                 <scope>application</scope>
                 <metadata>
                       <identity property="studentNumber"/>
                 </metadata>
                 <network>
                      <session-timeout>20</session-timeout>
                      <paging enabled="false" pageSize="10" />
                      <throttle-inbound policy="ERROR" max-frequency="500"/>
                      <throttle-outbound policy="REPLACE" max-frequency="500"/>
                 </network>
                 <server>
                      <hibernate-entity>org.fleksray.samples.model.Student</hibernate-entity>
                      <fill-method>
                           <name>fill</name>
                           <params>java.util.List</params>
                      </fill-method>
                      <fill-configuration>
                           <use-query-cache>false</use-query-cache>
                           <allow-hql-queries>true</allow-hql-queries>
                      </fill-configuration>
                  </server>
            </properties>
       </destination>


Der Aufbau für die Course Destination ist ähnlich.
25, August 2007

  »  Die Flex Applikation

Die Student- und die Course Bean in ActionScript
Um erfolgreich mit den Java Objekten auf dem Tomcat kommunizieren zu können, müssen zwei Klassen in ActionScript implementiert werden, die das Gegenstück zu den Java Klassen Student und Course darstellen. Diese Klassen enthalten die gleichen Properties wie die Java Klassen. Die Properties werden als public Variablen deklariert, auf get- und set-Methoden wird hier verzichtet.
Per Definition muss in den ActionScript Klassen ein leerer Konstruktor deklariert werden. Die Klassen werden als Managed deklariert und ein Alias auf die entsprechenden Java Klassen wird gesetzt.

 Die ActionScript Klasse Student


     package org.fleksray.samples.model
{ import mx.collections.ArrayCollection; [Managed] [RemoteClass(alias="org.fleksray.samples.model.Student")] public class Student { public var studentNumber:Number; public var studentName:String; public var studentFirstName:String; public var courses:ArrayCollection; public function Student(){} } }

Die Klasse Course.as hat einen ähnlichen Aufbau.
Der DataService in Flex Anwendung
In der Flex Applikation ist ein DataGrid zuständig für die Anzeige der Eigenschaften der Studenten. Dieses DataGrid verwendet eine ArrayCollection, die mit Objekten vom Typ Student gefüllt wird. Dafür muss in der Anwendung eine Instanz der Klasse Student und eine Instanz der zu füllenden ArrayCollection erzeugt werden.
Im <mx:DataService> Tag ist für die destination ein Name erforderlich. Dieser Name entspricht genau der Id, die in der data-management-config.xml für die Student destination vereinbart wurde.

 Auszug aus der Flex Application

     
     <model:Student id="student"/>
     <mx:ArrayCollection id="studentArray" />

     <mx:DataService id="hibernateStudent" 
          destination="hibernate-student" 
          fault="handleFault(event)" 
          autoCommit="true" />


autoCommit="true"
Hier im Beispiel wird die Eigenschaft autoCommit auf true gesetzt. Damit wird erreicht, dass alle Änderungen, die an der ArrayCollection studentArray direkt auf den Server übertragen werden. Wird also die Eigenschaft editable des DataGrid auf true gesetzt, werden alle vom Anwender vorgenommen Änderungen, auf die von Hibernate verwalteten Objekte übertragen (ohne das ein Submit-Button o.ä. geklickt werden muss). Anwender die ebenfalls mit dem Server verbunden sind, sehen die vorgenommenen Änderungen sofort, ohne einen Reload ausführen zu müssen. Ein entscheidender Vorteil des Real Time Messaging Protokoll.
Füllen der ArrayCollection
Nun muss noch die ArrayCollection, die als DataProvider für das DataGrid dient, gefüllt werden. Dafür wird die Methode fill() am DataService aufgerufen. Diese Methode wurde oben ebenfalls in der data-management-config.xml unter <fill-method> deklariert.
Der fill() Methode werden drei Argumente übergeben. Erstes Argument ist die zu füllende ArrayCollection, dann folgt der Name des HQL-Query, wie er in der Student.hbm.xml vereinbart wurde. Der dritte Parameter wird hier nicht verwendet.

Der dritte Parameter der fill() Methode.
Der dritte Parameter wird verwendet, wenn direkt HQL-Querys aus der Flex Anwendung abgesetzt werden sollen. Das ist sinnvoll, wenn die Abfrage Variablen enthält, deren Wert zur Kompilierzeit nicht bekannt sind. Der dritte Parameter erwartet eine Array. In diesem Array ist der erste Wert der HQL-Query selbst, gefolgt von den dynamischen Parametern für diesen Query:
hibernateStudent.fill(studentArray, "flex:hql", ["from Student s where s.studentFirstName = :firstName", parameterMap]);
Die parameterMap enthält unter dem key "firstname" den Namen des Studenten, nach dem gesucht werden soll.

oder:

hibernateStudent.fill(studentArray, "flex:hql", ["from Student s where s.studentFirstName = ?", parameterArray]);
hier enthält das parameterArray den Namen des Studenten nach dem gesucht wird. Bei mehreren Parametern ist die Reihenfolge der Parameter zu beachten

Die Methode hibernateStudent.fill() wird in einer Mehtode mit dem Namen initialFill() aufgerufen. Diese Methode wiederum wird beim creationComplete() Event der Applikation aufgerufen. Damit wird das DataGrid beim ersten Aufruf der Applikation gefüllt.
Der DataService stellt weiterhin die Methoden deleteItem und createItem zur Verfügung, also die typischen Methoden einer DAO Klasse. Diese Methoden wurden im Beispiel an keiner Stelle definiert. Die Arbeit dafür übernimmt voll und ganz der Flex DataManagement Service.

 Die Methode zum Löschen von Studenten
            
            private function deleteStudent():void {
                 hibernateStudent.deleteItem(dgStudent.selectedItem as Student);
            }


Der Quellcode für die Anzeige, das Löschen und das Erzeugen von Kursen sieht ähnlich aus.

25, August 2007