Flex and Hibernate

For the past month or so I've been working on a new example that shows how to use the Hibernate data assembler in LiveCycle Data Services ES. If you aren't familiar with Hibernate, it is a way to easily persist Java objects - either singularly or in collections and with complex relationships. For example, if you have a data base of employees using several tables, you can make a single Java class that represents the employees and tell Hibernate how to bring it all together. You can load and save these objects using Hibernate and all of the tables will be updated properly.

LiveCycle Data Services ES includes Hibernate. Using the AMF protocol between the Flex client and LC DS you can persist ActionScript objects, too. You can create an Employee ActionScript class and point to a LC DS destination which maps to Hibernate and save and load your ActionScript objects. There's a bit more to it than that, of course, which is why I wanted to make an example.

This example is complex enough that I have broken it into two parts. This is the first part and shows how to use Hibernate with LC DS along with a simple Flex application. The next part focuses a bit more on the Flex side with a more complex application but still using the same example code from this part.

Here are the basic steps:


  1. You need a database. I've used MySQL 5 for the example. You need to create tables and foreign key relationships. The schema which accompanies this article includes that.

  2. You need LiveCycle Data Services ES. Once that's installed you follow a few more steps to turn on Hibernate. There is nothing else to download.

  3. You make some Java beans that represent your objects. There is a Hibernate tool and Eclipse plugin which can do this but I did it all by hand. If this were a larger project I would opt for the tool. Hibernate persists Java objects, not ActionScript objects, which is why you need these Java classes. LC DS will take care of mapping your ActionScript classes to the Java classes.

  4. You make Hibernate configuration files which maps the Java classes to the database tables. The example I've written keeps these pretty minimal, which is good the first time out. In reading a Hibernate book I can see that very complex things can be done using these files.

  5. You make corresponding ActionScript classes. When you request data through the remote data service in LC DS you get back ActionScript objects. There are special ActionScript metadata tags which tell the compiler to expect this.

  6. You make a Flex application.

You also might want to visit this blog to get a more rapid introduction to Hibernate and Flex: Mind the Gap

About the Data

Before going further I should explain the data being used. I work in the Flex support group and so I modeled this example on some of the tools we use to open and track questions from our customers.

The tables include one for Accounts (customer companies), AccountContacts (people who have questions), Consultants (people like me), Cases (the questions asked), and CaseNotes (the progress of the Case). Accounts can also have a Consultant assigned to them and a Consultant can have multiple Accounts assigned. This is a one-to-many relationship. The Java and ActionScript classes reflect this: you'll see Sets in the Java classes and ArrayCollections in the ActionScript classes.

Setup and Installation

DownloadArrow.pngClick arrow to download sample code
The download contains 2 zip files of Flex Builder 2 projects. If you cannot load the projects, unzip them into a clean directory and use the sources and assets directly.

To begin this example, install your database and create the tables from my schema. Create a database called "support" and if you are using MySQL 5 you should get no errors when you run the SQL statements. If you are using a different database you may have to change the SQL. This is one good reason to use Hibernate as it masks the database peculiarities from you.

Now install LC DS if you haven't already. Install it using the embedded JRun instance. This will make debugging and development simple.

Active the Hibernate components in LC DS as follows: (steps from documentation here).

Copy <install root>/resources/hibernate/*.jar to your web application's WEB-INF/lib directory (for example, on windows, this might be C:/lcds/jrun4/servers/default/samples/WEB-INF/lib/

Create a new Flex Builder Java project. Have the bin directory point to the WEB-INF/classes directory. Copy the contents of the classes directory to the WEB-INF/classes directory in LC DS. You'll see that there are both .class and .hbm.xml files. It is best if the Hibernate configuration files shadow the Java class files.

Modify your data-management-config.xml file that is in WEB-INF/flex directory. Here's a tip: in Flex Builder, add a new folder to your Java project, but click the Advanced button to make it a link to an existing folder. Browse to the WEB-INF/flex directory. Now you can edit the configuration files right from Flex Builder.

Start LC DS. You should see a lot of output, but no errors. If you do get errors, double-check your work.

Create a new Flex Builder Flex project. Indicate that you want to use LC DS, but compile locally in Flex Builder. You can compile on the server, too if you like. I prefer to leave my source files off the server.

Import the Flex sources into this new project. Notice how the bin directory points to the LC DS flex context root directory. Your compiled files will go right out to the server so all you need to do is run it.

In fact, all you need to do is run the TestingApp application. This is what you should see:

TestingAppScreenShot_thumb.jpg Click to enlarge

So how does all this work?

If you open the Flex application you'll see a couple of DataService tags. Note the destination values. Then open the data-management-config.xml file on the LC DS server and find the destination with the same name. Notice how this destination is tied to the Hibernate entity description.

When the Flex application requests all of the Account objects, LC DS uses the Hibernate adapter to get Hibernate to fulfill the query. Hibernate queries the database and assembles a collection of Java Account objects. LC DS then converts the Java classes into an AMF binary stream, including the class name meta data.

The AMF stream arrives at the Flash Player and the Flex code examines the metadata and matches it with ActionScript classes with the same metadata and creates the ActionScript objects.

What you get back in your Flex application is an ArrayCollection of ActionScript Account objects. But there is more than that. Notice how the Account class also defines a collection of AccountContacts. Hibernate has gone and fetches them, too.

I hope this is enough detail to get you going. Leave me some comments if there are parts I could explain better and I'll follow with another article. Once this part is well understood, I'll publish the next part which details a Flex application that makes use of this data.

Hibernate Mapping in Detail

Let's take a closer look at the Hibernate mapping files and how they relate to the application as a whole.

First open the data-management-config.xml file and locate the destination for account.hibernate:


<destination id="account.hibernate">
<adapter ref="java-dao" />
<properties>
<use-transactions>true</use-transactions>
<source>flex.data.assemblers.HibernateAssembler</source>
<scope>application</scope>
2. <metadata>
<identity property="id"/>
<one-to-many property="accountContacts" destination="accountContact.hibernate" read-only="true" lazy="true" />
<many-to-one property="consultant"
destination="consultant.hibernate" lazy="true" />
</metadata>

<server>1.
<hibernate-entity>support.Account</hibernate-entity>

<fill-configuration>
<use-query-cache>false</use-query-cache>
<allow-hql-queries>true</allow-hql-queries>
</fill-configuration>
</server>
</properties>
</destination>

#1: Notice in the <server> section the <hibernate-entity>? The value supplied is the name of the Hibernate entity class to use with this destination. Since it is "support.Account" you'll want to look into the support package for the entity configuration file. Open WEB-INF/classes/support/Account.hbm.xml:

<class name="support.Account" table="accounts"> This names the Java class associated with this Hibernate class entity and the database table it maps to.


<id name="id" column="accountid">
<generator class="native"/>
</id>

If you examine the database table description for "accounts" you'll see that its primary key is the account column. The Hibernate entity element, <id>, shows that the id property of the Java class maps to the accountid column of the "accounts" table.

Look back at the data-management-config.xml destination at #2, the <metadata> for the destination description. See how the <identity> element names the same property.

The data-management-config.xml destination <metadata> also names some associations:


<one-to-many property="accountContacts"
destination="accountContact.hibernate"
read-only="true" lazy="true" />
<many-to-one property="consultant"
destination="consultant.hibernate"
lazy="true" />

Go back to the Account.hbm.xml file and you'll see corresponding relationship mappings:


<set name="accountContacts" inverse="true" >
<key column="accountid" />
<one-to-many class="support.AccountContact" />
</set>

<many-to-one name="consultant"
column="consultantid"
class="support.Consultant"
not-null="false" />

Since an Account can have zero or more AccountContacts, the first association declares a one-to-many relationship (one Account to many AccountContacts). In Hibernate, this is represented as a Set and corresponds to the java.util.Set class in the Account java class. The Set's name (accountContacts) is the name of the property in the Java class; the set names the column to key off of and the one-to-many element identifies which Hibernate entity class to use for those elements.

Back in the data-management-config.xml file, the one-to-many association is repeated to let the Data Services Hibernate Assembler know the relationships should be formed.

The relationship between a Consultant and an Account is the reverse: many Accounts to one Consultant. So a many-to-one association is used. When Hibernate sees the many-to-one element it knows that the Java class property, "consultant" will be of the type, support.Consultant and be a single element, not a collection.

Where's the ActionScript?

When dealing with the server-side there is no ActionScript – that's in the Flex client. Hibernate uses Java classes. For example, support.Account.

The Data Services Hibernate Assembler takes the Java class instances returned by Hibernate (eg, support.Account) and creates a byte stream in AMF format. Part of the byte stream (or serialization) of the class instances contains the name of the Java class.

Back in the Flex client, the receipt of the byte stream causes a look-up of an ActionScript class with metadata that maps the Java class name to an ActionScript class. The Flex client code then instantiates an ActionScript class (eg, support.Account) and fills its properties with the corresponding values from the byte stream.

Posted by pent at October 9, 2007 11:21 AM

Comments

Hi Peter,

There seems to be a lot of good info here but I am getting tripped up at the point where I start creating projects. This is my first introduction to LCDS, Hibernate and even Java for the most part so I'm sure I am screwing up something obvious. Here is the error I'm getting in my Flex project:

Unexpected attribute 'url' found in 'endpoint' from file: services-config.xml.

Any help is appreciated.

Posted by: Ben at October 12, 2007 10:38 PM

Hi Ben,

I am also trying to set up a flex proyect with a J2EE and tomcat, there are some thinks that I still can`t configure with the examples of Peter Ent, but about yours I have the same problem. Try to renaming in services-config.xml all ocurrences of the param 'url' of the tag 'endpoint' to 'uri'.

That gives me another error

(Attribute 'messageTypes' must be specified for element 'service'),

but I think is a bit progress.
----------------
Peter: I will take a look at both of these issues; I'm not sure why you are having problems with something so basic.

Posted by: Jacko at October 16, 2007 09:48 PM

Hi Peter,

Thank you for this! It was a lifesaver. I was stuck on actionscript classes and mapping to java classes. The example code helped a lot!

Laurie Hall
Orlando, FL
------------------
Peter: Thanks!

Posted by: Laurie Hall at October 30, 2007 03:28 PM

It is really great! I'm just beginning playing with Flex and I couldn't imagine a better example for startup! Especially that it is exactly what I need - MySQL, Java, Hibernate, LiveCycle, Flex.

Just to let You know - I managed to set it up with Flex Builder 3 beta 3, LiveCycle 2.5.1 on Tomcat 5.5.

Should anyone find it helpful:
Minor issues:
- Unable to resolve resource bundle "data" for locale "en_US".
Solution here: https://bugs.adobe.com/jira/browse/FB-11241 - [projectlocation]/WebContent/web-inf/flex/locale/{locale} should be added to the library path manualy

- I had to add DistortionEffects.swc to flex_libs, from http://weblogs.macromedia.com/auhlmann/

- Error at runtime regarding insert/update/delete:
destination = "{something}.hibernate"
extendedData = (null)
faultCode = "Server.Processing"
faultDetail = (null)
faultString = "Unable to access UserTransaction in DataService."
Solution here: http://help.adobe.com/en_US/livecycle/es/lcds_installation.html#tomcat (I created context.xml file under META_INF and it works fine)

Thank a lot once again :-)

Regards!

Posted by: Micha? at December 19, 2007 07:22 PM

i use jpa instand of hibernate.Please demo me how to use JPa with Flex app.Thank.
---------------
Peter: I don't know what jpa is. If there is an Adapter for it, as there is with Hibernate, then it would work identically.

Posted by: DrNhut at January 16, 2008 08:19 PM

FYI: For people getting the 'url' and 'messageTypes' related errors, the solution is to update your version of the Flex SDK to Flex 2.0.1 Hotfix 2.
-----------
Peter: Thanks for the update!

Posted by: Vijay at January 25, 2008 05:09 PM

Hi Peter, have you used the cascade="all-delete-orphan" option with hibernate?
Do you have a sample of this?

Thanks
Francisco.
---------
Peter: I'm afraid I have not. This really isn't my area of expertise. I just created this for those of us who wanted to know more about it.

Posted by: Francisco Zarate at February 12, 2008 09:26 PM

there is a hot fix from adobe for the bug 'unexpected url found'..
get the fix - hotfix 2 from adobe site
http://kb.adobe.com/selfservice/viewContent.do?externalId=kb402000

Posted by: bibin at February 14, 2008 09:07 AM

Hello,

Can you do the same example with Blaze DS ?

Thanks a lot
FGI
-----------
Peter: On my list but I don't know when I'll get to it.

Posted by: fred at February 28, 2008 05:00 PM

Hello Peter
Thanks for your detailed tutorial,Your OpenSource economized time for me.
Thank you once more.

Posted by: CN-boy at March 12, 2008 12:40 PM

See in my blog how to avoid *.hbm.xml and use hibernate / ejb3 annotations (save your time).

http://tecav.blogspot.com/

Posted by: Claudio Fainschtein at March 25, 2008 01:23 AM

i got this error when i try to add a second item using dataservice and
hibernate.

[RPC Fault faultString="Item with id 'markingHibernate:::0' already
exists. Error on destination 'markingHibernate'"
faultCode="Local.Call.Failed" faultDetail="null"]

thx.

Posted by: lenoidas at May 15, 2008 05:29 AM


<script type="text/javascript" language="javascript"> </script>
<script type="text/javascript"> var webLogName ="Peter Ent"; </script> <script language="JavaScript" type="text/javascript"> var s_channel="WebLogs : " + webLogName; </script> <script language="JavaScript" type="text/javascript"> </script> <script language="JavaScript" src="http://www.macromedia.com/uber/js/omniture_s_code.js" type="text/javascript"></script> <script language="JavaScript" type="text/javascript"> </script>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值