You are on page 1of 9

High performance of Web dynpro ABAP Added by xiaohong wu, last edited by Bharadwaj p on Nov 21, 2010 (view

change) Performance for Web dynpro is very important, because it cover more than normal ABAP program, it's also related to Wgate, the HTTP request/response cycle, so the whole design is critical. First we still have to follow the performance rule for normal ABAP program when we receive the data from database, but we have to add something more based on web side, please keep in mind the basic rule: 1. lower memory consumption, better performance. 2. using MVC, split the component up if too large, using if_wd_component_usage=>delete_component to delete all web dynpro component instances as soon as no longer needed 3. Using dynamic navigation or dynamic component usages only if it is absolutely necessary. 4. Set the lifetime of a view to when visible, if this view is displayed not too much. 5. Keep context as small as possible, Create context only required by UI binding, use assistance class or other ABAP OO class as data exchange. Use singleton node, do not use any dynamic attributes if_wd_context_node_info->add_attribute, bad context design cause huge runtime memory. 6. Don't raise exception in supply function, these cause runtime dump. 7. Do not use container scrolling (scrollingMode<>none), create application screens that fits the standard browser, avoid deep nesting of containers, groups and tabstrips, use the dynamic UI element programming only if it's necessary Model part Use assistance class as model, Creating an assistance class for a component provides the following benefits: You can store coding there that is required within the component, but is not linked directly with the layout or with the function of a controller. This could be, for example, a call of the application layer or UI-based editing of the data. Method calls of the assistance class are much better from a performance point of view than calls of methods of a Web Dynpro controller. Assistance class can store the data in the memory, The instance is available to each controller of the component through the attribute WD_ASSIST and sub component usage. The instance of assistance is in the cache at runtime can save the data has been changed. The assistance class is automatically instantiated when a component is called. The second important function of the assistance class is the management of dynamic texts. Texts that are combined at runtime only and/or contain variables can be stored in the text pool of the assistance class as text symbols. In this tutorial I'm going to show you how to add buttons change, display, save, delete, cancel and exit on the WDA, all these buttons have the same function as SAP GUI, how to use assistance class to implement those functions and how to use dynamic programming to control the property of UI elements. I also show you how to use the input-help components, use the transaction code to start the WDA and exit WDA.

Goto SE11, I created table zcustomer with field customerId(pk), company code, city, zip code, street, zcontact with fields contactId(pk), first name, last name, email, customerId is the foreign key to zcustomer and all the related technical setting. Goto SE24, I created persistence class for these 2 tables, add zcl_oo_customer as the attribute of zcl_oo_contact. Persistence class is very important way to update database if there is no BAPI available, using transaction manager of persistence class can perform faster database update, it's not the goal for this tutorial, so I didn't cover here. Database preparation: se11, I created table zcustomer and zcontact, zcontact has the FK customerid for zcustomer and related persistence classes. Create assistance: se24, zcl_wd_assist should inherit from the abstract class CL_WD_COMPONENT_ASSISTANCE, public attribute ex_contact type table zcontact, public attribute tt_contact and td_contact type table of zcontact, tt_customer and td_customer type table of zcustomer, method fill_customer with input parameter i_bukrs type bukrs, return parameter r_zcustomer type table zcustomer, methods save_customer, save_contact, delete_customer and delete_contact, those 4 methods without parameter because the value comes from the attributes. Inside those methods I call the persistence class zca_oo_customer and zca_oo_contact, When I filled the customer data in the fill_customer, I filled the data to ex_contact as well. Controller part In the controller part, I only retrieve the data and put them into context, then bind to the UI element, I try to access the database only once if no necessary, the data are temporary store in the assistance class. Preparation the controller: se80, I created WD component z_WD_customer_demo, In the component controller, add assistance class zcl_wd_assist in the property. I created zcustomer node all the attributes from DDIC, cardinality 0:N, initial lead selection, singleton, selection 1:1. Child node zcontact all the attributes from DDIC, cardinality 0:N, singleton, initial lead selection, selection 0:N. Child node input with attribute i_bukrs. Add method fill_customer in the methods of component controller directly or use the service call to call the assistance class and generate the fill_customer for you automatically. method fill_customer. method: lr_input type ref to if_wd_context_element, lr_bukrs type wd_this->element_input-i_bukrs. lr_input = wd_context->get_child_node(name = wd_this->wdctx_input)->get_element(). lr_input->get_attribute( exporting name = 'I_BUKRS' importing value = lr_bukrs). Data lwa_customer type standard table of zcustomer. lwa_customer = wd_assist->fill_customer(lr_bukrs). Wd_context->get_child_node(name = wd_this->wdctx_zcustomer)->bind_table(i_customer). Endmethod. View part

View only display the data, this is not supposed to go the database for any reason, the view controller and window controller only get the data from component controller by binding or fill the data from assistance class, which means the data is already available for view in the runtime. I created main window and popup window, main view, popup view. Main view embed in main window, popup view embed in popup window. Add exit plug in the outbound plug and check the interface property.In the main view controller, I bind all the context of component controller to view controller and add local node readonly with attribute readonly type wdy_boolean. The node zcontact with supply function supply_contact. In the layout of view controller, I add 1 input field companycode binding with attribute i_bukrs of node input, search button on right of input field. 2 trays with 2 tables binding with nodes zcustomer and zcontact, the cell editor of table column is input field. I add buttons change, display, save, delete, cancel and exit at the bottom of all the UI elements. The readonly property of each column of 2 tables zcustomer and zcontact bind to attribute readonly in the context node readonly. Search button: I only trigger the componentcontroller to get the data, then the data would be available in the assistance class instance. Method onaction_search. Wd_this->get_componentcontroller_ctr()->fill_customer(). Endmethod. Search contact: I have the data in the assistance class instance, so I just fill the data in the supply function, It's never been a good idea to access the database and raise the exception in the supply function. Since I set the singleton for the customer node which means each time all the contact node must related to only one parent node, this is also important for the performance. Method search_contact. Data: lr_customer_strc type if_main=>element_zcustomer, lr_contact_node type ref to if_wd_context_node, lr_contact_strc type ref to if_main=>element_zcontact, lr_contact type ref to if_main=>elements_zcontact, Lt_contact type table zcontact, Lwa_contact type zcontact. Parent_element->get_static_attributes(importing static_attributes = lr_customer_strc). Refresh lt_contact. Loop at wd_assist->ex_contact into lwa_contact where kunnr = lr_customer_strc-kunnr. Move-corresponding lwa_contact to lr_contact_strc. Append lr_contact_strc to lt_contact. Endloop.

lr_contact_node = wd_context->get_child_node(wd_this->wdctx_zcutomer). lr_contact_node->bind_table(new_items=lt_contact). Endmethod. Change and display button: I want to switch change/display mode, then I can change the data, I bind the attribute readonly to the readonly property of input field of table column, I control the property by the button change and display. On event handler change, I set the value 'X', on event handler display, I set the value "". Method onactiongo_change. data: lr_node type ref to IF_WD_CONTEXT_NODE,

lr_element type ref to IF_WD_CONTEXT_ELEMENT, lr_ restrict lr_node type wdy_boolean.

= wd_context->get_child_node( wd_this->wdctx_readonly ).

Lr_element = l_node->get_element( ). lr_restrict = space. *lr_restrict = "X" for display lr_element->set_attribute(exporting name = "READONLY" value = lr_restrict). Endmethod. The user select the data and change it, then they want to save the data has been changed, but the problem is the customer table is singleton and the selection mode is single, the contact table is multiple selection, and the user doesn't want to save the data immediately, he wants to save the data at the end, he may change his mind and cancel the changing or delete the data. Now you can see the beauty of assistance, I'll show you how to do that in a minutes. Event onLeadSelect of table view: On the zcustomer table view add method to the onLeadSelect event property. Method onactionrow_selected_customer. data: lr_node type ref to IF_WD_CONTEXT_NODE,

lr_element type ref to IF_WD_CONTEXT_ELEMENT, lr_customer type ref to if_main=>element_zcustomer, lwa_customer type table zcustomer. lr_node = wd_context->get_child_node( wd_this->wdctx_zcustomer ).

lr_element = l_node->get_lead_selection( ). lr_element->get_static_attributes(importing static_attributes = lr_customer).

Clear lwa_customer. Move-corresponding lr_customer to lwa_customer. Append lwa_customer to wd_assist->tt_customer. Endmethod. On the zcontact table view I select the multiple selection. Method onactionrow_selected_contact. data: lr_node type ref to IF_WD_CONTEXT_NODE,

lr_element type ref to IF_WD_CONTEXT_ELEMENT, lr_contact type ref to if_main=>element_zcontact. lt_contact type ref to if_main=>elements_zcontact, lwa_contact type zcontact, lt_contact type table zcontact. lr_node = wd_context->get_child_node( wd_this->wdctx_zcontact ).

lt_contact = lr_node->get_selected_elements( ). Loop at lt_contact into lr_element. Move-corresponding lr_element to lwa_contact. Append lwa_contact to lt_contact. Endloop. wd_assist->tt_contact = lt_contact. Endmethod. Cancel button: When the user want to cancel the change, I just refresh all the data which has been store in the assistance class, I didn't go to database yet. Method onaction_cancel. Refresh wd_assist->tt_contact. Refresh wd_assist->tt_customer. Refresh wd_assist->td_contact. Refresh wd_assist->td_customer. Endmethod.

save button: When the user decide the save the data at the end, then I let the assistance class to perform this job. Method onaction_save. Call method wd_assist->save_contact(). Call method wd_assist->save_customer(). Refresh wd_assist->tt_contact. Refresh wd_assist->tt_customer. Endmethod. Delete button: Now I'going to show you the popup window when the user wants to delete the data, I just want to remind the user what he's doing. Method onaction_delete. Data: lr_window_manager type ref to if_wd_window_manager, Lr_component_api type ref to if_wd_component, Lr_compcontroller type ref to ig_componentcontroller. Lr_compcontroller = wd_this->get_componentcontroller_ctr(). Lr_component_api = wd_comp_controller->wd_get_api(). lr_window_manager = lr_component_api->get_window_manager(). Lr_compcontroller->mr_window = lr_window_manager->create_window(window_name= "POPUP"). Lr_compcontroller->mr_window->open(). Endmethod. In the delete button I want to get a popup window to ask the client that they want to delete the value they selected. First add public attribute mr_window type if_wd_window to component controller. add 2 trays and 2 tables of zcustomer and zcontact into layout popup view, the context node and binding are the same as main view. I set the value of context node zcustomer and zcontact from the assistance class of data which the user had selected in the wddoinit method. This is also another way to show you the power of assistance. On the layout of popup view, I add textview under ROOTUIELEMENTCONTAINER, text ="Are you going to delete these data?". Add extra buttons yes, no and close on the bottom of layout, the close button I close only the popup window, not the whole application. Method onaction_yes.

Call method wd_assist->delete_customer(). Call method wd_assist->delete_contact(). refresh wd_assist->td_contact. Refresh wd_assist->td_customer. Endmethod. Method onaction_no. Refresh wd_assist->td_contact. Refresh wd_assist->td_customer. Endmethod. Method onaction_close. Data: lr_compcontroller type ref to ig_componentcontroller. Lr_compcontroller = wd_this->get_componentcontroller_ctr(). Lr_compcontroller->mr_window->close(). Endmethod. Exit the application: On the main view the user want to exit the whole application in the normal way, so I trigger the exit plug, if the user wants to visit somewhere, you can also add the url of that application in the exit plug. Method onaction_exit. Data: lr_main_window type ref to ig_main. Lr_main_window = wd_this->get_main_window_ctr(). Lr_main_window->fire_exit_plug_plg(). Endmethod. Create transaction code for WDA The fact is the user can also call the application by transaction code as normal, I'll show you how to do that. First create the application z_wd_component_demo. Goto SE93, create transaction code z_wd_comp and description, choose option Transaction with parameters (Parameter transaction)>continue>create parameter transaction, in the Transaction field enter WDYID and select the checkbox Skip initial screen. Add the necessary entries to the Default Values table by using the F4 help. The values are automatically available after you enter WDYID in the Transaction field. Add z_wd_component_demo in the application. Run the transaction z_wd_comp, you'll trigger the WD. Create freely programmed value help by component usage I also created a input value help component to limit the value help for my input field company code.

This is just an example to show you how to create the programmed value help in case there is not search help on DDIC or, the search help offer the too much data. This component usage can be reused in any where if you want. Create z_wd_comp_sh with the interface iwd_value_help in the implemented interfaces tab, click the Reimplement button. The context T001 of the component is from table T001, cardinality 0:N, the selection context node is from interface iwd_value_help, also bind to table t001. Method supply_t001. Data: lt_t001 type if_componentcontroller=>elements_t001. *this selection is just an example, normally you should get the *value from assistance Select * from t001 into corresponding fields of table lt_t001 Where bukrs = "A" or bukrs ="B" or bukrs = "C". If sy-subrc = 0. Node->bind_table(new_items = lt_t001). Endif. Endmethod. In the event tab of component controller, I defined the event data_selected, vh_window_opened and vh_window_closed as interface. Overwrite set_value_help_listener. Method set_value_help_listener. Wd_this->value_help_listener = listener. Endmethod. Overwrite do_copy method. Method onactiondo_copy. Data: lr_node type ref to if_wd_context_node, Lr_element type ref to if_wd_context_element, Ls_t001 type if_v_default=>element_t001, Ls_selection type if_v_default=>element_selection. Lr_node = wd_context->get_child_node('T001'). Lr_element = lr_node->get_lead_selection(). static_attributes = ls_t001). Lr_element=>get_static_attributes(importing

Lr_node = wd_context->get_child_node('SELECTION'). Lr_node->bind_structure(new_item = ls_t001). Wd_comp_controller->fire_data_selected_evt(). Wd_comp_controller->value_help_listener->close_window(). Endmethod. On the main component z_wd_component_demo, define the usage usage_sh in the used components tab of z_wd_comp_sh. Modify the main view add usage_sh in the property tab, change the input value help mode from search help to user-defined programming, input help component usage usage_sh. Add event handler method on_data_selected to data_selected of usage_sh. Method on_data_selected. Data: lr_node type ref to if_wd_context_node, ls_input type if_main=>element_input, Ls_sel type if_v_default=>element_selection. Lr_node = wd_contex->get_child_node('SELECTION'). Lr_node->get_static_attributes(importing static_attributes = ls_sel). Ls_input-bukrs = ls_sel-bukrs. Lr_node =wd_context->get_child_node('INPUT'). Lr_node->bind_structure (new_item =ls_input). Endmethod. Add assistance class to sub component: For the more complicated situation, we have to split up the component and add the sub component z_wd_component_sub into main component z_wd_component_demo, and add the assistance into the sub component, add the z_wd_component_sub into component usage of z_wd_component_demo as sub. Over write the wddoinit method of z_wd_component_demo Method wddoinit. Data: lr_ui_usage type ref to if_wd_component_usage. Lr_ui_usage = wd_this->wd_cpuse_sub(). If lr_ui_usage->has_active_component() is initial. Lr_ui_usage->create_component(assistance_class = wd_assist). Endif. Endmethod.

You might also like