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_member187859
Participant

Look, you don't need to tell me.  I already know the truth, deep in my bones: ABAP is not the language the cool kids use.  Not even remotely on their radar.  They've got their Scalas, and their Rusts, and all 30 billion javascript frameworks to build hot startups with.  You can't even play with ABAP unless you work for a place that runs SAP or you're willing to download and install the massive (50 GB!) ABAP trial version

But when you look under the covers at the system functionality that ABAP exposes in SAP systems, it becomes apparent that the frameworks, libraries, and system tools that you have at your command can be crafted into an engine to power a phenomenal array of projects.  Just this morning I put together something that - while admittedly not incredibly useful all by itself - shows some of what you can accomplish if you have some familiarity with the tools SAP gives you in ABAP and Gateway. 

Let me show you.  It's not a ridiculously complex build, and it's just a slice of what you could do. 

At a high level what I've done is find an external RESTful web service, write some ABAP to consume it from the SAP side, and expose that data back out through Gateway.  It's a little bit contrived, since you could easily call this service without Gateway mediating the connection...but I think there are occasional valid reasons to mediate the service through Gateway.  You might have an account with the external service and need to manage your calls to it, or you might want to join the service data with other things from Business Suite services and make it all available in one entity type.  Or you're like me, and you just want to see if it could be done.  :smile:

I created a developer account with world weather online, so that I could use its API for free.  This lets you use a simple call to get a set of information on weather for a particular location, and in my case I use it to get the day's forecast with a given zip code.  If you sign up, you can use their neat API explorer to test out different ways to use the service. 

If I call the main weather service with my home zip code, I get the following structure back (some unnecessary stuff has been trimmed):

<?xml version="1.0" encoding="UTF-8"?>
<data>
   
<request>
       
<type>Zipcode</type>
       
<query>55426</query>
   
</request>
   
<weather>
       
<date>2014-03-27</date>
       
<tempMaxC>5</tempMaxC>
       
<tempMaxF>40</tempMaxF>
       
<tempMinC>-6</tempMinC>
       
<tempMinF>22</tempMinF>
       
<windspeedMiles>15</windspeedMiles>
       
<windspeedKmph>24</windspeedKmph>
       
<winddirection>ESE</winddirection>
       
<winddir16Point>ESE</winddir16Point>
       
<winddirDegree>123</winddirDegree>
        <weatherDesc>
            <![CDATA[Light rain]]>
       
</weatherDesc>
       
<precipMM>9.6</precipMM>
   
</weather>
</data>


Knowing the structure of what comes back to me, I can build some simple ABAP to do the same thing.  I set up a dictionary z-structure to hold the bits of data that I want to use:


I then set up a function module to do pull data from the service and put it into that structure:

FUNCTION zweather_read_zip.
*"---------------------------------------------------------------
*"*"Local Interface:
*"  IMPORTING
*"     VALUE(IM_ZIPCODE) TYPE  AD_PSTCD1
*"  TABLES
*"      ET_WEATHER STRUCTURE  ZWEATHER
*"---------------------------------------------------------------

  DATA: lo_http_client TYPE REF TO if_http_client,
        lv_service TYPE string,
        lv_result TYPE string,
        lo_ixml TYPE REF TO if_ixml,
        lo_streamfactory TYPE REF TO if_ixml_stream_factory,
        lo_istream TYPE REF TO if_ixml_istream,
        lo_document TYPE REF TO if_ixml_document,
        lo_parser TYPE REF TO if_ixml_parser,
        lo_weather_element TYPE REF TO if_ixml_element,
        lo_weather_nodes TYPE REF TO if_ixml_node_list,
        lo_curr_node TYPE REF TO if_ixml_node,
        lv_value TYPE string,
        lv_node_length TYPE i,
        lv_node_index TYPE i,
        ls_weather TYPE zweather,
        lv_node_name TYPE string,
        lv_node_value TYPE string.

  lv_service = 'http://api.worldweatheronline.com/free/v1/weather.ashx'.

  lv_service =
lv_service && '?q=' && im_zipcode && '&format=xml'.

  lv_service = lv_service && '&key=[use your own!]'.

  cl_http_client=>create_by_url(
    EXPORTING
      url                = lv_service
    IMPORTING
      client             = lo_http_client
    EXCEPTIONS
      argument_not_found = 1
      plugin_not_active  = 2
      internal_error     = 3
      OTHERS             = 4 ).

  lo_http_client->send(
    EXCEPTIONS
      http_communication_failure = 1
      http_invalid_state         = 2 ).

  lo_http_client->receive(
    EXCEPTIONS
      http_communication_failure = 1
      http_invalid_state         = 2
      http_processing_failed     = 3 ).

  "Prepare XML structure
  CLEAR lv_result .
  lv_result = lo_http_client->response->get_cdata( ).
  lo_ixml = cl_ixml=>create( ).
  lo_streamfactory = lo_ixml->create_stream_factory( ).
  lo_istream = lo_streamfactory->create_istream_string(
                                   lv_result ).
  lo_document = lo_ixml->create_document( ).
  lo_parser = lo_ixml->create_parser(
                         stream_factory = lo_streamfactory
                         istream        = lo_istream
                         document       = lo_document ).

  "This actually makes the XML document navigable
  lo_parser->parse( ).

  "Navigate XML to nodes we want to process
  lo_weather_element = lo_document->find_from_name_ns(
'weather' ).
  lo_weather_nodes = lo_weather_element->get_children( ).

  "Move through the nodes and assign appropriate values to export
  lv_node_length = lo_weather_nodes->get_length( ).
  lv_node_index = 0.
  CLEAR ls_weather.
  WHILE lv_node_index < lv_node_length.
    lo_curr_node = lo_weather_nodes->get_item( lv_node_index ).
    lv_node_name = lo_curr_node->get_name( ).
    lv_node_value = lo_curr_node->get_value( ).

    CASE lv_node_name.
      WHEN 'date'.
        REPLACE ALL OCCURRENCES OF '-' IN lv_node_value WITH ''.
        ls_weather-forecast_date = lv_node_value.
      WHEN 'tempMaxF'.
        ls_weather-high_temp_f = lv_node_value.
      WHEN 'tempMinF'.
        ls_weather-low_temp_f = lv_node_value.
      WHEN 'windspeedMiles'.
        ls_weather-wind_speed = lv_node_value.
      WHEN 'winddir16Point'.
        ls_weather-wind_direction = lv_node_value.
      WHEN 'weatherDesc'.
        ls_weather-description = lv_node_value.
      WHEN 'precipMM'.
        ls_weather-precipitation = lv_node_value.
    ENDCASE.

    ADD 1 TO lv_node_index.
  ENDWHILE.

  APPEND ls_weather TO et_weather.

ENDFUNCTION.


I sprinkled some comments in the code to help, but I use the cl_http_client class to do the call to the service (and it can be set up and done in just 3 method calls), and then use a few of the xml library classes to parse the result and put it into the structure.  You can see here that though I've only made the zip code dynamic in the call, you could actually be pretty dynamic in choosing services to leverage. 

Why did I use a function module?  It's actually pretty easy to use a function module as a basis for building services in SEGW on your Gateway system, so it can be convenient to wrap custom functionality into a function module and then just import definitions.  That's what I did to set up the entity and entity set for this simple service: 

Note especially that the GetEntity method is mapped with zip code as the incoming parameter:


After this, when I activated the service, it's as simple as calling the URI with a parameter of some zip code that I want to see :



Like I mentioned before, by itself this isn't much use.  But combine this with some other information and you start to see what you can really pull together and expose through Gateway.  It's pretty awesome to think that anything you could pull from a REST service on the web can also be a resource for your application. 

86 Comments
Former Member
0 Kudos

Thank you ! that clarifies it.

and thanks for sharing all the details in this blog.

It really helps!

Meghna

Former Member
0 Kudos

HI paul,

If we have to pass some values in the header , like the api key and format.

How can we achieve it.

I have tried the following :

CALL METHOD lo_http_client->request->set_method( if_http_request=>CO_REQUEST_METHOD_GET ).

   "Set Header field

   CALL METHOD lo_http_client->request->set_header_field

     EXPORTING

       name  = 'API-KEY'

       value = 'XXXXXXXXX'.

   "Set Header field

   CALL METHOD lo_http_client->request->set_header_field

     EXPORTING

       name  = 'Accept'

       value = 'application/xml'.

   lo_http_client->send(

   EXCEPTIONS

   http_communication_failure = 1

   http_invalid_state = 2 ).

   lo_http_client->receive(

   EXCEPTIONS

   http_communication_failure = 1

   http_invalid_state = 2

   http_processing_failed = 3 ).

But the code hangs indefinitely on the 'Receive' method.

Meghna

Former Member
0 Kudos

Hi Paul,

Thanks for the post. I have a question, can I do similar code for a "https" service call.

Thanks,

JM

Former Member
0 Kudos

HI paul,

Can we use this for HTTPS service calls?

If we have to pass some values in the header , like the api key and format.

How can we achieve it.

I have tried the following :

CALL METHOD lo_http_client->request->set_method(if_http_request=>CO_REQUEST_METHOD_GET ).

   "Set Header field

   CALL METHOD lo_http_client->request->set_header_field

     EXPORTING

       name  = 'API-KEY'

       value = 'XXXXXXXXX'.

   "Set Header field

   CALL METHOD lo_http_client->request->set_header_field

     EXPORTING

       name  = 'Accept'

       value = 'application/xml'.

   lo_http_client->send(

   EXCEPTIONS

   http_communication_failure = 1

   http_invalid_state = 2 ).

   lo_http_client->receive(

   EXCEPTIONS

   http_communication_failure = 1

   http_invalid_state = 2

   http_processing_failed = 3 ).

But the code hangs indefinitely on the 'Receive' method.

Meghna

former_member187859
Participant
0 Kudos

Hi Meghna,

I would try this on a simple known good https url - like https://www.google.com. Take out the header field params and just do the call that way. See if you get a real response...the problem could possibly be in your system's overall HTTP setup.

If you get the right stuff from the bare HTTPS request, then what I do is use a tool like Postman or Advanced Rest Client (both Chrome extensions, but you can find good stuff for Firefox or other browsers) and make sure my header parameters are appropriate for the web API I'm calling.

If you're willing to share more code I can probably help more.

Paul

Former Member
0 Kudos

Hi Paul,

Thanks for this post.

I have one scenario to be mapped in SAP. Can you please help me out?

I need to call a JSON API (https://api-sandbox.grovo.com/users) from ABAP. This API needs a valid token which to be received from another API call (https://api-sandbox.grovo.com/token), after providing API id and password.


for API details - https://grovo-api.readme.io/v1.0/docs


For each API subsequent call I would need to call this Token API.

Can you please help me understand which SAP function module / class to call to get token from (https://api-sandbox.grovo.com/token) API , and how to pass this token value to call subsequent API (https://api-sandbox.grovo.com/users))? 

Thanks

Vijay

vamsixk
Active Participant
0 Kudos

Hi Paul,

thank you for this Post. It helped me a lot.

However i do have some questions.

I am trying to call an OData Service with Authentication involved.

I know we can use the authenticate method in the CL_HTTP_CLIENT class, but is there a way to use the Create_by destination method so the user/ID password details can be stored securely in an SM59 connection.

While doing the SM59 Configuration, how can we pass the parameters to the URI?

Have you considered/encountered such a scenario?

Kind Regards,

Vamsi

former_member187859
Participant
0 Kudos

Hi Vasmi,

I see that you put a blog up recently on this topic - I'm sorry I was too late to respond to try to help you, but I'm glad that you put something out there that I could learn from. Well done!

Regards,

Paul

jeff_broodwar
Active Participant
0 Kudos

Hello Paul,

I find the article interesting, hope you can send private message, need your help. thanks in advance.

matt
Active Contributor
0 Kudos

This is a site for sharing information. Do not ask for private messages.

jeff_broodwar
Active Participant
0 Kudos

Sorry, I just dont have a way to ask pauls help and might be off topic if I post my concern here.I can create a new thread just want pauls attention thats all. Tnks

matt
Active Contributor
0 Kudos

This is one way of attracting his attention. Paging paul.mindset 🙂

former_member187859
Participant
0 Kudos

I engaged with Jeff privately on this. If the discussion is at all worthwhile to be made generic and shared I will absolutely do so.

Former Member
0 Kudos

Hi Paul,

Thanks for the blog. I have created a FM and using the code in my FM.

But I'm getting a dump at this line.

  lo_weather_element = lo_document->find_from_name_ns( 'weather' ).

  lo_weather_nodes = lo_weather_element->get_children( ).

The issue is the lo_weather_element is Initial and not having the corresponding node. I have checked doing F5 at this statement. But it goes to the below code and comes out of it.

method if_ixml_document~find_from_name_ns
by kernel module abkm_iXMLDocument_FindFromNameNS.
endmethod.

Can you please share some info on this about how to make this work.

Thank you,

Kritika

former_member189275
Discoverer
0 Kudos

Hello,

The requirement is to consume a web service REST-POST. Base URL is provided along with other credentials which are constant value. Web service will return a JSON format which I need to map into ABAP structure. Following the above code and comments from Paul and other members, I tried to start with CREATE BY URL. It seems didn't work and came to know that I need to trigger a POST method using FORM DATA. I have no clue how to achieve this using FORM DATA in order to prepare my URL.

Once the URL is triggered and JSON is returned. It will be mapped into ABAP structure, so planning to use the /UI2/CL_JSON=> deserialize to convert the JSON data into ABAP structure.  Kindly let me know how to prepare the URL using POST method for JSON.

0 Kudos

Hi,

I have implemented both GET/POST everything works as expected ..is that possible to implement as below PUT method.

lo_client->request->set_method( 'PUT' ).

Let me know if you have any advice's on this.

Thanks,

Syam

Former Member
0 Kudos
Hi Paul,

Thanks for the blog. I have created a FM using the above given code.

But I’m getting a dump at this line.

lo_weather_element = lo_document->find_from_name_ns( ‘weather’ ).

lo_weather_nodes = lo_weather_element->get_children( ).

I tried to execute the same in the debugger and found that the API key is invalid.

I have generated the API key by registering as a (free) developer on https://developer.worldweatheronline.com/auth/register site.

Could you please help by providing the appropriate solution.

Thanks.

Rohini
former_member187859
Participant
0 Kudos

Hi Rohini,

It’s been a few years since I looked at this stuff. The world weather online service may have changed how it checks/supplies keys. You may need to switch “free” for “premium” in the URL for the api call.

You might also make sure you're using the right version of the API call in the URL. Since you signed up recently, you'll need "v2" in the URL instead of "v1". 

If that doesn’t work, try using a tool like Postman to figure out how the API call needs to look before plugging that back into the ABAP code.

Let me know if that helps!

-Paul

former_member283476
Discoverer
0 Kudos
HI Paul,

{"Time":"2017-03-13T05:05:39-04:00","Result":"9"}

This my webservice result in json format. Can anybody help me how to read this using ABAP? i tried with above piece of code but i am getting dump.
former_member187859
Participant
0 Kudos
Hi Vamsi,

The above code expects the results of a web service call in XML format. If the service you're calling is returning JSON, then may I suggest looking at the below for a call transformation solution to serializing/deserializing JSON<==>ABAP.

E.g.  https://blogs.sap.com/2013/07/04/abap-news-for-release-740-abap-and-json/

Also https://blogs.sap.com/2013/01/07/abap-and-json/

Hope this helps!

-Paul
amitkumar_singh2
Participant
0 Kudos

@paul.mindset: Thanks for the great blog post.

I want to ask here you have provided URL manually in the program code. This approach is not practical for typical business application. How to achieve the same via reading configuration done on gateway.

Another point what if at design time the structure of requested resource from web service is not known, so what would be approach to consume it. Do we have enriched client side library in SAP so less parsing is required in such case?

Thanks for your help.

former_member187859
Participant
Hi Amit,

You can achieve URL configuration in any number of ways. A custom table, a TVARV value...anything like that. Store the URL as a string in one of those places, and read it at runtime.

If you don't know at design time what the structure will look like, you can look at an approach like the one in this git repository: https://gist.github.com/mydoghasworms/2291540 . Method "json_to_data" should let you have any json be output as generic ABAP data. Though if you don't know the structure of what you're asking for from the web service, it may be hard to extract the right thing from that structure for your use.

Paul
Former Member
0 Kudos

Hi Paul,

Thanks alot for the wonderful post.

I tried your example but i am getting initial value when executing this statement (  lo_weather_element = lo_document->find_from_name_ns( ‘Weather’ ).

I looked at the blog and tried /o/IWFND/GW_CLIENT the transaction and executed it by giving the URL then i received an error “HTTP Receive failed: SSL handshake with api.worldweatheronline.com:443 failed: SSSLERR_PEER_CERT_UNT” .

Can you please let me know how i can resolve this error.

But when I execute same URL from Program RSHTTP20 i am getting connect Error: Open SSL not available.

Thanks,

Kiran

 

kdass_lb
Explorer
0 Kudos
Hi Paul,

Firstly good blog. Guess this was needed when T-code "/IWBEP/OCI_SRV_GEN" wasn't available. However would like to know if you try to register external OData service( example XS Engine Odata) onto Gateway and consume on SAPUI5 app on gateway? As when I did only HHTP GET methods works and no POST and other HTTP methods

Reference: http://www.saplearners.com/how-to-consume-external-odata-services-in-sap-netweaver-gateway/

 
Former Member
0 Kudos
Hi Paul,

This is something new to us. We have a requirement to access to a portal using REST API with login id and password and read the data from that portal. We are not understanding from where to start with. Do we first need to create a service in SEGW and link a method/FM of ABAP to it? Bit confused.

Is it possible to provide your email address from where we can contact you?

Thanks,

Madhura.

 

 
Former Member
0 Kudos
Hi Paul,

Thanks for posting such a valuable post.But my question is how to post complex xml like following

<?xml version="1.0" ?>
<AccessRequest xml:lang='en-US'>
<AccessLicenseNumber>XXXXXXXXXXXXXXXXXXX</AccessLicenseNumber>
<UserId>XXXXXXXX</UserId>
<Password>XXXXXXX</Password>
</AccessRequest>
<?xml version="1.0" ?>
<AddressValidationRequest xml:lang='en-US'>
<Request>
<RequestAction>XAV</RequestAction>
</Request>
<AddressKeyFormat>
<AddressLine>100 Broad Street</AddressLine>
<Region></Region>
<PoliticalDivision2>NEWARK</PoliticalDivision2>
<PoliticalDivision1>NJ</PoliticalDivision1>
<PostcodePrimaryLow>75050</PostcodePrimaryLow>
<CountryCode>US</CountryCode>
</AddressKeyFormat>
</AddressValidationRequest>

 

Please give me some advice

Thankyou so much

 
vamsixk
Active Participant
0 Kudos
HI Paul,

I need to pass an authorization header in a HTTP Post service.

When i use the create_by_destination method, it always triggers a logon popup even when "NO Logon" is chosen in the RFC destination definition.

 

I have used the propertytype_no_logon_popup but it does not suppress the logon popup.

but whenever i call with create_by_destination the logon popup is always triggered.

we cannot use the create_by_url option because, we do not want to hardcode the URL.

Is there any way to configure the RFC destination so that, it does not trigger the popup and just uses the Authorization header?

Kind Regards,

Vamsi
sankar_bhatta
Participant
0 Kudos
HI,

 

I am trying to use class CL_HTTP_CLIENT to trigger SAP cloud workflow from ABAP. I am able to get the CSRF token part successfully but the second POST call fails with HTTP 403 Forbidden error. where I am going wrong?

https://answers.sap.com/questions/615947/trigger-scp-from-abap-program.html

 
atul_mohanty
Active Contributor
0 Kudos
Hi Paul,

Hope you are doing good.

I was following your this blog and was tryinging to replicate. But I am facing some issues. Could you please guide me further.

  1. I have registered as a developer in the website www.worldweatheronline.com to use API.

  2. I got an key till valid 6th Oct 2018.

  3. Using the API explorer in www.worldweatheronline.com & postman application, I can see xml file.

  4. I am using the following url ( I supress the key as 'mykey' 
    SPAN {
    font-family: "Courier New";
    font-size: 10pt;
    color: #000000;
    background: #FFFFFF;
    }
    .L0S32 {
    color: #3399FF;
    }
    .L0S55 {
    color: #800080;
    }
    .L0S70 {
    color: #808080;
    }
    http://api.worldweatheronline.com/premium/v1/weather.ashx?q=London&format=xml&date=2018-08-21&key=mykey

  5. However, when I am trying to use the code in SAP, I am getting error code '401'. Below is the code. 
    SPAN {
    font-family: "Courier New";
    font-size: 10pt;
    color: #000000;
    background: #FFFFFF;
    }
    .L0S31 {
    font-style: italic;
    color: #808080;
    }
    .L0S52 {
    color: #0000FF;
    }
    .L0S55 {
    color: #800080;
    }
    DATAlo_http_client     TYPE REF TO if_http_client,
    lv_service         TYPE        string,
    lv_result          TYPE        string,
    lo_ixml            TYPE REF TO if_ixml,
    lo_streamfactory   TYPE REF TO if_ixml_stream_factory,
    lo_istream         TYPE REF TO if_ixml_istream,
    lo_document        TYPE REF TO if_ixml_document,
    lo_parser          TYPE REF TO if_ixml_parser,
    lo_weather_element TYPE REF TO if_ixml_element,
    lo_weather_nodes   TYPE REF TO if_ixml_node_list,
    lo_curr_node       TYPE REF TO if_ixml_node,
    lv_value           TYPE        string,
    lv_node_length     TYPE        i,
    lv_node_index      TYPE        i,
    im_zipcode         TYPE        ad_pstcd1,
    *        ls_weather         TYPE        zweather,
    lv_node_name       TYPE        string,
    lv_node_value      TYPE        string.

    SPAN {
    font-family: "Courier New";
    font-size: 10pt;
    color: #000000;
    background: #FFFFFF;
    }
    .L0S33 {
    color: #4DA619;
    }
    .L0S55 {
    color: #800080;
    }
    lv_service 'http://api.worldweatheronline.com/premium/v1/weather.ashx?q=London&format=xml&date=2018-08-21&key= mykey'


  6. SPAN {
    font-family: "Courier New";
    font-size: 10pt;
    color: #000000;
    background: #FFFFFF;
    }
    .L0S52 {
    color: #0000FF;
    }
    .L0S55 {
    color: #800080;
    }
    Data :lv_rc TYPE i.


  7. SPAN {
    font-family: "Courier New";
    font-size: 10pt;
    color: #000000;
    background: #FFFFFF;
    }
    .L0S32 {
    color: #3399FF;
    }
    .L0S52 {
    color: #0000FF;
    }
    .L0S55 {
    color: #800080;
    }
    .L0S70 {
    color: #808080;
    }
    cl_http_client=>create_by_url(
    EXPORTING
    url                lv_service
    IMPORTING
    client             lo_http_client
    EXCEPTIONS
    argument_not_found 1
    plugin_not_active  2
    internal_error     3
    OTHERS             ).

    lo_http_client->send(
    EXCEPTIONS
    http_communication_failure 1
    http_invalid_state         ).


    lo_http_client->receive(
    EXCEPTIONS
    http_communication_failure 1
    http_invalid_state         2
    http_processing_failed     ).
    SPAN {
    font-family: "Courier New";
    font-size: 10pt;
    color: #000000;
    background: #FFFFFF;
    }
    .L0S31 {
    font-style: italic;
    color: #808080;
    }
    .L0S52 {
    color: #0000FF;
    }
    .L0S55 {
    color: #800080;
    }
    .L0S70 {
    color: #808080;
    }

  8. lo_http_client->response->get_status( IMPORTING code = lv_rc ).

    "prepare xml structure
    CLEAR lv_result .
    lv_result = lo_http_client->response->get_cdata( ).


 

I am getting error code '401.

Message as follows 'Description: Authorization is required for access to this proxy'.

 

But when I execute, the URL in the program 'RSHTTP20' , I am getting return code as 200.

Could you please guide, what could be the issue behind and how to resolve it ?

Thank you.

Regards,

Atul M

 

 

 

 

 

 

 
ashish_chanekar
Explorer
0 Kudos
Hi Paul,

just came across your blog - have some query in this regards,

  1. if we call the API directly from an ABAP program with out the gateway service then is it possible to trace the logging of request and response parameters as we get it when we create an API in ABAP and call it via SICF service without the gateway.


would appreciate your reply.

Thanks,

Ashish.

 
kmoore007
Active Contributor
0 Kudos
If someone has done this with SAP Concur API's, I'd love it if they could share the code!
elalan
Participant
0 Kudos
Hello to all , i use this code , and works really good , i can't thanks enough , but i have a problem when i get my data , is in string form , i use this

 


SPAN {
font-family: "Courier New";
font-size: 10pt;
color: #000000;
background: #FFFFFF;
}
.L0S31 {
font-style: italic;
color: #808080;
}
.L0S32 {
color: #3399FF;
}
.L0S33 {
color: #4DA619;
}
.L0S55 {
color: #800080;
}
.L0S70 {
color: #808080;
}
lo_weather_element lo_document->find_from_name_ns('search_api').
lo_weather_nodes lo_weather_element->get_children).

lv_node_length lo_weather_nodes->get_length)"  CUANTAS FILAS HAY
lv_node_index 0.

 


SPAN {
font-family: "Courier New";
font-size: 10pt;
color: #000000;
background: #FFFFFF;
}
.L0S55 {
color: #800080;
}
.L0S70 {
color: #808080;
}
  lo_curr_node  lo_weather_nodes->get_itemlv_node_index ).
lv_node_name  lo_curr_node->get_name).
lv_node_value lo_curr_node->get_value).

 

The item properly is RESULT but if i put result is getting separeted in columns as the example says , but , when i use this "search api" is getting me the right amount of rows or items , but all 1 place , is a string with no separetor .

 

Can someone please give a hand
vikash_pathak
Participant
0 Kudos

Hello ,


 

i implemented your code and got api as well , but getting error , i attached snap of api and error , please let me know if i have missed anything
TYPES : BEGIN OF t_weather,
forecast_date TYPE dats,
hight_temp_f TYPE int4,
low_temp_f TYPE int4,
wind_speed TYPE int4,
wind_direction TYPE char3,
description TYPE char40,
precipitation TYPE decfloat16,
END OF t_weather.

DATA:et_weather TYPE STANDARD TABLE OF t_weather.
DATA: IM_ZIPCODE TYPE AD_PSTCD1 VALUE '123456'.
DATA: lo_http_client TYPE REF TO if_http_client,
lv_service TYPE string,
lv_result TYPE string,
lo_ixml TYPE REF TO if_ixml,
lo_streamfactory TYPE REF TO if_ixml_stream_factory,
lo_istream TYPE REF TO if_ixml_istream,
lo_document TYPE REF TO if_ixml_document,
lo_parser TYPE REF TO if_ixml_parser,
lo_weather_element TYPE REF TO if_ixml_element,
lo_weather_nodes TYPE REF TO if_ixml_node_list,
lo_curr_node TYPE REF TO if_ixml_node,
lv_value TYPE string,
lv_node_length TYPE i,
lv_node_index TYPE i,
ls_weather TYPE t_weather,
lv_node_name TYPE string,
lv_node_value TYPE string.

lv_service = 'http://api.worldweatheronline.com/free/v1/weather.ashx'.

lv_service = lv_service && '?q=’ && im_zipcode && ‘&format=xml'.

lv_service = lv_service && '&key=[84494a1952094d158a582104200309]'.

cl_http_client=>create_by_url(
EXPORTING
url = lv_service
IMPORTING
client = lo_http_client
EXCEPTIONS
argument_not_found = 1
plugin_not_active = 2
internal_error = 3
OTHERS = 4 ).

lo_http_client->send(
EXCEPTIONS
http_communication_failure = 1
http_invalid_state = 2 ).

lo_http_client->receive(
EXCEPTIONS
http_communication_failure = 1
http_invalid_state = 2
http_processing_failed = 3 ).

* “Prepare XML structure
CLEAR lv_result .
lv_result = lo_http_client->response->get_cdata( ).
lo_ixml = cl_ixml=>create( ).
lo_streamfactory = lo_ixml->create_stream_factory( ).
lo_istream = lo_streamfactory->create_istream_string(
lv_result ).
lo_document = lo_ixml->create_document( ).
lo_parser = lo_ixml->create_parser(
stream_factory = lo_streamfactory
istream = lo_istream
document = lo_document ).
* “This actually makes the XML document navigable
lo_parser->parse( ).
* “Navigate XML to nodes we want to process
lo_weather_element = lo_document->find_from_name_ns( 'weather' ).
lo_weather_nodes = lo_weather_element->get_children( ).
* “Move through the nodes and assign appropriate values to export
lv_node_length = lo_weather_nodes->get_length( ).
lv_node_index = 0.
CLEAR ls_weather.
WHILE lv_node_index < lv_node_length.
lo_curr_node = lo_weather_nodes->get_item( lv_node_index ).
lv_node_name = lo_curr_node->get_name( ).
lv_node_value = lo_curr_node->get_value( ).
CASE lv_node_name.
WHEN 'date'.
REPLACE ALL OCCURRENCES OF '-' IN lv_node_value WITH '"' .
ls_weather-forecast_date = lv_node_value.
WHEN 'tempMaxF'.
ls_weather-hight_temp_f = lv_node_value.
WHEN 'tempMinF'.
ls_weather-low_temp_f = lv_node_value.
WHEN 'windspeedMiles'.
ls_weather-wind_speed = lv_node_value.
WHEN 'winddir16Point'.
ls_weather-wind_direction = lv_node_value.
WHEN 'weatherDesc'.
ls_weather-wind_direction = lv_node_value.
WHEN 'precipMM'.
ls_weather-precipitation = lv_node_value.
ENDCASE.
ADD 1 TO lv_node_index.
ENDWHILE.
APPEND ls_weather TO et_weather.

 
former_member187859
Participant
0 Kudos
It looks like you hard-coded square brackets around your API key. That might be the issue? The API key in your URL shouldn't have brackets.
ashok2021
Explorer
0 Kudos

Hi Paul,

I hope you are safe and doing well!!

i am new to making HTTP calls from ABAP to external RESTful API Services. I have a requirements where I have been given a service /sap/opu/odata/IBP/PLANNING_DATA_API_SRV/. I have to use this to post data back. Please let me know how I should proceed. i have created a sample ABAP program as shown below:

*************************************************************************************
**********************************CODING FOR THE GET METHOD***********
*************************************************************************************
*Create the HTTP client
cl_http_client=>create_by_destination(
EXPORTING
destination = c_rfcdest " Logical destination (specified in function call)
IMPORTING
client = lo_http_client " HTTP Client Abstraction
EXCEPTIONS
argument_not_found = 1
destination_not_found = 2
destination_no_authority = 3
plugin_not_active = 4
internal_error = 5
OTHERS = 6
).

CREATE OBJECT lo_rest_client
EXPORTING
io_http_client = lo_http_client.

* Create request instance
lo_request = lo_rest_client->if_rest_client~create_request_entity( ).

* Set HTTP version
lo_http_client->request->set_version( if_http_request=>co_protocol_version_1_0 ).

IF lo_http_client IS BOUND AND lo_rest_client IS BOUND.
*Fill headers and set URI for GET Method
*Create URI for the client
lv_query = 'getTransactionID'.

cl_http_utility=>set_request_uri(
EXPORTING
request = lo_http_client->request
uri = lv_query ).

ENDIF.

*Update the HTTP method
lo_http_client->request->set_method( method = lo_http_client->request->co_request_method_get ).
*********************************
*set Content type
lo_http_client->request->if_http_entity~set_content_type(
content_type = 'application/json' ).

lo_http_client->propertytype_accept_cookie = if_http_client=>co_enabled.
*
*set header field for festching x-csrf-token
lo_http_client->request->set_header_field(
name = 'x-csrf-token' " Name of the header field
value = 'Fetch' ). " HTTP header field value

*Trigger the GET Method
lo_http_client->send(
EXCEPTIONS
http_communication_failure = 1
http_invalid_state = 2
http_processing_failed = 3
http_invalid_timeout = 4
OTHERS = 5
).

lo_http_client->receive(
EXCEPTIONS
http_communication_failure = 1
http_invalid_state = 2
http_processing_failed = 3
OTHERS = 4
).
IF sy-subrc <> 0.
MESSAGE e000(oo) WITH 'Processing failed !'.
ENDIF.

DATA(wf_string1) = lo_http_client->response->get_cdata( ).
*
*Get x-csrf token from earlier response
lv_token = lo_http_client->response->get_header_field('x-csrf-token'). " Name of the header field

lv_session = lo_http_client->response->get_header_field('set-cookie').

*Convert JSON response to XML
DATA: json TYPE xstring.

*Return the HTTP body of this entity as binary data
json = lo_http_client->response->get_data( ).

CALL TRANSFORMATION id SOURCE XML json
RESULT XML DATA(xml).

DATA(reader) = cl_sxml_string_reader=>create( json ).
DATA(writer) =
CAST if_sxml_writer( cl_sxml_string_writer=>create( ) ).
TRY.
DO.
CLEAR lwa_node.
DATA(node) = reader->read_next_node( ).
IF node IS INITIAL.
EXIT.
ENDIF.
writer->write_node( node ).
CASE node->type.
WHEN if_sxml_node=>co_nt_element_open.
DATA(open_element) = CAST if_sxml_open_element( node ).
DATA(attributes) = open_element->get_attributes( ).

LOOP AT attributes INTO DATA(attribute).
lwa_node-node_type = `attribute`.
lwa_node-prefix = attribute->prefix.
lwa_node-name = attribute->qname-name.
lwa_node-nsuri = attribute->qname-namespace.
IF attribute->value_type = if_sxml_value=>co_vt_text.
lwa_node-value = attribute->get_value( ).
ELSEIF attribute->value_type =
if_sxml_value=>co_vt_raw.
lwa_node-value_raw = attribute->get_value_raw( ).
ENDIF.
IF lwa_node-value = 'LOCDESCR' OR lwa_node-value = 'LOCID'.
APPEND lwa_node TO lt_node.

ENDIF.
ENDLOOP.
CONTINUE.
WHEN if_sxml_node=>co_nt_element_close.
DATA(close_element) = CAST if_sxml_close_element( node ).
CONTINUE.
WHEN if_sxml_node=>co_nt_value.
DATA(value_node) = CAST if_sxml_value_node( node ).
lwa_node-node_type = `value`.
IF value_node->value_type = if_sxml_value=>co_vt_text.
lwa_node-value = value_node->get_value( ).
ELSEIF value_node->value_type = if_sxml_value=>co_vt_raw.
lwa_node-value_raw = value_node->get_value_raw( ).
ENDIF.
APPEND lwa_node TO lt_node.
CONTINUE.
WHEN OTHERS.
lwa_node-node_type = `Error`.
APPEND lwa_node TO lt_node.
EXIT.
ENDCASE.
ENDDO.
CATCH cx_sxml_parse_error INTO DATA(parse_error).

ENDTRY.

* GET TRANSACTION ID
DESCRIBE TABLE lt_node LINES DATA(lv_lines).
READ TABLE lt_node INTO DATA(lv_val) INDEX lv_lines.
IF sy-subrc = 0.
DATA(tranid) = lv_val-value. "transaction ID
ENDIF.
************************END OF LOGIC TO GET TRANSACTION ID**************************

*****************************************************************************************************
******************* LOGIC TO SEND DATA USING POST MTHOD *****
*****************************************************************************************************

free lo_http_client.
CONCATENATE 'https://.......scmibp.ondemand.com/sap/opu/odata/IBP/PLANNING_DATA_API_SRV/'
'(' '''' tranid '''' ')' INTO lv_url.
cl_http_utility=>set_request_uri(
EXPORTING
request = lo_http_client->request " HTTP Framework (iHTTP) HTTP Request
uri = lv_url " URI String (in the Form of /path?query-string)
).
ENDIF.

************************LOGIC TO CREATE NESTED JSON PAYLOAD*******************************
*** ABAP to JSON
*Create the nested JSON file to be used for data update
IF tranid <> space.
DATA(nav_unipa_2021) = VALUE t_nav_unipa_2021( ( keyfigure = 'CONSENSUSDEMANDQTY'
keyfiguredate = '2021/02/25'
product = 'E6603GA0'
customer = '54000'
location = '5450' ) ).
DATA(resp) = VALUE ty_response( transactionid = tranid
aggregationlevelfieldstrings = 'KEYFIGURE, KEYFIGUREDATE, PRODUCT, CUSTOMER, LOCATION'
navhasbroio = nav_unipa_2021 ).

DATA(json_response) = /ui2/cl_json=>serialize(
data = resp
).
**********************END OF LOGIC TO CREATE NESTED JSON PAYLOAD*********************

*Update the HTTP method
CALL METHOD lo_http_client->request->set_method
EXPORTING
method = lo_http_client->request->co_request_method_post.

*set the token received from GET method
CALL METHOD lo_http_client->request->set_header_field
EXPORTING
name = 'x-csrf-token'
value = lv_token.

*set the cookie received from the GET Method
CALL METHOD lo_http_client->request->set_cookie
EXPORTING
name = 'set-cookie'
value = lv_session.

*content type
CALL METHOD lo_http_client->request->set_content_type
EXPORTING
content_type = 'application/json'.

**Set body for the HTTP post request
lo_http_client->request->set_cdata( data = json_response ).

*Trigger the POST Method
lo_http_client->send( "Send the HTTP request
EXCEPTIONS
http_communication_failure = 1
http_invalid_state = 2
http_processing_failed = 3
http_invalid_timeout = 4
OTHERS = 5
).

lo_http_client->receive( "receive the response
EXCEPTIONS
http_communication_failure = 1
http_invalid_state = 2
http_processing_failed = 3
OTHERS = 4
).

DATA(l_result) = lo_http_client1->response->get_cdata( ).

write:/ l_result.
ENDIF.

Need your help. Please assist. i am stuck and dont know how to proceed now.

Thanks,

Ashok

Jigang_Zhang张吉刚
Active Contributor
0 Kudos
thanks for sharing this, very helpful!
Labels in this area