Application Development Blog Posts
Learn and share on deeper, cross technology development topics such as integration and connectivity, automation, cloud extensibility, developing at scale, and security.
cancel
Showing results for 
Search instead for 
Did you mean: 
_IvanFemia_
Active Contributor

In this article I would like to give you a tutorial in order to invoke SAP web services with Flex using Cairngorm framework.

1. What is Cairngorm?

Cairngorm is one of the primary MVC open source frameworks for application architecture in Adobe Flex.

This framework gives a rational organization to your project and simplifies its maintenance.

2. How Cairngorm works?

It follows the Model-View-Controller model and could be schematized with:

  • Model Locator
  • View
  • Front Controller
  • Command
  • Delegate
  • Service

Model Locator: it is similar to the HTTP session (but it’s stored on the client side) and it is used to save
all your application value objects.

View: it is the front end element; it’s formed by all the Flex UI objects, which are Buttons, Text field, Layout manager, etc.
Objects in the view are bounded with view locator application objects and throws events such as Clicked, Dragged, Dropped and so on.

Front Controller: Dispatch thrown events to the mapped Command element.

Command: Manage the business logic of your application. It instantiates Delegate Object in order to perform Remote Procedure Calls (Web services, HTTP requests, file system and updates the value of application value objects in the Model Locator.

Delegate: Handle the remote procedure calls.

3. Flow logic during a request/response

Below I would like to show the flow logic during a flex request/response.

  1. View throws an Event
  2. Event is thrown
  3. Front Controller handles the Event and invokes registered Command
  4. Command performs the business logic
  5. Business logic starts (delegates are invoked)
  6. Business logic ends
  7. Command updates the Value Objects
  8. Model Locator has updated Value Objects
  9. View displays bind Values Objects

4. What you need?

Below the requirements:

  • Adobe Flex installed on your system (I used Flex Gumbo 4.0, but it works also with Flex 3.0)
  • Adobe Flex Builder 3.0
  • Cairngorm library (cairngorm.swc)
  • Great passion ^_^

5. Ok let’s start

5.1.    Create a web service in SAP

First of all we need to create a SAP web service for our test. In this test I use ZFLEX_TEST created from Function Module BAPI_COMPANYCODE_GETLIST

It is out of scope of this weblog to give you the how to… You can read this web post on this blog Create a web service with ECC 6.0 or watch this video.

5.2.    Create a new Flex Cairngorm project

Create a new Flex or AIR project, I created a new AIR project (SAPExample), and add in the Flex build path a new SWC and select the cairngorm.swc.


Once you have created the new Flex project, we need to create the directories structure under the project root create a new folder (I used it/plinky) and add the following directories: business, commands, control, events, model, view and vo.

Now your project tree should appear like the image below:

5.3.    Create Model Locator

In the model directory create a new Action Script Class named ViewModelLocator and add in the interface list IModelLocator (com.adobe.cairngorm.model.IModelLocator) interface.

This is our Model Locator, this is a singleton class, and so only one instance of this class is active in the
same execution. As described above, this class will be used to store all Application Value Objects.

*********************************************************************
package it.plinky.model
{
import com.adobe.cairngorm.model.IModelLocator;
import it.plinky.vo.CompanyCodeVO;
[Bindable]
public class ViewModelLocator implements IModelLocator {
// Single Instance of Our ModelLocator
private static var instance:ViewModelLocator;
public function ViewModelLocator(enforcer:SingletonEnforcer) {
if (enforcer == null) {
throw new Error( “You Can Only Have One ModelLocator“ );
}
}
// Returns the Single Instance
public static function getInstance() : ViewModelLocator {
if (instance == null) {
instance = new ViewModelLocator( new SingletonEnforcer );
}
return instance;
}
// DEFINE YOUR VARIABLES HERE
public var currentView:uint = 0;
// DEFINE VIEW CONSTANTS
}
}
// Utility Class to Deny Access to Constructor
class SingletonEnforcer {}

5.4.    Create Front Controller

Now we create a new Action Script Class named AppController and add FrontController (com.adobe.cairngorm.control.FrontController) as superclass.

This class now is empty after we will map events to related commands.

package it.plinky.control
{
import com.adobe.cairngorm.control.FrontController;
import it.plinky.commands.*;
import it.plinky.events.*;
public class AppController extends FrontController
{
public function AppController()
{
super();
initializeCommands();
}
private function initializeCommands() : void
{
// TODO
}
}
}

5.5.    Initialize MXML Application

It’s time to edit the main application file, in the project root we have a MXML  application created by
Flex Builder default, it has the same name of your project, add the following lines of code to your file.

In this example I have an AIR MXML  file, if you have created a Flex project you have to modify the tag <mx:WindowedApplication> with <mx: Application>.

<?xml version=”1.0″ encoding=”utf-8″?>
<mx:WindowedApplication xmlns:mx=”http://www.adobe.com/2006/mxml” xmlns:view=”it.plinky.view.*”
xmlns:control=”it.plinky.control.*”
xmlns:business=”it.plinky.business.*”
xmlns:model=”it.plinky.model.*”
layout=”absolute” width=”100%” height=”100%” >
<mx:Script>
<![CDATA[
import it.plinky.model.ViewModelLocator;
[Bindable]
private var modelLocator:ViewModelLocator = ViewModelLocator.getInstance();
]]>
</mx:Script>
<control:AppController id=”controller” />
<business:Services id=”services” />
<mx:ViewStack id=”vsMain” width=”100%” height=”100%” selectedIndex=”{modelLocator.currentView}”>
<!– views list TO DO –>
</mx:ViewStack>
</mx:WindowedApplication>

5.6.    Create Delegate Object and remote repository

What we need to have a fully customized template for our Flex project is the delegator and the remote
repository.

In the business folder we create to files: Delegate as Action Script Class and Services as MXML Module.

Delegate object as described before will handle the remote calls using the “configuration” in the Services
module.

In the services module you have to configure your web service by inserting the sap WSDL; if you don’t know how to get SAP WSDL see video in section 5.1.

The project, as it is, is a fully customized Cairngorm one; you can use this template as default for all of your projects.

Service module source:

<?xml version=”1.0″ encoding=”utf-8″?>
<cairngorm:ServiceLocator xmlns:mx=”http://www.adobe.com/2006/mxml” xmlns:cairngorm=”http://www.adobe.com/2006/cairngorm“>
<mx:WebService id=”sapWS” wsdl=”YOUR WSDL URL” showBusyCursor=”true” />
</cairngorm:ServiceLocator>

Delegate source:

package it.plinky.business
{
import com.adobe.cairngorm.business.ServiceLocator;
import mx.collections.ArrayCollection;
import mx.rpc.IResponder;
public class Delegate
{
private var responder : IResponder;
private var service : Object;
public function Delegate(responder : IResponder)
{
this.service = ServiceLocator.getInstance().getWebService( “sapWS“ );
this.responder = responder;
}
// Add below your remotes call
}
}

5.7.    Create Value Object

We need to create the value objects that will store values to be displayed on our views. For this example
we need only one Value Object CompanyCodeVO that extends ArrayCollection class.

This object is very simple right now and it is not in scope of this tutorial to perform any other development.
In real projects is useful to enhance this Value Object in order to be similar to a Java Bean with get and set methods for each attribute (e.g. fields of an ABAP structure).

package it.plinky.vo
{
import mx.collections.ArrayCollection;
public class CompanyCodeVO extends ArrayCollection
{
public function CompanyCodeVO(source:Array=null)
{
super(source);
}
}
}

5.8.    Create Views

For this tutorial we need two views: Welcome and CompanyList. It would be enough only one view, but I prefer to create two views in order to explain how is possible to change view with the Model Locator.

In the folder view creates two MXML Components, based on Form component, named Welcome and CompanyList.

Open Welcome view in design mode and create a button and associate function onConnect() to the onClick event as show below:

Go into source mode and insert the script section as shown below:

<?xml version=”1.0″ encoding=”utf-8″?>
<mx:Form xmlns:mx=”http://www.adobe.com/2006/mxml” width=”100%” height=”100%”>
<mx:Script>
<![CDATA[
import it.plinky.events.ConnectEvent;
private function onConnect():void
{
var event:ConnectEvent=null;
event=new ConnectEvent();
event.dispatch();
}
]]>
</mx:Script>
<mx:Canvas width=”100%” height=”100%”>
<mx:Button x=”189″ y=”181″ label=”Invoke Web Service” id=”cmdConnect” enabled=”true” click=”onConnect()”/>
</mx:Canvas>
</mx:Form>

Save and close Welcome view and now edit CompanyList view. In desing mode create a new DataGrid as shown below:

Now go into the source mode and add the script content as shown below:

<?xml version=”1.0″ encoding=”utf-8″?>
<mx:Form xmlns:mx=”http://www.adobe.com/2006/mxml” width=”100%” height=”100%”>
<mx:Script>
<![CDATA[
import it.plinky.model.ViewModelLocator;
[Bindable]
private var modelLocator:ViewModelLocator = ViewModelLocator.getInstance();
]]>
</mx:Script>
<mx:Canvas width=”100%” height=”100%”>
<mx:DataGrid x=”67″ y=”46″ dataProvider=”{modelLocator.companyList}” id=”tblCompanyCode“
width=”408″ height=”292″>
<mx:columns>
<mx:DataGridColumn headerText=”Company Code” dataField=”CompCode“/>
<mx:DataGridColumn headerText=”Company Name” dataField=”CompName“/>
</mx:columns>
</mx:DataGrid>
</mx:Canvas>
</mx:Form>

Save the view and open your Model Locator class and in the section “DEFINE VIEW CONSTANTS” insert the definition of companyList Value Object and the view switcher constants in the section “DEFINE VIEW CONSTANTS”.

// DEFINE YOUR VARIABLES HERE
public var currentView:uint = 0;
public var companyList:CompanyCodeVO = new CompanyCodeVO();
// DEFINE VIEW CONSTANTS
public static const WELCOME:uint = 0;
public staticconst COMPANY_LIST:uint = 1;

Finally in the main application MXML, SAPExample, we add these two entries in the View Stack:

<mx:ViewStack id=”vsMain” width=”100%” height=”100%”selectedIndex=”{modelLocator.currentView}”>
<!– view list –>
<view:Welcome   width=”100%” height=”100%”/>
<view:CompanyList width=”100%” height=”100%”/>
</mx:ViewStack>

Do not consider syntax errors, we are going to create missing objects in the next step.

5.9.    Register event handler and implement the business logic

We need to register event in the Front Controller and create the Command object in order to manage the business logic.

In folder event create a new Action Script Class ConnectEvent with superclass CairngormEvent.

package it.plinky.events
{
import com.adobe.cairngorm.control.CairngormEvent;
public class ConnectEvent extends CairngormEvent
{
static public var EVENT_ID:String=“connect”;
public function ConnectEvent(bubbles:Boolean=false, cancelable:Boolean=false)
{
super(EVENT_ID, bubbles, cancelable);
}
}
}

Open your Front Controller and in the function initializeCommands insert the following instruction:

privatefunction initializeCommands() : void
{
addCommand(ConnectEvent.EVENT_ID, ConnectCommand);
}

Now, our event is registered and every time event Connect is thrown framework will invoke the ConnectCommand.

In the folder commands create a new ActionScript Class named ConnectCommand; in the interface list add these interfaces: ICommand (com.adobe.cairngorm.commands.ICommand), IResponder (mx.rpc.IResponder).

package it.plinky.commands
{
import com.adobe.cairngorm.commands.ICommand;
import com.adobe.cairngorm.control.CairngormEvent;
import it.plinky.business.Delegate;
import it.plinky.events.ConnectEvent;
import it.plinky.model.ViewModelLocator;
import it.plinky.vo.CompanyCodeVO;
import mx.collections.ArrayCollection;
import mx.rpc.IResponder;
public class ConnectCommand implements ICommand, IResponder
{
public var modelLocator:ViewModelLocator = ViewModelLocator.getInstance();
public function execute(event:CairngormEvent):void
{
getCompanyList(event as ConnectEvent);
}
private function getCompanyList (event:ConnectEvent): void
{
var e : ConnectEvent = event as ConnectEvent;
var delegate:Delegate = new Delegate ( this );
delegate.getCompanyList();
}
public function result( event : Object ) : void
{
var viewModelLocator:ViewModelLocator;
viewModelLocator = ViewModelLocator.getInstance();
viewModelLocator.companyList = CompanyCodeVO(event.result. CompanycodeList.toArray());
modelLocator.currentView = ViewModelLocator.COMPANY_LIST;
}
public function fault( event : Object ) : void
{
throw( new Error(event.message.toString()));
}
}
}

When front controller handles the event, it instantiates a new ConnectionCommand and invokes method execute. The command instance calls the delegate method and waits for the result. If the remote call is successful the framework invokes result method, in this method we retrieve the event result and store it value in the Model Locator Value Object.

The last step is to implement the remote call in the Delegate class; open this file and add this
function:

publicfunction getCompanyList():void {
var call : Object = service.CompanycodeGetlist(new ArrayCollection());
call.addResponder(responder);
}

In order to be sure to call the right method, you can get the remote function name looking into the WSDL definition.

6. Happy ending

We are ready to execute our application. Before you start you have to be sure that the crossdomain.xml is
accessible on the root of your application server. More information are available on this blog Add
crossdomain.xml on the root of SAP Web application server
.

Now your flex application using Cairngorm framework is ready!

1 Comment