Quantcast
Channel: Web Dynpro ABAP
Viewing all 141 articles
Browse latest View live

How to get PDF render trace of ABAP webdynpro interactiveForm control

$
0
0

In ABAP webdynpro you can use InteractiveForm control to achieve PDF render, as long as you specify the dataSource of PDF via context node, and form template uploaded via tcode SFP.

clipboard1.png

In some case you need to know the details about PDF rendering process by ADS, for example the PDF is failed to be rendered, and you want to know the root cause, or you meet with a performance issue of PDF rendering, and you want to find the bottleneck ( is it caused by too many elements in form template, or inefficient script written? ). Then you can follow the steps below to get the detail PDF render trace:

 

1. set a breakpoint on method CL_FP_PDF_OBJECT~EXECUTE_INTERNAL. Render your PDF as usual. The breakpoint should be triggered.

In the debugger callstack you can also know how the PDF render is triggered from ABAP webdynpro layer.

clipboard2.png

2. Change the variable _adstrace's content to 4 in debugger. The source code line 125 gives you a hint that you can just set a user parameter to avoid the manual change on _adstrace in debugger each time. 

clipboard3.png

System->Own Data:

clipboard4.png

And maintain the parameter value as 04.

clipboard5.png

3. Debug until you reach line 218. Click F6 to step over it.

clipboard6.png

Download the PDF binary code stored in variable l_soapresponse-rp_streams into your local laptop:

clipboard7.png

Open the local PDF, click the attachment icon as below, then you can find all types of useful information there:

 

1. the original form template

 

2. the runtime performance trace file (trace.txt)

 

3. the xml data file for the pdf (xfd.xml)

 

4. detail information raised by ADS server during PDF render time (error.pdf)

clipboard8.png

The error.pdf contains all kinds of information including warning messages raised by ADS, which could be used to improve your form template design.

clipboard9.png


New book: "100 Tips and Tricks for Web Dynpro ABAP"

$
0
0

Two weeks ago SAP Press published the following book in German:

 

 

"Web Dynpro ABAP - 100 Tipps und Tricks"

 

 

 

9783836222747.jpg

 

 

 

More about the content:

 

Wenn es darum geht, komplexe Benutzeroberflächen mit Web Dynpro ABAP effizient zu gestalten, kann Ihnen kaum einer etwas vormachen. Doch trotz Ihrer Erfahrung fragen Sie sich ab und zu, ob sich manche Aufgaben nicht noch besser lösen lassen? Die 100 Expertentipps in diesem Buch zeigen Ihnen, wie’s geht! Blättern Sie ein wenig und lesen Sie zum Beispiel, wie Sie Swap Root Element richtig einsetzen, neue Layout-Typen verwenden oder die Performance Ihrer Anwendungen optimieren. Darüber hinaus finden Sie Tipps zum Floorplan Manager. Mit diesem Buch haben Sie stets noch ein *** im Ärmel!


Aus dem Inhalt:

• Architektur und Komponenten von Web-Dynpro-Anwendungen

• Web-Dynpro-Context verwenden

• User-Interface-Elemente einbauen

• Mit Tabellen arbeiten

• Im Editor arbeiten

• Fehler beheben

• Web-Dynpro-Anwendungen analysieren

• Anwendungen mit Web Dynpro anpassen, konfigurieren und erweitern

• Administration

• Mit dem Floorplan Manager arbeiten

 

You can order the book and find out more information at

http://www.sap-press.de/3334

I'm looking forward for your Feedback.

 

Best regards

Dominik Ofenloch

How to get mandatory attribute list of ALV in Web dynpro ABAP

$
0
0

Hi,

 

Welcome, I will not take much time of yours

-------------------------------------

 

I have come across the scenario, where we need to check mandatory attributes of alv in Web dynpro abap.

 

In complex applications we may have many views with alv table data and we need to check mandatory attributes of alv tables accordingly.

 

We all know that,..... we can not perform the mandatory checks as we do for normal view fields by using methd CHECK_MANDATORY_ATTR_ON_VIEW of class CL_WD_DYNAMIC_TOOL,

instead, we need to use method CHECK_MANDATORY_ATTRIBUTES.

 

Problem:

The method CHECK_MANDATORY_ATTRIBUTES requires the attributes list, for which the mandatory check has to happen .

 

Oh, then

how to get the mandatory attributes from alv table by using VIEW reference?.

 

Then, isn't it a good idea,

          if we have a method which does the trick i.e. getting alv table mandatory attribute list by using VIEW reference.

 

Every alv table is embedded into an internal view called VIEW_TABLE and it contains all the columns details of alv during runtime.

 

Now, how to reach/get reference of  VIEW_TABLE element  from view ?

         We do get the reference of VIEW_TABLE by using recursive call of our method.

   

 

Okay, we got some idea of how we are going to get the columns of alv table using VIEW reference.

 

Now, its time to get into some coding part

 

Create a method GET_ALV_MANDATORY_ATTR as below

 

Parameters

params.PNG

 

GET_ALV_MANDATORY_ATTR

METHOD get_alv_mandatory_attr .

 

  "Define Data
  DATA:
    lt_view_elements  TYPE wdr_element_tab,
    lt_children       TYPE wdr_view_for_area_tab,
    ls_children       TYPE wdr_view_for_area_line,
    lo_wdr_view       TYPE REF TO cl_wdr_view,
    lo_wd_view        TYPE REF TO if_wd_view,
    lo_wdr_component  TYPE REF TO cl_wdr_component,
    lo_wd_column      TYPE REF TO cl_wd_table_column,
    lv_column_name    TYPE string,
    lv_node_path      TYPE string,
    lv_str            TYPE string,                          "#EC NEEDED
    lo_input_field    TYPE REF TO cl_wd_input_field,
    lt_ext_mapping    TYPE wdr_reverse_mapped_node_infos,
    ls_ext_mapping    TYPE wdr_reverse_mapped_node_info,
    ls_attr           LIKE LINE OF ct_attr_list.


  FIELD-SYMBOLS:
             <fs_view_element> TYPE wdr_element_line.

  "Get the delegating view reference and view elements
  lo_wdr_view ?= io_wd_view.

  lt_children = lo_wdr_view->children.

 

  "loop over to the view elements till the actual ALV table
  LOOP AT lt_children INTO ls_children.

 

    "Get the view object with table entries

    IF ls_children-view_object->get_id( ) EQ 'VIEW_TABLE'.

 

      lt_view_elements = lo_wdr_view->get_elements( ).


      "Loop over the view elements, set the properties


      LOOP AT lt_view_elements ASSIGNING <fs_view_element>.

 

        "if the element is an UI element proceed further to property
        "settings

 

        IF ( <fs_view_element>-view_element->_definition_name
                                            EQ 'INPUT_FIELD' ).

 

          lo_input_field ?= <fs_view_element>-view_element.

 

          IF lo_input_field->get_state( ) EQ 1.


            lo_wd_column ?= <fs_view_element>-view_element->_parent.


            lv_column_name = lo_wd_column->get_id( ).

            lo_wdr_component ?=
                      <fs_view_element>-view_element->_component.

 

            "Get external mapping details of interface controller

            lt_ext_mapping = lo_wdr_component->get_external_mappings( ).
            READ TABLE lt_ext_mapping INTO ls_ext_mapping INDEX 1.
            " Get node path
            SPLIT ls_ext_mapping-path AT '.'
                  INTO: lv_str lv_node_path.

 

            CLEAR ls_attr.
            ls_attr-node_path = lv_node_path.
            ls_attr-element_index = 0.
            ls_attr-attribute_name = lv_column_name.

            APPEND ls_attr TO ct_attr_list.

 

          ENDIF.
        ENDIF.

      ENDLOOP.

 

    ELSE.
      " Pass the next view object for recursive call
      lo_wd_view ?= ls_children-view_object.

   

     get_alv_mandatory_attr(
        EXPORTING
            io_wd_view = lo_wdr_view
        CHANGING
          ct_attr_list = ct_attr_list
    ).

 

    ENDIF.


  ENDLOOP.
ENDMETHOD.

 

Note:  The below statement

<fs_view_element>-view_element->_definition_name

                                            EQ 'INPUT_FIELD'

 

I have given an example of check for a column editor of type input field.

 

You can also check for CHECKBOX, TEXT_EDIT,DROPDOWN_BY_KEY, DROPDOWN_BY_IDX, etc

 

 

Hope this blog is helpful for those looking for getting mandatory columns of ALV table in Webdynpro ABAP using VIEW reference.

 

 

I appreciate your comments/suggestions/feedback.

 

Please award points if useful

How to disable the document edit in Word control

$
0
0
Recently I am working on a customer project and one customer requirement is they do not want to the word document be editable in the word control.
That means all buttons and menus in toolbar should be disabled.
1.png
The first idea comes to my mind is the flag "enableReadWrite".
2.png
As documented in sap helpit can fulfill my help but unfortunately it is deprecated. Regardless of this warning I have a try and found it does not work indeed.
4.png
Then I am speculating that if the document uploaded is read only, it is for sure that the toolbar will be disabled. So the issue turns to that how could I mark the document to be read only on the fly during uploading.
Since word 2007 the format of MS office follows the so called "Open office" protocal whose specification could be found here.
if you change the file type extension from .docx to .zip and open it with WinRAR, you will find the document is actually a bundle of several single files ( called document part in SAP internal ). The editability is controlled within the file settings.xml.
6.png 
if you don't know the exact syntax, just google it. I use the explaination from this one in google:
Now the task is quite easy, just add the necessary xml tag into the document source code. You do not need to manually parse the document source code since SAP has already done this job. You can just reuse standard class CL_DOCX_DOCUMENT.
Since I need to insert the document protection node in "settings" node, a simple transformation is written for this. The magic is between line 18 and 21.
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"  xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:o="urn:schemas-microsoft-com:office:office"
xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:m="http://schemas.openxmlformats.org/officeDocument/2006/math" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:w10="urn:schemas-microsoft-com:office:word"
xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main" xmlns:w14="http://schemas.microsoft.com/office/word/2010/wordml" xmlns:sl="http://schemas.openxmlformats.org/schemaLibrary/2006/main" mc:Ignorable="w14" version="1.0">  <xsl:output encoding="UTF-8" indent="no" method="xml" omit-xml-declaration="no" version="1.0"/>  <!-- Match everything all nodes and attributes -->  <xsl:template match="@*|node()">    <xsl:copy>      <xsl:apply-templates select="@*|node()"/>    </xsl:copy>  </xsl:template>  <xsl:template match="w:settings">    <xsl:element name="w:settings">      <xsl:for-each select="@*">        <xsl:copy/>      </xsl:for-each>      <xsl:element name="w:documentProtection">        <xsl:attribute name="w:edit">readOnly</xsl:attribute>        <xsl:attribute name="w:enforcement">1</xsl:attribute>      </xsl:element>      <xsl:copy-of select="./*"/>    </xsl:element>  </xsl:template></xsl:stylesheet>
and find a proper place to call the transformation:
 
 DATA: lr_element   TYPE REF TO if_wd_context_element,         lv_file_data TYPE xstring,         lv_ret       TYPE i,         lx_temp      TYPE xstring,         lv_msg       TYPE string,         lt_parms     TYPE /ipro/tt_key_value_pair,         ls_parm      LIKE LINE OF lt_parms.   lr_element = me->wd_context->get_element( ).   CHECK lr_element IS NOT INITIAL.   lr_element->get_attribute( EXPORTING name = 'BINARY' IMPORTING value = lv_file_data ).   DATA(lo_docx) = cl_docx_document=>load_document( lv_file_data  ).   DATA(lo_main_part) = lo_docx->get_maindocumentpart( ).   DATA(lo_docx_settings) = lo_main_part->get_documentsettingspart( ).   DATA(lx_settings) = lo_docx_settings->get_data( ).   /ipro/cl_docx_utilities=>transform( EXPORTING  iv_input_xstring    = lx_settings                                   iv_transform_name  = '/IPRO/DOCXCC_PROTECT'                                   it_parameters      = lt_parms                        IMPORTING  ev_result          = lx_temp                                   ev_ret             = lv_ret                                   ev_message         = lv_msg  ).   lo_docx_settings->feed_data( lx_temp ).   DATA(lx_docx_package) = lo_docx->get_package_data( ).   lr_element->set_attribute( EXPORTING name = 'BINARY'  value = lx_docx_package ).
after that the tag will be there in settings.xml:
9.png
The word control before upload document looks like below, buttons and menus available:
10.png
After upload, menu and button are disabled. If you try to edit the document, there will be notifications in the right pane to give you a hint that is not possible.
11.png
Of course this solution does not work for lower version of MS word like word2003. Fortunately my customer has enough money and they are already using Office 2013 so I do not need to worry about it

How to get mandatory attribute list of ALV in Web dynpro ABAP

$
0
0

Hi,

 

Welcome, I will not take much time of yours

-------------------------------------

 

I have come across the scenario, where we need to check mandatory attributes of alv in Web dynpro abap.

 

In complex applications we may have many views with alv table data and we need to check mandatory attributes of alv tables accordingly.

 

We all know that,..... we can not perform the mandatory checks as we do for normal view fields by using methd CHECK_MANDATORY_ATTR_ON_VIEW of class CL_WD_DYNAMIC_TOOL,

instead, we need to use method CHECK_MANDATORY_ATTRIBUTES.

 

Problem:

The method CHECK_MANDATORY_ATTRIBUTES requires the attributes list, for which the mandatory check has to happen .

 

Oh, then

how to get the mandatory attributes from alv table by using VIEW reference?.

 

Then, isn't it a good idea,

          if we have a method which does the trick i.e. getting alv table mandatory attribute list by using VIEW reference.

 

Every alv table is embedded into an internal view called VIEW_TABLE and it contains all the columns details of alv during runtime.

 

Now, how to reach/get reference of  VIEW_TABLE element  from view ?

         We do get the reference of VIEW_TABLE by using recursive call of our method.

 

 

Okay, we got some idea of how we are going to get the columns of alv table using VIEW reference.

 

Now, its time to get into some coding part

 

Create a method GET_ALV_MANDATORY_ATTR as below

 

Parameters

params.PNG

 

GET_ALV_MANDATORY_ATTR

METHOD get_alv_mandatory_attr .

 

  "Define Data
  DATA:
    lt_view_elements  TYPE wdr_element_tab,
    lt_children       TYPE wdr_view_for_area_tab,
    ls_children       TYPE wdr_view_for_area_line,
    lo_wdr_view       TYPE REF TO cl_wdr_view,
    lo_wd_view        TYPE REF TO if_wd_view,
    lo_wdr_component  TYPE REF TO cl_wdr_component,
    lo_wd_column      TYPE REF TO cl_wd_table_column,
    lv_column_name    TYPE string,
    lv_node_path      TYPE string,
    lv_str            TYPE string,                          "#EC NEEDED
    lo_input_field    TYPE REF TO cl_wd_input_field,
    lt_ext_mapping    TYPE wdr_reverse_mapped_node_infos,
    ls_ext_mapping    TYPE wdr_reverse_mapped_node_info,
    ls_attr           LIKE LINE OF ct_attr_list.


  FIELD-SYMBOLS:
             <fs_view_element> TYPE wdr_element_line.

  "Get the delegating view reference and view elements
  lo_wdr_view ?= io_wd_view.

  lt_children = lo_wdr_view->children.

 

  "loop over to the view elements till the actual ALV table
  LOOP AT lt_children INTO ls_children.

 

    "Get the view object with table entries

    IF ls_children-view_object->get_id( ) EQ 'VIEW_TABLE'.

 

      lt_view_elements = lo_wdr_view->get_elements( ).


      "Loop over the view elements, set the properties


      LOOP AT lt_view_elements ASSIGNING <fs_view_element>.

 

        "if the element is an UI element proceed further to property
        "settings

 

        IF ( <fs_view_element>-view_element->_definition_name
                                            EQ 'INPUT_FIELD' ).

 

          lo_input_field ?= <fs_view_element>-view_element.

 

          IF lo_input_field->get_state( ) EQ 1.


            lo_wd_column ?= <fs_view_element>-view_element->_parent.


            lv_column_name = lo_wd_column->get_id( ).

            lo_wdr_component ?=
                      <fs_view_element>-view_element->_component.

 

            "Get external mapping details of interface controller

            lt_ext_mapping = lo_wdr_component->get_external_mappings( ).
            READ TABLE lt_ext_mapping INTO ls_ext_mapping INDEX 1.
            " Get node path
            SPLIT ls_ext_mapping-path AT '.'
                  INTO: lv_str lv_node_path.

 

            CLEAR ls_attr.
            ls_attr-node_path = lv_node_path.
            ls_attr-element_index = 0.
            ls_attr-attribute_name = lv_column_name.

            APPEND ls_attr TO ct_attr_list.

 

          ENDIF.
        ENDIF.

      ENDLOOP.

 

    ELSE.
      " Pass the next view object for recursive call
      lo_wd_view ?= ls_children-view_object.

 

     get_alv_mandatory_attr(
        EXPORTING
            io_wd_view = lo_wd_view
        CHANGING
          ct_attr_list = ct_attr_list
    ).

 

    ENDIF.


  ENDLOOP.
ENDMETHOD.

 

Note:  The below statement

<fs_view_element>-view_element->_definition_name

                                            EQ 'INPUT_FIELD'

 

I have given an example of check for a column editor of type input field.

 

You can also check for CHECKBOX, TEXT_EDIT,DROPDOWN_BY_KEY, DROPDOWN_BY_IDX, etc

 

 

Hope this blog is helpful for those looking for getting mandatory columns of ALV table in Webdynpro ABAP using VIEW reference.

 

 

I appreciate your comments/suggestions/feedback.

Using a special tool while debugging in Web Dynpro ABAP

$
0
0


Hi, Welcome

 

I would like to demonstrate the scenario of using a special tool called "Web Dynpro" while debugging WDA applications.

 

While debugging Web dynpro applications, we would be looking for viewing the data filled at runtime in context nodes, along with available runtime objects of whole WDA component.

 

The new debugger application is having a special tool called "Web Dynpro", which helps in analyzing the WD context data at runtime along other runtime objects.

 

Pre-requisite:

Basic knowledge of Web Dynpro ABAP, OO ABAP

 

Scenario:

Here, I would like to demonstrate the simple application with a table filled with 3 rows of data as below

 

  • Creat a WDA component with a view V_MAIN
  • Create a context node with attributes FIRST_NAME & SECOND_NAME
  • Fill the data  in method WDDOINIT( )  of component controller & activate the component
  • Add an ui element TABLE and bind it to the context node of component controller
  • Creata an application and here is the out of our application

1.PNG

Now, I set "External Breakpoint" in method WDDOMODIFYVIEW( ) of view V_MAIN

 

When we run our application, the debugging window opens up as below

2.PNG

Choose your preferred desktop in debugging window & click on "New Tool" as shown in the above picture

 

Upon clicking on New tool button, a dialong box opens up as below

3.PNG

Choose  "Web Dynpro" option under "Special Tools" node ( as shown in above picture ) and now the web dynpro debugger window opens up as below

4_1.png

 

Here, we can see WD component structure with component controller, view, window information.

Chose component controller and then open the node DEMO_1, we can see the values filled inside the context node along with lead selection details

 

We can also, navigate into the context of view as below

5_1.png

Also, we can visit the component usages and analyze the data filled in respective context nodes.

 

This tool is very helpful for analysing context nodes and its data filled at runtime in complex applications

 

 

I appreciate any comments/feedback

Custom getter & setter methods in Webdynpro ABAP - Part 1

$
0
0

Hello... Welcome

 

While developing complex WDA applications, we may have to have many context nodes defined and its very much required to get and set data from/to these context nodes.

 

For getting and setting data from/to a context node, we need to follow the below process

 

  • Define data of type node ( element/elements )
  • Get the node reference by using node names
  • Get the elements using node reference
  • Get data / set data using element reference or node reference based on cardinality i.e. if cardinality is 0...1, 1..1 ( structure ) 0..n, 1...n ( table )

 

If we have many nodes in our application, say around 10-15 context nodes, we have to repeat above steps for each read/write data access

 

So, its better idea to have a common method for getting data from context node / for setting data to context node.

 

HELPER CLASS:

 

You would be wondering why this HELPER CLASS is needed ?,

 

It very much helpful to have all common methods in a class and it can be called from any view/ controller method.Hence,it is named as helper class to my application.

 

I have created the below 2 static methods in class ZCL_WD_HELPER_CLASS

  • GET_CTX_STAT_ATTR(  ) - Get static attributes / table data of context node
  • SET_CTX_STAT_ATTR(  ) - Set static attributes / table to context node

 

 

Now, let us look at these methods signature & logic

 

 

Method: GET_CTX_STAT_ATTR(  ).

 

Signature:

get.PNG

Logic:

GET_CTX_STAT_ATTR

METHOD get_ctx_stat_attr.
  DATA lo_nd                TYPE REF TO if_wd_context_node.
  DATA lo_nd_struct_descr   TYPE REF TO cl_abap_structdescr.
  DATA lo_nd_info           TYPE REF TO if_wd_context_node_info.
  DATA lo_stat_data         TYPE REF TO data.
  DATA lv_node_name         TYPE string.
  DATA lv_type_name         TYPE string.
  DATA lv_index             TYPE i.
  DATA lo_typedescr_target  TYPE REF TO cl_abap_typedescr.

  FIELD-SYMBOLS: <lt_stat_attr>     TYPE STANDARD TABLE,
                 <ls_stat_attr>     TYPE any.
  "----------------------------------------------------
  "Purpose: Get data from context node of given controller context
  "----------------------------------------------------
  CLEAR: ed_error_message,
          ed_stat_attr.

  "===================================


  "check if type of target is table
  lo_typedescr_target =
  cl_abap_typedescr=>describe_by_data( p_data = ed_stat_attr ).
  IF lo_typedescr_target IS NOT BOUND.
    RETURN.
  ENDIF.


  "check if context is supplied
  IF io_context IS  BOUND.
    lv_node_name = id_node_name.
    TRANSLATE lv_node_name TO UPPER CASE.


    TRY.
        "read node
        lo_nd = io_context->get_child_node( name = lv_node_name ).
        IF lo_nd IS BOUND.

          " Return if node is not dirty, and caller wants values only if dirty
          IF ib_only_if_dirty = abap_true AND
             lo_nd->is_changed_by_client( ) = abap_false.
            RETURN.
          ENDIF.

          "get node info
          lo_nd_info = lo_nd->get_node_info( ).
          IF lo_nd_info IS BOUND.

            "get the type descriptor of node
            lo_nd_struct_descr =
            lo_nd_info->get_static_attributes_type( ).
            "check if type name is DDtype
            IF lo_nd_struct_descr IS BOUND AND
               lo_nd_struct_descr->is_ddic_type( ) EQ abap_true.

              lv_type_name = lo_nd_struct_descr->get_relative_name( ).

              "============================================
              "based on node cardinality & supplied index,
              " create data type & get data from context

              IF lo_nd_info->is_multiple( ) EQ abap_true AND
                 id_index = 0.

                "============================================
                "return if target data type is not of kind - table

                IF  lo_typedescr_target->kind NE
                    lo_typedescr_target->kind_table.
                  ed_error_message = 'Data mismatch against context node'.
                  RETURN.
                ENDIF.

                "create data object based cardinality
                CREATE DATA lo_stat_data TYPE TABLE OF (lv_type_name).

                ASSIGN lo_stat_data->* TO <lt_stat_attr>.


                IF <lt_stat_attr> IS ASSIGNED.
                  lo_nd->get_static_attributes_table(
                   IMPORTING table = <lt_stat_attr> ).

                  ed_stat_attr = <lt_stat_attr>.
                ENDIF.
              ELSE.

                "============================================
                "return if target data type is not of kind - Structure
                IF  lo_typedescr_target->kind NE
                    lo_typedescr_target->kind_struct.
                  ed_error_message = 'Data mismatch against context node'.
                  RETURN.
                ENDIF.


                "Prepare lv_index, based on id_index
                IF id_index EQ 0.
                  lv_index = 1.
                ELSE.
                  lv_index = id_index.
                ENDIF.

                "create data object based cardinality
                CREATE DATA lo_stat_data TYPE (lv_type_name).

                ASSIGN lo_stat_data->* TO <ls_stat_attr>.

                IF <ls_stat_attr> IS ASSIGNED.
                  lo_nd->get_static_attributes(
                   EXPORTING index = lv_index
                   IMPORTING static_attributes = <ls_stat_attr> ).


                  ed_stat_attr = <ls_stat_attr>.
                ENDIF.
              ENDIF.
            ENDIF.
          ENDIF.
        ELSE.
          ed_error_message = 'Node does not exist in the provided context'.
        ENDIF.
      CATCH cx_root.                                     "#EC CATCH_ALL
        ##no_handler
        ed_error_message = 'Error occured during context node read'.
    ENDTRY.
  ELSE.
    ed_error_message = 'Context is not supplied'.
    RETURN.
  ENDIF.
ENDMETHOD.


Okay, now let us see how to use the method GET_CTX_STAT_ATTR( ) to get data from context node

 

Example:

Get data : Let us say we have a context node MY_NODE_T in component controller context with cardinality 0....n /1..n

 

DATA lt_my_node_t     TYPE wd_this->elements_my_node_t.  DATA lv_error_message TYPE string.  CALL METHOD zcl_wd_helper_class=>get_ctx_stat_attr    EXPORTING      io_context       = wd_context      id_node_name     = 'MY_NODE_T'
*     id_index         = 0
*     ib_only_if_dirty = ABAP_FALSE    IMPORTING      ed_stat_attr     = lt_my_node_t      ed_error_message = lv_error_message.

 

Get data : Let us say we have a context node MY_NODE_S in component controller context with cardinality 0....1 / 1...1

 

DATA ls_my_node_s     TYPE wd_this->element_my_node_s.  DATA lv_error_message TYPE string.  CALL METHOD zcl_wd_helper_class=>get_ctx_stat_attr    EXPORTING      io_context       = wd_context      id_node_name     = 'MY_NODE_S'
*     id_index         = 0
*     ib_only_if_dirty = ABAP_FALSE    IMPORTING      ed_stat_attr     = ls_my_node_s      ed_error_message = lv_error_message.

 

Continued.......

Custom getter & setter methods in Webdynpro ABAP - Part 2

Custom getter & setter methods in Webdynpro ABAP - Part 2

$
0
0

Hello welcome again

 

Hope, you have gone through the below link for custom getter method GET_CTX_STAT_ATTR( )

Custom getter & setter methods in Webdynpro ABAP - Part 1

 

Now, let us look into to the method SET_CTX_STAT_ATTR( ).

 

Method: SET_CTX_STAT_ATTR( )

 

Signature:

set.PNG

Logic:

Header 1

METHOD set_ctx_stat_attr.
  DATA lo_nd                TYPE REF TO if_wd_context_node.
  DATA lo_nd_info          TYPE REF TO if_wd_context_node_info.
  DATA lv_type_name        TYPE string.
  DATA lv_node_name        TYPE string.
  DATA lo_nd_struct_descr  TYPE REF TO cl_abap_structdescr.


  "----------------------------------------------------
  "Purpose: set data to context node of given controller context
  "----------------------------------------------------
  CLEAR: ed_error_message.

  "===================================
  "check if context is supplied
  IF io_context IS  BOUND.
    lv_node_name = id_node_name.
    TRANSLATE lv_node_name TO UPPER CASE.
    TRY.
        "read node
        lo_nd = io_context->get_child_node( name = lv_node_name ).
        IF lo_nd IS BOUND.
          " check if dirty flag needs to be set
          IF id_set_dirty EQ abap_true.
            lo_nd->set_changed_by_client( abap_true ).
          ENDIF.
          "get node info
          lo_nd_info = lo_nd->get_node_info( ).
          IF lo_nd_info IS BOUND.
            lo_nd_struct_descr =
            lo_nd_info->get_static_attributes_type( ).
            IF lo_nd_struct_descr IS BOUND AND
              lo_nd_struct_descr->is_ddic_type( ) EQ abap_true.
              lv_type_name = lo_nd_struct_descr->get_relative_name( ).

              "based on node cardinality, bind data
              IF lo_nd_info->is_multiple( ) EQ abap_true.
              ctx_bind_table(
                  EXPORTING io_node = lo_nd
                            id_node_name = lv_node_name
                            id_stat_attr = id_stat_attr
                            id_nd_type_name = lv_type_name
                  IMPORTING ed_error_message = ed_error_message ).

              ELSE.
                ctx_bind_structure(
                  EXPORTING io_node = lo_nd
                            id_node_name = lv_node_name
                            id_stat_attr = id_stat_attr
                            id_nd_type_name = lv_type_name
                  IMPORTING ed_error_message = ed_error_message ).

              ENDIF.
              FREE lo_nd_info.
            ENDIF.
            FREE lo_nd.
          ELSE.
            ed_error_message = text-001.
          ENDIF.
        ENDIF.
      CATCH cx_root.                                    "#EC CATCH_ALL
        ##no_handler
        ed_error_message = text-004.
    ENDTRY.
  ELSE.
    ed_error_message = text-003."context is not supplied,
    RETURN.
  ENDIF.
ENDMETHOD.

 

Now let us create 2 private methods  as below

 

  • CTX_BIND_TABLE( ) - Bind table to context node - For Internal use only
  • CTX_BIND_STRUCTURE( ) - Bind structure to context node - For Internal use only

 

Method: CTX_BIND_TABLE( )

 

Signature:

bind_table.PNG

Logic:

CTX_BIND_TABLE

METHOD CTX_BIND_TABLE.
  DATA lo_str_descr      TYPE REF TO cl_abap_structdescr.
  DATA lo_tbl_descr      TYPE REF TO cl_abap_tabledescr.
*  DATA lo_stat_data      TYPE REF TO data.
  DATA lv_nd_type_name    TYPE string.
  DATA lv_id_type_name    TYPE string.
  DATA lv_temp_type_name  TYPE string.

  FIELD-SYMBOLS: <lt_stat_attr>    TYPE STANDARD TABLE.

 

  CLEAR: ed_error_message,
        lv_nd_type_name,
        lv_id_type_name,
        lv_temp_type_name.

 

  IF io_node IS BOUND.
    lv_nd_type_name = id_nd_type_name.
    TRANSLATE lv_nd_type_name TO UPPER CASE.
    "get the type name of data provided
    lo_tbl_descr ?=
      cl_abap_tabledescr=>describe_by_data( id_stat_attr ).
    IF lo_tbl_descr IS BOUND.
      "check if the data type provided and
      "node type are same
      lo_str_descr ?= lo_tbl_descr->get_table_line_type( ).
      IF lo_str_descr IS BOUND.
        lv_id_type_name = lo_str_descr->get_relative_name( ).
      ENDIF.


      "check if the type name is used from context node
      IF lv_id_type_name NE lv_nd_type_name.
        CONCATENATE 'ELEMENT' id_node_name
        INTO lv_temp_type_name SEPARATED BY '_'.
        TRANSLATE lv_temp_type_name TO UPPER CASE.

        IF lv_id_type_name EQ lv_temp_type_name.
          lv_id_type_name = lv_nd_type_name.
        ENDIF.
      ENDIF.


      IF lv_id_type_name EQ lv_nd_type_name.
        ASSIGN id_stat_attr TO <lt_stat_attr>.
        IF <lt_stat_attr> IS ASSIGNED.
          io_node->bind_table(
          EXPORTING new_items = <lt_stat_attr> ).
        ENDIF.
      ELSE.
        ed_error_message = 'Data mismatch against context node'.
      ENDIF.
      FREE lo_tbl_descr.
    ENDIF.
  ENDIF.
ENDMETHOD.

 

 

Method: CTX_BIND_STRUCTURE( )

 

Signature:

bind_str.PNG

Logic:

CTX_BIND_STRUCTURE

METHOD CTX_BIND_STRUCTURE.

 

  DATA lo_str_descr      TYPE REF TO cl_abap_structdescr.
*  DATA lo_stat_data      TYPE REF TO data.
  DATA lv_id_stat_attr_type_name    TYPE string.
  DATA lv_temp_type_name  TYPE string.
  DATA lv_nd_type_name    TYPE string.
  FIELD-SYMBOLS: <ls_stat_attr>    TYPE any.

 

  CLEAR: ed_error_message,
        lv_nd_type_name,
        lv_id_stat_attr_type_name,
        lv_temp_type_name.

 

  IF io_node IS BOUND.
    lv_nd_type_name = id_nd_type_name.
    TRANSLATE lv_nd_type_name TO UPPER CASE.
    "get the type name of data provided
    lo_str_descr ?=
    cl_abap_structdescr=>describe_by_data( id_stat_attr ).
    "check if the data type provided and node type are same
    IF lo_str_descr IS BOUND.
      lv_id_stat_attr_type_name = lo_str_descr->get_relative_name( ).
      "check if the type name is used from context node
      IF lv_id_stat_attr_type_name NE lv_nd_type_name.
        CONCATENATE 'ELEMENT' id_node_name
        INTO lv_temp_type_name SEPARATED BY '_'.
        TRANSLATE lv_temp_type_name TO UPPER CASE.
        IF lv_id_stat_attr_type_name EQ lv_temp_type_name.
          lv_id_stat_attr_type_name = lv_nd_type_name.
        ENDIF.
      ENDIF.
      IF lv_id_stat_attr_type_name EQ lv_nd_type_name.
        ASSIGN id_stat_attr TO <ls_stat_attr>.
        IF <ls_stat_attr> IS ASSIGNED.
          io_node->set_static_attributes(
          EXPORTING index = 1
                    static_attributes = <ls_stat_attr> ).
        ENDIF.
      ELSE.
        ed_error_message = 'Data mismatch against context node'.
      ENDIF.
      FREE lo_str_descr.
    ENDIF.
  ENDIF.
ENDMETHOD.


Now, let us see how to bind data to context node by using method SET_CTX_STAT_ATTR( ).

 

Example:

Set data : Let us say we have a context node MY_NODE_T in component controller context with cardinality 0....n /1..n

DATA lt_my_node_t     TYPE wd_this->elements_my_node_t.  DATA lv_error_message TYPE string.    CALL METHOD zcl_wd_helper_class=>set_ctx_stat_attr    EXPORTING      io_context       = wd_context    " WD Context ref      id_node_name     = 'MY_NODE_T'    " Ctx Node Name      id_stat_attr     = lt_my_node_t
*     id_set_dirty     = ABAP_FALSE    IMPORTING      ed_error_message = lv_error_message.

Set data : Let us say we have a context node MY_NODE_S in component controller context with cardinality 0...1 /1..1

 

  DATA ls_my_node_s     TYPE wd_this->elements_my_node_s.  DATA lv_error_message TYPE string.    CALL METHOD zcl_wd_helper_class=>set_ctx_stat_attr    EXPORTING      io_context       = wd_context    " WD Context ref      id_node_name     = 'MY_NODE_s'    " Ctx Node Name      id_stat_attr     = ls_my_node_s
*     id_set_dirty     = ABAP_FALSE    IMPORTING      ed_error_message = lv_error_message.

 

 

Hope this helps for those who are looking for a common logic in place to get and set data from/to context node in WDA applications

 

 

I appreciate your comments/feedback


Custom timeout page for Web Dynpro applications

$
0
0

     Sometimes, users tend to open a lot of WD applications in multiple tabs. After some time (depending on SAP Basis configuration) the session is automatically closed by the application server (Web AS), which will result in a timeout. From a user's perspective this is confusing.


Requirement:

     Create a timeout page for system idles. The standard SAP response is:


     Instead, the system should return a custom (company-specific) page with both F5 (Refresh) functionality and a big "Refresh" button. For example:

timeout.png

     In transaction SICF both short dumps and session timeouts are treated as application errors:

sicf.png

     If you choose to implement an explicit response page, this will be shown for all kinds of application errors. But we don't want that, we only want to see a custom page for timeouts.

     The explicit page can be written in HTML+CSS, but a major issue is that it completely ignores JavaScript. This means, you cannot test the error type and switch between different responses.

  

Solutions:

     After trying multiple alternative, like redirecting to another URL and test the system tag <%=MESSAGE%>, I've found a working solution which is actually quite simple (Occam's razor states: "The simplest answer is usually the right one"):

     1. Create the .html page in any suitable program (Notepad++, or even a BSP application if you want to have the code available inside the system).

BSP.png

     2. You need to copy-paste the code inside an OTR long text using transaction SOTR_EDIT. (This is how the explicit pages are created in SICF)

 

     3. You'll have to create a modification in the core WD class CL_WDR_CLIENT_ABSTRACT_HTTP for method PREPROCESS_REQUEST. (This cannot be enhanced as you need access to instance attributes which is not possible inside pre-/post exits, so you'll need an access key)

wdr.png

     Here, instead of writing the code directly, I chose to call a static method in a customer class. Also, I do this because I don't want to use this timeout page in all applications. I've created a customizing table where I store the WD application name and a flag for 'Active', for all applications that should use this functionality.

 

method handle.

 
data:
    lr_server   
type ref to cl_http_server,
    lt_path      
type string_table,
    ls_appl      
type ytpf_t_appl_list,                       "#EC NEEDED
    ls_page     
type icf_response_page,
    lv_index    
type i,
    lv_service 
type string.

lr_server ?= ir_server
.
 
if lr_server is bound.

     "cl_wdr_task=>application->name can NOT be used here, as the instance is already destroyed...
   
split lr_server->m_runtime_memory_id at `/` into table lt_path[].

   
if not lt_path[] is initial.
     
describe table lt_path[] lines lv_index.
     
read table lt_path[] into lv_service index lv_index. refresh lt_path[].

     
if sy-subrc is initial.
       
translate lv_service to upper case.

 

        select single service_name active
                            
from ytpf_t_appl_list
                            
into corresponding fields of ls_appl
                            
where service_name eq lv_service
                                
and active       eq abap_true.

       
if sy-subrc is initial.
          ls_page
-body = `2C768A4E40741EE3A7A55C5708059340` "SOTR automatically generated GUID

          ir_server->set_page(
           
exporting
              response_page_type   
= ir_server->co_page_error_type
              response_option_page
= ls_page
           
exceptions
              invalid_parameter       
= 1
              document_not_found  
= 2
             
others                           = 3 ).

       
endif.
     
endif.
   
endif.
 
endif.

endmethod.

 

At runtime, if the application error type is a session timeout the explicit page is replaced with the custom page stored in the OTR long text.

This works both in IE and NWBC.

 

I've also started a discussion some time ago: Custom timeout page in SICF

 

Give it a shot and provide some feedback!

 

Tudor

WD ABAP, Search Help and ABAP Structures - A Knot

$
0
0

Background on Search Help, Structures - how its tied together to work in WD

 

Consider having multiple UI elements in a Form or table with couple them tied to automatic F4 helps. When you select a value from F4 the corresponding details / values of other fields are filled in the Form or Table. How is this done? We have our context nodes and attributes which are tied to some structures mostly. This structure in turn have Search Helps tied to them. There is a mapping done at the structure level to the fields from the Search Help. Classic !!! When this is setup properly then BINGO in WD ABAP we do not need to do anything and the values are automatically populated to the fields based on the F4.

 

Couple of Example Scenarios

 

1) Country Code and Description

2) PERNR and UserName Details

3) Order No and Descirption

4) Company Code and Description

.....and the list goes endless

 

Why this BLOG?

 

The F4 help implementation as such is a direct one when DDIC is used and there is no modifications to the standard structure. But often we end up handling with SAP standard components delivered with the business packages. One such requirement came to us to map one of the field and its description to a custom search help instead of the standard one. The Description field was read only and the code is the one that can be selected. Right away oh yeah this falls under a classic examples we saw above but the only difference is its in the standard component. We built a custom search help and then in our WD we made a call in one of our POSTEXIT's to use this custom search help through a sample code below -

 

Data: lo_nd_attrib type ref to if_wd_context_node,      lo_nd_attrib_info type ref to if_wd_context_node_info.
*  Get the Node and Attribute Information
lo_nd_attrib = wd_context->path_get_node( path = `Node PATH` ).
lo_nd_attrib_info = lo_nd_attrib->get_node_info( ).
* Set the custom search help that need to be executed for the context attribute
lo_nd_attrib_info->set_attribute_value_help( name = 'ATTRIBUTE_NAME' value_help_mode = '121' value_help = 'ZCUSTOM_SEARCHHELP' ).

Issue Faced:

 

Only the code was being populated back but the description was not mapped to the corresponding field and it was blank. I raised a question in our forum to get inputs on how this can be achieved. Enhancing F4 Search Help Issue - Standard Component

 

Thanks to Ramakrishnappa Gangappa for helping me in this thread with couple options that we discussed on achieving this solution.

 

Thought Process after hitting Roadblocks

 

From the discussion we had in the thread above I was left with either build an OVS or somehow handle the F4 close event in WDABAP Domodifyview. We are not on SAP 7.31 so there is no listeners like the register_on_enter_for_f4.

Then I came across the document written byChris Paineon Firing a WDA event on using a Search Help - how to do it, without an NDA


and thought ok this is the way I might need to approach the solution so I get the code back and through the listener classes I can handle the context elements...do a select statement to get the description based on the code selected from the F4. Yuppie !!! his blog worked like a charm and I was able to complete the requirement given .


Still Not Convinced

 

Got the solution but was not able to move on as there got to be some way that SAP provides us these values back to the front end instead taking all these approaches. Then, with the help of my colleagues and thanks a lot to them ( Mahesh Square - 2 guys but the combo had the same name ) who are core ABAPers and I wanted to check the Search Help Exit for the callcontrol-step = 'RETURN’


Tagging Magesh Basavaraj and Mahesh YS


And the SOLUTION We FOUND WAS


Basically, the standard search Help when it returns the values back there is an output flag which is set to 'X' and sent back. This was taken as the reference and we implemented the below code in our search help exit to achieve the solution !!!


DATA: shinterface TYPE DDSHIFACE.
FIELD-SYMBOLS: <lf_desc> TYPE DDSHFPROP.
IF callcontrol-step = 'RETURN'.  CLEAR: shinterface.
* A Mapping between the Search help field and the structure field has to be done here for all fields that need to carry data to Webdynpro    shinterface-SHLPFIELD = 'F4 Field'.    shinterface-VALFIELD  = 'ABAP STRUCTURE-FIELD'.    shinterface-F4FIELD   = 'X'.    APPEND shinterface TO shlp-INTERFACE.    LOOP AT SHLP-FIELDPROP ASSIGNING <lf_desc>.
* From the Search Help populate the output flag for fields that need to carry the data to Webdynpro      IF <lf_desc>-FIELDNAME = 'F4 Field_1' OR <lf_desc>-FIELDNAME = 'F4 Fild_2'.        <lf_desc>-SHLPOUTPUT = 'X'.      ENDIF.    ENDLOOP.
ENDIF.

Your Comments and critics are most welcome !!!

Open a new Window in Webdynpro as an action of a Button Click

$
0
0

Make two components of Web Dynpro ABAP, suppose one for flight Booking and the other for Customer details : Take two Webdynpro Components separately, Example: ZZ_CALLING_APPLICATION and ZZ_CALLED_APPLICATION. The navigation PDF is attached.

 

 

STEP 1: CREATE A WEBDYNPRO COMPONENT (SAY: ZZ_CALLING_APPLICATION) THAT WILL TAKE THE “Date on Which Record Was Created” MEANS AEDAT AND A BUTTON NAMED SHOW PURCHASE ORDER, AND A TABLE THAT WILL SHOW THE DETAILS OF PURCHASE ORDER OF THE MENTIONED DATE FROM EKKO TABLE.



img_1.jpg


STEP 2: CREATE AN ANOTHER COMPONENT (SAY: ZZ_CALLED_APPLICATION) WHERE TAKE A TABLE WITH ELEMENTS OF EKPO TABLE.




img_2.jpg


 

STEP 3: GOTO THE CALLING APPLICATION, SELECT THE TABLE AND GOTO THE EVENT “ON LEAD SELECTION” IN PROPERTY AND CREATE AN ACTION, SAY: ON_LEAD_SELECT.


img_3.jpg



PROPERTIES:


  img_4.jpg


STEP 4: DOUBLE CLICK ON THE EVENT NAME I.E. , ON_LEAD_SELECT AND WRITE THE CODE FOR THE ACTION TO OPEN THE SECOND APPLICATION FROM THE FIRST ONE ONCE THE USER SELECTS THE LEFT HAND SIDE OF THE DESIRED ROW.


img_5.jpg



THE PIECE OF CODE IS:


METHOD onactionon_lead_select .
DATA lo_nd_ekko_node TYPE REF TO if_wd_context_node.
DATA lo_el_ekko_node TYPE REF TO if_wd_context_element.
DATA ls_ekko_node TYPE wd_this->element_ekko_node.
DATA lv_ebeln LIKE ls_ekko_node-ebeln.
* navigate from <CONTEXT> to <EKKO_NODE> via lead selection
lo_nd_ekko_node = wd_context->get_child_node( name = wd_this->wdctx_ekko_node ).

* @TODO handle not set lead selection
IF lo_nd_ekko_node IS INITIAL.
ENDIF.

* get element via lead selection
lo_el_ekko_node = lo_nd_ekko_node->get_element(  ).

* @TODO handle not set lead selection
IF lo_el_ekko_node IS INITIAL.
ENDIF.

* alternative access  via index
* lo_el_ekko_node = lo_nd_ekko_node->get_element( index = 1 ).
* @TODO handle non existant child
* IF lo_el_ekko_node IS INITIAL.
* ENDIF.

* get single attribute
lo_el_ekko_node->get_attribute(
EXPORTING
name = 
`EBELN`
IMPORTING
value = lv_ebeln ).

DATA: lv_url
TYPE string.



CALL METHOD cl_wd_utilities=>construct_wd_url
EXPORTING
application_name =
'ZZ_CALLED_APPLICATION'
IMPORTING
out_absolute_url = lv_url.

DATA:lv_ebeln_out
TYPE string.

lv_ebeln_out = lv_ebeln.


*NOW ATTATCH THE VALUE TO THE URL AT THE RUN TIME.

CALL METHOD cl_http_server=>append_field_url
EXPORTING
name  =
'EBELN'
value = lv_ebeln_out
CHANGING
url   = lv_url.

*GENERATE THE WINDOW TO OUTPUT THE URL.

DATA:lv_comp1
TYPE REF TO if_wd_component.

lv_comp1 = wd_comp_controller->WD_GET_API( ).

DATA: lr_window_manager
TYPE REF TO if_wd_window_manager.

CALL METHOD lv_comp1->get_window_manager
RECEIVING
window_manager = lr_window_manager.

DATA: lr_window
TYPE REF TO if_wd_window.

CALL METHOD lr_window_manager->create_external_window
EXPORTING
url    = lv_url
title  = 'PURCHASE ITEM DETAILS'
RECEIVING
window = lr_window.

CALL METHOD
lr_window->open( ).


ENDMETHOD.




STEP 5: GOTO THE SECOND COMPONENT I.E., ZZ_CALLED_APPLICATION AND GOTO METHOD WDDOINIT ( ) , Controller Initialization Method, AND RIGHT THE PIECE OF CODE TO INITIALIZE THE DATA IN THE SECOND COMPONENT.



img_6.jpg



img_7.jpg


THE CODE IS:


method wddoinit .

DATA: LV_VAL
TYPE STRING.

DATA: LWA_EKPO
TYPE EKPO.

DATA: LT_EKPO
TYPE TABLE OF EKPO.

LV_VAL = WDR_TASK=>CLIENT_WINDOW->GET_PARAMETER(
'EBELN' ).




DATA lo_nd_ekpo_node TYPE REF TO if_wd_context_node.
DATA lo_el_ekpo_node TYPE REF TO if_wd_context_element.
DATA ls_ekpo_node TYPE wd_this->element_ekpo_node.
DATA LT_ekpo_node TYPE wd_this->elementS_ekpo_node.
* navigate from <CONTEXT> to <EKPO_NODE> via lead selection
lo_nd_ekpo_node = wd_context->get_child_node( name = wd_this->wdctx_ekpo_node ).


SELECT * FROM
EKPO
INTO TABLE LT_ekpo_node
WHERE EBELN = LV_VAL.

CALL METHOD lo_nd_ekpo_node->bind_table
EXPORTING
new_items            = LT_ekpo_node.



endmethod.




STEP 6 AND OUTPUT: CREATE THE WEB DYNPRO APPLICATION FOR BOTH THE COMPONENTS, AND ACTIVATE THEM AS WELL AS RUN THE FIRST. SELECT ONE DATE, ALL THE PURCHASE ORDER WILL GET OPENED OF THE SELECTED DATE FROM THE TABLE. THEN CLICK ON THE LEFT HAND SIDE OF ROW THAT YOU NEED TO SELECT FOR PURCHASE ITEM DETAILS, AND THE SECOND APPLICATION WILL GET OPENED WITH THE PURCHASE ITEM DETAILS FROM THE EKPO DB TABLE. THE SCREENSHOTS OF THE OUTPUT IS DEFINED BELOW:


img_8.jpg



img_9.jpg



img_10.jpg


CLICK ON THE LEFT HAND SIDE OF THE ROW YOU WANT TO SELECT.



img_11.jpg




img_12.jpg



THANKS & REGARDS,

 

JOYJIT BISWAS

Stateful(ish) Web Dynpro IFrames with Server Side Cookies

$
0
0

The Requirement

I recently had a requirement to embed a web based map within a Web Dynpro application to search for customers and display markers for each result found on the map.  I know there is an existing component for mapping but it's a little bit restrictive in some areas and not in line with our organisations grand plan.  Suffice to say we opted against using it and decided on Leaflet.js.  It's OpenSource and free from any vendor specific lock in (I.e. Nokia, Google, ESRI, etc).

 

The Approach

The only way for us to achieve integration with a Javascript based web map with a Web Dynpro application in NW 7.3 is via a BSP application embedded with an IFrame (but from NW 7.4 it may be possible with HTML5 integration but I've not tried it).

 

IFrames have long been a contentious subject in web development.  Most developers believe them to be evil and quick search in google can point you to a fair few posts around this. Things were so bad SAP banished them from ABAP WD (I don't know the version this happened from) deprecating it's from the language.  However in relatively recent turn of events the IFrame is back and from NW 7.03 and you can use them without fear of persecution (well almost).

 

But what about security?

In terms of security the web map has the same origin and can utilise the same authentication procedures as the Web Dynpro Application it is embedded in.

 

OK. But how can I react to the search event?

Now the SAP Help states that an IFrame should be used with caution, as the WebDynpro and the embedded content are effectively two independent applications.  Take a look at the SAP Help for more info.

 

IFrame -  Web Dynpro ABAP - SAP Library

 

As such you cannot really react to events raised from the Web Dynpro within the embedded IFrame.  You can however re-call the page, which will result in the page being rebuilt.  This may sound terrible, but bare in mind that depending on the type of content being loaded on the page , a lot of the static content should be cached after the first load, so subsequent reloads may not be so costly. 

 

On a side note as of NW 7.4 WebSockets support was introduced to ABAP.  In theory I believe it should be possible to use this to react to events triggered in ABAP within Javascript.  Unfortunately it's something I have not had a chance to try out, but hopefully in the next evolution of this it will happen....


I can't get the page to reload...

Yep. After looking at the APIs and searching the forums I could not find a way to trigger an IFrame refresh within the standard WebDynpro APIs. I'm not sure why this is not possible, but hey, that's just the way it is.  Thankfully there is a simple work around.

 

All you need to do is pass a changing request parameter in the IFrame URI for the BSP Web Map. This forces the framework and thus the browser into thinking the content has changed and results in the page refreshing.  I used a simple counter in the Web Dynpro code I wrote to get the URI for the map, that increments each time the search results were updated.

 

Please note nothing in the code for the BSP web map reacts to this additional parameter and as such it has no effect on the actual application processing.

 

METHOD get_map_uri.

  DATA: l_url         TYPE agr_url2,

        l_counter     TYPE char10,

        lt_url_params TYPE tihttpnvp,

        lo_bsp_runtime TYPEREFTO cl_bsp_runtime.

 

  FIELD-SYMBOLS: <http_param>TYPE ihttpnvp.

 

  APPENDINITIALLINETO lt_url_params ASSIGNING<http_param>.

  <http_param>-name = 'view'.

  <http_param>-value = 'AddressSearch'.

 

  APPENDINITIALLINETO lt_url_params ASSIGNING<http_param>.

  <http_param>-name = 'gui'.

  <http_param>-value = 'webdynpro'.

 

  " Add the optional sessionId param if passed

  IF im_session_id ISNOTINITIAL.

    APPENDINITIALLINETO lt_url_params ASSIGNING<http_param>.

    <http_param>-name = 's'.

    <http_param>-value = im_session_id.

  ENDIF.

 

  " Added a counter to fudge url param and trigger refresh of iframe, which works

  wd_this->g_counter = wd_this->g_counter + 1.

  l_counter = wd_this->g_counter.

  CONDENSE l_counter.

 

  APPENDINITIALLINETO lt_url_params ASSIGNING<http_param>.

  <http_param>-name = 'c'.

  <http_param>-value = l_counter.

 

  " Currently defaulting this to HTTPS but need a better way to identify this

  cl_bsp_runtime=>if_bsp_runtime~construct_bsp_url(EXPORTING    in_protocol = 'HTTP'

                                                                 in_application = 'ZEI_MAP'

                                                                 in_page = 'START.HTM'

                                                                 in_parameters = lt_url_params

                                                       IMPORTING out_abs_url = re_map_uri  ).

 

ENDMETHOD.

 

And then there is the session handling...

So how can I access the search results in my map from the WebDynpro each time the search results change.


At this point I should probably point out that I wrote a set of Restful APIs using BSP to generate GeoJSON that can be consumed by the web based map. For now that is all a little off topic for this blog and a much bigger subject in itself, as we need throw in a mix of Javascript, BSP, XML, JSON, HTTP and Simple Transformations to make it happen...

 

So let's get back on track..I don't want to embed a heap of content into the request body of the map URI called from the Web Dynpro only to then push the same content back to the server in a follow up request to retrieve the actual map data for obvious reasons.  Instead to get the search results map data I used something called server side cookies. 


They have actually been around for ages, but I only recently discovered they existed thanks to the main man of ABAP Thomas Jungwho mentioned it in a forum post.  These little gems can be used to store and retrieve large datasets on the server, independent of the session and persist them up until a specified expiry time has passed or can be explicitly deleted.  They are also super easy to implement. 

 

Server-Side Cookies and Data Persistency (SAP Library - Business Server Pages)

 

Two important fields for a server side cookie are the session ID and user ID and both must be specified when creating and retrieving them.


To get a unique session ID for my current WD application session I make a call to function module TH_GET_SESSION_ID. I subsequently use this session id to set my server side cookie for the authenticated user.  Next I set the URI of the IFrame to the web based map and also pass this session id as request parameter. 


In the web map I have some javascript code to retrieve the session id from the application request URI. I finally make the call to the Restful APIs to GET the map content and again pass this same session id as a request parameter.  Using the session ID and the user ID of the authenticated user (which is the same user as was authenticated by the Web Dynpro) I am able to retrieve the server side cookie containing the search results and use this to create the map data to pass back to the embedded web map.


Note that when setting the time a server side cookie be realistic.  Don't set huge timeouts.  In my scenario, nobody is going to click a button and wait for a response greater than one minute.  So persisting the server side cookies any longer than that makes no sense. 

 

The Conclusion

Things are not so bad with the old IFrames if used responsibly.  You'll be surprised at what you can achieve.

 

Here is a pic of the map I created and embedded within a WebDynpro ABAP FPM based search for addresses.  The map zooms to best dimensions to display all the search results on the map, each time a search is triggered.

 

Map1.PNG

 

It works nicely in Chrome, Firefox, Safari and with a little extra work on the Javascript side also works in IE (SAP dropped an IE7 compatibility mode bombsell setting in the page header, which causes havoc with JS as a lot of functionality was not around then).

HCM Process and Forms:Hiding sensitive employee information in the process overview

$
0
0

SAP standard uses WDA applications ASR_PROCESS_EXECUTE and ASR_PD_PROCESS_EXECUTE for handling HCM Process and Forms applications. These applications can also be configured in SWFVISU to launch P&F work items from UWL.

 

User can access information on people involved in the process from this application using link as shown below. On clicking process's user ID, we see information like Marital Status, Address etc. listed. If there is a requirement to remove this information for all HCM P&F Processes ( without impacting the standard functionality at any other place ), it can be achieved using  WDA component configuration, application configuration and SWFVISU without any coding change.

 

IMG1.jpg.png

 

Technical help shows application and component used.

IMG2.JPG

Create a custom application configuration and mark fields like marital status, birth date etc. as invisible UI elements.

 

Img 4.png

Create a custom application configuration and specify component configuration created in step above for address component used by the application.

Img 3.jpg

 

Once done, the final step required will be to specify corresponding custom application configuration in SWFVISU per details below.

 

 

Tasks

Application and application configuration to use

TS04000018

TS04000019

TS04000020

ASR_PD_PROCESS_EXECUTE/ < Name of application configuration for PD processes >

TS17900100

TS17900101

TS17900102

ASR_PROCESS_EXECUTE/ <name of application configuration for PA processes >

 

IMg 6.png

The curse of the Development Framework

$
0
0

I'm currently working on a really cool and challenging project, in which we're using quite some API's and frameworks that are new to me. I already know WebDynpro for ABAP. I also know FloorPlan Manager pretty well. GUIBB's are no rocket science to me either.

But there's one thing that annoys me with every new framework I learn.

 

Every development framework limits the possibilities for the developer.

 

You see, WebDynpro for ABAP is a really good framework, which allows ABAP developers to focus on the functionality code, and model the frontend via click 'n point.

Terrific, you can create really nice web-applications, without any knowledge of HTML. Great!

Except if you do know HTML really well and want to do some funky stuff. No-go in WDA.

I know, there's the HTML5 islands, but those weren't around when I first started WDA.

 

In any case, I don't want to rant about WebDynpro. I do very much still love the entire framework. It forces a developer to split out business logic from the view, and to work according to the MVC principle. I like it.  It's perfect for what it was intended to do: uniformize SAP based Web applications both in look and feel, and software architecture.

Once you know the framework, you can do really cool stuff with it.

 

Once you get to know it. That's the catch.

I've trained plenty of people in WebDynpro, and the typical classical ABAP developer can have quite some difficulty in learning it.

 

And there's plenty of frameworks to learn..

 

architecture.png

Our current architecture looks like a stack of Jenga blocks and contains lots and lots of frameworks. Somewhere in there, you see webdynpro, which itself limits the developer, but you get a lot back for those limitations:

  • HTML frontend, without writing a singe tag or Javascript line.
  • Session persistency
  • Data binding
  • uniformity across applications
  • security
  • ...

 

Trade-off

So with WebDynpro, there's a positive trade-off. You lose quite some flexibility, but you gain a lot out of the box.

Floorplan manager, in it's purest form doesn't limit you too much either. You can just compose a complete floorplan with freestyle applications.

 

But then there's the GUIBB's. There are only a dozen of UIBB types, which mean they further limit the developer possibilities.

And then there's the FBI, generic feeder, which only comes in two flavors: A form, or a list.

bummer...

 

Limitations.png

Just the idea of a generic feeder class already puzzled me. A feeder class was to intended to let the developer create the field-list definition, actions and data retrieval. A generic feeder class means that you pushdown the ABAP code even further down into some other framework, and try to strip out again, as much code as possible and replace it with configuration.

 

Sound like that old tagline again: "No developers required!"

 

Fact is, that every framework indeed further reduces the possibilities of a developer, up to the point that the developer can only do some really basic stuff and is practically obsolete. But then the complaints start coming in. The product is too limited. We want different behaviour...

 

So you ask the developer to implement these changes. Except that, the framework doesn't support it. So the developer has to work around the framework, which usually doesn't result in a nice solution, and is probably quite error-prone...

 

Final thought

And that's the curse of the framework: too little, and your developers go awol, too much and it renders itself obsolete. The more experienced your developer, the less he needs a framework, but the more he choses certain prefered productivity frameworks.

 

I like the WebDynpro framework, it manages to keep the balance, but can we stop adding more and more layers to it?

How to find a sample webdynpro for a specific UI elements

$
0
0

Usually when a sample webdynpro is required, we look into the packages like SWDP_DEMO , SALV_WD_DEMO or look for component using *DEMO*.

 

However when we need a specific UI, above methods wont help much.

 

In this blog, I am going to explain how to find a existing ABAP webdynpro where a particular UI element is implemented.

 

Behind each UI, there is an associated class. For example, CL_WD_BUTTON is used for buttons.  Doing a where used list on this class will give us the webdynpro component where it has been used.

 

Lets try to find out an existing component where Horizontal Contextual Panel is implemented.

 

  1. Look into the package SWDP_UIEL_STANDARD OR SWDP_UIEL_PATTERN for its class behind. Alternately search for CL*WD* in SE24. Match found: CL_WD_HORIZONTAL_CTX_PANEL
  2. Do where used as shown below

Capture.JPG

 

Capture2.JPG

3. List of webdynpro displayed. Choose one and press display button.

 

Untitled.jpg

Untitled.jpg

4.  You can refer this component on its usage. If component has an application, you can execute and test it as well.

 

Happy searching...


Secure transferring of parameters between WDA Applications

$
0
0

I need enough secure solution for transfer pernr number from one WDA application to Another.

We cant use parameter directly because experienced users can modify it and view restricted data.

 

Application must be completely independent without sharing interface controller variables.

 

 

Solution was found  in application HRESS_A_PERSINFO thanks to Bhaskar Tripathi's question http://scn.sap.com/message/15249282

 

 

WD component HRESS_C_PERNR_SELECTION uses Assistance Class CL_HRESS_AS_PERNR_SELECTION.

 

In Sender Apllication we write data to Memory and get random ID in  RV_MEM_ID.

 

CALL METHOD CL_HRESS_EMPLOYEE_SERVICES=>SET_PERNR_TO_MEMORY

   EXPORTING

     iv_pernr                  = lv_pernr

*     IV_DISP_CE_ASSIGTS_SCREEN =

*     IV_NON_EIC_MODE           =

   RECEIVING

     RV_MEM_ID                 = w_value

 

Then we construct URL and open second application.

 

* Get the URL of the called application

  CALL METHOD cl_wd_utilities=>construct_wd_url

    EXPORTING

      application_name = 'ZBHRWD_INC_CRiteria_ESS'

    IMPORTING

      out_absolute_url = w_url.

 

*Attach the parameters and its value with the URL that

* have to be passed to the 2nd application

  CALL METHOD cl_http_server=>append_field_url

    EXPORTING

      name  = 'PERNR_MEM_ID'

      value = w_value

    CHANGING

      url   = w_url.

 

In receiver application read the pernr by Memory ID

 

wd_assist->get_pernr_from_memory(

           exporting

           iv_pernr_mem_id      = wd_comp_controller->gv_memid

           IMPORTING

            ev_pernr = lv_pernr ).

 

In this case we need not to do authorization checks in receiver application.

Undocumented feature: How to use a Function Module as action handler in the POWL Inbox IBO_WDA_INBOX (CA-EPT-IBO)

$
0
0

Introduction

 

With the POWL Inbox (Web Dynpro Component name IBO_WDA_INBOX) customers can define custom tasks, actions and action properties just like with Business Workflow Workplace and UWL. SAP provides configuration at least for the most common ESS and MSS tasks. The POWL Inbox has two sets of configuration tables, SAP provided configuration and customer configuration tables. The most commonly used action handlers of the POWL Inbox are the Object Based Navigation (OBN) and Launchpad ones, OBJECTNAVIGATIONLAUNCHER and LAUNCHPADHANDLER respectively. There is a third one, the FUNCTIONMODULEACTIONHANDLER one. The last one isn't documented and I don't think that it is that apparent how to use it so this blog tries to address that.

 

Configuration

 

When defining actions, use FUNCTIONMODULEACTIONHANDLER as action type. When defining action properties use FUNCTIONMODULE as name and the function module you would like to invoke as value. Now this far most would have gotten just by reading the official documentation and using their gray cells, the tricky parts are to follow.

 

First thing you should know is that the function module to be used has to have generic (e.g. simple) import, export, tables and exceptions. For example LIKE isn't supported (only TYPE is) nor are complex types such as references (TYPE REF). The next thing to take notice of is that other action properties (besides FUNCTIONMODULE) that you define are considered as parameters of the function module. Let's say you define an action property named WI_ID with a value of WI_ID=${ITEM.EXTERNALID}. Doing so means your function module should have WI_ID as an import parameter (preferably of type SWW_WIID) to have the work item ID automatically passed to it. Another hard coded feature of the function module action handler is that it assumes to get error messages in a table named MESSAGE_LINES, similar to most SAP_WAPI function modules.

 

If you want to understand it in detail, have a look at the ABAP class CL_IBO_CH_WD_INB_ACTHDL_FM.

 

Conclusion

 

The function module action handler can be very useful. I used it myself to call a wrapper function module for SAP_WAPI_WORKITEM_COMPLETE in order to complete a work item just by clicking it. It's a shame that this feature might remain unnoticed by the masses if only relying on official documentation.

 

Links

 

The official documentation for the POWL Inbox can be found here. In order to learn more about the POWL Inbox, read POWL Inbox configurations for Manager Self-Service EhP5 and above and How to enable the existing Webdynpro based workflow inboxes to execute ALL tasks without config!.

Calling Transaction in SAP GUI

$
0
0

Calling SAP Transaction from WDA is a common requirement. There is a way to call SAP transaction in Web GUI. This is not an option in some cases.


Imagine a client that is using SAP GUI to run both SAP Transactions and WDAs. Such client wants to keep user interface consistent e.g. whenever WDA calls SAP transaction it needs to be run in SAP GUI (no jumps between SAP GUI and Web GUI).


There is an OOTB solution. Simply put, WDA needs to create SAP Shortcut and download it when user clicks on a link.

 

Below are screenshots of demo WDA that runs in SAP GUI and shows a list of SAP Flight model tables. Clicking on a table name from the list will call SE16 transaction in SAP GUI.

 

1. Call Z_WD_2_ABAP Transaction

Call Z_WD_2_ABAP Transaction.jpg

 

2. Click on a link

Click on a link.jpg

 

3. Confirm download

Confirm SAP Shortcut download.jpg

 

4. Voilà

Voilà.jpg

 

Below are step by step instructions how to create this demo WDA:

 

1. Create Z_WD_2_ABAP Component

Create Z_WD_2_ABAP Component.jpg

 

2. Create SFLIGHT context node in MAIN view. Set the context node cardinality to 0..1. Add two attributes: TABLENAME of type TABNAME and DESCRIPTION of type DDTEXT

Create SFLIGHT Context Node.jpg

 

3. Create VIEWCONTAINER ViewContainerUIElement on MAIN view

Create VIEWCONTAINER ViewContainerUIElement.jpg

 

4. Add ALV use of SALV_WD_TABLE Component to Z_WD_2_ABAP Component

Add ALV Component Use of SALV_WD_TABLE Component.jpg

 

5. Add ALV use of SAV_WD_TABLE Component to MAIN View

Add ALV Use of SALV_WD_TABLE to MAIN View.jpg

 

6. Embed TABLE view of SALV_WD_TABLE used component into VIEWCONTAINER element

Embed TABLE View of SALV_WD_TABLE Component into  VIEWCONTAINER Element.jpg

 

7. Implement WDDOINIT method of MAIN view

Note: code below populates ALV table with a list of SAP FLIGHT model tables

 

METHOD wddoinit.
DATA: wd_sflightTYPE wd_this->elements_sflight.
DATA: node_sflightTYPE REF TO if_wd_context_node.
DATA: wa_columnTYPE salv_wd_s_column_ref,
      wt_column
TYPE salv_wd_t_column_ref.
DATA: component      TYPE REF TO if_wd_component_usage,
      interface     
TYPE REF TO iwci_salv_wd_table,
      config         
TYPE REF TO cl_salv_wd_config_table,
      table_settings 
TYPE REF TO if_salv_wd_table_settings,
      std_functions 
TYPE REF TO if_salv_wd_std_functions,
      column_settings
TYPE REF TO if_salv_wd_column_settings,
      column         
TYPE REF TO cl_salv_wd_column,
      column_header 
TYPE REF TO cl_salv_wd_column_header,
      action         
TYPE REF TO cl_salv_wd_uie_link_to_action.

 
SELECT l~tabnameAS tablenamet~ddtextAS description
 
INTO CORRESPONDINGFIELDS OF TABLE wd_sflight
 
FROM ( dd02l AS l INNERJOIN dd02t AS t
                           
ON l~tabname= t~tabname)
                   
INNERJOIN tadirAS d
                           
ON l~tabname= d~obj_name
 
WHERE t~ddlanguage= 'E'
   
AND d~object    = 'TABL'
   
AND d~devclass  = 'SAPBC_DATAMODEL'.
  node_sflight
= wd_context->get_child_node( wd_this->wdctx_sflight).
  node_sflight
->bind_table( new_items= wd_sflight).

  component
wd_this->wd_cpuse_alv( ).
 
IF component->has_active_component( ) IS INITIAL.
    component
->create_component( ).
 
ENDIF.

  interface
= wd_this->wd_cpifc_alv( ).
  interface
->set_data( node_sflight).
  config
= interface->get_model( ).

  table_settings ?= config.
  table_settings
->set_selection_mode(cl_wd_table=>e_selection_mode-none ).
  table_settings
->set_visible_row_count(20 ).

  std_functions ?= config.
  std_functions
->set_view_list_allowed(abap_false).
  std_functions
->set_filter_filterline_allowed(abap_false).
  std_functions
->set_dialog_settings_allowed(abap_false).
  std_functions
->set_pdf_allowed(abap_false).
  std_functions
->set_export_allowed(abap_false).

  column_settings ?= config.
  wt_column
= column_settings->get_columns( ).
 
LOOP AT wt_columnINTO wa_column.
    column
= wa_column-r_column.
   
CASE wa_column-id.
   
WHEN 'TABLENAME'.
     
CREATE OBJECT action.
      action
->set_tooltip_fieldname( wa_column-id).
      action
->set_text_fieldname( wa_column-id).
      action
->set_type( cl_wd_link_to_action=>e_type-navigation ).
      column
->set_cell_editor( action ).
   
WHEN 'DESCRIPTION'.
      column_header
= column->get_header( ).
      column_header
->set_text('Description' ).
      column_header
->set_tooltip('Description' ).
      column_header
->set_ddic_binding_field(
        if_salv_wd_c_column_settings
=>ddic_bind_none).
   
ENDCASE.
 
ENDLOOP.

ENDMETHOD.


8. Create ON_CLICK event handler method for ON_CLICK Event of ALV usage

Create ON_CLICK Event Handler Method for ON_CLICK Event of ALV Usage.jpg

 

9.  Implement ON_CLICK event handler method

Program logic:

- Get clicked table name;

- Set trx. SE16 Table Name field to clicked table name;

- Create SE16 SAP Shortcut skipping first screen. See Note 103019 - SAPshortcut: Program parameters for more information.

- Download SAP Shortcut

 

METHOD on_click.
DATA: w_filenameTYPE string.
DATA: w_parameterTYPE text255.
DATA: w_shortcutTYPE xstring.
DATA: wt_shortcutTYPE soli_tab.
FIELD-SYMBOLS: <tablename> TYPE tabname.

* Get clicked table name
  ASSIGN r_param->value->* TO <tablename>.

* Set trx. SE16 Table Name field to clicked table name
  CONCATENATE 'DATABROWSE-TABLENAME=' <tablename> INTO w_parameter.
* Create SE16 SAP Shortcut skipping first screen
  CALL FUNCTION 'SWN_CREATE_SHORTCUT'
     
EXPORTING
            i_transaction  =
'*SE16'
            i_parameter   
= w_parameter
     
IMPORTING
            shortcut_table
= wt_shortcut.
  w_shortcut
= cl_bcs_convert=>raw_to_xstring(it_soli= wt_shortcut).
  CONCATENATE 'Table_' <tablename> '.sap' INTO w_filename.

 

* Dowload SAP Shortcut
  cl_wd_runtime_services
=>attach_file_to_response(
    i_filename     
= w_filename
    i_content       
= w_shortcut
    i_mime_type     
= 'sap' ).

ENDMETHOD.

 


10. Create Z_WD_2_ABAP Application

Create Z_WD_2_ABAP Application.jpg

 

11. Create Z_WD_2_ABAP parameter transaction

Create Z_WD_2_ABAP Transaction with parameters.jpg

Code Snippet Series: Trimming Leading and Trailing Whitespace

$
0
0

This post is part of a series on code snippets. The complete list of posts in the series is available in the document Code Snippets: A Blog Series.

 

ABAP keyword CONDENSE is useful to remove leading and trailing space characters from a character string, however CONDENSE does not recognize other non-printing whitespace characters such as carriage returns, newlines and horizontal tabs.

 

Regular expressions give us a useful tool to recognize a wide variety of whitespace characters. The regular expression abbreviation [[:space:]], alternatively written as \s, represents the character set for all non-printing blank characters including space, carriage return, newline and horizontal tab.

 

The method below removes first trailing then leading whitespace characters from a changing parameter a_string of type string. This code may be used in any ABAP routine but is particularly useful for post-processing of user input in Web Dynpro UI elements such as a TextEdit.

 

METHOD trim_whitespace.  DATA lv_strlen TYPE i.  DATA lv_char TYPE string.
* Remove trailing whitespace from a_string  DO.      lv_strlen = strlen( a_string ) - 1.      lv_char = a_string+lv_strlen(1).      FIND REGEX '[[:space:]]' IN lv_char.      CASE sy-subrc.          WHEN 0.              SHIFT a_string RIGHT DELETING TRAILING lv_char.          WHEN OTHERS.              EXIT.      ENDCASE.  ENDDO.
* Remove leading whitespace from a_string  DO.      lv_char = a_string+0(1).      FIND REGEX '[[:space:]]' IN lv_char.      CASE sy-subrc.          WHEN 0.              SHIFT a_string LEFT DELETING LEADING lv_char.          WHEN OTHERS.              EXIT.      ENDCASE.  ENDDO.
ENDMETHOD.

POWL CHIP or Workload CHIP

$
0
0

Workload CHIP (POWL Link List)

 

Displays categories and links to a personalized selection of worklists in a summary-like format.

 

Overview

With the CHIP "POWL Link List" you can embedd the navigation part of the original POWL UI into Page Builder.

 

Configuration

The following parameter need to be set on configuration level (not visible in personalization level):

 POWL Application ID: The identifier of your POWL application. Input help available

 Configuration Identification: This is the Web Dynpro configuration used by the POWL framework to determine the OBN targets for POWL applications. By default the configuration "POWL_COLLECTOR_DEFAULT_CONFIG" is used, which maps any POWL application to the OBN target "POWL.DISPLAY"

 Enable Personalization: By setting this flag you allow the end user to access the personalization features for the POWL navigation area.

 

Multiple Applications

It is possible to show content from multiple POWL applications within the same CHIP:

 Create a new application which acts as group (TA FPB_MAINTAIN_HIER)

 Then assign this group application as parent of all your applications

 In the configuration of the POWL Link List you select the group application as POWL Application ID.

 All child applications of the group will be collected and displayed. Ordering is done automatically.

 

Navigation

 

If you only have one Workload CHIP in your role, you only need one navigation information. By default OBN target information BO System "SAP_ERP_Common", BO Name "POWL" and BO Operation "DISPLAY" is used. If you would like to use more than one Workload CHIP within your role, you have to define a component configuration for WD component POWL_COLLECTOR. You then use the configuration in the CHIP configuration identification field.

 

 

Step-by-Step

1. Add the POWL Link List CHIP to the page.

2. Configure the CHIP via "Define Link List"

3. Set the title of the CHIP (e.g. "Workload")

4. Save the Page.

Viewing all 141 articles
Browse latest View live


<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>