Tag Archives: Flex

A new Parsley Extension: The DynamicServices tag

I just pushed a new Parsley extension project to GitHub – support for the <DynamicService /> tag.

Typically in a project, I like to structure my services layers pretty cleanly – for each service I would declare the following:

  • An interface which defines the services contract
  • A concrete implementation of the interface, which abstracts away the RemoteObject
  • A stub implementation of the interface, for testing when the services layer is unavailable

For example, a simple EchoService might look a little something like this:

// IEchoDelegate.as
public interface IEchoDelegate
{
     function echoMessage(source:String):AsyncToken;
}

// EchoDelegate.as
public class EchoDelegate
{
   [Inject]
   public function service:RemoteObject;

   public function echoMessage(source:String):AsyncToken
   {
      return service.echoMessage(source);
   }
}

Here, you can see the concrete delegate is really just boiler-plate code.  It’s pretty repetitive, and while I find lots of value in the pattern, the actual implementation can be a bore.

So, I put together a Parsley extension to generate these delegates on the fly.

Here’s an example:

<?xml version="1.0" encoding="utf-8"?>
<parsley:Objects>
   <fx:Declarations>
      <services:DynamicService type="{IEchoService}" endpoint="http://localhost:8080/testdrive/messagebroker/amf" destination="echoService" />
   </fx:Declarations>
</parsley:Objects>

This definition combines the Interface and the remote object defininition in the context. An implementation of the interface is generated on-the-fly at runtime, and is available to be injected into classes as required.

Eg:

// EchoCommand.as
	public class EchoCommand
	{
		[Inject]
		public var service:IEchoService;

		public function execute(message:EchoMessage):AsyncToken
		{
			return service.echo(message.source);
		}

		public function result(result:String):void
		{
			trace("Received from the server:" + result);
		}
	}

Source

The source for this is available now on github.  There’s also a demo project available here

A word of warning

Under the covers, this extension makes use of the ASCommons-Bytecode library to build an implementation of the interface.

Unfortunately, this dynamic goodness is not free, and incurs a one-off cost at startup when the ByteCode library parses the bytecode of the swf into memory.  As a result, you’ll notice that Parsley takes a little longer to intitialize than you might be used to.  This is a tradeoff that must be considered before using this approach.

Tagged ,

Flapper: An extension library for AOP with Parsley

I’ve just thrown a quick project up on Google Code for allowing simple AOP style programming with Parsley:

Flapper

The project aims to allow simple registration of AOP interceptors by registering a metatag with an interceptor.

It uses the awesome as3-commons bytecode library for proxy generation

Configuration

The aim is to have simple configuration.  You activate Flapper by simply declaring  AspectSupport in your parsley context:

        <parsley:ContextBuilder>
            <parsley:FlexConfig type="{ParsleyConfig}" />
            <tag:AspectSupport>
                <tag:MetatagAspectDefinition metatag="Log" aspect="{new LoggingAspect()}" />
            </tag:AspectSupport>
        </parsley:ContextBuilder>

In this example, I’m registering the Log metatag with my LoggingAspect.

Now, any class which has a method annotated with Log will be proxied, and the LoggingAspect will get invoked before the actual method itself.

Eg:

    public class Calculator
    {
        [Log]
        public function add(a:int,b:int):int
        {
            return a + b;
        }

    }

The aspects themselves are also extremely simple, implementing an Aspect interface.

Here’s my LoggingAspect:


    public class LoggingAspect implements Aspect
    {
        public function intercept(pointCut:ProceedingJoinPoint):void
        {
            trace(pointCut.targetMember.localName + " called with params: " + pointCut.arguments.join(","));
            pointCut.proceed();
            var returnValueString:String = pointCut.returnValue ? pointCut.returnValue.toString() : "null";
            trace(pointCut.targetMember.localName + " returned " + returnValueString );
        }
    }

This simply traces out the method name that was called, and the arguments that were passed in.

Usage

That’s all the configuration that’s required.  Now, any time I call calculator.add(), the aspect will trace out the call to the console window.

Note – classes that will be proxied must be decalred using Parsley’s Object tag, rather than as an instance.

Eg:

    <fx:Declarations>
        <!-- Don't do this -- it won't work -->
        <sample:Calculator />

        <!-- Instead, decalre using the Object tag -->
        <parsley:Object type="{Calculator}" />
    </fx:Declarations>

Usage from here is no different than with any other injected class.

Example:

            [Inject]
            public var calculator:Calculator;

            private function addNumbers():void
            {
                 // Results in a message being traced out "Called add with arguments: 2,3"
                calculator.add(2,3)
            }

The project and a demo are available to be checked out here. It’s still fairly early days, and the project hasn’t really been tested – but feel free to grab it and have a play.

Important Credit

This whole project took 2 nights to write.  The main reason it was so quick and simple  is because all the hard work has already been done by two awesome existing projects.

The as3-commons team have done an amazing job on the project, but also in providing thorough clear documentation.

Equally so, Jens Halm has done an outstanding job on Parsley, making the framework so easy to extend, with a solid API, and killer docs.  Not to mention he’s extremely responsive in the forums.  Both these projects rock.

Update:

I’ve updated this blog post to reflect the move to the Aspect interface, where previously I was using the ascommons-bytecode IInterceptor.  This has made chaining Aspects easier.  Note – I’m still using ascommons-bytecode underneath, but it’s now abstracted away a little more.

Tagged , ,

dpHibernate and Spring transactions

I’ve recently been getting my feet wet in Java, and starting integrating with dpHibernate to facilitate lazy loading across to Flex.

Here’s what my stack looks like:

  • Spring 2.5.6
  • Hibernate 3.3 (including annotations, and transaction management)

Trying to get dpHibernate wired in, I was getting lots of errors along the lines of the following:

No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here

 

The problem here is that using transaction management, things get a lot tighter on how and when you can get access to a hibernate session.  dpHibernate tries to get it’s session by essentially calling sessionManager.getCurrentSession();

However, as far as Spring’s transaction manager (which is wired into the SessionManager) is concerned, the thread which is executing has no session, and has no business trying to create one — specifically, outside of a transaction.

After spending several hours trying to work out how to sidestep Springs transaction management, I realized the trick was simply to wire dpHibernate closer to spring.  This is tricky, because dpHibernate is using an extension of the flex’s JavaAdapter, and exists completely outside of the Spring infrastructure.

HibernateSerializer makes a call to a dpHibernate object called SessionManager, which returns the current session outside of a valid Spring transaction.

So, I ditched the SessionManager completely, and replaced it with a good old fashionsed SessionFactory object, as follows:

    @Resource
    private SessionFactory sessionFactory;

    public void setSessionFactory(SessionFactory sessionFactory) {
        this.sessionFactory = sessionFactory;
    }

    public SessionFactory getSessionFactory() {
        return sessionFactory;
    }

The @Resource tag there tells Spring to give me a wired up sessionFactory instance.

I also decorated the HibernateSerializer with a @Transactional tag, so that Spring knows the context in which this will operate:

@Transactional(readOnly=true)
public class HibernateSerializer implements ISerializer
{

Now, if I add the HibernateSerializer as a bean, Spring knows to give it access to a sessionManager, and to do so in the context of an active transaction.

Add the bean declaration as follows:

<bean id="hibernateSerializerBean" class="net.digitalprimates.persistence.translators.hibernate.HibernateSerializer" />

Nearly there. Finally, I just need to tell dpHibernate to go and fetch this wired up Serializer from Spring, rather than instantiate it’s own. Inside SerializationFactory, I modified the getSerializer() call to read as follows:

    public static ISerializer getSerializer(String type)
    {
        if( HIBERNATESERIALIZER.equals(type) )
        {
            ServletContext ctx = FlexContext.getServletContext();
            WebApplicationContext springContext = WebApplicationContextUtils.getRequiredWebApplicationContext(ctx);
            ISerializer serializer = (ISerializer) springContext.getBean("hibernateSerializerBean");
            if (serializer == null)
            {
                throw new RuntimeException("bean named hibernateSerializerBean not found");
            }
            return serializer;
        }

        throw new RuntimeException("unsupport serialization type: " +type);
    }

Note that I’ve hard coded the name of the bean here for simplicity sakes. Chances are you’ll want to paramaterize that.

That’s it! Now, calls that pass through dpHibernate happen with a Spring managed transactional session. Great!

 

Edit: Espen came up with a simpler alternative over on his blog — check it out : http://espenskogen.wordpress.com/2009/06/04/more-dphibernate/

Tagged , , ,

Mock Webservice in AS3

An important part of a good test suite is repeatability, and independance from external changes. Therefore, if your method loads data from an external source, that’s a real testing no-no.

However, using the features of dynamic classes in AS3 we can whip up a mock webservice which gives us a guaranteed result, every time.

Here’s the class:

package com.martypitt.testing.mockObjects
{
    import flash.utils.Dictionary;
    import flash.utils.flash_proxy;

    import mx.core.Application;
    import mx.core.mx_internal;
    import mx.messaging.messages.AsyncMessage;
    import mx.messaging.messages.IMessage;
    import mx.rpc.AbstractOperation;
    import mx.rpc.AsyncToken;
    import mx.rpc.events.ResultEvent;
    import mx.rpc.soap.WebService;

    use namespace flash_proxy;
    use namespace mx_internal;

    public dynamic class MockWebService extends WebService
    {

        /** The default response is returned if a call is made to a method that has not been explicitly
         * set using setResponse() */
        private var _defaultResult:Object;

        /** Determines bevahiour if a call is made to a method where the response has not been explicity set.
         * If true, an error is thrown.
         * If false (default) the defaultResponse is returned.
         * */
        private var _throwErrorIfResultNotSet:Boolean = false;

        private var _resultDictionary:Dictionary = new Dictionary();

        public function get defaultResult():Object {
            return _defaultResult;
        }
        public function set defaultResult(value:Object):void {
            _defaultResult = value;
        }

        /** responseDictionary holds a list of predefined methods and their associated responses.
         * */
        protected function get resultDictionary():Dictionary {
            return _resultDictionary;
        }
        protected function set resultDictionary(value:Dictionary):void {
            _resultDictionary = value;
        }
        public function get throwErrorIfResultNotSet():Boolean {
            return _throwErrorIfResultNotSet;
        }
        public function set throwErrorIfResultNotSet(value:Boolean):void {
            _throwErrorIfResultNotSet = value;
        }

        public function MockWebService(destination:String=null, rootURL:String=null)
        {
            super(destination, rootURL);
        }

        /** callProperty is called by the Flex / flash framework when something tries to access
         * a method or property of a dynamic object which has not been defined in code.
         * Here we override the default behaviour to return the correct response.
         * */
        override flash_proxy function callProperty(name:*, ... args:Array):*
        {
            var response:Object;
            var methodName:String = getLocalName(name);

            switch (true) {
                case (_resultDictionary[methodName] == null && throwErrorIfResultNotSet) :
                    throw new Error(String(methodName) + " does not have an appropriate result set.");

                case (_resultDictionary[methodName] == null && !throwErrorIfResultNotSet) :
                    response = defaultResult;
                    break;

                case (_resultDictionary[methodName] != null) :
                    response = _resultDictionary[methodName]
                    break;

                default :
                    throw new Error("Unhandled switch case scenario in MockWebService");
            }

            var message:IMessage = new AsyncMessage()
            var token:AsyncToken = new AsyncToken(message)

            // We want to return the Async token now (just like a normal webservice would)
            // but we get the app to dispatch the ResultEvent on the next frame

            // It's important that the result event is dispatched from the operation itself.
            var operation:AbstractOperation = super.getOperation(methodName);
            Application.application.callLater(operation.dispatchEvent,[ResultEvent.createEvent(response,token,message)]);
            return token;
        }

        public function setResult(methodName:String,responseValue:Object):void {
            _resultDictionary[methodName] = responseValue;
        }

    }
}

Nothing overly swanky, but all the magic happens courtesy of this line :
override flash_proxy function callProperty(name:*, ... args:Array):*

This method gets invoked whenever you call a method on the class which has not been defined in code. We catch the call, and generate an Async token that makes the caller think that we’re busily off chatting to our webserver.

The other key line is this:
Application.application.callLater(operation.dispatchEvent,[ResultEvent.createEvent(response,token,message)]);

In essence, we’re just dispatching a result event here. But, because our method is called syncronously, and webservices behave asyncronously, it’s important that we dispatch the event on the next frame. Hence Application.application.callLater.

Also, the result event must come from the operation itself, not our mock service, so that whoever has called this method gets notified of the result event, just like they would if it were a normal webservice.

So, with all that done, we simply set up the webservice, and invoke it:


var result:XML = new XML();
var ws:MockWebService = new MockWebService();
ws.setResult("callMyRemoteMethod",result)
someClass.webservice = ws;

It’s important (and good design practice) that you expose the webservice on your class as property that can be modified at runtime.

That’s pretty much it.

Questions and comments welcomed.

Marty

Tagged , ,

Custom Metatags and slicker unit tests in Flex

I’m a fan of unit tests. And, although I probably wouldn’t blazen it across my chest like some, I am sold of the benefits.

However, coming from .NET, I miss quite a bit of the elegance present in NUnit when working with FlexUnit.

Most specifically, the setup of a test suite is kinda clunky.

Normally, you have several classes of unit tests, each which have a static suite() method, returning a test suite comprising the unit tests in that class.

Check out the following example:



 public static function suite():TestSuite {

    	var ts:TestSuite = new TestSuite();	   	ts.addTest( new MyTestClass("testMethodA") );

    	ts.addTest( new MyTestClass("testMethodB") );

    	ts.addTest( new MyTestClass("testMethodC") );

    	ts.addTest( new MyTestClass("testMethodD") );

    	return ts;

 }

As you can appreciate, it doesn’t take long for this to get long and clunky. Also, maintanence is a pain in the butt — adding tests don’t get run if you forget to add it in the Suite method, changing names causes RTE, etc etc etc.

In NUnit (and, presumably JUnit), you just decorate a class with [TestFixture], and a method with [Test], and NUnit takes care of the rest using that groovy cat, Reflection.

Luckily for us, Flex gives us the ability to tell the compiler to retain custom metatags in Flex 3. This means we can achieve similar functionailty — at least at the method level.

The first step is to set the compiler option. In Flex Builder 3, right click your project, hop into Flex Compiler, and add this to the list of compiler options:

-keep-as3-metadata+=Test

Then, using flash.utils.describeType() we can find any methods within a class that are decoared with our [Test] method.

The following method examines a class, and returns a TestSuite which contains a test for each decorated method.

        /**

         * Generates a test suite with all the methods in a class decorated with [Test] metadata

         * @param clazz

         * @return

         *

         */

        public static function fromClass(clazz:Class):TestSuite {

            var suite:TestSuite = new TestSuite();

            var testMethodNames : XMLList = describeType(clazz).method.(metadata.(@name==”Test”)).@name

            for each (var node:XML in testMethods) {

                    var methodName:String = node.value()

                    var test:Test = new clazz(methodName);

                    suite.addTest(test);

            }

            return suite;

        }

Personally, I chose to add this to the TestSuite class in FlexUnit, though you may prefer a seperate util class.

Now, getting all the tests for a class is as simple as:

var suite:TestSuite = TestSuite.forClass(myClass);

Much more readable!

Comments welcomed.

Marty

Update : I modified the disvoery method to use the E4X expression suggested by Theo. I must’ve been having a brain-fart at the time, as I’m a huge fan of the E4X syntax. Nice spotting Theo!

Tagged , ,
Follow

Get every new post delivered to your Inbox.

Join 189 other followers