Google+ Facebook Twitter MySpace SC

Friday, August 24, 2012

WebDynproModel


WebDynproModel


This chapter presents the role of a model in a multicomponentWeb Dynpro application, showing not only themodality to use such a model, but also to create it. We are going to focus on three types of models: Assistance class, BAPI and Web Service.
So far,we have created only small applications used to access the data contained in a table,through the SQL statements introduced in the methods defined in the views. This art of programming is not in concordance with the MVC design pattern.
According to the Model View Controller MVC paradigm,the application data and their user interface are separated. The Model represents the business logic, the View represents the user interface and the controller has certain responsibilities, as the communication between the model and the view,or data processing at runtime.

In this way,it is possible to change the user interface without changing the business logic,or it is possible to change the business logic without having to change the user interface.In the same time,we can reuse the same business logic for more user interfaces.
In the Web Dynpro ABAP, the model can be implemented by the:
  • Assistance class
  • BAPI
  • WebService
  • Faceless Component,etc.
A Web Service can be compared with a “black box” that offers certain functionalities.These functionalities can be integrated in a client application (in our case,Web dynpro ABAP)that consumes the respective web service. In this respect,a Web Servicemay require certain inputs fromthe client application and delivers it the proper answer.Usually, Web Services are used to communicate between different platforms.
As mentioned before,an assistance class is a normal ABAP class that inherits from the CL_WD_COMPONENT_ASSISTANCE.Each Web Dynpro component can have a uniquely assigned assistance class that offers certain benefits,as follows:
  • It works with text symbols
  • It’s more advantageous to call its methods than to call the methods defined in a Web Dynpro controller.
The Business Application Program Interfaces (BAPI)are specific methods for business object types that offer the possibility to access external data and processes.
The Faceless Component is a Web Dynpro Component that doesn’t have any View or Window;in conclusion, it’s a Component that doesn’t have any User Interface,but it encapsulates functionality and can be used to build a Model.
Assistance Class as a Model for a Multicomponent Application
Essentially,each ABAP class can be used as a model. The particularity of an assistance classes is that we can assign it to a Web Dynpro component and it is automatically instantiated when the proper component is called.
We create an assistance class named YCL_AC_MODEL.
Assistance class
In this assistance class,we create three methods named SEARCH_CANDIDAT,SELECT_CANDIDATE and INSERT_CANDIDATE. Here, we store the coding required within the WD components to look for a candidate,to select all the candidates and to insert information about a candidate into or from the database table YPERSON.
Methods for the assistance class
Before implementing our methods,we created the lowest level of coding that abstracts the data access.In this case,we choose to implement the simplest data access method by using the classical ABAP tools,respective through the Function Modules,but we can also use other tools,e.g.the Persistent Object Classes,required to benefit of the object oriented programming(OOP).In case we want to use Persistent Objects to access the data from the database table in the Object Oriented mode,we can use for our Web Dynpro project the same structure (by taking the Assistance class as a model). But,in this case,we have to replace the Function Modules with Persistent Classes.table One of the created Function Modules will be used later,as the end point for a BAPI.It will be also used to create a Web Service.
A Function Module (FM)is a procedure with public interface, which can be created within a Function Group. To create a Function Group, we select Create--> Function Group from the context menu of our package name. We create a Function Group named YFG_DBACCESS.Here,we implement three FMs,named.
YFM_SEARCH_ CANDIDATE,
YFM_SELECT_CANDIDATE and YFM_ INSERT_CANDIDATE.
Listing shows the implementation of YFM_SEARCH_CANDIDATE.
The exception class YCX_EXCEPTION_T100_TXT was defined hereinbefore,when we have seen how we can work with the exception classes in WD.
Shows the implementation of YFM_SEARCH_CANDIDATE
 FUNCTION YFM_SEARCH_CANDIDATE .
 *"--------------------------------------------------------------------
 *"*"Local Interface:
 *" IMPORTING
 *" VALUE(ID_CANDIDATE)TYPE YPERSON-ID_PERSON
 *" EXPORTING
 *" VALUE(ITAB)TYPE YTABLE_TYPE
 *" RAISING
 *" YCX_EXCEPTION_T100_TXT
 *"----------------------------------------------------------------------
 TRY.
 SELECT *
 FROM yperson
 INTO TABLE itab WHERE id_person = id_candidate.
 IF sy-subrc <> 0.
 RAISE EXCEPTION TYPE ycx_exception_t100_txt
 EXPORTING
 textid = ycx_exception_t100_txt=>ycx_no_candidate
 id_candidate = id_candidate.
 ENDIF.
 ENDTRY.
 ENDFUNCTION.
Listing Implementation of YFM_SELECT_CANDIDATE
 FUNCTION YFM_SELECT_CANDIDATE.
 *"------------------------------------------------
 *"*"Local Interface:
 *" EXPORTING
 *" VALUE(ITAB) TYPE YTABLE_TYPE
 *" RAISING
 *" YCX_EXCEPTION_T100_TXT
 *"-------------------------------------------------
 TRY.
 SELECT *
 FROM yperson
 INTO TABLE itab.
 IF sy-subrc <> 0.
 RAISE EXCEPTION TYPE ycx_exception_t100_txt
 EXPORTING
 textid = ycx_exception_t100_txt=>ycx_select_no_posible.
 ENDIF.
 ENDTRY.
 ENDFUNCTION.
This FM selects the information about all the candidates. In this case,we create a new message ID–001“Data cannot be selected!”and a new exception ID YCX_ SELECT_NO_POSSIBLE with the text from the message class – message ID 001
Listing shows the implementation of YFM_INSERT_CANDIDATE
 FUNCTION YFM_INSERT_CANDIDATE .
 *"------------------------------------------
 *"*"Local Interface:
 *" IMPORTING
 *" VALUE(ID_CANDIDATE)TYPE YPERSON-ID_PERSON
 *" VALUE(FIRSTNAME)TYPE YPERSON-FIRSTNAME
 *" VALUE(LASTNAME)TYPE YPERSON-LASTNAME
 *" VALUE(AGE) TYPE YPERSON-AGE
 *" VALUE(TELEPHONE)TYPE YPERSON-TELEPHONE
 *" VALUE(ID_COUNTRY)TYPE YPERSON-ID_COUNTRY
 *" RAISING
 *" YCX_EXCEPTION_T100_TXT
 *"------------------------------------------
 DATA wa_person TYPE yperson.
 wa_person-mandt = sy-mandt.
 wa_person-id_person =id_candidate.
 wa_person-firstname =firstname.
 wa_person-lastname =lastname.
 wa_person-age = age.
 wa_person-telephone =telephone.
 wa_person-id_country =id_country.
 TRY.
 INSERT into yperson values wa_person.
 IF sy-subrc <> 0.
 RAISE EXCEPTION TYPE ycx_exception_t100_txt
 EXPORTING textid = ycx_exception_t100_txt=>ycx_insert_no_possible.
 ENDIF.
 ENDTRY.
 ENDFUNCTION.
This FM inserts in the database table YPERSON the information about a candidate.In this case,we create a new message ID–002 “Candidate insert cannot be done!”and a new exception ID YCX_INSERT_NO_POSSIBLE with the text from the message class – message ID 002.
A FM can be tested by using the Test/Execute Button .In this way,we can check if our created FM works correctly.Then,we implement our first method from the assistance class.
Implementation of the SEARCH_CANDIDATE method
Pattern
Implementation of the SELECT_CANDIDATE method
 Implementation of the INSERT_CANDIDATE method
The Class Builder provides a test environment for classes.We can test our class by using the same test/execute Button.
Testing the assistance class
In this way,we have autonomous units that can be independently tested before we integrate them into bigger applications. If we look backwards to the example that refers to the Exception class with OTR text,we can see that the entire coding was integrated in a method of the view controller.So,we didn’t separate the application layer from the business layer and from the presentation layer.
We create the presentation layer through a WD application. We create a main component named Y_MAIN,in which we will use three secondary elements:
Y_SEARCH,Y_SELECT and Y_INSERT.
WD component’s structure
All the components defined the same assistance class,the YCL_AC_MODEL.Any changes made to the model class in the Framework are available for any other component that has this model class defined as assistance class.In this way,we can share data among components.
As we have mentioned above,each ABAP class can be used as a model class,but the services offered by the Web Dynpro Framework in this respect are available only for an assistance class that inherits the abstract class CL_WD_COMPONENT_ASSISTANCE.
The Y_MAIN component represented the start point of this application;it is the only component that has a Web Dynpro application defined.We assign our assistance class YCL_AC_MODEL for our components.
Assistance class assigned to our components
The V_MAIN layout
By using the ViewContainerUIElement,we show one of the views:
V_SELECT,V_INSERT or V_SEARCH.
To be able to navigate among the three used Views,we have to define three outbound plugs.Figure shows the defined outbound plugs and the window structure.
Outbound plugs
Before being able to create the instance of the used components,e have to create usages at the V_MAIN View level.
When the user presses the linkToAction UI element–Insert–the Framework triggers the event handler method onactioninsert.
Event handler method
 METHOD onactioninsert .
 DATA: lr_cmp_usage TYPE REF TO if_wd_component_usage.
 lr_cmp_usage = wd_this->wd_cpuse_insert( ).
 IF lr_cmp_usage->has_active_component( ) IS INITIAL.
 lr_cmp_usage->create_component(assistance_class = me->wd_assist).
 ENDIF.
 Wd_this-fire_op_to_v_insert_plg( ).
 ENDMETHOD.
As we can see,through the statement
lr_cmp_usage--> create_component (assistance_class = me >wd_assist), the existing instance for the assistance class that belongs to the main component is assigned to the used component instance.In this way,we ensure that both components access the same instance of the assistance class.
The event handler methods onactionselect and onactionsearch have the same structure,excepting the outbound plug NAME that is fired when the user presses the respective linkToAction UI elements.
Listing Event handler methods
 METHOD onactionsearch .
 ….…….
 wd_this->fire_op_to_v_search_plg( ).
 ENDMETHOD.
 METHOD onactionselect.
 ……………
 wd_this->fire_op_to_v_select_plg( ).
 ENDMETHOD.
In this way,we create the instance of the used component and we specify the reference to the active instance of the assistance class.
The V_SELECT view layout and the context structure are presented.
View layout and context
Here,we show all the records from our YPERSON database table. The node “CANDIDATE” has the dictionary structure YPERSON, cardinality 1...n, Singleton,supply function SUPPLY_CANDIDATE. Listing Supply function method
METHOD supply_candidate.
wd_this->populate_node( ).
ENDMETHOD
As we can see,we call the user defined method POPULATE_NODE to populate the context node with values. We have chosen to create this method in order to populate with data the context node and to update its contained data every time the user presses the Refresh button.
When the component Y_SELECT is called,the assistance class is automatically instantiated. Then,this instance is available through the attribute WD_ASSIST:
lt_person = wd_assist!select_candidate( ).
The POPULATE_NODE method
 METHOD populate_node.
 DATA lr_node TYPE REF TO if_wd_context_node.
 DATA ls_data TYPE wd_this->element_candidate.
 DATA lr_oref TYPE REF TO ycx_exception_t100_txt.
 DATA lt_person TYPE STANDARD TABLE OF yperson.
 lr_node = wd_context->get_child_node('CANDIDATE').
 TRY.
 lt_person = wd_assist->select_candidate( ).
 lr_node->bind_table(new_items = lt_person).
 CATCH ycx_exception_t100_txt INTO lr_oref.
 DATA lr_api_controller TYPE REF TO if_wd_controller.
 DATA lr_message_manager TYPE REF TO if_wd_message_manager.
 lr_api_controller ?= wd_this->wd_get_api( ).
 lr_message_manager = lr_api_controller->get_message_manager( ).
 lr_message_manager->report_exception(message_object =lr_oref).
 ENDTRY.
 ENDMETHOD.
In this way,we call the method select_candidate from the assistance class and we pass the result in the lt_person internal table.
When the user presses the Refresh button, the Framework triggers the event handler method onactionrefresh.
Listing The ONACTIONREFRESH event handler method
 METHOD onactionrefresh.
 wd_this->populate_node( ).
 ENDMETHOD.
View layout and the view context
The CANDIDATE node has the dictionary structure YPERSON, cardinality 1...1,Singleton.By using this component,we insert records in our database table YPERSON.
When the user presses the Save Button,the Framework triggers the event handler method onactionsave.
The onactionsave event handler method
 METHOD onactionsave.
 DATA lr_oref TYPE REF TO ycx_exception_t100_txt.
 DATA lr_node TYPE REF TO if_wd_context_node.
 DATA lr_element TYPE REF TO if_wd_context_element.
 DATA ls_data TYPE wd_this->element_candidate.
 DATA: lv_firstname LIKE ls_data-firstname,
 lv_lastname LIKE ls_data-lastname,
 lv_age LIKE ls_data-age,
 lv_telephone LIKE ls_data-telephone,
 lv_id_country LIKE ls_data-id_country.
 lr_node = wd_context->get_child_node('CANDIDATE').
 lr_element = lr_node->get_element( ).
 lr_element->get_static_attributes(
 IMPORTING static_attributes = ls_data).
 lv_firstname =ls_data-firstname.
 lv_lastname =ls_data-lastname.
 lv_age = ls_data-age.
 lv_telephone = ls_data-telephone.
 lv_id_country = ls_data-id_country.
 TRY.
 wd_assist->insert_candidate(firstname = lv_firstname
 lastname = lv_lastname age = lv_age telephone = lv_telephone
 id_country = lv_id_country ).
 DATA: lv_success_text TYPE string.
 lv_success_text = wd_assist->if_wd_component_assistance~get_text('M01').
 wd_this->atr_mm->report_success(message_text = lv_success_text).
 CATCH ycx_exception_t100_txt INTO lr_oref.
 wd_this->atr_mm->report_exception(message_object = lr_oref) .
 ENDTRY.
 ENDMETHOD.
We have to firstly verify if the end user has inserted values in all the mandatory fields.To perform this check,we use the wdDoBeforeReaction Hook method that has the structure presented inthe“view controller methods”chapter.
If the user has inserted values in all the fields,we call the method insert_candidate from the model class and we pass the inserted values in the method parameters.
wd_assist!insert_candidate(firstname = lv_firstname lastname = lv_lastname age = lv_age telephone = lv_telephone id_country = lv_id_country).
In case the data were successfully saved,we informthe end user about this,through a message defined in our assistance class with the identification symbol - M01.
When an exception occurs,we show to the end user this message through the report_exception method.
“Atr_mm” represents an attribute created in the attribute tag of the current view.
This is declared of ref to if_wd_message_manager type.By using the wdDoInit Hook method,we pass in the atr_mm attribute the reference to the Message Manager:method,we pass in the atr_mm attribute the reference to the Message Manager:
DATA lr_api_controller TYPE REF TO if_wd_controller.lr_api_controller ?= wd_this-->;wd_get_api( ).
wd_this!atr_mm = lr_api_controller-->get_message_ manager( ).
View layout and context structure
The context structure is the same as for the context realized to exemplify the exception class with OTR text. When the user presses the Search Button,the Framework triggers the onactionsearch event handler method.
Event handler method
 METHOD onactionsearch.
 DATA lr_oref TYPE REF TO ycx_exception_t100_txt.
 DATA: lt_candidate TYPE STANDARD TABLE OF yperson,lr_node TYPE REF
 TO if_wd_context_node,lv_id_candidate TYPE yperson-id_person.
 lr_node = wd_context->get_child_node('SEARCH').
 lr_node->get_attribute(EXPORTING name ='ID_PERSON'IMPORTING value = 
 lv_id_candidate).
 TRY.
 lt_candidate =
 wd_assist->search_candidate(id_candidate = lv_id_candidate).
 DATA lr_subnode TYPE REF TO if_wd_context_node.
 lr_subnode = lr_node->get_child_node('PERSON').
 lr_subnode->bind_table(new_items = lt_candidate).
 CATCH ycx_exception_t100_txt INTO lr_oref.
 wd_this->atr_mm->report_exception(message_object = lr_oref ).
 ENDTRY.
 ENDMETHOD.
When the component Y_SEARCH is called,the assistance class is automatically instantiated.Then,this instance is available through the attribute WD_ASSIST:
lt_candidate = wd_assist!search_candidate(id_candidate = lv_id_candidate). In this way,we call the method search_candidate from the assistance class and we pass the result in the lt_candidate internal table. When an exception occurs, we show the message to the end user,through the report_exception method.
run time
 We can extend our application by adding the possibility to change a candidate record.For the database table YPERSON, we have defined in the ABAP Dictionary a Lock Object. We can use it to synchronize the access to the same data in our database table YPERSON with more that one WD application.
Locking objects
To set a lock and to release a lock, we can define,in our assistance class,two additional methods that use the generated Function Modules  ENQUEUE_YPERSON and DEQUEUE_YPERSON. After this,we call our defined methods from our WD methods every time we want to lock one or more data records or to release the locked data records.
In case we need to perform a search in a database table to find all the records that contain a certain searched pattern, we can use the ABAP classes CL_ABAP_ REGEX and CL_ABAP_MATCHER. In our case,we search the database table YPERSON, column “firstname”,to find all the records that contain the string we are looking for.This value will be found in the local variable lv_firstname.
Search with CL_ABAP_MATCHER
 TYPES: BEGIN OF st_person,
 mandt TYPE yperson-mandt,
 id_person TYPE yperson-id_person,
 firstname TYPE yperson-firstname,
 lastname TYPE yperson-lastname,
 telephone TYPE yperson-telephone,
 age TYPE yperson-age,
 id_country TYPE yperson-id_country,
 END OF st_person.
 DATA: it_person TYPE TABLE OF st_person,
 lv_firstname TYPE yperson-firstname.
 FIELD-SYMBOLS <fs_person> LIKE LINE OF it_person.
 SELECT * FROM yperson INTO TABLE it_person.
 LOOP AT it_person ASSIGNING <fs_person>.
 IF cl_abap_matcher=>contains(pattern = lv_firstname text =
 <fs_person>-firstname)= abap_true.
 INSERT <fs_person>INTO TABLE itab.
 ENDIF.
 ENDLOOP.
As can be seen,we used the static method CONTAINS of the class
CL_ABAP_MATCHER,where “pattern” represents the searched pattern and “text” represents the text we search to find this pattern.
The result will be “abap_true” if the search was successfully finalized:
cl_abap_matcher  => contains  (pattern = lv_firstnametext = < fs_person > firstname )= abap_true.
After each successful search,we insert the respective records in the internal table itab.Then,we populate with these values the node bound at the table where the results are displayed.
BAPI as a Model
BAPI as a Model
BAPI are standard SAP interfaces, defined as methods for the business object types that can be used in the business data exchange among the SAP components, and among the SAP and the non SAP components. In our example, we use the YFM_SEARCH_CANDIDATE Function Module to create a simple BAPI example that we use as a model in a WD component. To be able to do this, we should firstly make some changes at the Function Module level.
Creating a BAPI
We create a new Function Group, where we copy the YFM_SEARCH_CANDIDATE and rename it YBAPI_YCANDIDATE_SEARCH. For a BAPI, we have a name convention BAPI_<name_object_type>_<method_name>. In case of asearch( ) BAPI, which reads the details for the object type YCANDIDATE, the name of the associated Function Module is YBAPI_YCANDIDATE_SEARCH. In the Attributes tab of the Function Module, we have to activate the option Remote-Enabled Module.

The remoteenabled module option – RFC
After this, we create a structure in the ABAP Dictionary with the same components as our YPERSON table.

Structure YBAPI_YPERSON
We use this structure to define our parameters id_candidate type YBAPI_ YPERSON-ID_PERSON and itab LIKE YBAPI_YPERSON. Now, we have to make another change, because we cannot use exceptions anymore.
RAISE EXCEPTION TYPE ycx_exception_t100_txt EXPORTING
textid = ycx_exception_t100_txt=>ycx_no_candidate
id_candidate = id_candidate.
In order to return a message in case no records exist in the database table YPERSON with the specified ID, we use an export Return parameter for returning the exception messages to the calling application. With this Return parameter, based on the reference structure BAPIRET2, we are able to record and classify all the possible errors that may occur. The structure BAPIRET2 has the structure presented.

The BAPIRET2 structure
We can fill this structure via the Function Module BALW_BAPIRETURN_GET2 .
 CALL FUNCTION 'BALW_BAPIRETURN_GET2'
  EXPORTING
  type =
  cl =
  number =
  * PAR1 = ' '
  * PAR2 = ' '
  * PAR3 = ' '
  * PAR4 = ' '
  * LOG_NO = ' '
  * LOG_MSG_NO = ' '
  * PARAMETER = ' '
  * ROW = 0
  * FIELD = ' '
  * IMPORTING
  * RETURN
Pattern for BALV_BAPIRETURN_ GET2
The Listing shows the Function Module structure. Function module
FUNCTION ybapi_ycandidate_search .
  *"----------------------------------------------------------------------
  *"*"Global Interface:
  *" IMPORTING
  *" VALUE(ID_CANDIDATE) TYPE YBAPI_YPERSON-ID_PERSON
  *" TABLES
  *" ITAB STRUCTURE YBAPI_YPERSON OPTIONAL
  *" RETURN STRUCTURE BAPIRET2 OPTIONAL
  *"----------------------------------------------------------------------
  DATA msg_id_candidate LIKE sy-msgv1.
  CLEAR msg_id_candidate.
  REFRESH: return, itab.
  SELECT *
  FROM yperson
  INTO TABLE itab
  WHERE id_person = id_candidate.
  IF sy-subrc <> 0.
  msg_id_candidate = id_candidate.
  CALL FUNCTION 'BALW_BAPIRETURN_GET2'
  EXPORTING
  type = 'E'
  cl = 'YCL_T100_MSG'
  number = '000'
  par1 = msg_id_candidate
  IMPORTING
  return = return.
  APPEND return.
  ELSE.
  APPEND return.
  ENDIF.
  ENDFUNCTION.
As we can see, instead of raising an exception in case we don’t find any records with the specified ID, we use the BALW_BAPIRETURN_GET2 Function Module to fill the structure BAPIRET2. We have used the defined YCL_T00_MSG message class number 000, and we have replaced the parameter placeholder with the value inserted by the user as a candidate ID. After saving and activating, we can release our Function Module: Function Module ! Release ! Release. As result of our RELEASE action, we’ll get a message of YBAPI_YCANDIDATE_SEARCH type. By using the SWO1 (Business Object Builder) transaction, we create an object named YCANDIDATE.

Creating the object candidate
We add a Method named SEARCH: Utilities ! API Methods ! Add Method.

Creating the API method
We have to release our object. We choose from the menu Edit ! Change Release Status ! Object Type ! To model. We make the same steps for To implement and To release, and the same steps for Object Type Component. After releasing the object, we can test it.

Testing the BAPI
Using the Created BAPI as a Model We create a WD component named Y_BAPI, where we use the created BAPI as a model to obtain the data required from the database table YPERSON.

WD component structure
By right-clicking on the WD component name, we choose from the contextual menu Create ! Service call. The Web Dynpro Wizard is open, creating an appropriate context structure and generating a method that contains the required coding for the service call.
The Wizard steps are:
l Start
l Select controller – we use the existing controller

Selecting the controller
l Select Service Type – we select the Function Module.

Selecting the service type
l Select Service – we specify only the name of the YBAPI_YCANDIDATE_ SEARCH Function Module; the Destination box remains unfilled (blank). In this way, the Function Module will be locally called

Selecting the service
l Adapt Context – here, we can choose which object type we want to use to represent the service function parameters in the WD controller: as a parameter, as a controller attribute or as a context node or context attribute.

Adapting the context
l Specify Method Name – we have to specify the name of the generated method that shall execute the service.

Specifying the method name
l Generate Controller
After the last step, we press the COMPLETED button and the wizard ends. I generates the COMPONENTCONTROLLER context and the proper method EXECUTE_ YBAPI_YCANDIDATE_SEARC that shall execute the service

The generated context and method
The node IMPORTING contains the ID_CANDIDATE attribute in which is stored the value of the ID we are looking for. The node CHANGING contains the two nodes ITAB and RETURN. The node ITAB holds the information about the candidate with the searched ID. The node RETURN has the structure BAPIRET2; we need to use its message attribute to display the return messages on the screen for the end user. The View layout has the structure presented.

View layout and view context
When the user presses the button to look for a candidate, the Framework triggers the event handler method onactionsearch.
METHOD onactionsearch.
  wd_comp_controller->execute_ybapi_ycandidate_searc( ).
  DATA: lr_bapi_node TYPE REF TO if_wd_context_node,
  lr_changing TYPE REF TO if_wd_context_node,
  lr_return TYPE REF TO if_wd_context_node.
  DATA lv_bapi_message TYPE bapi_msg.
  lr_bapi_node = wd_context->get_child_node( `YBAPI_YCANDIDATE_SEA` ).
  lr_changing = lr_bapi_node->get_child_node( `CHANGING` ).
  lr_return = lr_changing->get_child_node( `RETURN` ).
  lr_return->get_attribute( EXPORTING name = 'MESSAGE'
  IMPORTING value = lv_bapi_message ).
  IF lv_bapi_message IS NOT INITIAL.
  DATA:lr_api_controller TYPE REF TO if_wd_controller,
  lr_message_manager TYPE REF TO if_wd_message_manager.
  lr_api_controller ?= wd_this->wd_get_api( ).
  lr_message_manager = lr_api_controller->get_message_manager( ).
  lr_message_manager->report_error_message(
  message_text = lv_bapi_message ).
  ENDIF.
  ENDMETHOD.
The mode of calling the BAPI is encapsulated in the method generated by the wizard in COMPONENTCONTROLLER. All we have to do is to call this method: wd_comp_controller!execute_ybapi_ycandidate_searc( ). When the searched ID doesn’t exist in the database table YPERSON, we show the proper error message stored in the attribute message of the RETURN node. Figure shows the runtime result.

Runtime
Web Service
The Application Server ABAP can be a Web Service provider and a Web Service required. The basic architecture of the Web Service Framework of AS ABAP.
Basic web service framework architecture
The Web Service provider creates the WS and its definition. After this,it can publish the WSDL document to a Universal Description Discovery and Integration (UDDI) service directory, or it can create a direct exchange of WSDL document with the WS client.The Web Service Description Language(WSDL)is a special form of XML that contains all the information required by a client to connect with the Web Service provider and all the required information to programmatically work with the respective service (e.g.number of parameters passed to the service,structure of the returned result,type of the used parameters).
We can store the released Web Services in an UDDI registry. There are many organizations that offer web services we can use for free.Such free Web Services we can find. The web address of the public UDDI service directory for SAP we can find.
With the ABAP Workbench,we have many options to create a Web Service (inside-out type).We can use, for example, a BAPI, a Function Module,a Function Group or an Interface message.
In our case,we want to provide the same search option for our YPERSON database table.A Function Module implementation will be used as a Web Service endpoint.After Function Module implementation,we create the Web Service definition with only a few mouse clicks,we test it and we consume it in the Web Dynpro ABAP,as a model for our WD component.In our case,we don’t focus on the WS security,but we only create a small example required to exemplify how we can consume a Web Service in the Web Dynpro ABAP.
Creating the Web Service
 First,we copy the Function Module used to search for a candidate and we slightly modify it(Listing ).To be possible to further transform it into a RFC-enabled Module,in the Attributes tab of the Function Module,we have to activate the option Remote-Enabled Module.
As we have mentioned before, no exception classes can be used in the RFCenabled FunctionModule.This is the reason why,for the purpose of this example, we have chosen to create a non class exception:NO_ID.To manage the exceptions that may occur,we can use the BAPIRET2 structure similar to the latter example.
Listing Implementation of YFM_SEARCH_PERSON
 FUNCTION YFM_SEARCH_PERSON.
 *"------------------------------------------------------------------
 *"*"Local Interface:
 *" IMPORTING
 *" VALUE(ID_CANDIDATE)TYPE YPERSON-ID_PERSON
 *" EXPORTING
 *" VALUE(FIRSTNAME)TYPE YPERSON-FIRSTNAME
 *" VALUE(LASTNAME)TYPE YPERSON-LASTNAME
 *" VALUE(TELEPHONE)TYPE YPERSON-TELEPHONE
 *" VALUE(AGE)TYPE YPERSON-AGE
 *" VALUE(ID_COUNTRY)TYPE YPERSON-ID_COUNTRY
 *" EXCEPTIONS
 *" NO_ID
 *"----------------------------------------------------------------------
 DATA wa_person TYPE yperson.
 SELECT SINGLE firstname lastname telephone age id_country
 INTO CORRESPONDING FIELDS OF wa_person
 FROM yperson
 WHERE id_person EQ id_candidate.
 if sy-subrc <> 0.
 raise no_id.
 endif.
 firstname = wa_person-firstname.
 lastname = wa_person-lastname.
 telephone = wa_person-telephone.
 age = wa_person-age.
 id_country = wa_person-id_country.
 ENDFUNCTION.
Then,we transform our RFC into a Web Service.We have many possibilities to do this,as follows:
  • Right click on the FM name and,from the contextual menu,we choose Create --> Web Service.
  • From Function Builder (Transaction SE37), we choose from the menu Utilities --> More Utilities --> Create Web Services.
The Wizard steps are:
Object Type – we can choose the object type; in our case,the Web Service is a service provider.
Object type wizard step
  • Service Provider - we create a service provider for an existing ABAP Object (Inside Out).
Service provider wizard step
  • Object type - here,we enter a name and a short description for our Web Service,and we can choose the type of the Endpoint use.
Object type wizard step
  • Choose Endpoint - here,we can enter the name of the Function Module that we want to use as endpoint for our Web Service.
Choosing the endpoint wizard step

  • Configure Service - here,we choose an Authorization profile.As we have mentioned above,for the purpose of this example we choose the profile PRF_DT_IF_SEC_NO.
Configuring the service wizard step
Enter Package/Request - here, we have to enter the name of the package Y_WEBDYNPRO and the Transport Request.
Completeit’s the last step in the wizard,where we are informed that the Web Service with the desired name will be generated after pressing the “Complete” button.
The generated service definition
Web Service Configuration
To perform the necessary configuration tasks,we use the SOA Manager,accessible through the SOAMANAGER transaction.By using “Single Service Administration”,we can search for our created WS and configure it(Fig).We can find this option in the tab: “Application and Scenario Communication”.
Searching for our web service
By pressing the“Apply Selection” button,we can see the Details of our Service Definition.Using the“Configurations”tab,we can create a Service and a Service- Endpoint for our Service Definition YWEB_SERVICE.
Details of service definition configurations
Each Service Definition may have more than one Service and,for each Service, we can create more than one Endpoint.Each Service-Endpoint can configure a service in a different way.
Testing the Web Service
After configuring our endpoint, we save it and go into the “Overview”tab.
Details of service definition overview
From here,we choose the link “Open WSDL document for selected binding”and we copy the URL address from the window that appears. By selecting the link “Open Web Service navigator for selected binding”,the Web Service test page opens and we can test our new created Web Service after pressing the “Test” button.
Web service navigator
In case an error occurs,we have to configure the J2EE server access information (the host name and a port number),because the Web Service test page (Web Service Navigator) runs on Java stack. To do this,we can use the same SOAMANAGER transaction --> the tabTechnical Configuration --> the option System Global Settings.
Testing our web service request/response
Consuming the Web Service in Web Dynpro
To be able to consume the created Web Service into the Web Dynpro application, we have to firstly create a Proxy.To create it, we can use the same Wizard as for the Web Service creation.
In this case, the Wizard steps are:
Object type Service Consumer.
Wizard object type step
Select Source offers the possibility to select the source of the WSDL document.
Wizard selected source step
Select Source here,we enter our Web Service’s URL.We can use copy and paste to take this URL from the SOAMANAGER transaction.
Wizard selected source step
Enter Package/Request we have to enter the package name, the prefix and the Workbench Request.Because,in the same time with the generation of the proxy class,there are also generated other development objects (e.g.Dictionary objects,classes and interfaces),it is recommended to generate these objects in a separate package (in our case, the Y_PROXY package).
Wizard enter package/request step
Complete after the last step,theWizard generates the consumer proxy.
The consumer proxy
Generated development objects
Before pressing the RUN button to test our Consumer Proxy, we have to create a logical port by using the SOAMANAGER transaction or the old LPCONFIG transaction.
In the SOAMANAGER transaction,in the same window where we searched for the Web Service,we can search now for a consumer proxy with the external name: “yweb_service”.
Searching for a consumer proxy
By pressing the “Apply Selection” button, we open the field where we can create the Proxy Definition.Into the “Configurations” tab,we can create the Logical Port.In the next step,we have to create the Web Dynpro component to use the created Client Proxy.We create a Web Dynpro component named Y_WS_CONSUMER with a view named V_VIEW and a default window.
By using the Service Call(similar to the “BAPI” example),we can integrate our Client Proxy into our WD application. In this case,we have to use the “Web Service Proxy” option as service type.Then,we have to enter the proxy class name,the public method and the logical port.
Because in the latter example we showed how to use this Wizard, now we are going to show,through this example,how to use the proxy without the Wizard’s help.In case we have more complex structures, it happens that Wizard generates only one attribute instead of a node with attributes.In this case,we have to make manually the adequate modifications.
The V_VIEW view context and the layout are presented. The ID_PERSON attribute is of the YPERSON-ID_PERSON type and shall be used to maintain the ID of the searched competitor. The Person child node has the YPERSON dictionary structure,so here we are going to find the data about the searched competitor: his first name,last name,telephone,age and his country id.In the View Layout,we have inserted the UI elements: Group, InputField,Label and Table.
View context und view layout
When the user presses the Search button,the Framework triggers the event handler method onactionsearch.
The onactionsearch event handler method
 METHOD onactionsearch .
 DATA: lr_node TYPE REF TO if_wd_context_node,
 lr_subnode TYPE REF TO if_wd_context_node,
 ls_subnode TYPE wd_this->element_person,
 lv_id_person TYPE yperson-id_person.
 DATA: obj1 TYPE REF TO ysco_yweb_service,
 obj2 TYPE REF TO cx_ai_system_fault,
 ls_input TYPE ysyfm_search_person,
 ls_output TYPE ysyfm_search_personresponse.
 lr_node = wd_context->get_child_node('SEARCH_PERSON').
 lr_subnode = lr_node->get_child_node('PERSON').
 lr_node->get_attribute( EXPORTING name = 'ID_PERSON'
 IMPORTING value = lv_id_person).
 TRY.
 CREATE OBJECT obj1.
 CATCH cx_ai_system_fault INTO obj2.
 ENDTRY.
 ls_input-id_candidate = lv_id_person.
 TRY.
 CALL METHOD obj1->yfm_search_person
 EXPORTING
 input = ls_input
 IMPORTING
 output = ls_output.
 CATCH cx_ai_system_fault INTO obj2.
 CATCH cx_ai_application_fault .
 ENDTRY.
 IF ls_output IS INITIAL.
 DATA lr_api_controller TYPE REF TO if_wd_controller.
 DATA lr_message_manager TYPE REF TO if_wd_message_manager.
 lr_api_controller ?= wd_this->wd_get_api( ).
 lr_message_manager = lr_api_controller->get_message_manager( ).
 lr_message_manager->report_exception(message_object = obj2).
 ELSE.
 ls_subnode-firstname = ls_output-firstname.
 ls_subnode-lastname = ls_output-lastname.
 ls_subnode-telephone = ls_output-telephone.
 ls_subnode-age = ls_output-age.
 ls_subnode-id_country = ls_output-id_country.
 lr_subnode->set_static_attributes(ls_subnode).
 ENDIF.
 ENDMETHOD.
When we use proxy objects in methods or programs we can use drag and drop to ease the code generation.
Drag and drop for code generation
As we can see,we have declared a reference variable for proxy (obj1 TYPE REF TO ysco_yweb_service) and two local structures to set the input parameter (ls_input TYPE ysyfm_search_person) and to get the response (ls_output TYPE ysyfm_search_personresponse).
After creating the proxy,we call it and pass the response values in the corresponding child node “PERSON”.At runtime,we have.
Runtime

No comments:

Post a Comment