»  Running Tomcat
To start the Flex Application at the Tomcat execute the file tomcat/bin/startup.bat
Then point your browser to the url:
http://localhost:8080/ RemoteObject_Hibernate/ RemoteObject_Hibernate.mxml
  »  JUnit for Hibernate
The Eclipse workspace contains a JUnit-Test for the Hibernate classes. With this test you can check the Java classes without using the Flex Application.
The test only runs if the Hypersonic Database is up and running. For that reason you need to start the Tomcat.
The JUnit-Test overwrites the values in the database. If you start the Flex application after a Unit-Test the DataGrid will be empty.
To restore the default values copy the file tomcat/db/_fleksraydb.script to tomcat/db/fleksraydb.script

  »  Flex LiveCycle DataManagement Service and Hibernate together

Hibernate and Adobe Flex frontends are easily connected by using the DataManagement Service. In Java developed classes can be accessed in the Flex application using a ActionScript class with the same setter- and getter methods. This ActionScript class represents the Java class in the Client. Any changes you make at the ActionScript class are directly effecting the class on the server.

There is no need to develop DataAccess classes. All create-, update-, and delete-operations are handled by the DataManagement Service. Behind the Scenes the class flex.data.adapters.JavaAdapter is taking care of the CRUD-Operations.

But there is also a disadvantage. The Service is based on the Real Time Messaging Protocol which uses the port 2038. This port might be blocked by firewalls. This actually limits this service to closed Environments like intranets. If you want to use Hibernate in for a internet application it might be better implementing your own DataAccess objects and provide the public methods of these Objects to your clients by a Webservice.

Hibernate mit Flex DataManagement Service

The student course application


Students and courses, a m:n Relationship
In the following example we develop a application which enables you to manage students and courses. For both entities we create the Bean classes in Java and ActionScript. Hibernate takes care of persisting the Java objects. As database we using Hypersonic SQL, the web application server is a Tomcat.
When you start the Tomcat the Hypersonic Database is up and running too.

This Flex application enables you to create, update and delete students and courses. To make the example less complex we do not develop a feature which enables you to assign courses to students. In the default database are already a few assignments made. Our application can show this assignments.

Flex Hibernate

The application shows the assigned courses for a certain student


Don't understand this as a tutorial. I do not give any explanation here like: now go to this folder, do this....bla. I just mention the important things. If you want to run the example download the tomcat or the sources (have a look at the boxes at the left side).
03. November 2007

  »  The Java classes and the Hibernate config-files

The Java Classes
For the entities student and course we create two simple Bean classes. For the complete source code check out the upper left box on this page.

The class student has the properties and the appropriate getter and setter methods
studentNumber; studentFirstName; studentLastName
The class course has the properties and the appropriate getter and setter methods
courseNumber; courseName; description

The Java class Student contains a HashSet named courses. This set contains the courses the student has signed in.
The Java class Course contains a HashSet named students. This set contains all the students who have signed in for this particular course.

This is what we call a m:n relationship.

A student can assign to many courses.
A course is assigned by many students.

The Hibernate config-Files
The hibernate.cfg.xml conatains common settings for the database connection, the SQL dialect and a few more which are not explained in detail here..
In the StudentCourse.hbm.xml we map the classes Student and Course. Lets have a closer look at this file.

The mapping file has a root tag called <hibernate-mapping>. Within this tag the classes are mapped for the SQL database. In more complex applications every class should have it own mapping file. To make things easy we just use one for both classes.
This is the mapping for the student class. The mapping for the courses is similar.

 The mapped Student class
  			
            <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>			
            

In the opening <class> tag we provide the name of the class and the table of the database where the students are stored.
In the <id> tag we need to contribute the primary key of the Class and the related column in the database. In our case the property studentNumber is the property which represents the primary key. This key is stored in the column student_number of the table student.

Now we declare the properties. As long the name of the property equals the name of the database column no further declarations have to be made (Hibernate offers a lot of possibilities for fine tuning here but this is not our subject here).

In the <set> tag we declare a collection which contains the course objects for the courses the student has assigned. The name of the set in the config-file has to be the same as the name of the property in the student class. For the table we declare the table which manages the m:n relationship.

Remember: for a m:n relationship you need a help-table which contains only the primary key pairs of the related classes. The table course_student contains the two colums student_number and course_number. These columns represent the primary keys of the primary keys of the tables student and course.

With the tag <many-to-many> we tell Hibernate the kind of the relationship, the Class at the "other side" of the realtionship and the primary key column of the "other-side" Class.

If we set the property lazy to true the Student Class will be instantiated with an empty course-set. In the cascade tag you can tell Hibernate when to fill this set.

At the end of the config-file we declare a HQL-Query. This Query is used later by the Flex application to fill a Collection with Student objects. We come back to this query further down in the Box: The Flex application.
The mapping for the class course is more or less similar.
13. September 2007

  »  The config-files for the DataManagement Service

Configuration of the RMTP-Channel and the Destinations
Like all configuration files for the Adobe LiveCycle Service you will the DataManagement config files in the folder [CONTEXT-ROOT]/WEB-INF/flex of your web application server in this case the Tomcat. The important files for our application are services-config.xml and data-management-config.xml.

In the services-config.xml we have to declare the RTMP Channel. The file contains this entry mostly by default.

 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 the data-management-config.xml we need to declare the so called destinations for our developed Java classes. In
the <destination> tag we give this destination an ID. This ID is used later by the Flex application to refer to this particular destination.

Within the destination we declare the following properties.
<adapter> We declare the adapter class which communicates with the Java objects. This class is provided by the Flex DataManagement Service. The name of the class is flex.data.adapters.ASObjectAdapter.

Now following a few properties to manage the communication between the Java classes, Hibernate and the DataManagement Service. I just mention the important properties.

<source> The class for the Hibernate Assembler. This is also a class which is provided by the Flex LiveCycle Service. This class ist the Interface to the Hibernate Framework.
<scope> This is the scope for our developed Java classes. As you might know from any other Java web application the possible values are application, session und request. Refer to the documation of you web application server to find out more about the scope.
<identity> The primary property of the declared class
<hibernate-entity> The complete CLASSPATH to the custom class
<fill-method> Name a fill method and a Container class which shell contain your custom objects.
<fill-configuration> Set the <allow-hql-queries>true</allow-hql-queries> to true. This makes it possible to call the HQL-query we defined in the StudentCourse.hbm.xml directly from the Flex application.

 The Definition of the Student destination in the 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>


The course Destination looks similar.
13. September 2007

  »  The Flex application

The Student- and the Course Bean in ActionScript
To communicate successful with the Java objects at the Tomcat we need to implement two ActionScript classes which are the counterpart to the Java classes. These classes have the same properties as the Java classes. We declare the properties public so there is no need to write get- and set methods.

By definition the ActionScript classes must contain a empty constructor. The classes are declared as managed and we set an alias to the corresponding Java class.

 The ActionScript class 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(){} } }

The class course looks similar.
The DataService in the Flex application
In the Flex application a DataGrid is responsible for showing the properties of the students and courses. This DataGrid uses a ArrayCollection as DataProvider which is filled with Student objects. For that reason we have to instantiate a Student Object and ArrayCollection.
In <mx:DataService> tag we set the property "destination" to the name of the destination as we declared it in the data-management-config.xml.

 Part of the main mxml file

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

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


autoCommit="true"
In this example we set the property to true. With that we force that any change made at the ArrayCollection is directly send to Java application at the server.

If you set the editable property of the DataGrid to true every change in the application is committed to the server as soon the editable field looses the focus. There is no need for a commit button. Any other user connected to the server will see the changes imediatly without performing a reload.
This is the big advantage of the Real Time Messaging Protokoll.

Filling the ArrayCollection
We still have to fill the ArrayCollection which is the DataProvider for the DataGrid. For that we call the method fill() on the DataService object. Remember: We declared the fill() method in the data-management-config.xml.

The fill() method needs three arguments.
The first one is the ArrayCollection we want to fill. The second is the name of HQL-Query we declared in the StudentCourse.hbm.xml file. We don't use the third parameter in this example. Have a look at the following Box if you are interested of the meaning of the third parameter.

The third parameter of the fill() method.
You can use the third parameter to set up directly HQL-querys from your Flex application. This makes sense if you don't know the exact query at compile time. If your query depends on user input this approach is your choice. Imagine you want to fill your ArrayCollection only with certain students.
hibernateStudent.fill(studentArray, "flex:hql", ["from Student s where s.studentFirstName = :firstName", parameterMap]);
The parameterMap contains the name of the student you are looking for. The name of the student is provided by the key named "firstName".

or:

hibernateStudent.fill(studentArray, "flex:hql", ["from Student s where s.studentFirstName = ?", parameterArray]);
in that case the parameterArray contains the name of the student. Because the parameters are not named the order of the parameters in the Array is important if you using more then one parameter.

The method hibernateStudent.fill() is called within a method named initialFill(). This method itself is executed on the creationComplete Event of the application. That means if you start the example application the DataGrid shows you already the students and courses.

The DataService also provides methods like deleteItem() and createItem() the typical methods of Data Access Objects. Note that we never declared or implemented these methods. This work is already done by the Flex DataManagement Service.

 The method for deleting students
            
            private function deleteStudent():void {
                 hibernateStudent.deleteItem(dgStudent.selectedItem as Student);
            }


The code for viewing, deleting and creating courses looks similar.
13. September 2007