SAP Web Services in Flex Builder

SAP web services are really complex, tables inside rows inside tables inside structures.  I’ve been fielding an increasing number of questions about using these in the forum so, instead of answering everyone separately here are a few examples from simple to complex.

Let’s start off with one of the simpler examples just to get the hang of it.  Use SAPLink and install this function group and generate a web service from the one function in it.  Now, lets write some Flex code to call this.

Import Statements

A few people have asked me to add the import statements to this.  For reference if you go to the object that has the error, move your cursor to the end of the word hold control and press space the import will be added for you automatically, welcome to the wonderful world of a good IDE.  But the following in a <mx:Script> block between the <mx:Application> tags.

import mx.rpc.AbstractOperation; import mx.rpc.events.FaultEvent; import mx.rpc.events.ResultEvent; import mx.rpc.soap.LoadEvent; import mx.rpc.soap.WebService;

Simplest Example

Step 1 - Get your WSDL

1 private function callWebService():void{ 2 fooService = new WebService(); 3 fooService.wsdl = "http://localhost/sap/bc/srt/rfc/sap/Z_TEST_CHANGING_PARAM?sap-client=300&wsdl=1.1"; 4 fooService.addEventListener(LoadEvent.LOAD, loadListener); 5 fooService.addEventListener(ResultEvent.RESULT, resultTrigger); 6 fooService.addEventListener(FaultEvent.FAULT,fault); 7 fooService.loadWSDL(); 8 }

Line by Line:

  1. Declare a function that will start the whole process
  2. Create a WebService object, this should be global or at least visible to the other methods ( you’ll need it later )
  3. Point the WS to the location of the WSDL
  4. Add an EventListener for when the Loading of the WSDL is complete
  5. Add an EventListener for the results coming back from the call
  6. Add an EventListener for any errors that occur
  7. Tell the WS to load the WSDL

Step 2 - Set Some Parameters

1 private function loadListener(event:LoadEvent):void{ 2 var op:AbstractOperation = fooService.getOperation("Z_DOUBLE_ROWS"); 3 var input:Object = new Object(); 4 input.TEST = new Array(); 5 input.TEST.push("foo"); 6 input.TEST.push("bar"); 7 op.arguments = input; 8 op.send(); 9 }

Line by Line:

  1. Declare a function who handles the event you subscribed to in the Step 1 line 4.
  2. Get the Operation from the WSDL file.  This is one of those “standard” ways of doing things.  If you look at your WSDL file you will see that it could have more then one operation in it, this gets the particular operation you want to call.
  3. Create a dynamic object that will hold the inbound parameters to your WS.  In this case the parameter TEST is a table of strings.
  4. Here we create what Flex builder thinks is how to hold  a table, an Array.
  5. Then we push each “row” of the table into the array again, in this case it’s just one string at a time.
  6. See Line 5
  7. We then map the input object to the arguments of the WS.
  8. Send our request including all the input data to the server

Step 3 - Look at the Output

1 private function resultTrigger(event:ResultEvent):void{ 2 var item:String; 3 for each(item in event.result){ 4 trace(item); 5 } 6 }

Line by Line

  1. Define a function to handle the event from section 1 line 5
  2. Declare on object to hold each result
  3. Loop at each item in the result list, which happen to be strings.
  4. Print them out to the debug console

I will talk about more advanced parsing of the result set later on.

Inbound Table Parameter

First, get your WSDL, in this case I will be using the FM BAPI_FLIGHT_GETLIST from the SFLIGHTS example we are all so fond of.  You should run this FM a few times to make sure you have data on the ABAP side, I will be passing in a date range to this FM so, you might want to find two dates that return some data for you. ( I named my WebService “Z_GET_FLIGHT_LIST” )

Step 1 - Get Your WSDL

This is the same exact thing you did before, just with a different WSDL.

Step 2 - Set some Parameters

There is a strange behavior with ABAP WebServices where if you have a table that is both Input and Output you must pass it as part request to get it filled.  You’ll see in a second:

1 private function loadListener(event:LoadEvent):void{ 2 var op:AbstractOperation = fooService.getOperation("BAPI_FLIGHT_GETLIST"); 3 var input:Object = new Object(); 4 input.FLIGHT_LIST = new Array(); 5 input.RETURN = new Array(); 6 op.arguments = input; 7 op.send(); 8 }

Line by Line

  1. Define a function that handles the event
  2. Get the right operation
  3. Dynamic input object
  4. You have to pass blank parameters to the WS so that the Web Application Server will fill them
  5. See line 4
  6. Same as last time
  7. Same here

Set Table Parameters

1 var dateRangeRow:Object = new Object(); 2 input.DATE_RANGE = new Array(); 3 dateRangeRow.SIGN = "I"; 4 dateRangeRow.OPTION = "EQ"; 5 dateRangeRow.LOW = "2002-12-20"; 6 dateRangeRow.HIGH = ""; 7 input.DATE_RANGE.push(dateRangeRow);

Line by Line ( add this between lines 5 and 6 from the prior example )

  1. Create a new dynamic object that holds a Row of the DATE_RANGE table
  2. Create an array called DATE_RANGE which will map to the DATE_RANGE input parameter
  3. Set each field dynamically
  4. More fields
  5. More fields
  6. More fields ( don’t need to pass this one because it’s blank )
  7. Push this row into the array

Step 3 - Look at the Output

1 private function resultTrigger(event:ResultEvent):void{ 2 var row:Object; 3 for each (row in event.result.FLIGHT_LIST){ 4 trace(row.AIRLINE + " " + row.CITYFROM); 5 } 6 }

Line by Line

  1. Function, again.
  2. Use a place holder dynamic object
  3. Loop at the table called FLIGHT_LIST ( looks like ABAP doesn’t it? )
  4. Print to the console the fields you want ( looks like ABAP doesn’t it? )

Disclaimer: There are a number of ways to call WebServices in Flex, I believe this is the most complete and “standard” way to call them, if not someone please point me to Adobe docs that show the most correct way.

8 Responses to “SAP Web Services in Flex Builder”

  1. Craig Cmehil Says:

    Sweet and perfect timing for Bangalore! Thanks!

  2. Durairaj Athavan Raja Says:

    Thanks for the excellent blog.

  3. Durairaj Athavan Raja Says:

    Hi Dan,

    I we look at the soap request of BAPI_FLIGHT_GETLIST ws, the date range variable name in the wsdl is DateRange whereas the same is DATE_RANGE in Function module definition. However you have used DATE_RAGE in your sample above. Is this the way it is supposed to be used?

    Regards
    Raja

  4. dan Says:

    Raja -
    I tested all this code on a Discovery system I have access to. I guess the ABAP stack alters naming conventions depending on the version. I will update the blog entry to show the WSDL and where to look for the variable names instead. I assumed ( incorrectly ) that the ABAP stack would be consistent about it’s naming. Thanks for the correction.

  5. Durairaj Athavan Raja Says:

    Dan,

    Just found out the cause. during webservice creation , if you choose the check box for name mapping then you dont get the parameter name same as the abap field name. (in this option DATE_RANGE will be DateRange in wsdl)

    if you uncheck the check box for name mapping then you get the same name as ABAP field name (in this option DATE_RANGE is referred as DATE_RANGE in wsdl as well)

    Regards
    Raja

  6. Parag Bhise Says:

    Hi Dan,
    Great job Done …I am trying out this .I know basic of flex and I started with that recently .I am ABAPer actully . Now when I was trying out calling SAP web Service in Flex I was bit confused .
    1. Are there two ways two call web service
    Way1 .

    Thats using mx:web service tag

    way 2. which u have given ..Taking Web serive object and all ..If I am not wrong we will do it in CDATA ….If so Do we need to import some packages …Because in my case in Step 1 only its showing error .
    If we need to import some package ,if yes which are those .

    You have given SAPLink and some link to FunctionGroup ..But what it does ..I am not able to correlate what should done on ABAP side …
    Can we come with something involving things should be done on both side .

  7. shaira Says:

    Hey can u jus guide me as to how i can integrate SAP xMII with Adobe Flex for designing UIs.

    Cheers,
    Shaira

  8. dan Says:

    @parag: Yes there are two ways to call webservices in Flex. With MXML tags and this way the more “actionscript” way. I prefer this way as it is more programmer focused.

    I have added the imports to each section, although just going to the object that is unknown, moving your cursor to the end of it and holding down the control key while pressing space will add the import for you.

    Please go read up on SAPlink here http://www.saplink.org.

    @shaira:
    No, I can’t and won’t guide you, Flex consumes web services it doesn’t care at all about how those services are exposed. I have included the ABAP stuff here just to make it easy for everyone to get started. xMII is a cross app and therefore probably already has services exposed. Front-ending it with Flex should be just like calling the ABAP WebServices shown here.

Leave a Reply