« January 2010 | Main | March 2010 »

February 2010 Archives

February 4, 2010

Axis2, Spring and Annotations

Axis2 is a Web Services, SOAP, WSDL engine which current release, 1.5.1, comes with many interesting features among which there is the Spring Framework support.
Axis2 documentation offers some good example of Spring integration, such as the How to create a Spring-based POJO Web Service guide or the Axis2 Integration with the Spring Framework, but there's no mention of the use of Spring annotations.
Spring annotations work like a charm in Axis2 if you follow exactly the steps of the previous guide, but my tip is to build your service structure without using annotations in a first stage (unless you are already skilled in this field), then incrementally simplify your code adding Spring annotations.
Here is an example of a simplified application-config.xml when using Spring annotations with Axis:

<beans>

  <bean id="applicationContext" class="org.apache.axis2.extensions.spring.receivers.ApplicationContextHolder" />
  <context:component-scan base-package="service"/>
  <context:component-scan base-package="bean"/>
</beans>

Now all your beans inside the packages 'service' and 'bean' will be deployed on Spring application context start or refresh. To annotate a class as Spring bean just use the @Component annotation on your class.
If you want to initialize your service on deployment time, add the @PostConstruct annotation on your initialization method. If your bean needs to access another bean, just use the @Autowired annotation on your class field.
Here a simple example:

@Component
public class MyService{

@Autowired
private MyBean bean;

@PostConstruct
protected void init() {
//init operations
}

Don't forget to add the SpringBeanName parameter in your services.xml:

<parameter name="SpringBeanName" >myService</parameter>

Annotations simplify your life reducing time spent configuring every bean you need in your application and using them in Axis allows you to build complex WebServices with less code.
Have fun.

February 11, 2010

How to test upload bandwidth to a FMS

How the download bandwidth check works

Flash Media Server has a native method to check download bandwitdh of the client, a feature that becomes very useful when you are going to stream multi bitrate content.
In a fresh installation of a Flash Media Server you can find a couple of default applications: live and vod, both come with a main.far containing the server side Actionscript code. To get a readable version you can grab the files from your FMS_ROOT/samples/applications/. Unless you have a Flash Media Interactive Server you are not authorized to substitute the original main.far with your own version, your server would throw an error; anyway you have a complete freedom in modifying and/or adding new applications if you use a developer edition (with its inbound connection limit).

Going back to the main.asc file, we can check the last lines of application.onConnect


function( p_client, p_autoSenseBW )
{
  ...
  if (p_autoSenseBW)
    p_client.checkBandwidth();
  else
    p_client.call("onBWDone");
}

application.onConnect is unsurprisingly a function called when a client connects to a FMS, the last if-block checks for the p_autoSenseBW flag; if it's present and true, a routine that checks the client bandwidth is called and does a callback on onBWDone when finished, otherwise onBWDone is called directly.
The bandwidth check can be called programmatically as well:


nc.call("checkBandwidth", null);

where nc is our NetConnection after a successful connection to the server.

Why you can need to check the upload

Sometimes you can need a bandwidth check from client to server, i.e. the upload bandwidth a client has toward the server. The most common scenario is a streaming from a client webcam. Via Actionscript we are able to adjust the camera quality affecting directly the amount of data transferred from the client, the best we can do is to get the best stream quality using all the bandwidth at our disposal; this will result in a smooth and good quality flv.

We can use the same approach used in Flash Media Server for the download bandwidth check. Basically the server starts sending chunks of data bigger and bigger until a size limit specified in the configuration or a timeout is reached. More info here http://www.adobe.com/livedocs/flashmediaserver/3.0/docs/help.html?content=08_xmlref_057.html#216930

Server side code

We can just do thinks the other way round, so the first thing we need server side is a function that accepts data from the client and subsequently calls a callback:


Client.prototype.recData = function(data)
{
  trace('recData('+data.size+')')
  var s = this.getStats();
  this.call("ack", 0, s.ping_rtt);
};

This server side code makes available to all clients a method called "recData" that takes as input generic data and calls a client side method "ack" passing the round trip time between client and server.

Client side code


The client will call the "recData" function on the server until a certain condition is met


startUploadTime=new Date().time;
_netConn.call("recData", new Responder(onRecDataResult, onRecDataFault), data);

we are calling the server side function passing a responder (not used) and the data. The data can be a simple string filled with a cycle (es. 4096 chars for 4KB). The "ack" method can be something like this:


public function ack(result:*):void
{
  finishUploadTime=new Date().time;
  var rtt:Number=new Number(result);
  // calculate time considering round trip time
  var totalTime:Number=(finishUploadTime - startUploadTime - rtt) / 1000;
  // calculate current bandwidth, current data size is base size * attempt number
  var bw:Number=UPLOAD_DATA_SIZE*(current_try+1) / totalTime;

  // check the attempts limit
  if (current_try < UPLOAD_BANDWIDTH_REPEATS)
  {
     // use a sum to make a final average
    bw_sum+=bw;
    // check the timeout limit
    if(totalTime>MAX_WAIT) {
       // set the bandwidth calculated so far
       if (Camera.getCamera())
         Camera.getCamera().setQuality(int(bw_sum / (current_try)), 0);

       uploadTestFinished = true;
       return;
     }

     // increase data size
     current_data += data;
     current_try++;
     startUploadTime=new Date().time;
     // recall the server side method
     _netConn.call("recData", new Responder(onRecDataResult, onRecDataFault), current_data);
     return ;
  }

  // Attempts limit reached, calculated the bw
  if (Camera.getCamera())
     Camera.getCamera().setQuality(int(bw_sum / (current_try)), 0);
}

Use the result to set up camera quality

ActionScript gives us a useful method to set up the camera quality: http://livedocs.adobe.com/flash/9.0/ActionScriptLangRefV3/flash/media/Camera.html#setQuality()
In our case we will set the bandwidth limit as found with our routine and set the quality to 0, i.e. the best quality supported by the current bandwidth.

February 19, 2010

Filtering nested elements of a Tree data provider

Rich Internet applications developed with Flex benefit of many of the built-in functionality already provided by this framework. One of such enhancement is the filterFunction, that can be applied to instances of class ListCollectionView (and extending ones, such as the more commonly used ArrayCollection) and allows for fast and easy to implement filtering of data. This feature, used with advanced visualization controls as DataGrid or List, provides a rich environment for the end user, that can fully control the data he/she is working with.

The filter function is best suited with visualization controls that do not consider hierarchical data, but there may be cases in which the filter should be applied to hierarchical objects, displayed, for example, into a Tree component. If we apply the filterFunction to the data provider of a Tree component, the filter will only be applied to the first elements in the hierarchy and will not be applied to nested children. This may appear as an unwanted feature of the Tree, but it was actually meant to be that way, as the Tree control strives to be as independent as possible from the underlying displayed data and allows for personalization through it's descriptor.

In order to filter all nodes of a Flex Tree component, the solution is to apply the filter function to each nested element of the data provider. This can be accomplished by creating a new hierarchical structure, already filtered (can be rather expensive), or using dynamic filtering over the Tree's default descriptor, as shown below.

I extended the DefaultDataDescriptor used by the Tree, into a FilteredDataDescriptor, that has an additional field, namely filterFunction, which is applied as filter to each element of the nested structure:


private var _filterFunction:Function;

public function get filterFunction():Function {
return _filterFunction;
}

/**
* Applies this filter function to the children of every node.
* @param value
*/
public function set filterFunction(value:Function):void {
_filterFunction = value;
}

In order to apply the filter to the children of the data provider we can override getChildren() and, before returning the collection of children, apply the filter function:


override public function getChildren(node:Object, model:Object=null):ICollectionView {
var collection:ICollectionView = super.getChildren(node, model);

if (collection && (collection is ListCollectionView)) {
(collection as ListCollectionView).filterFunction = _filterFunction;
}
return collection;
}

Note that this will work only for classes extending ListCollectionView (obviously Array is out of the picture) and that we also do not need to specifically call refresh() on the children collection, as it will be called later by the framework itself. All that's left now is to assign the newly created tree descriptor to a Tree and pass it the proper filter function(s).

February 26, 2010

New Pantaste feature - Column constrained dashboard

A new feature have been implemented to the Pantaste library. Now you can create a dashboard and constrain the movement of the panels or block only along the defined columns.

How can i implement this?
Simply by placing the <DashBlock> components inside the <DashPanelContainer>. And then placing all your <DashPanel> components inside the desired <DashBlock> this will be the first configuration and after launching your application you will be able to move the panels only along the defined DashBlocks.

So download the latest source and use the following code to create your first column constrained dashboard:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
layout="horizontal"
xmlns:components="com.comtaste.pantaste.components.*">

<mx:Style source="/assets/style.css"/>

<components:DashPanelContainer width="100%"
height="100%"
backgroundColor="#EEEEEE">

<mx:HBox width="630" backgroundColor="#EEE"
height="30">
<mx:Text fontSize="30"
text="PANTASTE COLUMN EXAMPLE" fontWeight="bold"/>
</mx:HBox>

<components:DashBlock width="300"
y="50"
height="100%">
<components:DashPanel backgroundAlpha="1"
width="300"
title="Styled panel 1"
showTitleText="true"
titleBarHeight="35"
backgroundColor="#CCCCCC"/>
</components:DashBlock>

<components:DashBlock x="330"
y="50"
width="300"
height="100%">
<components:DashPanel backgroundAlpha="1"
width="300"
title="Styled panel 2"
showTitleText="true"
titleBarHeight="35"
backgroundColor="#CCCCCC">
<mx:TextArea text="Blocco 2 "/>
</components:DashPanel>
<components:DashPanel backgroundAlpha="1"
title="Styled panel 3"
width="300"
showTitleText="true"
titleBarHeight="35"
backgroundColor="#CCCCCC">
<mx:TextArea text="Blocco 4 "/>
</components:DashPanel>
</components:DashBlock>


<components:DashBlock x="660"
width="300"
height="100%">
<components:DashPanel width="300"
title="Styled panel 4"
showTitleText="true"
titleBarHeight="35"
backgroundAlpha="1"
backgroundColor="#CCCCCC">
<mx:TextArea text="Blocco 3 "/>
</components:DashPanel>
<components:DashPanel width="300"
title="Styled panel 5"
showTitleText="true"
titleBarHeight="35"
backgroundAlpha="1"
backgroundColor="#CCCCCC">
<mx:TextArea text="Blocco 5 "/>
</components:DashPanel>
</components:DashBlock>

</components:DashPanelContainer>

</mx:Application>

About February 2010

This page contains all entries posted to Comtaste Consulting | Enterprise RIA consulting and development in February 2010. They are listed from oldest to newest.

January 2010 is the previous archive.

March 2010 is the next archive.

Many more can be found on the main index page or by looking through the archives.

Powered by
Movable Type 3.33