Flextrine Tutorial – CRUD in a simple Flex 4 address book: Loading the entities

Introduction
Setting up the server
Creating the entities
Creating the database schema
Loading the entities
Creating new entities
Deleting entities
Updating entities
Conclusion

In FlashDevelop or Flash Builder create a new Flex 4 project and add the Flextrine client side library (in flextrine/src of the Flextrine download) to the classpath of your project.  Alternatively you can use the compiled flextrine/bin/flextrine.swc.  Now return to the Flextrine manager and click on GENERATE AS3 CLASSES.  You will be prompted to download a zip file – extract its contents into the src directory of your project.  You should now have AS3 versions of vo.ContactGroup and vo.Contact for use in your Flex application.

For reference, here are a few screenshot of what we will be working towards.  The tree on the left will show the groups and contacts, and the area on the right will have the group editor at the top and the contact editor below.  We will also have some buttons to create, delete and save contacts and groups.

Flextrine Contacts 1Flextrine Contacts 2

Create the Main.mxml entry class

We will begin by creating the Main.mxml entry class for our application.  To start with we will just create the basic MXML Application with a creationComplete event listener that configures Flextrine’s central class – the EntityManager.  For our simple application the only configuration that is required is to set the URL of gateway.php in the Flextrine server side component – in this case http://localhost/contacts/gateway.php.

   1: <?xml version="1.0" encoding="utf-8"?>

   2: <s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"

   3:                xmlns:s="library://ns.adobe.com/flex/spark"

   4:                xmlns:mx="library://ns.adobe.com/flex/mx"

   5:                xmlns:local="*"

   6:                creationComplete="creationComplete()">

   7:

   8:     <fx:Script>

   9:         <![CDATA[

  10:         import org.davekeen.flextrine.orm.Configuration;

  11:         import org.davekeen.flextrine.orm.EntityManager;

  12:

  13:         private var em:EntityManager;

  14:

  15:         /**

  16:          * Initialize the Flextrine EntityManager, set the dataprovider of the tree and load the ContactGroups.

  17:          */

  18:         private function creationComplete():void {

  19:             // Setup the entity manager

  20:             var configuration:Configuration = new Configuration();

  21:             configuration.gateway = "http://localhost/contacts/gateway.php";

  22:

  23:             em = EntityManager.getInstance();

  24:             em.setConfiguration(configuration);

  25:         }

  26:

  27:         ]]>

  28:     </fx:Script>

  29:

  30: </s:Application>

Now we’ll add the GUI.  We’ll add a Flex Tree on the left with id tree, along with the buttons and the layout.

   1: <?xml version="1.0" encoding="utf-8"?>

   2: <s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"

   3:                xmlns:s="library://ns.adobe.com/flex/spark"

   4:                xmlns:mx="library://ns.adobe.com/flex/mx"

   5:                xmlns:local="*"

   6:                creationComplete="creationComplete()">

   7:

   8:     <fx:Script>

   9:         <![CDATA[

  10:         import org.davekeen.flextrine.orm.Configuration;

  11:         import org.davekeen.flextrine.orm.EntityManager;

  12:

  13:         private var em:EntityManager;

  14:

  15:         /**

  16:          * Initialize the Flextrine EntityManager, set the dataprovider of the tree and load the ContactGroups.

  17:          */

  18:         private function creationComplete():void {

  19:             // Setup the entity manager

  20:             var configuration:Configuration = new Configuration();

  21:             configuration.gateway = "http://localhost/contacts/gateway.php";

  22:

  23:             em = EntityManager.getInstance();

  24:             em.setConfiguration(configuration);

  25:         }

  26:

  27:         ]]>

  28:     </fx:Script>

  29:

  30:     <s:HGroup width="100%" height="100%">

  31:         <!-- The groups and contacts tree -->

  32:         <s:VGroup height="100%">

  33:             <mx:Tree id="tree" width="100%" height="100%" />

  34:         </s:VGroup>

  35:

  36:         <s:VGroup width="100%" height="100%">

  37:             <!-- The editors will go here -->

  38:

  39:             <mx:Spacer height="100%" />

  40:

  41:             <mx:HRule width="100%" />

  42:

  43:             <!-- The buttons -->

  44:             <mx:ControlBar width="100%" horizontalAlign="center">

  45:                 <s:Button label="New group" />

  46:                 <s:Button label="New contact" />

  47:                 <s:Button label="Delete" />

  48:                 <s:Button label="Save" />

  49:             </mx:ControlBar>

  50:         </s:VGroup>

  51:     </s:HGroup>

  52:

  53:

  54: </s:Application>

Loading the contacts into the tree

Now its time to load some data into the tree.  Obviously at this point there isn’t any data to load so for the moment we’ll manually add some into the database so we have something to see.  Execute the following SQL against the contacts database to create some test data.  This creates two groups and three contacts, just like in the screenshots at the top of this section.

   1: INSERT INTO `contact` (`id`,`name`,`telephoneNumber`,`birthday`,`contactGroup_id`) VALUES

   2:  (1,'Arthur','01332 823636','1976-01-12',2),

   3:  (2,'Mum','07884 763623','1976-01-13',1),

   4:  (3,'Peter','0131 827 3625','1977-12-06',2);

   5:

   6: INSERT INTO `contactgroup` (`id`,`name`) VALUES

   7:  (1,'Family'),

   8:  (2,'Friends');

At this point we should talk about the concept of Flextrine’s entity repositories.  Every entity in your application has its own EntityRepository, so for our application we have one EntityRepository for ContactGroup and one for Contact.  Entity repositories perform a number of functions:

  • First and foremost entity repositories provide local storage for your entities.  Each EntityRepository has an attribute called entities which is an ArrayCollection containing the entities currently in existence in your application.
  • Secondly entity repositories make sure that there is only ever one instance of a particular entity in existence at any one time.
  • Finally entity repositories watch their entities for changes and mark them for updating when they change.

Add the following lines to the end of creationComplete() remembering to add import vo.ContactGroup to the top of the script tag.

   1: tree.dataProvider = em.getRepository(ContactGroup).entities;

   2: em.getRepository(ContactGroup).loadAll();

The first line sets the entities of the ContactGroup EntityRepository as the dataProvider of the tree.  Obviously at this point there are no entities in the ContactGroup repository, but Flextrine is very careful to respect Flex databinding throughout its lifecycle so in fact it doesn’t matter that entities is currently empty.  Any Flex component bound to the entities will automatically update themselves when the repository changes with no extra work required.

The second line calls the loadAll() method on the ContactGroup repository.  As you would expect this loads all the ContactGroups into the ContactsGroup repository and Flex databinding will take care of updating the tree once the load is complete.  By default Flextrine runs in EAGER mode, which means that when loading entities it will follow all associations and load any linked objects, so in fact loading the ContactGroups will also load all the Contacts.  Flextrine also supports LAZY loading which won’t automatically follow associations and requires you to to explicitly request unitialized entities; see Loading Associations for more details.

If you now run the application it will look like this.

Flextrine Contacts 3

We can see that the two ContactGroups are loading from the database and that Flex databinding has updated the tree automatically to reflect the loaded entities.  Unfortunately the tree doesn’t realise that it should be showing contacts as children of the contact groups, so we need to explicitly tell it so by adding a children attribute to ContactGroup.  Flextrine allows you to add logic to your entities by seperating Flextrine specific code into an ‘EntityBase’ class, and then creating an empty main entity class which you can ammend.  The idea behind this is that if you later update your entities you can replace the EntityBase without losing any functionality you added to the main entity class.

Open up vo/ContactGroup.as and add a getter function that simply returns the contacts:

   1: package vo {

   2:     import mx.collections.ArrayCollection;

   3:

   4:     [RemoteClass(alias="vo/ContactGroup")]

   5:     [Entity]

   6:     public class ContactGroup extends ContactGroupEntityBase {

   7:

   8:         public function get children():ArrayCollection {

   9:             return contacts;

  10:         }

  11:

  12:     }

  13:

  14: }

We also want the labels in the tree to show the name property of both ContactGroup and Contact so add labelField=”name” to the Tree component in Main.mxml:

   1: <mx:Tree id="tree" width="100%" height="100%" labelField="name" />

Now running the application should show the following!

contacts4

Lets see how we can create new entities.

PureMVC Tutorial – Flex, PureMVC, Jabber and XIFF 3: Part 1 – Frameworks

Introduction
Part 1 – Frameworks
Part 2 – Directory structure
Part 3 – Application and ApplicationFacade
Part 4 – Notifications, Commands & Use Cases
Part 5 – Model & Proxy
Part 6 – The Application View & Mediator
Part 7 – The Login View & Mediator
Part 8 – The Roster View & Mediator
Part 9 – The Chat View & Mediator
Conclusion, Demo & Downloads

Now that we’ve got a basic FlashDevelop project setup we can install the frameworks we’ll be using.

PureMVC

Download the PureMVC framework from here. Put this into a directory somewhere on your machine and add this to the FlashDevelop project classpath like so:

  1. Right click on ‘XIFFer’ and select Properties…
  2. Go to the Classpaths tab
  3. Click Add Classpath… and in the directory selector choose the PureMVC src folder.

XIFF

XIFF is an excellent Actionscript XMPP (Jabber) framework that we’ll be using to take care of the internals of Jabber communication. Its been around since Actionscript 2 but has recently been ported to Actionscript 3 (albeit in beta form). Download it here, put it into a directory and add the classpath as above.

As XIFF is currently in beta you’ll need to make a small change in order to get it to play nice with ejabberd – a common Jabber server written in Erlang. Research tells me that this is actually a problem with ejabberd’s implementation rather than XIFF’s, but whatever the issue might be this will fix it 🙂

  1. Open org.jivesoftware.xiff.core.XMPPSocketConnection
  2. Goto line 108
  3. Remove the version=”1.0″ / so that the line now reads:

openingStreamTag = “<?xml version=”1.0″?><stream:stream to=”” + server + “” xmlns=”jabber:client” xmlns:stream=”http://etherx.jabber.org/streams”>”;

Now we’re all sorted with the bits we require and its time to set up our directories and packages.