Learning Flex – Lesson 18, Accessing Server Side Objects

where <mx:WebService> uses XML based transfer, <mx:RemoteObject> uses the binary Action Message Format (AMF) to communicate between server and presentation layer. This means it’s faster (see James Ward’s post on this). Another advantage is the capability to pass native objects directly which saves you from translating basic generic Objects to your richer custom classes.

Flex supports communication with ColdFusion, Java (via Livecycle Data Services (LCDS), the open source BlazeDS or other 3rd party apps such as GraniteDS) or PHP (Zend Framework) and .Net (Fluorine FX) . The AMF spec is available here so other implementations may also be available.

This post will deal with configuration basics but you can look at some of my prior posts for some references and help with working with BlazeDS. The other framework sites linked to above will help you with the alternatives.

You need to use a configuration file (generally services-config.xml) to define how to make calls to the server. To use this in a standalone app (ie not deployed on a server) you need to specify it’s location in the additional compiler arguments using the -services switch.

This configuration file will define three main sections as follows:

Technology Adapter

This defines the class that translates the AMF message for the technology you’re using (Java PHP etc). The <adapters> tag contains an <adapter-definition> tag which has an id, class, and optional default (boolean) attributes.

Channels

This section defines the location of the remote server and the type of channel to be used (AMFChannel, SecureAMF, etc). A <channel-definition> tag has an id and class attribute and contains an <endpoint> tag which contains a url and class. The endpoint url may make use of special tokens {server.name}, {server.port} and {context.root} which are replaced with the server name, port and web app context root based on the url the swf is served from.

Depending on the type of channel, it may have additional parameters declared within a <properties> tag. A <default-channels> tag may be used to specify a <channel> tag with a ref attribute which is the id of the default channel to use.

Destination Handle

This is what the Flex code will refer to when using a remote object. A <destination> tag has an id attribute and contains a <properties> tag which will have a <source> tag to define either * (meaning all) or a specific class the destination is allowed to deal with on the server. A destination may also specify it’s own channels if it doesn’t use a default.

Defining a Remote Object

A <mx:RemoteObject> tag has an id attribute to reference it by and a destination attribute which is the id of the destination to use from the configuration. If you did not specify a specific class in the destination config, the source attribute should be used to specify the server class to use. You may also define result and fault event handlers. showBusyCursor is a boolean attribute that can be used to graphically indicate you’re talking to the server. It’s purely graphical and does not stop the user from interacting with the application.

As an alternative to the result event handler, you can bind directly to the lastResult of a remote object method call similarly to the way you can for a HttpService eg {ro.getResultList.lastResult} where ro is the id of my remote object and getResultList is a method on the server object. You call a remote object method in the same way you do a web service call.

Mapping ActionScript Objects to Server Objects

It’s possible  to define a mapping between an ActionScript class and it’s equivalent on the server such that when an object arrives from the server, it’s automatically converted into the ActionScript version rather than a generic Object.

To achieve this, a RemoteClass metadata tag is placed before the class definition with an alias to the server side version for example:

[RemoteClass (alias="com.mycompany.MyClass")]
public class MyClass{...

To prevent a property from being sent to the server use the [Transient] metadata tag above the declaration of that property.

As long as the number of properties and their names match, the mapping will occur. If either version of the class changes, Flex will revert to returning a generic object.

Advertisements

Learning Flex – Lesson 17, Working with Web Services

Flex applications can use web services that are defined by a WSDL (web Service Description Language) an XML based standard that defines available operations and possibly data types used by the operations.

Flex supports web service requests and responses that are formatted as SOAP (Simple Object Access Protocol) documents which are XML based.

There are two main ways to access web services in Flex, using tags or ActionScript.

Using the <mx:WebService> tag, the wsdl property specifies the URL to find the wsdl file at. Flex will load this file to find out the available operations. Once the wsdl file is loaded successfully, the WebService broadcasts a load event. You may also define a fault and result event handler for all interactions with the server.

The WebService tag may contain multiple <mx:operation> tags which have a name property for the service to be used and may specify result and fault event handlers specific to that operation.

Within the operation tag, you may specify an <mx:request> tag which can be used to specify the values for parameters to the operation (using binding for these values allows them to automatically update).

A fully declared WebService would look like this:

<mx:WebService
  id="myWebService"
  wsdl="http://myServer.com/wsdls/Services.wsdl"
  fault="handleError(event)">
    <mx:operation name="getAccountDetails" result="acountResult(event)">
      <mx:request>
        <name>{username}</name>
        <id>{userID}</id>
      <mx:request>
    </mx:operation>
</mx:WebService>

You can just specify the operation (declared method) within the WebService so you get to use the individual result/fault handlers and specify the parameters when you use the service or not bother with the operations at all (undeclared method) and specify everything when you use the service (but you’ll need to at least declare a result handler for the WebService in this case).

To call a WebService operation, you call the send() method on that operation, so for our previous definition, that would be:

myWebService.getAccountDetails.send();

To define a WebService using ActionScript, you must manually load the wsdl using the loadWSDL() method. Otherwise, it maps pretty closely as can be seen here:

private var myWS:WebService;
myWS = new WebService();
myWS.wsdl = "http://myServer.com/wsdls/Services.wsdl";
myWS.addEventListener("fault",handleError);
myWS.getAccountDetails.addEventListener("result",accountResult);
myWS.loadWSDL();

account = myWS.getAccountDetails(username,userID);

Note that you don’t need the send() this way.

You will run into naming issues if the operation you try to use happens to match a defined method of WebService. To get around this, you can use the getOperation() method on your WebService providing the operation name as a String. This will return an Operation for you to call using it’s send() method eg

myWS.getOperation("disconnect").send(param);

FlexBuilder has the capability to generate supporting code to use a wsdl’s operations by using the “import web service” wizard in the data menu.

You can find more detailed information on dealing with soap headers etc here. A useful tool when working with web services (to inspect wsdls, generate soap requests etc) is the free SoapUI tool.

Histogram Based Bias for FLARM Auto Threshold Class

Here’s the auto threshold class I created for the FLAR Manager that I promised in my previous post. It uses a histogram of the source image to figure out what the bias level should be but is otherwise identical to the “drunk walk” thresholder Eric provides. It should adapt better to varying lighting conditions.

The bias calculation takes the histogram of the source and sums the lowest and highest 20 values for the 3 channels. It then uses these sums to decide if the bias should be negative, zero or positive. I did consider scaling the difference to give more resolution to the bias value but in my experiments, the main improvement was in getting the direction right and changes in the absolute bias value did not seem too significant.

To use it, save the code as DrunkWalkHistoThresholdAdapter.as in the src\com\transmote\flar\utils\threshold directory (note this is a modified version of a transmote class I wrote and should not be considered part of the “official” FLAR Manager library.  It is provided with the same license terms)

Follow the FLAR Manager instructions on customization or the alternative process outlined in my prior post.

/*
 * PROJECT: FLARManager
 * http://transmote.com/flar
 * Copyright 2009, Eric Socolofsky
 * --------------------------------------------------------------------------------
 * This work complements FLARToolkit, developed by Saqoosha as part of the Libspark project.
 *  http://www.libspark.org/wiki/saqoosha/FLARToolKit
 * FLARToolkit is Copyright (C)2008 Saqoosha,
 * and is ported from NYARToolkit, which is ported from ARToolkit.
 *
 * ******************* MODIFIED *************************
 * This version adds histogram for bias calculation
 * Author: Matt Reynolds
 * https://mattreyuk.wordpress.com
 * *******************************************************
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this framework; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */

package com.transmote.flar.utils.threshold {
  import flash.display.BitmapData;

  /**
   * DrunkWalkHistoThresholdAdapter calculates a new threshold using weighted randomization.
   * when marker detection is poor, DrunkWalkHistoThresholdAdapter adjusts the threshold by moving a random amount
   * away from the current threshold value based on this.speed and a bias calculated from the source histogram.
   *
   * see the following URLs for more information:
   * http://blog.jactionscripters.com/2009/05/18/adaptive-thresholding-experiment/comment-page-1/#comment-367
   * http://makc3d.wordpress.com/2009/07/03/alternative-to-adaptive-thresholding/
   * https://mattreyuk.wordpress.com/2009/08/10/augmented-reality-via-flart-flarm/
   */
  public class DrunkWalkHistoThresholdAdapter implements IThresholdAdapter {
    private static const MIN_VARIANCE:Number = 5;
    private static const MAX_VARIANCE:Number = 50;

    private var _speed:Number;

    private var adaptiveThresholdingStep:Number = MIN_VARIANCE;

    public function DrunkWalkHistoThresholdAdapter(speed:Number = 0.3){
      this._speed = speed;
    }

    /**
     * init from a name-value paired object that contains parameters parsed from XML.
     */
    public function initFromXML(paramsObj:Object):void {
      if (!isNaN(paramsObj.speed)){
        this.speed = parseFloat(paramsObj.speed);
      }
    }

    /**
     * calculate a new threshold.
     * @param  source      used to calculate bias.
     * @param  currentThreshold  current threshold value.
     * @return            new threshold value.
     */
    public function calculateThreshold(source:BitmapData, currentThreshold:Number):Number {
      var thresholdAdaptationMod:Number = (Math.random() - 0.5 + 0.5 * calculateBias(source));
      this.adaptiveThresholdingStep = Math.min(Math.pow(this.adaptiveThresholdingStep, 1 + this._speed), MAX_VARIANCE);

      var newThreshold:Number = currentThreshold + (thresholdAdaptationMod * this.adaptiveThresholdingStep);
      newThreshold = Math.max(0, Math.min(newThreshold, 255));
      return newThreshold;
    }

    /**
     * reset calculations.
     */
    public function resetCalculations(currentThreshold:Number):void {
      this.adaptiveThresholdingStep = MIN_VARIANCE;
    }

    /**
     * free this instance for garbage collection.
     */
    public function dispose():void {
      //
    }

    /**
     * returns false;
     * DrunkWalkThresholdAdapter runs only when confidence is low (poor marker detection).
     */
    public function get runsEveryFrame():Boolean {
      return false;
    }

    /**
     * the speed at which the threshold changes during adaptive thresholding.
     * larger values may increase the speed at which the markers in uneven illumination are detected,
     * but may also result in instability in marker detection.
     *
     * value must be zero or greater.  the default is 0.3.
     * a value of zero will disable adaptive thresholding.
     */
    public function get speed():Number {
      return this._speed;
    }

    public function set speed(val:Number):void {
      this._speed = Math.max(0, val);
    }

    private function calculateBias(source:BitmapData):Number {
      var histogram:Vector.<Vector.<Number>> = source.histogram();
      var darkSum:Number = 0;
      var lightSum:Number = 0;
      var bias:Number = 0;

      //sum the darkest and lightest values
      for (var c:int = 0; c < 20; c++){
        darkSum += histogram[0][c] + histogram[1][c] + histogram[2][c];
        lightSum += histogram[0][c + 235] + histogram[1][c + 235] + histogram[2][c + 235];
      }
      //calculate bias
      if (darkSum > lightSum){
        //scene is dark, set threshold bias -ve
        bias = -0.5;
      } else if (lightSum > darkSum){
        //scene is light, set threshold bias +ve
        bias = 0.5;
      } else {
        //even - set threshold bias 0
        bias = 0;
      }
      return bias;
    }
  }
}

In case you’re wondering how my code presentation suddenly got so much better, it’s all down to this great tool

Posted in Flex. 7 Comments »