Native AMF based IOS applications
Reuse of AMF based service in IOS Applications
Author: Fabio Trentini, BTC Business Technology Consulting, July 2011
Every Flashbuilder(Flex) developer knows and appreciate the extremely easy way to integrate and acccess remote services using BlazeDS. The code on the client is compact and the nature of services used on the backend systems can be exchanged with no (or very reduced) efforts. The mobile facilities of Flashbuilder enable in addition designers and developer to reuse action script code for application running among others on IOS devices such as iPad, iPod Touch and iPhone. At first glance therefore no need to switch to Objective C in order to write Mobile applications for IOS when we already use Flashbuilder applications.
According to the business requirements, it may be in fact much more easy and straightforward to use today Flashbuilder mobile project and cross generate action script for IOS devices. If however the requirements are to access a high number of native IOS API's not (yet) available in Flashbuilder (although Faslhbuilder provides a bridge to access native IOS API's from Actionscript), the approach of writing a 100% native IOS Application (understand in Objective C) may need to be considered.
Adobe is definitively improving the performance of cross generated code on IOS but still, there may be situations where a native implementation may become more effective or necessary.
The objective of this article won't be however to present the full set of code required but just stick to the basics examples and the assumption is that the reader is familiar with at least the basics of Iphone/Ipad development using Objective C and Xcode.
All we want to emphasize here is the possibility to share backend services as described in the following diagram :

The main message here is therefore that the common denominator (understand here the backend services layer) can still be reused "as is", even if we would decide to opt for Objective C instead of Actionscript on the client. Flasbuilder developer may use the Adobe commercial release (Lifecycle) or opt for the opens source integration layer provided by BlazeDS. Typically, BlazeDS is used to enable the access of Java remote objects using AMF (Adobe Message Format) as transport protocol which, besides the easy integration, also provides advantages in terms of performance due to its binary characteristics.
Besides AMF, BlazeDS enables to expose for example also REST based services and in this respect, the access from an IOS native applicationn may benefit form an existing infrastructure originally meant to be used by Flex clients.
The sample case study:
We are going to reuse here the same service described in my previous article. The following recalls the server implementation that we used for the getCustomerList() using BlazeDS and Spring annotations:
package ch.btconsulting.flex.spring.tutorial;
import java.util.ArrayList;
import java.util.List;
import org.springframework.flex.remoting.RemotingDestination;
import org.springframework.flex.remoting.RemotingInclude;
import org.springframework.stereotype.Service;
@Service ("myFirstServiceForFlex")
@RemotingDestination(channels={"my-amf","my-secure-amf"})
public class CustomersService {
@RemotingInclude
public Object[] getCustomersList(){
List returnValues=new ArrayList();
// extract here the customers from the database and put the data in returnValues
returnValues.add(new Customer("0001","ACME corp","Switzerland",12000));
returnValues.add(new Customer("0002","ACYOU ltd","Switzerland",10000));
returnValues.add(new Customer("0003","ACME & Co","USA",40000));
returnValues.add(new Customer("0004","TestCorp","Germany",20000));
returnValues.add(new Customer("0005","LosCompaners ltd","Spain",25000));
return returnValues.toArray();
}
}
Notice a small difference. I return now an array of Objects (Object[]) as opposed to a java List. The reason is due to the IOS Objective C library used where an Array is expected as opposed to a java Collection.
The remaining part of the server implementation remains however identical.
In Flashbulder we would use the following code in order to declare a client service proxy object:
<s:RemoteObject id="BTCSPRINGSERVICES"
endpoint="http://localhost:8080/BTCSpringServerTest/messagebroker/amf"
destination="myFirstServiceForFlex">
<s:method name="getCustomersList" result="resultFinListHandler(event)" />
</s:RemoteObject>
You may recall the endpoint URL (indicating where to reach the BlazeDS message dispatcher), the destination (logical identification of the remote service object/channel and of course the java method name to invoke (getCustomerList)
Calling AMF from IOS in Objective C using CocoaAMF:
The example below uses the nesium CocoaAMF that you can find and download here.
The intention here is not to describe in details what the reader can find on the official site of COCOAAMF. The aim is rather to make aware, once again, that an access from a native IOS Objective C application can be straightforward and simple
Here is the Objective C code required in order to access the remote BlazeDS getCustomerList service:
#import "myFirstServiceForFlex.h"
@implementation myFirstServiceForFlex
@synthesize delegate=m_delegate;
- (id)init
{
if (self = [super init])
{
m_remotingCall = [[AMFRemotingCall alloc] init];
m_remotingCall.URL = [NSURL URLWithString:@"http://localhost:8080/BTCSpringServerTest/messagebroker/amf"];
m_remotingCall.service = @"myFirstServiceForFlex";
m_remotingCall.delegate = self;
m_delegate = nil;
}
return self;
}
- (void)dealloc
{
[m_remotingCall release];
[super dealloc];
}
- (void)getCustomersList
{
m_remotingCall.method = @"getCustomersList";
m_remotingCall.arguments = [NSArray array];
[m_remotingCall start];
}
(void)remotingCallDidFinishLoading:(AMFRemotingCall *)remotingCall
receivedObject:(NSObject *)object
{
// process here the returned data
}
- (void)remotingCall:(AMFRemotingCall *)remotingCall didFailWithError:(NSError *)error
{
// error handling here
}
@end
In the the sample code I omitted to describe the logic required in order to process the returned data (since this would explode this paper with information that you can find in the sample reference application provided by nesium) that is delivered in the method called remotingCallDidFinishLoading (in this respect similar to the return function declared in Actionscript (Flashbuilder).
There are at this point different possible design approaches to process data returned by a service (and here I am not describing anything new). We may include the implementation in an Objective C class supporting the AMFRemotingCallDelegate protocol in which case we would directly manipulate the customer information received or we can opt for a delegate approach where we can call a delegate method to the caller. Last but not least, we can also use a singleton pattern approach and invoke within the result method on a singleton enabling the further process of information.
In this respect, all approaches have advantages and disadvantages and the internet is full of arguments in favor of the one or the other approach.
The header file to include (myFirstServiceForFlex.h) is reported below:
#import <Foundation/Foundation.h>
#import <objc/message.h>
#import "AMFRemotingCall.h"
@protocol DemoCallerDelegate;
@interface DemoCaller : NSObject <AMFRemotingCallDelegate>
{
AMFRemotingCall *m_remotingCall;
NSObject <DemoCallerDelegate> *m_delegate;
}
@property (nonatomic, assign) NSObject <myFirstServiceForFlex> *delegate;
- (void)getCustomersList;
@end
@protocol DemoCallerDelegate
- (void)callerDidFinishLoading:(DemoCaller *)caller receivedObject:(NSObject *)object;
- (void)caller:(DemoCaller *)caller didFailWithError:(NSError *)error;
@end
Notice that in order to be able to process the returned data, the implementation has to implement the AMFRemotingCallDelegate protocol.
As mentioned above, the idea here was not to present a detailed implementation but rather to let readers be aware that reusing a remote flex based server running under BlazeDS (or Lifecycle) is, and this thank to nesium providing us with an AMF based library for IOS, not bound with particular hurdles or difficulties.
In a separate article, I will describe more in details the combined approach of using Objective C, CocoaAMF and Flashbuilder mobile where we will implement a simple tracking GPS based system.