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

    Do a Screen Capture with Adobe AIR

    April 24th, 2008

    I have created a sample AIR application that takes screen shots and saves them to disc. Impossible? Well yes it would be impossible if I were only using AIR. However, thanks to the Merapi Java bridge, we have new functionality exposed to AIR. Yes, it is true that currently there is no shell execute functionality from AIR to start up the Java service. Hopefully, this will change with future versions of AIR.
    Read the rest of this entry »


    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.


    Artemis Test AIR - opening a Text Editor

    May 4th, 2007

    Running on Windows:

    To run this on Window, simply unzip the artemis_w_command.zip file and double click on run.bat.

    Then install and run the ArtemisTextEditor.air file. It will recognize Windows vs Mac and will guess at the location of NotePad on Windows or TextEdit on Mac.

    As long as it says that the connection to Artemis has been established the Launch Button will be active and it will launch NotePad or TextEdit.

    Running on Mac:

    Although, I have run this successfully on my Mac by running the Java project within eclipse following the directions here. Unfortunately due to my limitations with shell scripts, this download contains only a windows bat file. Just make sure you also add this jar when in Step 8 of the directions.

    If you can create a .sh file, please send it to me and I will update this post to make the launching of the app much easier for Mac users.

    After you have the java files running within eclipse, install and run the ArtemisTextEditor.air file.

    Thanks to Gonzalo Huerta for creating the CommandHolder classes and the guys at EffectiveUI for the Artemis project.

    Rich


    Artemis First Tutorial

    April 30th, 2007

    This tutorial covers a very simple Artemis library to reverse strings. The tutorial is designed to illustrate the basics of passing information between Apollo and Artemis.

    Try it out here

    My experiences with this tutorial are very good.  After setting up Java 1.6 jre, I had no problem getting the Java backend to run  in eclipse and once it was running the Apollo frontend worked perfectly.
    Please post your comments as well.


    Artemis Alpha Released

    April 17th, 2007

    artemis.jpg

    Artemis is a community focused project aimed at bringing external libraries to the Flex / Flash environment. The goal of Artemis is to provide features in the Flex / Flash desktop application domain that are not currently available. The Artemis framework allows a developer to create their own custom libraries (currently written in java with plans to support other languages) that integrate with a Flex / Flash Apollo application.

     

    For Flex Developers:
    Artemis provides a way for developers to collaborate on building extension to the Apollo framework. Nearly any java API can be encapsulated in an Artemis Library and exposed to an Apollo application through the Artemis framework.

    For Java Developers:
    Throw away your Swing UIs. Artemis brings the UI capabilities of Flex to java developers. Look for samples coming to our web site that will compare ease of use and functionality between a Flex UI and a Swing UI. No more Grid Bags!

    I am currently testing Artemis and will post my experiences as soon as possible. Please post any comments on your experiences with Artemis here as well.

    UPDATE: I was able to run the screen shot application successfully on both Windows XP and Mac OSX 10.4.9. For Mac, you will need to get the Java 6 download from Apple’s ADC site which is free to join.