Wednesday, January 16, 2013

Using client proxies in ABAP coding

Last week I posted an article about how to import WSDL files (WebService Definitions) into SAP.
This was done in SE80  ->edit object -> Tab ‘Enterprise Services’ -> Client Proxy.

The result is a generated proxyclass. Today we are going to take a look at this proxy class and see how this can be used in ABAP coding, resulting in calling the functions from the webservice.

Proxy definition

The easiest way to look at the proxy from an abap viewpoint is to open the client proxy definition in SE80, and looking at the tab 'Internal View'. This shows the definition from the SAP side of the webservice. As mentioned in the previous post, importing the WSDL in SAP results in the generation of a class with methods similar to the functions of the webservice. Also, data structures will be generated needed for the webservice to function.

If we look at the 'OrderService' as an example, we can see the proxy class name in the top of the hierarchy. This class contains methods similar to the methods in the WSDL.


Calling the webservice in ABAP

In order to call the webservice from ABAP, you just need create the class and call the method. There is one more thing you need to do concerning the 'logical port', but I will explain this later.
For you readers who are not familiar with object oriented abap, I will add some example code to instantiate the class and call the method. You will notice that I have also added the catching of an exception. If the WSDL is properly programmed, the proxyclass should also contain an exception class. You can use this class to retrieve any errors in case problems occur in the called system.

* Defining the object
DATAlr_orderservice TYPE REF TO <your proxy class>,
      lr_exception TYPE REF TO <your exception class>.

* Defining the communication structures
DATAls_create_order_request  TYPE <the request structure of the method>,
      ls_create_order_response TYPE <the response structure of your method>,

* Creating the object
      CREATE OBJECT lr_orderservice
          logical_port_name '<your logical port>'.

* Calling the method
            CALL METHOD lr_orderservice->create_order
          create_order_request  ls_create_order_request
          create_order_response ls_create_order_response.

* Catching exceptions
    CATCH <your exception class> INTO lr_exception.

In the example coding, the data that is transferred to the webservice is contained in the ls_create_order_request. Of course, to make the interface work, you should make sure that the data structure inside this filled properly. In some cases, the WSDL will help you by telling that some fields are obligatory, but not always. Also, the syntax check does not help you on this. Make sure you have the webservice documentation at hand.

Logical Ports

In the example code, when instantiating the proxy class, I mention exporting the logical port. The logical port determines the place where the webservice is called. Basically, this would be the URL and port from the WSDL.

The logical port is key in the functioning of the webservice, and is maintained in the soamanager.
For those of you not familiar with the SOAManager (SOA being Service Oriented Architecture), soamanager is a webdynpro application that can be started using transaction SOAMANAGER. Note that a webbrowser session will be started. Welcome to SOAMANAGER.

In SOAMANAGER, go to tab 'Application and Scenario Communication', option 'Single Service Administration'.
Here, select the option 'Consumer Proxy' and search for your client proxy. Note that the third field allows you to also search on 'both names'. This might make it easier.
Select the line of your webservice and click the 'Apply Selection' button.
Below the search results, an extra screen will appear. In the second tab (Configurations), you will see a table containing all the logical port definitions. If this table contains no entries, you have work to do :-).
Click on the button 'Create Logical Port' and enter the data in the popup screen. In the 'Logical Port Name', choose an easy to remember name for the logical port. The field 'Logical Port Name' is the string you'll need to enter in the coding where I previously mentioned '<your logical port>'.
Same as in the creation of the client proxy, here you can choose to upload the WSDL from the HTTP access, or if this doesn't work, just upload from your local PC.
The data from the WSDL will be used to determine the information needed in the logical port.
Apply the settings by activating/saving.
Note that creating the logical port should be done on every instance, so after having done this on your development system, you should also do these steps in Qas and Production.
The reason of this being an additional step is probably because you might want to communicate with different systems depending on whether you are in DEV, QAS or PRD. Also, this enables you to dynamically determine the target system. Hypothetically, you can have several destinations containing the same webservices. In this case, you can have one client proxy communicating with different destinations using several logical ports.
Once you have imported the WSDL as a Logical Port, you can click the edit button and change settings. I have not needed to do this, so I can't tell you what the impact would be.
When running your code, you will now see that the method will result in a result. The result can either be the response structure (lucky you!) or the exception class )-: containing data.
Good chance you will have soms kind of exception. 'Authorization errors' will be popular in this stage. I will take a short look at this next week, as well as logging and monitoring in the SOAMANAGER.