5 Replies Latest reply on Mar 21, 2010 11:30 AM by Dan Thomas

    [After] asynchronous

    Dan Thomas

      I'm playing about trying to put together some integration tests for an AIR app with local database.

       

      I want to basically setup a database in my [Before] setup and get rid of it using [After] teardown with my tests obviously then free to operate on a completely clean db each time. This would be fine but I can't seem to close my SQLConnection in my [After] method as it apparently needs a flash.net.Responder to be called before it'll completely clean itself up (even with a synchronous connection).

       

      I might be wrong on several levels here but can I do an async teardown with a flash.net.Responder somehow?

        • 1. Re: [After] asynchronous
          mlabriola Level 4

          Sorry for the long post, I am going to give you a solution which isn't great, but should work for you. AIR made several choices along the lines of using flash.net responders which weren't compatible with the IRespodners common in Flex. We need to extend our support to make this easier, but for now you can do something like this:

           

           

          var rpcResponder:IResponder = Async.asyncResponder( this, new ErrorOnlyResponder(), 500 );
          var flashResponder:ResponderAdapter = new ResponderAdapter( rpcResponder );
          //then pass flashResponder onto the AIR call which is looking for a flash responder

           

          the ResponderAdatper class *is* a Responder, so it will be accepted by AIR. It in turn just calls the other cascade of classes. If the operation fails, an error is thrown. If the operation succeeds, it just continues. I just quickly wrote these two classes so they aren't posted anywhere else (and aren't tested, but they should work). As they don't exist elsewhere, I am going to include the code here.

           

          Sorry for the cut and paste but let me know if this solves the issue,

          Mike

           

          ---

           

          package net.digitalprimates.responder {
              import mx.rpc.IResponder;
             
              public class ErrorOnlyResponder implements IResponder {
                  public function ErrorOnlyResponder() {
                  }
                 
                  public function result(data:Object):void {
                  }
                 
                  public function fault(info:Object):void {
                      throw new Error( "An Error Occurred" );
                  }
              }
          }

           

          ---

           

          package net.digitalprimates.responder {
              import flash.net.Responder;
              import mx.rpc.IResponder;
             
              public class ResponderAdapter extends Responder {
                  private var responder:IResponder;
                  public function ResponderAdapter( responder:IResponder ) {
                      super(result, status);
                      this.responder = responder;
                  }
                 
                  public function result( data:Object ):void {
                      if ( responder ) {
                          responder.result( data );
                      }
                  }
                 
                  public function status( info:Object ):void {
                      if ( responder ) {
                          responder.fault( info );
                      }
                  }
              }
          }

          • 2. Re: [After] asynchronous
            Dan Thomas Level 1

            So I'm not even sure if the problem is as I described, I was getting the same issue as experienced here:

             

            http://blog.arulprasad.com/2008/07/something-about-closing-and-reopening.html

             

            I'm trying to run some tests against FlexOrm and there's possibly some form of reference issue there or a bug in the Synchronous SQLConnection that doesn't like being closed, nulled then re-instansiated. If anyone has any suggestions then I'm all ears.

             

            In the meantime I'm carrying on just without closing the SqlConnection in my teardown which works fine. The odd thing is in my teardown I am actually deleting the database file so i don't see how it's not closing the connection but that seems to make the difference.

             

            In summary:

             

            I have a "Run tests" button that I've added to my testrunner UI which just calls core.run( myTests );

             

            Then my test case is akin to:

             

            [Before]

            public function setup() : void

            {

                 this.dbFile = File.applicationStorageDirectory.resolvePath("tests.db");

                 sqlConnection = new SQLConnection();

                 sqlConnection.open(dbFile);

            }


            [Test]

            public function someTest() : void

            {

                 // uses flexorm to insert into db

            }


            [After]

            public function teardown() : void

            {

                 //this.em.sqlConnection.close(); // uncommenting this line will make the test fail the 2nd time I run the tests

                 this.dbFile.deleteFile();

                 this.sqlConnection = null;

            }

            • 3. Re: [After] asynchronous
              Dan Thomas Level 1

              Sorry hadn't seen this, thanks for that far nicer than the hack I'd come up with, but alas as per my other post it didn't actually solve my problem. However, I'm sure your solution will be needed imminently anyway.

              • 4. Re: [After] asynchronous
                legrosb Level 3

                I may be totally missing the obvious, but why not just register a handler on the SQLConnection for the SQLEvent.CLOSE event?  Looks like it fires after the connection has been closed, not just at the method being called (at least in the asdocs -- http://help.adobe.com/en_US/FlashPlatform//reference/actionscript/3/flash/data/SQLConnecti on.html#event:close):

                 

                [After(async)]

                public funciton tearDown() : void

                {

                   this.em.sqlConnection.addEventListener(SQLEvent.CLOSE, Async.asyncHandler(this, destroyConnection, 500), false, 0, true);

                   this.em.sqlConnection.close();

                   this.dbFile.deleteFile();

                }

                 

                private function destroyConnection() : void
                {

                    this.em.sqlConnection = null;

                }

                 

                If there are known hacks needed to work with the responder, isn't listening for the event another alternative?  If the weak listener reference doesn't hold up, you can always remove the event listener in destroyConnection.  Just a suggestion.

                 

                -Brian

                • 5. Re: [After] asynchronous
                  Dan Thomas Level 1

                  Sorry for totally wasting everyones time, the problem was caused by a bug in FlexOrm keeping a reference to the old connection (which I've now fixed).

                   

                  Pretty much all of the approaches suggested here work but the easiest is as legrosb suggested however worth noting the SQLEvent.CLOSE doesn't fire if you have sent in a Responder.

                   

                  Thanks guys really appreciate it!