Flex in Application Logging

For an LCDS application that we are building, I wanted to be able to display log messages to the screen, such as “Sending request to server” and “Received server response: OK.” Although this has little to do with actual functionality, I wanted to document my efforts to create this component.

To utilize the Flex logging framework, we need to provide a Logger and a Log Target. The Logger, of course, does the logging itself based on two factors: (1) its category and (2) the logging level. This is similar to the operation of the popular Java logging framework Log4J. The Log Target defines where the messages are written. Flex comes with the TraceTarget predefined – this is the target for all trace() statements. For this example, I will also provide an MXML component that can be used to display log messages on screen.

First, the Logger class:

    public class Logger
    {
        //~ Instance Attributes -----------------------------------------------
        private var logger : ILogger;

        //~ Constructor -------------------------------------------------------
        /**
         * SingletonEnforcer parameter ensures that only the getInstance
         * method can create an instance of this class.
         */
        public function Logger(category : String, enforcer : SingletonEnforcer) : void
        {
            this.logger = Log.getLogger(category);
        }

        //~ Methods -----------------------------------------------------------
        public static function getInstance(category : String) : Logger
        {
            return new Logger(category, new SingletonEnforcer());
        }

        public static function addTarget(target : ILoggingTarget) : void
        {
            Log.addTarget(target);
        }

        public static function removeTarget(target : ILoggingTarget) : void
        {
            Log.removeTarget(target);
        }

        public function debug(message : String) : void
        {
            this.logger.debug(message);
        }

        // other logging methods by level (e.g. warn, error)

    }

With our Logger class in place, we can now define a LogTarget class that defines a TextArea to which the log messages will be written:

    // be sure to use the mx_internal namespace (and import it)
    import mx.core.mx_internal;
    use namespace mx_internal;

    public class LogPanelTarget extends LineFormattedTarget
    {
        private var console : TextArea;

        public function LogPanelTarget(console : TextArea)
        {
            super();
            this.console = console;
        }

        override mx_internal function internalLog(message : String) : void
        {
            this.console.text += message + "\n";
            }
        }
    }

Finally, our LogPanel MXML component brings everything together by (1) instantiating a new Logger and (2) providing a TextArea for log messages:

<mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml"
        width="300" height="300" initialize="init()">
    <mx:Script>
        <![CDATA[
            import mx.logging.Log;
            import mx.logging.LogEventLevel;
            import mx.collections.ArrayCollection;

            public  var open   : Boolean = true;
            private var target : LogPanelTarget;
            [Bindable] private var targets : ArrayCollection;

            private function init() : void
            {
                this.target = new LogPanelTarget(output);
                // here we define which categories are written to our target
                this.target.filters = ["iamjosh.samples.*"];
                // and here which log levels are written
                this.target.level   = LogEventLevel.ALL;
                this.target.includeCategory = true;
                this.target.includeTime = true;
                Logger.addTarget(this.target);
            }

            private function setVerticalPosition() : void
            {
                this.output.verticalScrollPosition =
                        this.output.maxVerticalScrollPosition + 1;
            }
        ]]>
    </mx:Script>

    <mx:TextArea  id="output" x="0" y="0" width="100%" height="100%"
            editable="false" updateComplete="this.setVerticalPosition()"
            verticalScrollPolicy="on"/>
</mx:Canvas>

We can now include the LogPanel component anywhere we wish and log messages from anywhere in our code within the category “iamjosh.samples.*” will be written to it. For example:

    public class Foo
    {
        // notice that we provide a category here, this determines if the log
        // message will be written to a give LogTarget
        private var logger : Logger = Logger.getInstance("iamjosh.samples.Foo");

        public function logSomething() : void
        {
            this.logger.debug("I log because I can");
        }
    }

That’s it. Although I would prefer to define where my log messages go external to the code, Flex’s logging framework is fairly straightforward and easy to work with.

References

Advertisements

Flex Custom Preloader

I was getting a little tired of the aqua loading screen that appears by default in all of my Flex applications, so I took a stab at building a custom preloader. A Flex application is really a two frame Flash movie, with the first frame containing all of the initialization and the second the application itself. The preloader is part of the initialization frame and we can use it to create a custom loading screen for our application. I found a few articles on the topic, with the most promising being this one from Ted on Flex.

I wanted my custom preloader to contain two elements: (1) a graphical logo and (2) a progress bar. Ted’s article provides information on loading the graphic (a PNG) by utilizing a subclass of flash.display.Loader. Because our preloader will perform its actions during the initialization frame, those handy graphical Flex classes (e.g. Image, ProgressBar) will not be available to us. Instead, we will need to create these items on our own.

If you would like to follow along, I have posted my complete source code. Please note that I embedded an MP3 in the application purely to increase its download size. I would recommend that you include a 2-3MB MP3 in your application, otherwise, the progress will not be noticeable.

To get started, we will extend the mx.preloaders.DownloadProgressBar class as suggested by Ted. As explained in the Flex documentation, the DownloadProgressBar can be extended to provide user feedback on the download and initialization phases of our Flex application. Also of note is that we need to implement it as an ActionScript class and not in MXML as the latter loads to slowly at runtime.

The CustomPreloader class is very much like Ted’s sample code, the exception being that as the SWF is loaded, we calculate the percent complete and update the progress value in our custom loading screen (LoadScreen):

    private function SWFDownloadProgress(event : ProgressEvent) : void
    {
        var prog : Number = event.bytesLoaded / event.bytesTotal * 100;
        if (this.loader)
            this.loader.progress = prog;
     }

On initialization of the CustomPreloader, we also utilize a Timer to ensure the stage is available before we try to add and position the load screen:

    override public function initialize() : void
    {
        super.initialize();

        this.loader = new LoadScreen();
        this.addChild(this.loader);

        this._timer = new Timer(1);
        this._timer.addEventListener(TimerEvent.TIMER, handleTimerTick);
        this._timer.start();
    }

From here, we extend flash.display.Loader to provide the utility for loading our logo image and drawing the progress bar. We do this by drawing both the logo and the progress bar on screen by creating a BitMap and then using the PNGEncoder to write the image to the screen as a PNG image. We are actually creating an animation on the fly here:

    public function refresh() : void
    {
        this._logoData = this.draw();
        var encoder : PNGEncoder = new PNGEncoder();
        var bytes   : ByteArray  = encoder.encode(this._logoData);
        this.loadBytes(bytes);
    }

    private function draw() : BitmapData
    {
        // create bitmap data to create the data
        var data : BitmapData = new BitmapData(this.width, this.height, true, 0);

        // draw the progress bar
        var s : Sprite = new Sprite();
        var g : Graphics = s.graphics;

        // draw the bar background
        g.beginFill(_BarBackground);
        g.lineStyle(2, _BarOuterBorder, 1, true);
        var barX : int = (this.width - _BarWidth) / 2;
        var barY : int = _TopMargin + _LogoHeight + _Padding;
        g.drawRoundRect(barX, barY, _BarWidth, _BarHeight, 2);
        var containerWidth : Number = _BarWidth - 4;
        var progWidth : Number = containerWidth * this.progress / 100;
        g.beginFill(_BarColor);
        g.lineStyle(1, _BarInnerColor, 1, true);
        g.drawRect(barX + 1, barY + 1, progWidth, _BarHeight - 3);
        data.draw(s);

        // draw the logo
        data.draw(this._logo.bitmapData, null, null, null, null, true);
        return data;
    }

To bring everything together, we are utilizing a Timer instance in our CustomPreloader class to update and redraw the progress bar on each timer tick. This calls the refresh() method in LoadScreen, which then redraws the an updated progress image. Now, we just need to add the following to our as an attirbute of the Application tag in our application MXML file to utilize the our custom preloader:

  preloader="iamjosh.samples.preloader.CustomPreloader"

Finally, let’s change the background color of the application to match our logo a little better. Just add the following Flex compiler argument:

  -default-background-color #FFFFFF

References

Update: I just found an article that accomplishes a similar task to my own buried in the comments of one of Ted’s articles. I was a little happier with how he handled the graphics of drawing the progress bar, so I have updated my code and added the article as a reference.


Adobe Open Sourcing LiveCycle Data Services as BlazeDS

One of the downsides for LCDS development for me has been the lack of folks out there who have worked with the technology and that it is only available for Java backends (unless you use third party technology). Now, Adobe has announced that it will be open sourcing LCDS under the name “BlazeDS,” with a beta version available now on the Adobe Labs site. This is very exciting news as it will open the messaging and remoting framework that we use for Java to other platforms and will probably increase the pool of developers using it.

Adobe is also publishing the Action Message Format (AMF) protocol specification. According to Adobe, delivery of messages via AMF is up to ten times faster than with XML as it is already in a machine readable format (binary) and does not need to be translated, as is the case with XML.

Of note, however, is that the data management services component (which is what I have primarily been using) will still only be available as part of LCDS, which will also include new technologies around offline data synchronization in the future.

This is extremely exciting news for those of us working with LCDS…I mean BlazeDS.

References


Serialization of Custom Collections for Flex Data Services

In my current project, we have a custom collection on the Java side that is supposed to be sent via LCDS to the Flex client. When we began testing, however, we found that the collection was not being passed, only the properties of “standard” Java types were (e.g. String, int). It seems that if LCDS does not know how to handle an object, it simply ignores it and does not include it in the serialization process. This was the case here, LCDS did not understand how to serialize our custom collection and simply did not include it in the transfer.

For example, in the model code below, when an instance of MyListKeeper is serialized and sent to the Flex client, only the name property is included, not myList.

     public class CustomList
         extends ArrayList<Foo>
         implements List<Foo>, Serializable
     {
         // constructors
         // extension methods, e.g.
         public Bar getFirstBar() { ... }
     }

     public class MyListKeeper
         implements Serializable
     {
         private CustomList myList;
         private String name;

         // getters & setters
     }

We were able to solve this by writing custom serialization methods (via the java.io.Externalizable interface) for both the collection and the class that contains a reference to it. In the code below, notice that our classes now implement Externalizable (a subclass of Serializable).

     public class CustomList
         extends ArrayList<Foo>
         implements List<Foo>, Externalizable
     {
         // as in the previous example ...

         public void writeExternal(ObjectOutput out)
             throws IOException
         {
             // externalizes the list - LCDS knows how to handle an ArrayList
             out.writeObject(new ArrayList(this));
         }

         public void readExternal(ObjectInput in)
             throws IOException, ClassNotFoundException
         {
             // start by clearing the current collection
             this.clear();
             // now read in the new list and store it
             this.addAll((List)in.readObject());
         }
     }

     public class MyListKeeper
         implements Externalizable
     {
         // as in the previous example ...

         public void writeExternal(ObjectOutput out)
             throws IOException
         {
             out.writeUTF(this.name);
             out.writeObject(this.myList);
         }

         public void readExternal(ObjectInput in)
             throws IOException, ClassNotFoundException
         {
             this.name  = in.readUTF();
             // the following may not be 100% correct, feel free to correct me
             this.myList = (CustomList)this.readObject();
         }
     }

Finally, we need to mirror our custom serialization on the Flex side. In ActionScript, classes with custom serialization implement the flash.utils.IExternalizable interface.

    [Managed]
    [RemoteClass(alias="CustomList")]
    public class CustomList
        implements IExternalizable
    {
        public var list : IList;

        // other methods, etc

        public function readExternal(input : IDataInput) : void
        {
            this.list = ArrayCollection(input.readObject());
        }

        public function writeExternal(output : IDataOutput) : void
        {
            output.writeObject(this.list);
        }
    }

    [Managed]
    [RemoteClass(alias="MyListKeeper")]
    public class MyListKeeper
        implements IExternalizable
    {
        public var myList : CustomList;
        public var name : String;

        // other methods, etc

        public function readExternal(input : IDataInput) : void
        {
            this.name = input.readUTF();
            // the list itself is received as an ArrayCollection, so we just assign it directly
            this.myList.list = input.readObject();
        }

        public function writeExternal(output : IDataOutput) : void
        {
            output.writeUTF(this.name);
            output.writeObject(this.myList);
        }
    }

Adobe has a nice overview of custom serialization as well, but focuses primarily on utilizing it to control which parameters are serialized.

References


Unit Testing DAO Classes with JUnit, Spring

Unit testing data access code can be quite challenging – we need to be constantly aware of what is currently in the database, what should be there, and what will be there next. This makes testing a simple data access class more complex than it need be. That’s where Spring comes in. Spring provides a convenient base class (AbstractTransactionalDataSourceSpringContextTests) that extends the JUnit base test case class to provide per-test transactions. At the end of each test method, all changes are automatically rolled back, meaning that our database is never in a testing induced state of flux. Since Spring provides support for a number of persistence frameworks, it is fairly easy to test both Hibernate and iBatis-based DAO classes. To start, I created a simple abstract class to provide the basis for all of my DAO test cases:

    public abstract class AbstractDataAccessTest
        extends AbstractTransactionalDataSourceSpringContextTests
    {
        /**
         * Reference the Spring configuration file for the test case.
         */
         protected String[] getConfigLocations()
         {
             return new String[]{ "test-applicationContext.xml" };
         }

        /**
         * Spring will automatically inject the SessionFactory instance on startup.
         * Only necessary for Hibernate-backed DAO testing
         */
         public void setSessionFactory(SessionFactory factory)
         {
             this.sessionFactory = factory;
         }
    }

Our abstract class simply defines where Spring can find our configuration (in the classpath) and, for Hibernate, provides a setter for the SessionFactory , which will be injected by Spring when the test begins. Spring wires components of our test case together (e.g. DataSource, SessionFactory) via dependency injection as defined in the Spring configuration.

Next, we define our data source, session factory (for Hibernate only), and transaction manager in test-applicationContext.xml (I will leave the data source and session factory, if needed, to you):

Hibernate

<bean id="txManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
    <property name="sessionFactory"><ref local="sessionFactory"/></property>
</bean>

iBatis

<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource"><ref bean="dataSource"/></property>
</bean>

We can now define our test class:

    public class UserDAOTest
        extends AbstractDataAccessTest
    {
        private UserDAO dao;

        // Spring will automatically inject the UserDAO
        public void setUserService(UserDAO dao)
        {
            this.dao= dao;
        }

        @Test
        public void testGetUser()
        {
            // query with jdbc template to get expected value
            String query = "select first_name from users where id=1";
            String name  = (String)this.jdbcTemplate.queryForObject(query, String.class);
            assertNotNull("User of id 1 was not found", name);

            // call the UserDAO to get the actual value returned
            User user = this.dao.getUserById(1);

            // test if the correct record was returned
            assertNotNull("User of id 1 was not found by service", user);
            assertEquals("User first names do not match", name, user.getFirstName());
       }
    }

One item of particular note here is the use of the jdbcTemplate, which is provided by Spring to query for or set-up test data in the database without going through the DAO class under test. Here, we use the JDBC template to check the first name of the record found by our class under test.

That’s it. When our test completes, any transactions that affected the database will be rolled back. For example, had we updated a user record during the test, we would find all of the changes gone after the test completes. This ensures that we will always know that state of our test database at the start and end of tests.


A Change to iBatis

In my previous post, I covered how to build a small LCDS application that utilizes Spring and Hibernate on the backend. This application was very simple and limited, but I was able to easily apply the same principles to a more complex project at work.

Following the design pattern I typically follow, I started by designing the data model (I guess I am a bit bias towards how Rails does things, but in general, I feel this is a better pattern for designing applications). The data model was slightly more complex than my sample in that it would require a couple of joins to support my model classes appropriately. I felt this was simple enough, the SQL is.

Hibernate seemed to disagree though. It became very difficult to map my data model to my model classes and if I wanted to follow my designed data model, I would be forced to change the semantics of the model layer. I also ran into difficult in persisting a custom collection, but was able to solve that (will try to post details soon). In the end it all just became to much. Hibernate is great, if you do things the way it does things – I evidently do not.

A colleague recommended that I check out iBatis as an alternative to Hibernate. When using iBatis, the developer is responsible for creating the SQL called by the application and defining the relationship between query results and model properties. Hibernate, on the other hand, requires a mapping from the database schema to the model classes and generates SQL on its own. You could say that there is some degree of “magic” to Hibernate.

Utilizing the same architectural pattern I followed in my sample application, I was able to quickly replace Hibernate-backed implementations of my DAO classes with iBatis ones. Spring also provides integration with iBatis, so bringing it into the application was very straightforward.

In the end, I was a bit disappointed to have to pull out Hibernate, but there were just to many challenges on to short of a schedule.