SAP NetWeaver Gateway - SOAP and OData Services
Why is this relevant?
From time to time I see questions posted here in SCN or I receive questions via mail asking how SAP NetWeaver Gateway can help translate an existing SOAP service coming from a remote location into OData for usage in user-centric scenarios. In this blog I would like to demonstrate one possible solution using a very simple scenario.
If the required data is already exposed via OData (either from an SAP or non-SAP system - http://www.odata.org/ecosystem/#1) then SAP NetWeaver Gateway could access this OData source directly using the OData Services Consumption and Integration http://scn.sap.com/docs/DOC-47366 . However, also SOAP is still a widely-used protocol, so there should be an easy way to also connect to these data sources.
Let us assume I want to build a user interface showing the current weather details in e.g. HTML5 via SAP UI5 or a mobile User Interface using the SAP NetWeaver Gateway Productivity Accelerator https://tools.hana.ondemand.com/#gateway (SAP NetWeaver Gateway Productivity Accelerator for Microsoft http://scn.sap.com/community/netweaver-gateway/blog/2013/10/21/introducing-sap-netweaver-gateway-productivity-accelerator-for-microsoft - GWPAM – is now also available) based on OData. In this blog the data source is a service in the internet.
Generating the proxies
As this is a simplified example I am not covering the aspects of authentication or writing to a SOAP service.
The SAP Application-Server ABAP provides support for consuming SOAP services by generating ABAP interfaces and classes, which are acting as proxy for the remote service http://help.sap.com/saphelp_erp60_sp/helpdata/en/81/845f3c31727d59e10000000a114084/content.htm .
You can start this function in transaction SPROXY. A wizard guides you through the process and asks various questions. In this example we would like to create the proxy as a Service Consumer based on an external WSDL from a URL. In this example, I would like to generate the code as a Local Object
with the prefix ZMB_. As a port type I select here ‘WeatherSoap’. After saving and activating, this part is completed. The SOAP service is now wrapped in a normal ABAP class.
In the ABAP Workbench or in transaction SPROXY, I can now display the new service. From here, it is also possible to navigate directly to the SOA-Manager. This SOA-Manager will then be launched in a Web browser.
In the SOA-Manager on the Configurations-tab, you have to verify, that a ‘logical port’ is maintained. Please also note down the name of the logical port from your system as you will need this later. Here, additional settings such as the proxy server can be defined. This will be important when you want to connect to the external SOAP service.
Back in the ABAP proxy display, we can now test the proxy. The ‘logical port’ from the SOA Manager is here required to start the test application.
On the test screen, ‘String 1’ is now displayed as the ZIP-code. Of course there is no such town with this ZIP code – however, by downloading the XML to the desktop, changing it to an existing ZIP code, and uploading it back to the test workbench, I can now test whether it works.
In my example, I entered the ZIP code ‘94304’, which is the ZIP code for Palo Alto. If everything is configured correctly, we can now see in the test application the result retrieved by the SOAP service.
Developing the OData Service
Now that we have functioning ABAP classes, the rest of the exercise is ‘business as usual’ for SAP NetWeaver Gateway.
I am now creating a structure in the data dictionary with the required input and output fields as none of the generated fields had both input and output fields in one structure. Here, I use one of the structures as a template, remove fields that I do not need, and add the ‘ZIP’ field.
Now in the Service Builder, I create a new project for my new OData service and import the DDIC structure that I have just created.
In this very simple scenario, I am only implementing the get_entity class. This means that I will only be able to call the service using an available ZIP code. Other OData features like getting lists or querying will not be implemented in this scenario. The code is available in the appendix of this blog. Once I have saved and activated the implementation, I can then register and maintain the service – just like for any other Gateway service as well.
You can use the Gateway Client to test the service directly. For example, I can view the $metadata. This displays the available attributes of the OData service.
When I now call the OData service using the ZIP code ‘94304’ for Palo Alto and, in addition, I would like to receive the answer in JSON and not in XML, I just need to enter this URL either in the Gateway Client application or in a browser: …/sap/opu/odata/sap/Z_WEATHER_1_SRV/WeatherCollection('94304')?$format=json
This OData service can now be used easily in various User Interface technologies as mentioned above just as if it were coming directly from the SAP system.
DATA: z_cl_weather TYPE REF TO zmb_co_weather_soap.
DATA: l_input TYPE zmb_get_city_weather_by_zipso1,
l_output TYPE zmb_get_city_weather_by_zipsoa,
l_return TYPE zmb_weather_soap,
lo_sys_exception TYPE REF TO cx_ai_system_fault,
ls_key_tab TYPE /iwbep/s_mgw_name_value_pair.
* Find and assign Key
READ TABLE it_key_tab INTO ls_key_tab WITH KEY name = 'Zip'.
CHECK sy-subrc IS INITIAL.
MOVE: ls_key_tab-value TO l_input-zip.
* instantiate Weather object
CREATE OBJECT z_cl_weather
logical_port_name = 'TESTLOGICALPORT'.
* call method
CALL METHOD z_cl_weather->get_city_weather_by_zip
input = l_input
output = l_output.
* move the result to the transfer structure
MOVE-CORRESPONDING l_output-get_city_weather_by_zipresult TO l_return.
MOVE: l_input-zip TO l_return-zip.
CATCH cx_ai_system_fault INTO lo_sys_exception.
CATCH cx_ai_application_fault .
* fill the OData structure and return
is_data = l_return
cr_data = er_entity