• Home
  • About Me
  • AIR Central
  • AS3 Libs
  • Books
  • Flex Central
  • Resources
  • The Guru's
  •  

    Ahh Finally, It’s out of the bag

    May 31st, 2007

    Mike Chambers made it officially public knowledge today that Apollo will ship with an API to access an embedded copy of SQLite. Here is his post. This has been a very difficult secret to keep. :-)


    Amazon S3 ActionScript Classes

    May 30th, 2007

    If you have seen this video showing the Apollo, you saw an Apollo app that communicated with Amazon’s S3 data storage service. Well, Christian Cantrell has now posted the ActionScript classes that he wrote for this communication. I have also added this to the AS3 Libs section of this blog.


    Artemis/Hibernate Apollo Application

    May 30th, 2007

    Well it has been a while that I have been promising to document this sample app. Here is the basis. ArtemisEmployee is an application that uses a Hibernate back end with an embedded hsqldb database to store the employee data. The UI is built with Apollo and the data streams between the Java back end and the Apollo UI via the Artemis Bridge.

    Here is the code involved in the Java back end. It is a very simple application consisting of a single bean class and a delegate for point of connection. The delegate has 2 methods for getting and Employee object and updating an Employee object.

    Here is the Employee.hbm.xml file:

    <?xml version="1.0"?>
    <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
    <!-- Generated May 9, 2007 7:38:47 AM by Hibernate Tools 3.2.0.beta8 -->
    <hibernate-mapping package="com.everythingflex.artemisEmployee.vo" default-lazy="false">
        <class name="Employee" table="Employee">
            <id name="employeeId" type="int">
                <column name="EMPLOYEE_ID" />
                <generator class="assigned" />
            </id>
            <property name="firstName" type="string">
                <column name="FIRST_NAME" length="50" not-null="true" />
            </property>
            <property name="lastName" type="string">
                <column name="LAST_NAME" length="50" not-null="true" />
            </property>
            <property name="email" type="string">
                <column name="EMAIL" length="50" not-null="true" />
            </property>
            <property name="jobTitle" type="string">
                <column name="JOB_TITLE" length="50" not-null="true" />
            </property>       
        </class>
    </hibernate-mapping>

    Here is the corresponding Employee.java bean:

    package com.everythingflex.artemisEmployee.vo;

    public class Employee {

        private int employeeId;
        private String firstName;
        private String lastName;
        private String email;
        private String jobTitle;
        /**
         *
         */

        public Employee() {
            super();
            // TODO Auto-generated constructor stub
        }
        /**
         * @param employeeId
         * @param firstName
         * @param lastName
         * @param email
         * @param jobTitle
         */

        public Employee(int employeeId, String firstName, String lastName, String email, String jobTitle) {
            super();
            this.employeeId = employeeId;
            this.firstName = firstName;
            this.lastName = lastName;
            this.email = email;
            this.jobTitle = jobTitle;
        }
        /**
         * @return the email
         */

        public String getEmail() {
            return email;
        }
        /**
         * @param email the email to set
         */

        public void setEmail(String email) {
            this.email = email;
        }
        /**
         * @return the employeeId
         */

        public int getEmployeeId() {
            return employeeId;
        }
        /**
         * @param employeeId the employeeId to set
         */

        public void setEmployeeId(int employeeId) {
            this.employeeId = employeeId;
        }
        /**
         * @return the firstName
         */

        public String getFirstName() {
            return firstName;
        }
        /**
         * @param firstName the firstName to set
         */

        public void setFirstName(String firstName) {
            this.firstName = firstName;
        }
        /**
         * @return the lastName
         */

        public String getLastName() {
            return lastName;
        }
        /**
         * @param lastName the lastName to set
         */

        public void setLastName(String lastName) {
            this.lastName = lastName;
        }
        /**
         * @return the jobTitle
         */

        public String getJobTitle() {
            return jobTitle;
        }
        /**
         * @param position the jobTitle to set
         */

        public void setJobTitle(String jobTitle) {
            this.jobTitle = jobTitle;
        }
       
       
    }

    The Delegate is the point of access between Apollo and Java. Here is the Delegate class:

    package com.everythingflex.artemisEmployee.business;

    import org.hibernate.Session;
    import org.hibernate.SessionFactory;
    import org.hibernate.Transaction;
    import org.hibernate.cfg.Configuration;

    import com.effectiveui.artemis.ArtemisBridge;
    import com.effectiveui.artemis.event.ArtemisResultEvent;
    import com.everythingflex.artemisEmployee.vo.Employee;


    public class Delegate {
       
        private SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();

        public ArtemisResultEvent getEmployee(Integer id){
            ArtemisResultEvent result = new ArtemisResultEvent();
            Session session = null;
            try{;
                session = sessionFactory.openSession();
                Employee e = (Employee) session.load(Employee.class,id);
                result.setResult(e);
            } catch (Exception E) {
                System.out.print(E);
            } finally {
                session.flush();
                session.close();
            }
            return result;
        }
       
        public ArtemisResultEvent updateEmployee(Employee employee){
            ArtemisResultEvent result = new ArtemisResultEvent();
            Session session = null;
            Transaction tx = null;
            Boolean results = true;
            try{
                session = sessionFactory.openSession();
                tx = session.beginTransaction();
                session.update(employee);
                tx.commit();
            } catch (Exception E) {
                results = false;
                System.out.print(E);
            } finally {
                tx = null;
                session.flush();
                session.close();
            }
            result.setResult(results);
            return result;
        }
       
        /**
         * @param args
         */

        public static void main(String[] args) {
            // TODO Auto-generated method stub
            ArtemisBridge.getInstance().bootstrap();
            //Delegate d = new Delegate();
            //d.getEmployee(1);
        }

    }

    OK, now for the Apollo side of the application:

    Here is the Employee ActionScript class that maps to the Java Employee class:

    package com.everythingflex.artemisEmployee.vo
    {
        [RemoteClass(alias="com.everythingflex.artemisEmployee.vo.Employee")]
        [Bindable]
        public class Employee
        {
           
            public var employeeId:int;
            public var firstName:String;
            public var lastName:String;
            public var email:String;
            public var jobTitle:String
        }
    }

    This is the bridge class that is making the connection between Apollo and Java and handling the results.

    package com.everythingflex.artemisEmployee.bridge
    {
        import com.effectiveui.artemis.mirror.ArtemisObject;
        import com.effectiveui.artemis.mirror.call.ArtemisObjectCall;
        import flash.utils.getQualifiedClassName;
        import mx.rpc.events.ResultEvent;
        import flash.events.EventDispatcher;
        import com.everythingflex.artemisEmployee.vo.Employee;
       
        public class EmployeeArtemisObject extends ArtemisObject
        {
           
            public static const LIB_ID:String = "com.everythingflex.artemisEmployee.business.Delegate";
           
            public function EmployeeArtemisObject(){
                super();
            }
                   
            public function getEmployee(employeeId:int):void{
                var artemisCall:ArtemisObjectCall = new ArtemisObjectCall(LIB_ID, "getEmployee", employeeId);
                artemisCall.addEventListener(ResultEvent.RESULT, getEmployeeResult);
                send(artemisCall);
            }
           
            public function getEmployeeResult(e:ResultEvent):void{
                EventDispatcher(e.target).removeEventListener(e.type, getEmployeeResult);
                var rEvent:ResultEvent = new ResultEvent("employeeResult", false, true, e.result);
                dispatchEvent(rEvent);
            }
           
            public function updateEmployee(employee:Employee):void{
                var artemisCall:ArtemisObjectCall = new ArtemisObjectCall(LIB_ID, "updateEmployee", employee);
                artemisCall.addEventListener(ResultEvent.RESULT, updateEmployeeResult);
                send(artemisCall);
            }
           
            public function updateEmployeeResult(e:ResultEvent):void{
                EventDispatcher(e.target).removeEventListener(e.type, updateEmployeeResult);
                var rEvent:ResultEvent = new ResultEvent("updateEmployeeResult", false, true, e.result);
                dispatchEvent(rEvent);
            }
           
        }
    }

    Finally the main Apollo application file which makes the connection to the bridge and the calls to get the Employee objects from the hsqldb and also update the Employee as well.

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

    <mx:ApolloApplication xmlns:mx="http://www.adobe.com/2006/mxml" xmlns:custom="custom.*"
        creationComplete="initArtemisBridge()"
        backgroundImage="@Embed('bg.png')"
        backgroundColor="#FFFFFF" height="420" width="340" layout="absolute">


        <mx:Script>
            <![CDATA[
                import mx.collections.ArrayCollection;
                import com.effectiveui.artemis.mirror.call.ArtemisObjectCall;
                import mx.rpc.events.ResultEvent;
                import com.effectiveui.artemis.event.ArtemisServiceEvent;
                import com.effectiveui.artemis.ArtemisBridge;
                import com.everythingflex.artemisEmployee.vo.Employee;
                import com.everythingflex.artemisEmployee.bridge.EmployeeArtemisObject;
               
                private var bridge:ArtemisBridge = ArtemisBridge.getInstance();
                private var employeeArtemisObject:EmployeeArtemisObject;
                [Bindable]
                private var isBridgeStarted:Boolean = false;
                [Bindable]
                private var updateEnabled:Boolean = false;
               
                [Bindable]
                private var employee:Employee;
               
                private function initArtemisBridge():void{
                    ti.text = "Bridge Not Running \n";
                    bridge.startServer();
                    bridge.addEventListener(ArtemisServiceEvent.ARTEMIS_STARTED, bridgeStarted);
                    employeeArtemisObject = new EmployeeArtemisObject();
                    employeeArtemisObject.addEventListener("employeeResult", employeeResult);
                    employeeArtemisObject.addEventListener("updateEmployeeResult", updateEmployeeResult);
                }
                private function bridgeStarted(e:ArtemisServiceEvent):void{
                    ti.text += "Bridge Started \n";
                    isBridgeStarted = true;
                }
               
                private function getEmployee():void{
                    ti.text += "getEmployee(" + employeeId.value + ") \n";
                    ti.verticalScrollPosition += 50;
                    employeeArtemisObject.getEmployee(employeeId.value);
                }
               
                private function employeeResult(_employee:ResultEvent):void{
                    employee = Employee(_employee.result);
                    if(employee.employeeId > 0){
                        updateEnabled = true;
                    }
                }
               
                private function updateEmployee(employee:Employee):void{
                    ti.text += "updateEmployee(" + employee + ") \n";
                    ti.verticalScrollPosition += 75;
                    employee.firstName = firstName.text;
                    employee.lastName = lastName.text;
                    employee.email = email.text;
                    employee.jobTitle = jobTitle.text;
                    employeeArtemisObject.updateEmployee(employee);
                }
               
                private function updateEmployeeResult(status:ResultEvent):void{
                    if(status.result){
                        ti.text += "update successful \n";
                    } else {
                        ti.text += "update failed \n";
                    }
                }
               
               
            ]]>
        </mx:Script>
        <mx:Style>
            TextArea {
                backgroundAlpha: .2;
                color: #FFFFFF;
            }
            TextInput {
                backgroundAlpha: .2;
                color: #FFFFFF;
            }
            Label {
                color: #FFFFFF;
            }
        </mx:Style>
        <mx:TextArea id="ti" width="300" height="189" x="19" y="33"/>
        <mx:NumericStepper minimum="1" maximum="9" id="employeeId" stepSize="1" x="151.5" y="230" enabled="{isBridgeStarted}" width="45"/>
        <mx:Button click="getEmployee()" label="Load Employee" x="207" y="230" enabled="{isBridgeStarted}"/>
        <mx:Label x="19" y="232" text="Search by EmpoyeeId:"/>
        <mx:Label x="19" y="260" text="First Name:"/>
        <mx:Label x="19" y="286" text="Last Name:"/>
        <mx:Label x="19" y="312" text="Email:"/>
        <mx:Label x="19" y="340" text="Job Title:"/>
        <mx:TextInput x="89" y="284" id="lastName" text="{employee.lastName}" width="230"/>
        <mx:TextInput x="89" y="258" id="firstName" text="{employee.firstName}" width="230"/>
        <mx:TextInput x="89" y="310" id="email" text="{employee.email}" width="230"/>
        <mx:TextInput x="89" y="338" id="jobTitle" text="{employee.jobTitle}" width="230"/>
        <mx:Label x="19" y="15" text="Status Log"/>
        <mx:Button x="257" y="378" label="Update" width="62" click="updateEmployee(employee)" enabled="{updateEnabled}"/>
    </mx:ApolloApplication>

    So, here is what actually is taking place in this example.

    First, (after manually starting the Java ArtemisBridge) the Apollo application makes its connection to the listening port on the Java class.

    Making the connection

    Then the user loads an Employee object by id using the Hibernate load method. The Java Employee object is retrieved from the hsqldb and passed into the Apollo application.

    Employee is loaded

    The user then may edit the Employee data and send it back to Java where it is updated using the Hibernate update method.

    Employee Updated

    The ArtemisBridge will obviously need to started automatically by the Apollo application and this will be possible in future versions of the Apollo runtime.


    Flex Maniacs - Sold Out

    May 23rd, 2007

    Flex Maniacs has officially sold out!  I am looking forward to seeing all of you who registered in Washington D.C next month.  Look for me there and you may get a free copy of my new book. Professional Flex 2 from Wrox publishers


    Professional Flex 2 Book Update

    May 18th, 2007

    I have my copies IN HAND of Professional Flex 2 and the outlets like Barnes and Noble, Amazon, BookPool, etc. will be shipping very very soon. :-) The Look Inside functionality is also working now at Amazon.
    Also, the code site is up and all source code is available for download here.