Technology Blog Posts by Members
cancel
Showing results for 
Search instead for 
Did you mean: 

Hello, everyone!

This is my first blog, and I’m excited to share my experience while working with RAP-based OData services. As a learner diving into the RAP world, I struggled to find a method to directly display forms in RAP applications .During my exploration, I discovered a workaround to render Adobe forms using a RAP-based OData service—without relying on SEGW-generated services.

Here’s the code that I used:

 " Create object reference for HTTP response
    DATA: lo_cached_response TYPE REF TO if_http_response.

    " Set the output parameters for the Adobe form
    ls_outputparams = VALUE #( getpdf = 'X' nodialog = 'X' ).

    CALL FUNCTION 'FP_JOB_OPEN'
      CHANGING
        ie_outputparams = ls_outputparams.

    " Get the name of the generated function module for the Adobe form
    CALL FUNCTION 'FP_FUNCTION_MODULE_NAME'
      EXPORTING
        i_name     = 'YUS_DEMO' "Your Adobe Form 
      IMPORTING
        e_funcname = lv_fmname.

    IF sy-subrc = 0.
      " Call the generated function module to render the Adobe form
      CALL FUNCTION lv_fmname
        EXPORTING
          /1bcdwb/docparams  = ls_docparams
          t_bar              = lt_adobe_bar
          i_preview          = abap_true
        IMPORTING
          /1bcdwb/formoutput = ls_form_output
        EXCEPTIONS
          usage_error        = 1
          system_error       = 2
          internal_error     = 3.


      " Close the spool job for the Adobe form
      CALL FUNCTION 'FP_JOB_CLOSE'.
    ENDIF.

    " Create an HTTP response object for hosting the PDF
    CREATE OBJECT lo_cached_response
      TYPE cl_http_response
      EXPORTING
        add_c_msg = 1.

    " Generate a unique GUID for the PDF file
    CALL FUNCTION 'GUID_CREATE'
      IMPORTING
        ev_guid_32 = lv_guid.

    " Set the PDF data in the HTTP response
    lo_cached_response->set_data(
      data   = ls_form_output-pdf
      length = xstrlen( ls_form_output-pdf ) ).

    " Set the content type to PDF
    lv_app_type = 'application/pdf'.
    lo_cached_response->set_header_field(
      name  = if_http_header_fields=>content_type
      value = lv_app_type ).

    " Set the content disposition to inline with the generated filename
    lo_cached_response->set_header_field(
      name  = if_http_header_fields=>content_disposition
      value = |inline; filename="{ lv_guid }.pdf"| ).

    " Allow cross-origin requests
    lo_cached_response->set_header_field(
      name  = 'Access-Control-Allow-Origin'
      value = '*' ).

    " Set the HTTP response status

    lo_cached_response->set_status( code = 200 reason = 'OK' ).

    " Set the cache timeout for the response
    lo_cached_response->server_cache_expire_rel( expires_rel = 120 ).

    " Construct the base URL for the OData service
    CALL METHOD cl_wd_utilities=>construct_wd_url
      EXPORTING
        application_name = 'YUS_SR_DEMO_MAS_V2' "Your RAP Based Odata Service
      IMPORTING
        out_host         = lv_host
        out_port         = lv_port
        out_protocol     = lv_protocol.

    " Build the full URL for accessing the Adobe PDF 
    lv_link = |http://{ lv_host }:{ lv_port }|.
    lv_url = |{ lv_link }/sap/opu/odata/sap/YUS_SR_DEMO_MAS_V2/{ lv_guid }.PDF|.

    " Cache the constructed URL with the HTTP response object
    cl_http_server=>server_cache_upload(
      url      = lv_url
      scope    = 1
      response = lo_cached_response ).

    CONCATENATE   '/opu/odata/sap/YUS_SR_DEMO_MAS_V2/' lv_guid '.' 'PDF' INTO e_url.

 

How Does It Work? This method dynamically generates a PDF URL for the Adobe form and hosts it using an HTTP response object. The RAP-based OData service YUS_SR_DEMO_MAS_V2 is used here. You can replace this service with any RAP-based OData service you are using in your application.

 

Furthermore, once you have the URL of the PDF, you can integrate it into your UI5 application. Here's how you can do it:

  • Use this code in your custom entity cds, virtual element or RAP action to get the URL.

  • In your UI5 app, show the PDF in an iframe.

Here’s how you can configure your data source in the manifest file:

"DEMO_DEV": {
    "uri": "sap",
    "type": "OData",
    "settings": {
        "annotations": [],
        "odataVersion": "2.0"
    }
}

In the controller, resolve the destination URL and combine it with the PDF URL like this:

var sDestination = that.getOwnerComponent().getManifestObject().resolveUri(that.getOwnerComponent().getManifestEntry("sap.app").dataSources.DEMO_DEV.uri); //DEMO_DEV is a datasource in manifest

var sPdfUrl = sDestination + oData.preview.Url.toString(); //PDF Url

This approach allows you to seamlessly display the Adobe form PDF in your UI5 application using an iframe.

We can do the same with Smartforms as well. This method can also be adapted to render Smartforms in a similar manner.

Feedback and Best Practices While this method achieves the goal, I am unsure if it fully aligns with SAP’s best practices. If you have suggestions or alternative approaches for displaying forms directly in RAP applications, please share them. Your feedback would be immensely helpful!

Conclusion In this approach, we are hosting the Adobe form on our RAP-based OData service. Additionally, this workaround makes it easy to integrate the PDF into your UI5/RAP application. The same method works for Smartforms as well, offering a consistent and effective solution for both technologies.

Thank you for reading my first blog!

 

ABAP RESTful Application Programming Model 

SAP Interactive Forms by Adobe  

 

 

3 Comments
Labels in this area