Technology Blogs by Members
Explore a vibrant mix of technical expertise, industry insights, and tech buzz in member blogs covering SAP products, technology, and events. Get in the mix!
cancel
Showing results for 
Search instead for 
Did you mean: 
Former Member

REST instead of SOAP


SOAP at the moment is still the leading standard as it comes to web services. Only with mobile applications the usage and consumption of wsdl files take a lot of overhead. The wsdl files will get big and complex when services are getting bigger proportions. The usage of SOAP is not a standard feature in the android environment. I would like to keep the mobile application as small and standard as possible.

I wanted to connect a standard function module to android and not using SOAP? And that’s when I found a blog titled Real Web Services with REST and ICF by Dj Adams. With a quick and clear solution how to call web services via ICF. And the best thing about it  is that it uses http and nothing else.  Which of course is standard available in the android environment.

For this example I used a standard function module called DATE_GET_WEEK which will give the according week for the supplied date.


Making the function module available as a REST enabled web service.

For making the function module available as a web service I used the ICF framework. You can create a new service by transaction SICF and adding a new sub-element. You have to define a handler element which will take care of the request. In my case I called it Z_CL_DATE_GET_WEEK.

Next step is creating the handler class which has to implement the interface IF_HTTP_EXTENSION. This will make the following method available in your class IF_HTTP_EXTENSION~HANDLE_REQUEST. To understand how to implement the method HANDLE_REQUEST. A brief explanation on how the URL handling works     The URL I will be using to call the service will be similar to this. http://system:8000/sap/zrest/week_by_date/20101208.

This can be divided in:
Server and portnumber:  system:8000

Namespace: sap
Service: zrest
Parameters to service:  week_by_date, 20101208

In my example see code below. I ‘ll only be using the second parameter as a date string. By using the date string as the exporting param you can call the function module in reply you will get a week number back including the year. I'm not interested in the year so I will only return the week with the service. It’s an option to also put some error handling in the service.

Implementation of method HANDLE_REQUEST:


method IF_HTTP_EXTENSION~HANDLE_request.
*  [DATA DEFINITION]
DATA:
     path_info     TYPE string,
     verb          TYPE string,
     w_action      TYPE string,
     w_attr        TYPE string,
     w_body        TYPE string,
     gv_date       TYPE datum,
     gv_week       TYPE kweek.
*  [INTERPRET REQUEST]
   path_info = server->request->get_header_field( name = '~path_info' ).
  verb = server->request->get_header_field( name = '~request_method' ).
*  (CHECK METHOD)
* Check if method is get.
   IF verb NE 'GET'.
     CALL METHOD server->response->set_header_field(
       name = 'Allow'       value = 'GET' ).
      CALL METHOD server->response->set_status(       code = '405'       reason = 'Method not allowed' ).
     EXIT.
   ENDIF.
     SHIFT path_info LEFT BY 1 PLACES.
     SPLIT path_info AT '/' INTO w_action w_attr.
*  (RETRIEVE DATA)
* Try to retrieve the week by input date.
   gv_date = w_attr.
    CALL FUNCTION 'DATE_GET_WEEK'
     EXPORTING
       date         = gv_date
     IMPORTING
       week         = gv_week
     EXCEPTIONS
       date_invalid = 1
       OTHERS       = 2.  
*  (NO VALID DATE OR OTHER ERROR OCCORRED)
* Abort with 404 if error
    IF sy-subrc ne 0.
      CALL METHOD server->response->set_status(
       code = '404'
       reason = 'ERROR' ).
      CONCATENATE ''  ''  ''  ''  ''  'h1. ERROR with input param:  '  w_attr  ' '  ''  ''  INTO w_body. 
     CALL METHOD server->response->set_cdata( data = w_body ).   
          EXIT.
     ENDIF.
*  (STORE ATTRIBUTE)
   w_body = gv_week+4(2). "We only need the last to characters for displaying the correct week.
*  (SET CONTENT TYPE)
* Return attribute value in response body
   CALL METHOD server->response->set_header_field(
     name = 'Content-Type'
     value = 'text/plain; charset=utf-8' ).
*  (PUT DATA IN RESPONSE BODY)
   CALL METHOD server->response->set_cdata( data = w_body ).
endmethod.                    "IF_HTTP_EXTENSION~HANDLE_REQUEST

This wraps up the back-end bit. But before using the service in android you can test the service in the browser by calling the URL. The result will look like this.

Note: Because I didn't change the default service settings you'll be prompted with a logon screen.

Android App

I developed the Android app in Eclipse. For more information on How to develop an android app click here. I’ll only explain how to call the web service in the android environment. You can call the web service via the org.apache.http.impl.client.DefaultHttpClient class which is standard provided in Android and actually is from the HTTP Components project of The Apache Software foundation. Because the service is using Basic Authentication it’s necessary to provide username and password to the DefaultHttpClient. The only problem is this is not by default supported in the HTTP Components project and is only available in the latest beta version. So for a quicker development I used this beta version. It's also an option to change the authentication settings of the service.

Implementation of the RESTService call





private String callRESTservice(String date) {
    String result = "";
    HttpHost targetHost = new HttpHost("saperp.ciberlabs.local", 8000, "http");
    DefaultHttpClient httpclient = new DefaultHttpClient();
    httpclient.getCredentialsProvider().setCredentials(new AuthScope(targetHost.getHostName(), targetHost.getPort()), new UsernamePasswordCredentials(_username, _password));
    // Create AuthCache instance
    AuthCache authCache = new BasicAuthCache();
    // Generate BASIC scheme object and add it to the local auth cache
    BasicScheme basicAuth = new BasicScheme();
    authCache.put(targetHost, basicAuth);
    // Add AuthCache to the execution context
    BasicHttpContext localcontext = new BasicHttpContext();
    localcontext.setAttribute(ClientContext.AUTH_SCHEME_PREF, authCache);
    HttpGet request = new HttpGet("/sap/zrest/test/" + date);
    ResponseHandler<String> handler = new BasicResponseHandler();
    try {



result = httpclient.execute(targetHost, request, handler);
    } catch (ClientProtocolException e) {



e.printStackTrace();

result = "ClientException. The input was: " + date;
    } catch (IOException e) {



e.printStackTrace();

result = "IOException. The input was: " + date;
    }
    httpclient.getConnectionManager().shutdown();
    return result;



}

The DefaultHttpClient you provide the URL and the user credentials. After calling the execute function the week number will be returned.
When the application is called and you will click a button to execute the service. The following result will be displayed.

   

11 Comments
Labels in this area