Experiences with SAP Gateway

"My foots always in my mouth i just can't stomach defeet" – Hilltop Hoods

Posts Tagged ‘ODATA

Working with OData Dates and Times

leave a comment »

When consuming Gateway services in JavaScript the task of working with dates and times is made even harder because of the different representations the objects take. In this blog I will highlight how Gateway OData dates and times are represented in both JSON and JavaScript and show by example how to use these values in SAPUI5 with the JavaScript Date Object and the Class sap.ui.core.format.DateFormat.

TLDR: You can use sap.ui.core.format.DateFormat to format and parse date and time objects when working with Gateway services, see http://jsbin.com/irewuq/9/edit for an example.

Below is the formatted JSON representation of Gateway Entity, similar to what you get using the Flight Service in the Demo Gateway system. eg http://gw.esworkplace.sap.com/sap/opu/odata/IWBEP/RMTSAMPLEFLIGHT_2/FlightCollection?$format=json


Highlighted below are Date and Time passed in this service

"FlightDate": "/Date(1354665600000)/",  - JSON Date Object
"DepartureTime": "PT11H00M00S", - XSD Duration

FlightDate is represented as a JSON Date object, the value is the date in milliseconds since Unix Epoch.

Unix EPOCH time = Date(0) = Thu Jan 01 1970 00:00:00 GMT, this value is handy to know if your going to work with dates. http://en.wikipedia.org/wiki/Unix_time

DepartureTime is represented as an XSD:Duration Date Type

The letters in PT11H00M00 – P: Period, T: Time, H: Hours, M: Minutes see http://www.w3schools.com/schema/schema_dtypes_date.asp

Luckily if you use the ODataModel, datajs the OData library SAPUI5 uses has regular expressions and code logic which parses these values into JavaScript for us. Below is how this Entity looks parsed to JavaScript.

ODataModel values highlighted
FlightDate : Wed Dec 05 2012 11:00:00 GMT+1100 (AUS Eastern Daylight Time)
DepartureTime : { __edmtype: "Edm.Time", ms: 39600000}

FlightDate looks like a string, it is in fact the string representation of a JavaScript Date Object

The JavaScript Date Object supports the following ways for instantiating a date, if you are in the AEDT timezone then the following values will be equal.

var a = new Date('Wed Dec 05 2012 11:00:00 GMT+1100 (AUS Eastern Daylight Time)');
var b = new Date(1354665600000);
var c = new Date('2012/12/05');
a.getTime()===b.getTime()&& a.getTime()===c.getTime()

date.getTime() returns the number of milliseconds since Epoch.

Important to note is the Timezone offset when comparing dates, was +1100 AEDT in December, today its +1000 due to daylight savings.

new Date( )  = Sun Apr 28 2013 14:05:52 GMT+1000 (AUS Eastern Standard Time)
To get a consistent Timezone offset use the one from Epoch

var TimezoneOffset = new Date(0).getTimezoneOffset(); // -660 minutes
DepartureTime is a millisecond value wrapped in a edmtype object.

39600000/3600000 = 11 hours 00 min  // 3600000 is the number of milliseconds in an hour 60 minutes *60 seconds *1000 milliseconds

We can use the value in a javascript date object and it will give us the time since Epoch

new Date(39600000).toUTCString() = Thu, 01 Jan 1970 11:00:00 GMT
new Date(39600000).getUTCHours() = 11

SAPUI5 provides the Class sap.ui.core.format.DateFormat that can be used with JavaScript Date Objects for formatting and parsing dates and times.

The example i’ll give is formatting dates and times to formats you may want to use in a mobile application. eg
date1 time1
There is not much to it if you handle everything in UTC milliseconds, to do this we add the timezone offset when formatting and remove it when parsing.


*Note to SAPUI5 developers DateFormat.format has a to UTC flag, DateFormat.parse could use a from UTC flag.

The following is a list of the pattern elements in the DateFormat class, use them to derive the date and time formats you need.
I have shown you the JSON and JavaScript representations Gateway services have for date and time, given an overview of how to use some of the functions of the JavaScript Date Object, shown an example of how I use the sap.ui.core.format.DateFormat Class to format values for a mobile application which integrates with Gateway services. All that’s left is to share working code http://jsbin.com/irewuq/9/edit.

Written by rsol1

April 28, 2013 at 7:36 am

Posted in Uncategorized

Tagged with , , ,

Gateway Batch Calls from SAPUI5

leave a comment »

One of the features available with the latest release of the UI Development Toolkit for HTML5 (1.8.4) is the ability to batch multiple OData operations into a single call.

I thought I would share a quick example of how its done.

Below is a code snippet showing how to batch the creation of multiple Contact entities and POST them to SAP Netweaver Gateway. The code is part of a simple applications which displays Contacts retrieved from a Gateway OData call in a Table Control. The application has a button ‘Batch Save’, when the button is pressed the function below is called, on completion of the $Batch operation the Table Control shows the new Contact Entities.  The code also shows how easy it is to deep insert a second entity (CREATE_DEEP_ENTITY), Contact_Status represents a separate Entity which has a many to one relationship with the Contact entity.


Here is the HTTP Request, multiple operations wrapped up in a single Multipart MIME message.


And the results of the Gateway callback.

contact_list (1)


Written by rsol1

November 18, 2012 at 6:37 am

Posted in Uncategorized

Tagged with , , , , ,

SAP Netweaver Gateway Client

leave a comment »

I have been using the SAP NetWeaver Gateway 2.0 SP4 Pre-Packaged Trial Version for Linux for a couple of weeks now and one of the things I really like is the SAP Netweaver Gateway Client (trx /IWFND/GW_CLIENT). Very similar in features to the Firefox RESTClient, it allows you to create custom HTTP requests and directly test requests against a Gateway server and this is done within the SAPGui.

The thing that i like the most is the ability to create and re-use Test Cases.

As the SAP Help suggests, it enhances the Error Log

While the Error Log provides you with an overview of detailed context information about errors that have occurred at runtime and enables you to navigate easily to the affected source code, the Gateway Client allows you to reproduce the exact runtime situation that led to a particular error.

In the Error Log (trx /IWFND/ERROR_LOG) you can replay requests in either the Gateway Client or Web Browser.

Written by rsol1

September 19, 2012 at 6:40 am

Posted in Uncategorized

Tagged with , , , ,

Nested Views in SAPUI5 MVC

leave a comment »

Last month Steffen Schwark wrote a good blog on Structuring an SAPUI5 application with MVC, his blog inspired me to port a SAPUI5 application I had been working on to use MVC. I thought I would share the code here on SCN in the hope that others will do likewise and share their experiences.

The code for the application is available on Code Exchange or here as a zip. Follow the simple installation instructions below, when you run it should look something like the pics below.



Application Structure

The application has three main views

  • a customers view with master details and a google map, this view has 3 nested views, one of each type (xml, js and json)
  • a products view with master details filtered by categories
  • a shell view which houses the customers and products views

Each of the main views has its own controller, the customers and products views present data from OData Models.


Installing The Application

I developed the application locally using the IIS (Internet Information Services/Server) web server on my laptop. IIS is very easy to use

GOTO Control Panel\All Control Panel Items\Administrative Tools\Internet Information Service (IIS) Manager

Right click the PC -> Start, you have a webserver running locally

Follow Getting Started with SAPUI5 Installing the SAPUI5 SDK on Visual Studio 2010, the steps are very similar for IIS

Unpack or deploy the source to a folder name ‘nested’ and add as a website like step above

You should now be able to access the application using http://localhost/nested/


My original application had grown into a big ball of mud, all the javascript code was in a single file and it had become very hard to manage. By separating the concerns of my application into small pieces and following the MVC paradigm, the code is now a lot more flexible, easier to test, reuse and build upon.

I am very interested in hearing from others, please download and run the code and get back to me with any comments and suggestions. One thing I would like to hear from those more learned is in how best to implement MV* with SAPUI5, whether it is better to follow MVC, MVP or MVVM.

* The images included in the application were sourced using the Creative Commons search engines.

Written by rsol1

June 24, 2012 at 7:46 am

Posted in Uncategorized

Tagged with , , ,

How to: Windows 8 and OData Services in a Metro Style Application

leave a comment »

A couple of people have requested that I share how I created my Metro App.

The services I used were created on my SAP Netweaver Gateway system, I have recreated the application to use the ODATA.org Northwind service and use images from the Telerik demo site.

As I said in the original post I used the following  blog as a guideline, recreating the application I found there were a couple of notable differences so I will start from the beginning.

I downloaded Windows 8 Consumer Preview ISO image and then installed it as a WMWare Workstation, then I Installed Visual Studio 11 Premium edition.

Once installed and activated inside VS11  Click File –> Add New Project. Select the Split Application template under JavaScript -> Windows Metro style.

Then install the datajs package, Tools -> Library Package Manager -> Package Manager Console. Type ‘install-package datajs’.

I didn’t install the jquery package

Inside of default.html add a reference to datajs, I found I needed to add it before other references, there are dependencies in data.js to the sequence.

Next create the data.js code. I kept it simple and retained a lot of the code from the template.

In splitPage.html added some of the additional fields

 <h2 class="article-title win-type-ellipsis" data-win-bind="textContent: title"></h2>
 <h3 class="article-subtitle" data-win-bind="textContent: qty">
 <h3 class="article-subtitle" data-win-bind="textContent: price">

And that’s about it.

To get datajs working in Windows 8 with Netweaver Gateway XML OData services I had to make the following change to return window.DOMParser() instead of the ActiveXObject

The end result should look something like this


Written by rsol1

May 20, 2012 at 12:08 pm

SAPUI5 Gateway and Google Maps

leave a comment »

Lately I have been using the Google Maps API in an Android App I have been working on, thought I would see how easy it was to get the javascript API working with SAPUI5.

Turns out it was a lot easier than I expected, I was able to easily reuse some of the code java code.

Once again I have shared an example on google code, I have extended the Master Slave example with a simple Google Map (see pic below)

For those interested in the Android app

Written by rsol1

May 19, 2012 at 11:35 am

Windows 8 Metro Style Apps and Gateway

leave a comment »

Unfortunately I will have to keep this post brief.  Below are some screen shots from my first Windows 8 Metro Style Application consuming SAP Netweaver Gateway data.

At present there are not many examples of how to consume OData in a Metro Style application, even harder to find an example using javascript.

I used the following blog as a guideline


Once I got started it was actually very easy.

I did however have a slight problem getting Datajs to parse Xml, for which I luckily found a simple work around.

My mind isn’t completely made up about Windows 8 development, I think I will have to code a couple more applications first, I will say it is a completely different experience to the other tools and platforms I have been developing on lately, it is very familiar and very simple, which kind of scares me.

Useful Resources:

Writing code for Metro style apps (JavaScript): http://msdn.microsoft.com/en-US/library/windows/apps/hh770842

Data Model: http://msdn.microsoft.com/en-us/library/windows/apps/hh758329.aspx

Asynchronous programming in JavaScript: http://msdn.microsoft.com/en-US/library/windows/apps/hh700330

Debugging apps: http://msdn.microsoft.com/en-US/library/windows/apps/hh441474

Written by rsol1

May 7, 2012 at 12:43 pm

Using Gateway data in Excel 2010 PowerPivot

with one comment

I thought I would quickly show how to use PowerPivot in Excel with data from SAP Netweaver Gateway.

PowerPivot is a free add-in to the 2010 version of the spreadsheet application Microsoft Excel. It extends the capabilities of the PivotTable data summarisation and cross-tabulation feature by introducing the ability to import data from multiple sources. As such, PowerPivot falls under Microsoft’s Business Intelligence offering, complementing it with its self-service, in-memory capabilities [http://en.wikipedia.org/wiki/PowerPivot]

To start with you need to download and install the PowerPivot add-in, you can find it at http://www.microsoft.com/en-us/bi/powerpivot.aspx

Once installed, open up Excel and click PowerPivot tab then PowerPivot Window.

Choose Get External Data -> From Data Feeds

Enter the connection details

Press Advanced button to enter authentication details

Select and import the tables you want to use

Then Create Relationships between the tables

Select PivotTable -> Chart and Table (Horizontal)

From there you can drag the fields you want for the axis and values, in this example Products by count of Orders

This shows how simple it is to start, now you can go further and add slicers and filters etc. or add data from other sources.

Written by rsol1

April 13, 2012 at 1:27 pm

Posted in Uncategorized

Tagged with , , , , ,

SAPUI5 data binding master slave with Gateway services

with 6 comments

Spent the day trying out the SAPUI5 framework, of all the new products and initiatives I saw at SAP TechEd last year, this library (collection) sparked my interest the most, mainly because over the years I have used reluctantly JQuery, DOJO, Prototype, YUI, ExtJS etc. on SAP projects, now there is something supported by SAP I can imagine a lot of that reluctance will disappear .

There is a lot in SAPUI5,  it will take me some time to get familiar and comfortable enough to start using on customer sites, I hope they don’t stop here and there is a lot more features and functionality to come. My first impressions are very positive, for some reason the data binding takes me back to a time before WD4A and after HTMLB, reminding me of the flexibility and freedom of BSP or an early WD4J.

It seems appropriate the first thing I developed with SAPUI5 was a data binding master slave solution, it was the first thing I learnt with WD4J and WD4A , it gives a good perspective of what is possible, next up will be MVC.

I have shared on google code a simple example of master slave data binding, it uses the ODATA.org Northwind service (see pic below) , I got it working with an association, but I also show in the code how it is possible using filters.

Written by rsol1

February 16, 2012 at 3:32 pm

Posted in Uncategorized

Tagged with , , , ,

Filter String How To

leave a comment »

Today I was asked during a demo to share how I use IV_FILTER_STRING and get round the Filter String Gotcha.

To start with the following code is not optimized and should be used for reference purposes only, for example it uses string values, not types and the select should use an index key select first before getting results.

I use a Paging Query Provider (see image below), it has a method SET_FILTER_STR which converts the provided IV_FILTER_STRING into a table of Filter String Select Options, these values are then passed to a method SET_WHERE_FILTER which is used to assign filter select options to one of 10 available range tables.

The range tables are then used to create a WHERE clause for a generic SQL SELECT statement which looks similar to below.

SELECT ( m_fields )
UP TO ( m_up_to )
INTO  TABLE et_results
FROM ( m_table )
WHERE ( m_where_str )
ORDER BY ( m_order_str )

The Code for the filter string conversion looks something like –

* <SIGNATURE>---------------------------------------------------------------------------------------+
 * +-------------------------------------------------------------------------------------------------+
 * | [--->] IV_FILTER_STRING               TYPE        STRING
 * +--------------------------------------------------------------------------------------</SIGNATURE>
 METHOD zif_gwpagingquery~set_filter_str.

     lt_filter_select_options TYPE /iwbep/t_mgw_select_option,
     lt_filter_string TYPE TABLE OF string,
     lt_key_value TYPE /iwbep/t_mgw_name_value_pair,
     ls_filter_string TYPE string,
     lv_input TYPE string,
     lv_name TYPE string,
     lv_value TYPE string.

     co_substringof TYPE string VALUE 'substringof(',
     co_startswith TYPE string VALUE 'startswith(',
     co_endswith TYPE string VALUE 'endswith('.

     <fs_range_tab> LIKE LINE OF lt_filter_select_options ,
     <fs_select_option> TYPE /iwbep/s_cod_select_option,
     <fs_key_value> LIKE LINE OF lt_key_value.

   lv_input = iv_filter_string.

 *--- get rid of ) & ' and make AND's uppercase
   SPLIT lv_input AT 'AND' INTO TABLE lt_filter_string.

 *--- build a table of key value pairs based on filter string
   LOOP AT lt_filter_string INTO ls_filter_string.
     APPEND INITIAL LINE TO lt_key_value ASSIGNING <fs_key_value>.

     IF ls_filter_string CS co_substringof.
       ls_filter_string = substring_after( val = ls_filter_string sub = co_substringof ).
       CONDENSE ls_filter_string.
       SPLIT ls_filter_string AT ',' INTO lv_value lv_name.
       <fs_key_value>-value = |*{ lv_value }*|.
     ELSEIF ls_filter_string CS co_startswith.
       ls_filter_string = substring_after( val = ls_filter_string sub = co_startswith ).
       CONDENSE ls_filter_string.
       SPLIT ls_filter_string AT ',' INTO lv_name lv_value.
       <fs_key_value>-value = |{ lv_value }*|.
     ELSEIF ls_filter_string CS co_endswith.
       ls_filter_string = substring_after( val = ls_filter_string sub = co_endswith ).
       CONDENSE ls_filter_string.
       SPLIT ls_filter_string AT ',' INTO lv_name lv_value.
       <fs_key_value>-value = |*{ lv_value }|.
       CONDENSE ls_filter_string.
       SPLIT ls_filter_string AT ' EQ ' INTO lv_name lv_value.
       <fs_key_value>-value = |{ lv_value }|.
     <fs_key_value>-name = to_upper( lv_name ).

 *--- add key value pairs to filter select options
   LOOP AT lt_key_value ASSIGNING <fs_key_value>.
     APPEND INITIAL LINE TO lt_filter_select_options ASSIGNING <fs_range_tab>.
     <fs_range_tab>-property = <fs_key_value>-name.
     APPEND INITIAL LINE TO <fs_range_tab>-select_options ASSIGNING <fs_select_option>.
     <fs_select_option>-sign = 'I'.
     IF <fs_key_value>-value CS '*'.
       <fs_select_option>-option = 'CP'.
       <fs_select_option>-option = 'EQ'.
     <fs_select_option>-low = <fs_key_value>-value.
 *--- call method that create where string for filter select options
   me->set_where_filter( lt_filter_select_options ).
 * <SIGNATURE>---------------------------------------------------------------------------------------+
 * +-------------------------------------------------------------------------------------------------+
 * +--------------------------------------------------------------------------------------</SIGNATURE>
 METHOD zif_gwpagingquery~set_where_filter.

     lv_property TYPE string,
     lv_range_name TYPE string.

     <fs_filter_select_option> LIKE LINE OF it_filter_select_options,
     <fs_range> TYPE /iwbep/t_cod_select_options.

   LOOP AT it_filter_select_options ASSIGNING <fs_filter_select_option>.
     ADD 1 TO m_range_tabix. "Assumption max 10 filters
     lv_range_name = |MRA_RANGE{ m_range_tabix }|.

     ASSIGN (lv_range_name) TO <fs_range>.
     <fs_range> = <fs_filter_select_option>-select_options.

     lv_property = to_upper(<fs_filter_select_option>-property).
     "build where string
     IF m_where_str IS NOT INITIAL.
       m_where_str = |{ m_where_str } AND |.

     m_where_str = |{ m_where_str }{ lv_property } IN { lv_range_name }|.


At runtime.

The result.

Written by rsol1

January 25, 2012 at 2:35 pm

Posted in Uncategorized

Tagged with , , , , ,