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: 
parichaypatra
Discoverer
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.


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.


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.


 

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 @parichaypatra

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

 
Labels in this area