Skip to Content
SAP Gateway

SAP NetWeaver Gateway - SOAP and OData Services

Tags:

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.

When I Google the terms ‘wsdl’ and ‘weather’, one of the first results is this service: http://wsf.cdyne.com/WeatherWS/Weather.asmx?WSDL. The example below should work for other services in the same way.

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.

The field ‘ZIP’ has to be defined as a ‘Key’ field in the usage column. This is all I have to do in the Service Builder. I can now save the project and the system generates the empty classes for my own implementation.

One of the generated classes is called xyz_DPC_EXT. This is the extension class that was generated by the Service Builder. Now, even if the OData model definition in the Service Builder is updated and the project re-generated, this extension class will not be overwritten.



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.

That’s it – everything should now be up and running!

Testing


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.

Appendix

METHOD /iwbep/if_mgw_appl_srv_runtime~get_entity.



 
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.



 
CASE iv_entity_name.
************************************************************

   
WHEN 'Weather'.
* 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

       
EXPORTING

          logical_port_name
= 'TESTLOGICALPORT'.

     
TRY.
*         call method

         
CALL METHOD z_cl_weather->get_city_weather_by_zip

           
EXPORTING

             
input  = l_input

           
IMPORTING

             
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.


*       Errors?

       
CATCH cx_ai_system_fault INTO lo_sys_exception.

       
CATCH cx_ai_application_fault .

     
ENDTRY.


* fill the OData structure and return

      copy_data_to_ref
(

         
EXPORTING

            is_data
= l_return

         
CHANGING

            cr_data
= er_entity

       
).



 
ENDCASE.
ENDMETHOD.