Hello everyone. The purpose of this document is to shed some light on the process to call Adobe Forms Service API (for Cloud Foundry environment) from ABAP cloud. It sometimes becomes very confusing because of the different components involved especially when you are implementing the ABAP part.

Let’s begin with the prerequires first. We need: –

  • SAP BTP CF Environment
  • Forms Service by Adobe (You must have a valid license; it is not free).
  • SAP Destination Service
  • Adobe Live Cycle Designer
  • ABAP Cloud Service

Here in this blog, I shall mostly focus on the backend part and so to proceed, you need to create an application from which you will call the API.

Once done, let us follow the steps we are discussing here.

Create a destination in BTP

We have created an instance of the Adobe Form Service and created the service key. The details from the service key will be needed to create the cloud destination.

Please refer below configuration to set up the destination.

Service Instance name: ‘ADOBE_FORMS_SRV_CF’

Destination Name: ‘ADOBE_FORMS_DEST_CF’

<Type>: ‘HTTP’

<Proxy Type>: ‘Internet’

<Authentication>: ‘OAuth2ClientCredentials’

<URL>: Value of Rest API URL

<Client ID>: Value of clientid in the service key

<Client Secret>: Value of clientsecret in the service key

<Token Service User>: Value of clientid in the service key

<Token Service Password>: Value of clientsecret in the service key

<Token Service URL> : Value of XSUAA <url> in the service key followed by /oauth/token?grant_type=client_credentials

( For me it is something like below:- https://<xyzabcd>.authentication.us10.hana.ondemand.com/oauth/token?grant_type=client_credentials )

Point to be noted: ‘/oauth/token?grant_type=client_credentials’ is required for successful authentication.

Additional Property: –

scope: generate-ads-output

trustall: true

 

Testing the configuration.

Create a Communication Arrangement for ABAP Service

We also need a communication arrangement using scenario SAP_COM_0503. You can refer help.sap ( Communication Arrangement for Forms Service ) for details of this configuration.

 

Call the API from ABAP

Now we will create the implementation of the backend logic (in ABAP ) to call the rest api.

I have created a transformation in ABAP to convert the data into XML in a predefined format. Field names are kept same in data model, transformation and xdp template in Adobe Live Cycle Designer.

sample_transformation

Now we have three major steps to follow.

Create the request object instance and for this, we need the destination, uri of API  and other details like query parameter and header details of the request.

request%20instance

Note: The API endpoint will be different for Neo Environment. Please check API Hub for API Endpoint for Neo.

Prepare the data and convert it to XML via transformation.

transformation

 

Build the template and then call API.

Here, few things to notice.

  • XDP Template is <Form_Name>/<Template_Name>. It is the name of the document when you download it from Template Store.
  • Form Type has to be one of three options available (i.e interactive, print, dynamicInteractive).

Interactive: Editable Forms

Print: Non-Editable Forms

Dynamicinteractive: Editable Forms + Freely Expandable Sections.

Below code sample is written by me for demo purpose and not for productive environment.

CLASS zdmo_ads_assistance DEFINITION
  PUBLIC
  FINAL
  CREATE PUBLIC .
  PUBLIC SECTION.

    TYPES: BEGIN OF ty_doc,
             docnum(10)   TYPE c,
             docchild(10) TYPE c,
           END OF ty_doc,
           ts_docs TYPE ty_doc,
           BEGIN OF struct,
             xdp_template TYPE string,
             xml_data     TYPE string,
             form_type    TYPE string,
             form_locale  TYPE string,
             tagged_pdf   TYPE string,
             embed_font   TYPE string,
           END OF struct,

           BEGIN OF ty_header,
             DocumentNumber(10)    TYPE c,
             DocumentStatus(12)    TYPE c,
             ShortDescription(40)  TYPE c,
             ChangeResponsible(40) TYPE c,
           END OF ty_header,

           BEGIN OF ty_footer,
             PrintedOn(10)   TYPE c,
             GeneratedBy(40) TYPE c,
           END OF ty_footer,

           BEGIN OF ty_print_data,
             header TYPE TY_header,
             footer TYPE ty_footer,
           END OF ty_print_data.

    METHODS: generate_ads_forms  IMPORTING iv_documents TYPE ts_docs
                                 RAISING   cx_web_http_client_error.
  PROTECTED SECTION.
  PRIVATE SECTION.
ENDCLASS.

CLASS zdmo_ads_assistance IMPLEMENTATION.

  METHOD generate_ads_forms.

    FIELD-SYMBOLS:   <fs_val_ref>     TYPE data.

    DATA: ls_print_data   TYPE ty_print_data,
          lv_file_content TYPE string,
          lo_val_ref      TYPE REF TO data.

    FIELD-SYMBOLS: <fs_pdf_data>    TYPE data,
                   <fs_pdf_encoded> TYPE string,
                   <fs_file_name>   TYPE data.
    CONSTANTS: lc_success TYPE i VALUE 200.

    " Sample Data for the form
    ls_print_data-footer-generatedby = 'Shin-Chan N'.
    ls_print_data-footer-printedon =  '01/12/2022'.
    ls_print_data-header-changeresponsible = 'Buri Buri Zaemon'.
    ls_print_data-header-documentnumber = '0030002084'.
    ls_print_data-header-documentstatus = 'Closed'.
    ls_print_data-header-shortdescription = 'Adventures of Buri Buri Zaemon'.

    TRY.

* First Let us create the destination of the API

        DATA(lo_destination_instance) = cl_http_destination_provider=>create_by_cloud_destination(
                                 i_name                  = 'ADOBE_FORMS_DEST_CF'
                                 i_service_instance_name = 'ZDMO_COM_0503'
                                 i_authn_mode            = if_a4c_cp_service=>service_specific
                               ).

*   Second  client is created
        DATA(lo_http_client) = cl_web_http_client_manager=>create_by_http_destination( i_destination = lo_destination_instance ).

*   Then create the request instance from the Client
        DATA(lo_request_obj) = lo_http_client->get_http_request( ).


* Let us now create header of the request
        DATA lv_header_fields TYPE  if_web_http_request=>name_value_pairs.
        lv_header_fields = VALUE #(
                       ( name = 'Accept' value = 'application/json, text/plain, */*'  ) ##NO_TEXT
                       ( name = 'Content-Type' value = 'application/json;charset=utf-8'  ) ).

        lo_request_obj->set_header_fields( i_fields = lv_header_fields ).

* Set the api URI for the request
        lo_request_obj->set_query( query =  'templateSource=storageName' ).
        lo_request_obj->set_uri_path( i_uri_path = '/v1/adsRender/pdf' ).

** Lets create the xml data from the sample data we have created at the beginning.
        DATA(lo_xml_conv) = cl_sxml_string_writer=>create( type = if_sxml=>co_xt_xml10 ).

        CALL TRANSFORMATION zdmo_ads_form SOURCE root = ls_print_data RESULT XML lo_xml_conv.

        DATA(lv_output_xml) = lo_xml_conv->get_output( ).

        DATA(ls_data_xml) = cl_web_http_utility=>encode_x_base64( lv_output_xml ).

** Lets create the form template
        DATA(ls_form_structure) = VALUE struct( xdp_template = 'ZDMO_ADS_FORM/ADS_DOCUMENT_TEMPLATE'
                                      xml_data = ls_data_xml
                                      form_type = 'dynamicInteractive'
                                      form_locale = 'en_US'
                                      tagged_pdf = '0'
                                      embed_font = '0' ).

        DATA(lv_formmated_json) = /ui2/cl_json=>serialize( data = ls_form_structure compress = abap_true pretty_name = /ui2/cl_json=>pretty_mode-camel_case ).

        lo_request_obj->set_text( EXPORTING i_text   = lv_formmated_json ).

** Execute the request and get the response object
        DATA(lo_response_obj) = lo_http_client->execute( i_method = if_web_http_client=>post ).

        IF lo_response_obj IS BOUND AND lo_response_obj->get_status( )-code EQ lc_success.
** Success
        ENDIF.

      CATCH cx_root INTO DATA(lv_error).
** Report errors here

    ENDTRY.
  ENDMETHOD.
ENDCLASS.

Congratulations, you have reached to the end of the topic. I appreciate that you have completed this journey.

By following the steps mentioned in this blog, I hope you will successfully call the Forms Service API from ABAP.

Note: You may get an error as ‘BEHAVIOR_ILLEGAL_STATEMENT’ when calling the API directly from behavior implementation through static action. In that case, you can create a custom action via an extension of the application from BAS and call a new entity under the same service ( via odatamodel.read ). You can then implement the API logic inside the new entity.

Please let me know your comments/feedback and revert if any query. You can also follow me @Parichay Patra

More on this topic, you can refer to below links:-
– Q&A
– Blogs

 

Sara Sampaio

Sara Sampaio

Author Since: March 10, 2022

0 0 votes
Article Rating
Subscribe
Notify of
0 Comments
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x