Hey, lets switch to something completely different! AMF is a messaging format commonly used in flash/flex applications that retrieve data from a server, and like all server-side logic you might feel the urge to do some functional or load-testing to make sure that things are holding up ok. And although the current version of soapUI doesn't have dedicated AMF support (the next version will), a bit of groovy scripting can help us immensely. Check it out!

Getting Started

In this post I'm going to use the BlazeDS platform available from Adobe for demonstration purposes; download and install it from http://opensource.adobe.com/wiki/display/blazeds/BlazeDS/ and make sure you have the samples up and running locally (the turnkey distribution should have you up in no time).

Since we are going to use the AMFConnection related APIs from soapUI, copy the jar files in your <blazeds>\resources\lib folder into the <soapui>\bin\ext folder and start soapUI. You should see the following in the soapUI log after starting it up:

flexjars

Create a standard soapUI Project:

createproject

and then manually add a TestSuite and TestCase, to which you finally add a groovy script TestStep which will do the actual request for us:

emptyproject

Create the script

The actual script that makes the AMF-request is pretty straight forward:

import flex.messaging.io.amf.ASObject;
import flex.messaging.io.amf.client.AMFConnection;
def amfConnection = new AMFConnection();
amfConnection.instantiateTypes = false
try
{
   amfConnection.connect(  "http://127.0.0.1:8400/samples/messagebroker/amf" );
   amfConnection.registerAlias( "", "flex.samples.product.Product" );
   def result = amfConnection.call( "product.getProduct", 9  )
   return result.toString()
}
finally
{
   amfConnection.close()
}

Some key points need explanation here:

- amfConnection.insantiateTypes = false : this tells the AMFDeserializer not to look for Java Objects matching those in the AMF Response Message (since we haven't added these to the classpath), instead it will return all objects as ASObjects

- amfConnection.registerAlias(... ) : a workaround required for this sample; the instantiateTypes property doesn't affect types in the flex.* package, and since the Adobe sample classes are just that (duh!), we need to add a separate alias for the class that will be returned by our service (aliasing the class name with "" will result in ASObject being used). Be sure to put your own objects in a package not starting with "flex" and this line will not be required.

- the actual call "product.getProduct" can be tricky to figure out since AMF services lack a WSDL-counterpart for describing services, operations, etc. In BlazeDS, you'll need to download the source distribution (from the same link as above) and open the remoting-config.xml file under the <blazeds-src>/apps/samples/WEB-INF/flex folder to find the available service ids and which java classes they are mapped to. For our product service the entry is

<destination id="product">
   <properties>
      <source>flex.samples.product.ProductService</source>
   </properties>
</destination>

then you need to dig into the sources to find the actual interface for the ProductService; its in the <blazeds-src>/apps/samples/WEB-INF/src/flex/samples/product/ProductService folder.

(Actually, I wish I was wrong here... if you know a standard/easier way to "discover" AMF services and their operations please let me know).

Ok, run the script and if you have blazeds running ok, you should see the following:

script1

Cool! We got a result over AMF! Next is to format this result as XML so we can use it in property-transfers, etc. For this I'm going to use another fine open-source library; XStream. Download the XStream distribution from http://xstream.codehaus.org/download.html, unpack it and put the xstream-1.3.1.jar file in the <soapui>\bin\ext folder (together with the amf-jars above). Restart soapUI to make sure it gets picked up ok;

alljars

Now back to our script; change the line

return result.toString()

to

return new com.thoughtworks.xstream.XStream().toXML( result )

And when we run the script; Presto!

script2

What's so good about that? Well, now if we have (for example) a Property-Transfer, we can set the Groovy Script as the source step and the "Result" property as the source property; in soapUI Pro the standard XPath popup wizard will help us select the desired node for transferring to some target request/property/etc;

propertytransfer

Other possibilities are branching with Conditional Gotos, saving of results with DataSink, validating the results with another groovy script, etc.

Load testing AMF

How about load-testing? Piece-o-cake; just add a LoadTest to your TestCase  and fire it off;

loadtest

pretty decent performance I would say :-)

Wrap-up

Ok, this is might be a bit crude but it does get the job done and the test can easily be combined with standard SOAP/REST/HTTP tests to create more complex scenarios. Keep your eyes open for the 3.5 release of soapUI, which will sport a bunch of new protocols, including AMF, JMS, etc. And as always, don't hesitate to get in touch regarding this or anything else.

Thanks for your time!

/Ole

  • Digg
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • DZone
  • E-mail this story to a friend!
  • Technorati
  • Turn this article into a PDF!
  • Twitter