Issue while creating Odata with RFC mapping
Gateway service call not triggering DPC_EXT class
Hi,
I have created a gateway project and have implemented the DPC_ EXT method of getentityset. While testing in Gateway client I am getting status 200 for the service call [/sap/opu/odata/sap/ZTEST_SRV/EmpolyeeadressSet?$filter=Pernr eq'00000012'], but there is no data in results object. I have put external debugger for my user in the DPC_EXT ->EmployeeadressSet_getentityset method, but not getting triggered even as iam testing the service with my userid. (Gateway is implemented as Hub. Trusted RFC connection has login user configured. Was able to debug gateway services of standard fiori apps previously in the same way ).
thanks in advance
CORS Issue While Consuming ODATA from Gateway Hub
Hi
We have developed the odata service and trying to use it in the non sap custom application but we are getting error Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource (Reason: CORS header 'Access-Control-Allow-Origin' missing)
We are on ECC 6.0 EHP7 and using the Separate Gateway Hub. We are using MSSQL as database. As mentioned in some of the post have also tried setting up the header in the server side in the service:
DATA: ls TYPE ihttpnvp.
ls-name = 'Access-Control-Allow-Origin'.
ls-value = '*'.
CALL METHOD super->/iwbep/if_mgw_conv_srv_runtime~set_header
EXPORTING
is_header = ls.
But still getting the error. Application that is calling the ODATA is residing at the localhost.
Appreciate your responses. Let me know in case further information is required.
Regards,
Rohit
Convert RTF format to PDF format to PHP
Hi Team,
I want to convert an RTF format to PDF format in sap code.
Can anyone suggest an idea on it .
Regards,
Karthik S
Conversion from RTF format to PDF in odata service
Hi Team,
Module - EHS - Doc in DMS
I have converted the binary table content to Xstring and when i have sent it to PHP system, they were
able to see the data only in RTF format not in PDF format.
Can i know the steps in convvertin to PDF from RTF format .
Regards,
Karthik S
sample code for converting RTF to ITF in sap abap
Hi Team,
Request to provide the sample code with required parameters in converting the RTF to ITF format , so that
i can convert ITF to PDF and display it in PHP System via ODATA .
Can suggest an idea on it .
Regards,
Karthik S
Consume HANA XSODATA services on SAP NW GW
Hi Team,
We have an requirement for UI5 application to consume HANA DATA via XSODATA services.
The solution architecture is defined as following .
SAP NW GW system connected with HANA DB with HTTP Destination having system alias configured. The UI5 application get deployed into SAP GW, here GW is a just web container and not using any ABAP functionalities with ui5 application.
In order to consume the XSODATA services on SAP GW , followed below links and tried to consume ODATA service at application side .
• http://www.saplearners.com/how-to-consume-hana-xs-odata-service-in-sap-netweaver-gateway/
• http://scn.sap.com/thread/3587498
We are able to get the metadata of XSODATA service and as well as Entityset data at GW client , but $Filter is not working when passed on URI. PFB the details
/sap/opu/odata/sap/ZFINALSANVIEW_SRV/getPdaPgaData?$filter=MSN eq '07102'
Getting error attached while testing above link at GW client
But the $filter is working on XSODATA when applied as below
please let us know if we need to implement any logic with-in runtime classes as similar as we do in general for SAP ODATA services. I suspect here that the final filter should happen on HANA side and GW ODATA just to pass the request as part of service configured within its definition
please share your pointers , advance thanks for your support
Thanks ,
Ratnakar
Getting /IWBEP/CX_SBCM_FATAL from SEGW
Hello Experts,
I don't know why but since this morning every time I want to check/generate from SEGW I'm getting dump:
Category ABAP Programming Error
Runtime Errors UNCAUGHT_EXCEPTION
Except. /IWBEP/CX_SBCM_FATAL
ABAP Program /IWBEP/CL_SBUI_CONTROLLER=====CP
Application Component OPU-BSE-SB
Date and Time 16.11.2015 10:07:39
An exception has occurred that was not caught.
What happened?
Exception '/IWBEP/CX_SBCM_FATAL' was raised, but it was not caught anywhere
along the
call hierarchy.
Since exceptions represent error situations, and this error was not
adequately responded to, ABAP program '/IWBEP/CL_SBUI_CONTROLLER=====CP' had
to be terminated.
Error analysis
An exception has occurred which is explained in more detail below. The
exception, which is assigned to class '/IWBEP/CX_SBCM_FATAL' was not caught and
therefore caused a runtime error. The reason for the exception is:
Fatal error in Service Builder
This exception is closely related to a previous exception "CX_SY_NO_HANDLER",
which
was raised in program "/IWBEP/CL_SBDSP_DATA_SOURCE===CP", in line 1 of
(include) program "/IWBEP/CL_SBDSP_DATA_SOURCE===CM00T". The
reason for the exception occurring was:
An exception with the type CX_SY_REF_IS_INITIAL occurred, but was neither
handled locally, nor declared in a RAISING clause
This exception is closely related to a previous exception
"CX_SY_REF_IS_INITIAL", which
was raised in program "/IWBEP/CL_SBDSP_DATA_SOURCE===CP", in line 11 of
(include) program "/IWBEP/CL_SBDSP_DATA_SOURCE===CM00T". The
reason for the exception occurring was:
Dereferencing of the NULL reference
How to correct the error
If the error occurs in a non-modfied SAP program, you might be able to
find a solution in the SAP Notes system. If you have access to the SAP
Notes system, check there first using the following keywords:
"UNCAUGHT_EXCEPTION" /IWBEP/CX_SBCM_FATAL
"/IWBEP/CL_SBUI_CONTROLLER=====CP" bzw. /IWBEP/CL_SBUI_CONTROLLER=====CM00C
"/IWBEP/IF_SBUI_CONTROLLER~ON_COMMAND_REQUESTED"
Chain of Exception Objects
Attrib. Name Value
Level 1 Class /IWBEP/CX_SBCM_FATAL
Program /IWBEP/CL_SBUI_CONTROLLER=====CP Include /IWBEP/CL_SBUI_CONTROLLER=====CM00C Row 152
Short Te
Long Tex
T100_MSGID /IWBEP/SBCM
T100_MSGNO 000
IS_RESUMABLE
KERNEL_ERRID
Level 2 Class CX_SY_NO_HANDLER
Program /IWBEP/CL_SBDSP_DATA_SOURCE===CP Include /IWBEP/CL_SBDSP_DATA_SOURCE===CM00T Row 1
Short Te An exception with the type CX_SY_REF_IS_INITIAL occurred, but was neither handled locally
, nor declared in a RAISING clause
Long Tex
An exception of type 'CX_SY_REF_IS_INITIAL' occurred, that was not caught anywhere in
the call hierarchy. It was not handled locally or declared using a RAISING clause.
CLASSNAME CX_SY_REF_IS_INITIAL
IS_RESUMABLE
KERNEL_ERRID UNCAUGHT_EXCEPTION
Level 3 Class CX_SY_REF_IS_INITIAL
Program /IWBEP/CL_SBDSP_DATA_SOURCE===CP Include /IWBEP/CL_SBDSP_DATA_SOURCE===CM00T Row 11
Short Te Dereferencing of the NULL reference
Long Tex
An attempt was made to execute a dynamic method callon an initial(NULL-) object
reference. The reference must refer to an object.
IS_RESUMABLE
KERNEL_ERRID
Information on where terminated
The termination occurred in ABAP program "/IWBEP/CL_SBUI_CONTROLLER=====CP",
in "/IWBEP/IF_SBUI_CONTROLLER~ON_COMMAND_REQUESTED". The main program
was "/IWBEP/R_SBUI_SERVICE_BUILDER".
In the source code, the termination point is in line 152 of (Include)
program "/IWBEP/CL_SBUI_CONTROLLER=====CM00C".
Source Code Extract
Line SourceCde
122 WHEN gc_cc_sb_cancel.
123 mr_active_call->exit_command_active = abap_true.
124 cancel_input_validation( ).
125 WHEN gc_lc_wz_back.
126 mr_active_call->exit_command_active = abap_true.
127 cancel_input_validation( ).
128 WHEN OTHERS.
129 fetch_pending_user_input( ). " fetch pending input befo
130 ENDCASE.
131 * --- move current selection ---
132 IF mr_active_call->command_in_process-select EQ abap_true.
133 mr_active_call->nav_state_current-marked = mr_active_call->command_in_process-requ
134 mr_active_call->nav_state_current-marked_nodes = mr_active_call->command_in_proces
135 mr_active_call->navigation_mandatory = abap_true.
136 ENDIF.
137 * --- do process the command ---
138 mr_active_call->command_in_process-rcode = handle_command( io_sender = mr_active_cal
139 CASE mr_active_call->command_in_process-rcode.
140 WHEN gc_rc_cancelled.
141 MESSAGE ID '/IWBEP/SBUI' TYPE 'S' NUMBER '024' DISPLAY LIKE 'S'.
142 LOG-POINT ID /iwbep/sbui FIELDS mr_active_call->command_in_process-request-fcode
143 WHEN gc_rc_error.
144 MESSAGE ID '/IWBEP/SBUI' TYPE 'S' NUMBER '026' DISPLAY LIKE 'S'.
145 LOG-POINT ID /iwbep/sbui FIELDS mr_active_call->command_in_process-request-fcode
146 WHEN gc_rc_rejected.
147 LOG-POINT ID /iwbep/sbui FIELDS mr_active_call->command_in_process-request-fcode
148 WHEN gc_rc_undefined.
149 LOG-POINT ID /iwbep/sbui FIELDS mr_active_call->command_in_process-request-fcode
150 ENDCASE.
151 CATCH /iwbep/cx_sbcm_exception cx_sy_no_handler INTO lx_error.
>>>>> RAISE EXCEPTION TYPE /iwbep/cx_sbcm_fatal EXPORTING previous = lx_error.
153 ENDTRY.
154 ENDLOOP.
155 * --- unlock queue processing ---
156 CLEAR mr_active_call->command_in_process.
157
158 ENDMETHOD.
How can I solve this error?
Regards,
Omri
Fiori Like app from AMDP
Hi,
Can anyone guide me on creation of fiori like app from AMDP.
Just we have to create list view in UI5.
-Amit
properties for Entity types and Entity sets
Dear Experts,
For my entityset I've checked Requires filter Indicator and I've checked Filterable flag for entity type.
but when I can call my webservice "Read Entityset" without $filter suffix.
Do I missed any thing because as what I understand that Requires filter Indicator will enforce $Filter suffix.
missing : Release Notes for SAP Gateway SP15
Dear Gateway Team,
We recently upgraded our Hub deployment gateway system running on netweaver 7.4 to SP15 (SAP_GWFND=SP15). Is there any official link to see the new features in SP15 of gateway.
I can only find release notes from SAP updated in help documents for SP12 here and official announcements in SCN for SP09 here. Is there any other link that i am missing to stay updated with the product features shipping as the new releases..
Regards
Virinchy
Reusable READ functionality. Part 3
Welcome Back
Welcome back again to our third installment of the series. Today we will cover off navigation and the odata $expand operator. If you haven’t followed along already check out the previous 2 blogs to find out how we ended up here, at part 3.
Part 1 - Developing data driven reusable READ functionality.
Part 2 - Reusable READ functionality. $select, $orderby, $top, $skip, $inlinecount, $count
SEGW
Let’s start with defining some new entities to use in our examples. Referring back to part 1 of this series we’ll import from DDIC structures to create our new entities. We’ll create 3 new entities, Flight (using table SFLIGHT), FlightSchedule (using table SPFLI) and Plane (using table SAPLANE). Define them as below with their Name, Key and ABAP fieldname.
Association / Navigation / Referential Constraints
Now let’s create some associations and navigations using the wizard, as below. As part of the creation we will also setup some referential constraints. This is the information we will be using in our navigation routine to determine associations between entities.
AirlineToSchedule
The first association and navigation we will create is from the Airline entity to the FlightSchedule entity. As in the image below, in the first step specify the association details and navigation property followed by the referential constraints. Use the search help to look the values up to make it a little easier. Although you will need to type the Association Name and Navigation Property (if you wish to change it as below ).
ScheduleToFlight
Next we will create the association and navigation from the FlightSchedule entity to the Flight entity. Follow the same steps as above with the below image as reference.
FlightToPlane
Finally we will create an association and navigation from the Flight entity to the Plane entity. Again follow the same steps using the image below as reference.
Though note in this last example we are setting the dependent navigation property.
Complete Model
After all the changes made the complete model should look as below in the overview section.
Now save the model and generate our runtime objects as we did in part 1. Make sure you can see your new entities and associations by running the service with the $metadata uri option:
/sap/opu/odata/sap/ZFLIGHT_SRV/$metadata
All good? Let’s continue.
Data Provider Extension Class - ZCL_ZFLIGHT_DPC_EXT
Now we will redefine our data provider methods for the newly created entities. Simply redefine the below methods of class
ZCL_ZFLIGHT_DPC_EXT and add our standard code for get_entity() and get_entityset(), as we did in part 1 of the series for the Airline entity.
Redefine the methods:
Code for ...get_entity():
get_gw_helper( )->get_entity( exporting io_tech_request_context = io_tech_request_context changing cs_entity = er_entity cs_response_context = es_response_context ).
Code for ...get_entityset():
get_gw_helper( )->get_entityset( exporting io_tech_request_context = io_tech_request_context changing ct_entityset = et_entityset cs_response_context = es_response_context ).
This stems back to our original goal of adding as little as possible to our data provider extension class in the way of reading entities and allowing the helper class to do most of the work dynamically for us.
Finished, that’s it for the data provider class. Save the changes and activate.
Helper Class - ZCL_GATEWAY_HELPER
Now let’s add the expand and navigation logic to our helper class.
First we will create two new class attributes as below.
Mv_conv_keys, will be used to determine if we should convert our source keys, mv_entity_name will be used to check if we need to run though our init() method due to a new entity, as explained below in the init() change.
Init(), change
Now we will be running though the gateway frame work executing expands. So we’ll place a check in this method to ensure that we are not loading all the model details again for the same entity. We will check the entity name passed in does not match the entity last processed.
Place these new lines of code after the declaration for the field symbols.
field-symbols: <ls_property> like line of lt_table_properties. * first check if we already loaded this entity, eg we might be processing * through a $expand. if mv_entity_name <> iv_entity_name.
and the following new lines at the end of the method:
* save this for comparison on the next round though. * if we have already computed this then lets not do it again, eg in an $expand! mv_entity_name = iv_entity_name. endif. endmethod.
get_entity_nav(), new method, protected
The first new method we will create is a helper method to be used with our next method process_nav_path(). The purpose of this method is select our current navigation entity in readiness for our next navigation. The method will take 3 parameters the entity name, the where condition and the returned entity selected. This entity can then be used as the data for next navigations required keys. Don’t forget to add the exceptions also.
Method Signature
At the start we just free any data which may be left over from a previous call, as you’ll see in the next method the call is embedded in the navigation loop. Next we get the DDIC structure name from the entity as we have seen in previous examples. We create some data based on this DDIC structure and assign to a field symbol ready for selection. The select is then processed using the where condition passed in. An exception will be raised if no data can be selected as we’ll be unable to continue our navigation.
method get_entity_nav. data: lr_entity type ref to /iwbep/if_mgw_med_odata_types=>ty_s_med_entity_type. field-symbols: <ls_entity> type any. lr_entity = mr_model->get_entity( iv_entity_name ). free: er_entity. * create our data to select into create data er_entity type (lr_entity->attribute_struct). assign er_entity->* to <ls_entity>. * select entity, for navigation select single * into <ls_entity> from (lr_entity->attribute_struct) where (iv_db_where). if sy-subrc <> 0. raise exception type /iwbep/cx_mgw_busi_exception exporting textid = /iwbep/cx_mgw_busi_exception=>business_error_unlimited message_unlimited = 'Navigation select failed on entity, ' && iv_entity_name && '.'. endif. endmethod.
process_nav_path(), new method, protected
This is a big one! I’ll try to explain most of what is going on here and justifications, in a way which makes sense!
To start the method takes 4 parameters, these being the navigation path, the source keys, a returned parameter to determine if we are navigating and finally the OSQL where condition to be executed in the calling get_entity() or get_entityset() method. Again remember to add the exceptions.
Method Signature
Initially we check to see if there is any navigation, if not simply exit. Otherwise we continue to loop over the navigation table.
First iteration
In the first iteration only (defined by AT FIRST.) we build our OSQL where condition based on the source keys. The source keys will only be converted if this is the first time though a get…() method, for example not an subsequent call via an expand or navigation, as in this case the keys should already be converted.
To convert the keys we use the key converter contained in the navigation structure attribute KEY_CONVERTER. We do this by defining some dynamic data based on the DDIC structure and call the EXECUTE() method of the key converter, the results are returned back into our field symbol to be used in our source key loop, again only if this is the first time in a get…() method. Otherwise we simply use the keys passed into parameter it_source_keys.
Once the OSQL where condition has been built we call our new method above get_entity_nav() to retrieve our entity details.
All iterations
Continuing on from the above first / initial processing, we can either process navigation keys or process our referential constraints.
Navigations with keys
Following on from the first lot of processing, we check to see if we have any key fields from navigations. For example:
If we do then we convert the navigation keys using the class: /iwbep/cl_mgw_req_key_convert. We first create the key converter using the target entity type. Next create some dynamic data based on the DDIC structure of the target entity, and finally call execute() method of the key converter to convert our key values. We loop over the key tab first attempting to get the same key value from the entity details we have at hand. This is in an attempt to stop invalid navigations where keys do not match, for example:
If the key value can be found in the entity and it does not match the value in the navigation key an exception is raised, otherwise the value is added to the OSQL where condition. If the key value cannot be found in the entity then the value is taken directly from our converted navigation keys.
Lastly we check if this is the last navigation, if so we want to return this OSQL where condition back to the caller to process. Otherwise we select our next entity, set the source entity to the previous target entity and continue our next loop iteration.
Referential Constraints
If we had no navigation keys then we will drop into processing the referential constraints. We set these up at the start of this blog during the association and navigation section. We first retrieve the navigation property, from this we can then pick up the association and from the association we then pick up the referential constraints. We loop over the referential constraints retrieving the target property and matching this up with the source key property value from our entity. Using this information we can build our OSQL where condition, to be passed back to the caller.
Finally after the navigation loop we combine the where condition with the one passed in, being the condition from the odata $filter operator.
method process_nav_path. data: lv_tech_name type /iwbep/if_mgw_med_odata_types=>ty_e_med_technical_name, lr_entity_type type ref to /iwbep/if_mgw_med_odata_types=>ty_s_med_entity_type, lr_nav_prop type ref to /iwbep/if_mgw_med_odata_types=>ty_s_med_reference, lr_assoc type ref to /iwbep/if_mgw_odata_re_assoc, lr_assoc_ref type ref to /iwbep/if_mgw_med_odata_types=>ty_s_med_reference, lt_ref_constraints type /iwbep/if_mgw_odata_re_assoc=>ty_t_mgw_odata_ref_constraints, lv_value type string, lv_db_and type string value '', lv_db_where type string, lr_entity type ref to data, lv_max_nav type i, lv_src_entity type /iwbep/mgw_tech_name, lr_key_values type ref to data, lv_ddic type string, lr_key_conv type ref to /iwbep/if_mgw_req_key_convert, lr_etype type ref to /iwbep/if_mgw_odata_fw_etype. field-symbols: <ls_nav_path> like line of it_nav_path, <ls_key_values> type any, <ls_keytab> type /iwbep/s_mgw_tech_pair, <ls_ref_constraints> like line of lt_ref_constraints, <ls_key> like line of it_source_keys, <lv_any> type any. ev_navigating = abap_false. * check if we are navigating if it_nav_path is not initial. ev_navigating = abap_true. * get maximum number of navigations, as we what to process the * last select from the callers method. lv_max_nav = lines( it_nav_path ). loop at it_nav_path assigning <ls_nav_path>. at first. * in our initial iteration, read our entity using our source keys * as this is our starting point if first time through a get...() * method then convert keys, otherwise keys should already be converted if mv_conv_keys = abap_true. lr_key_conv ?= <ls_nav_path>-key_converter. lv_ddic = lr_key_conv->get_entity_type( )->get_structure( ). create data lr_key_values type (lv_ddic). assign lr_key_values->* to <ls_key_values>. lr_key_conv->execute( exporting it_tech_pair = it_source_keys importing es_key_values = <ls_key_values> ). endif. loop at it_source_keys assigning <ls_key>. * grab key from converted source keys? if mv_conv_keys = abap_true. assign component <ls_key>-name of structure <ls_key_values> to <lv_any>. lv_value = <lv_any>. else. * otherwise directly from source keys lv_value = <ls_key>-value. endif. lv_db_where = lv_db_where && lv_db_and && `( ` && <ls_key>-name && ` = '` && lv_value && `' )`. lv_db_and = ` and `. endloop. * select our entity to complete navigation get_entity_nav( exporting iv_entity_name = <ls_nav_path>-source_entity_type iv_db_where = lv_db_where importing er_entity = lr_entity ). lv_src_entity = <ls_nav_path>-source_entity_type. endat. free: lv_db_where,lv_db_and. * if we have navigation key then lets process them if <ls_nav_path>-key_tab[] is not initial. * Create a key converter here based on the target entity type and convert our keys lr_etype = mr_model->get_entity_type( <ls_nav_path>-target_entity_type ). free: lr_key_values, lr_key_conv. create object lr_key_conv type /iwbep/cl_mgw_req_key_convert exporting io_entity_type = lr_etype. lv_ddic = lr_etype->get_structure( ). create data lr_key_values type (lv_ddic). assign lr_key_values->* to <ls_key_values>. lr_key_conv->execute( exporting it_tech_pair = <ls_nav_path>-key_tab[] importing es_key_values = <ls_key_values> ). loop at <ls_nav_path>-key_tab[] assigning <ls_keytab>. * * first attempt is to retrieve key from source entity, if it can be found use it, * otherwise use key from keytab, this is to stop this sort of thing returning * valid results: * * ZFLIGHT_SRV/AirlineSet(AirlineId='AA')/FlightScheduleSet(AirlineId='AZ',ConnectionId='555') * \------> KEYS NOT EQUAL <------- / * assign lr_entity->(<ls_keytab>-name) to <lv_any>. if sy-subrc = 0. if <lv_any> = <ls_keytab>-value. lv_value = <lv_any>. else. raise exception type /iwbep/cx_mgw_busi_exception exporting textid = /iwbep/cx_mgw_busi_exception=>business_error_unlimited message_unlimited = 'Key fields differ during navigation.'. endif. else. * read value from our converted keys assign component <ls_keytab>-name of structure <ls_key_values> to <lv_any>. lv_value = <lv_any>. endif. lv_db_where = lv_db_where && lv_db_and && `( ` && <ls_keytab>-name && ` = '` && lv_value && `' )`. lv_db_and = ` and `. endloop. * if we are on the last navigation don't process. Pass where condition back * to our caller, get_entity() or get_entityset() to complete if sy-tabix <> lv_max_nav. * select our entity to continue next navigation loop get_entity_nav( exporting iv_entity_name = <ls_nav_path>-target_entity_type iv_db_where = lv_db_where importing er_entity = lr_entity ). lv_src_entity = <ls_nav_path>-target_entity_type. endif. else. * if no navigation keys, then try and build our navigation from * our referential constraints if lv_src_entity is not initial. lr_entity_type = mr_model->get_entity( lv_src_entity ). * get navigation property lv_tech_name = <ls_nav_path>-nav_prop. lr_nav_prop = mr_model->/iwbep/if_mgw_odata_fw_model~get_nav_property_by_tech( iv_name = lv_tech_name ir_entity_type = lr_entity_type ). * get association, and ref. contraints lr_assoc_ref = mr_model->get_association_by_id( lr_nav_prop->target_entity_id ). lr_assoc = mr_model->/iwbep/if_mgw_odata_re_model~get_association( lr_assoc_ref->name ). lt_ref_constraints = lr_assoc->get_ref_constraints( ). * loop over ref contraints and marry up targets to sources loop at lt_ref_constraints assigning <ls_ref_constraints>. assign lr_entity->(<ls_ref_constraints>-target_property-name) to <lv_any>. if sy-subrc = 0. lv_db_where = lv_db_where && lv_db_and && `( ` && <ls_ref_constraints>-target_property-name && ` = '` && <lv_any> && `' )`. lv_db_and = ` and `. endif. endloop. endif. endif. endloop. * return our where condition, either as is, or appended to our $filter if cv_db_where is not initial. cv_db_where = cv_db_where && ` and ` && lv_db_where. else. cv_db_where = lv_db_where. endif. endif. endmethod. "process_nav_path
get_entity(), change
Now time to insert our navigation processing into our get_entity() method. First we create a new variable to determine if we are navigating. Next we add the code to call our new method process_nav_path() passing the required parameters. Then we check to see if we are navigating, if so execute the returned OSQL where condition. Otherwise continue as we previously have. Finally we update our class attribute mv_conv_keys to false, check for source key conversion in our process_nav_path() method.
New modified method
method get_entity. data: lt_keys type /iwbep/t_mgw_tech_pairs, lv_db_where type string, lv_db_and type string value '', lv_db_select type string, lr_data type ref to data, lv_navigating type abap_bool. field-symbols: <ls_key> like line of lt_keys, <ls_data> type any, <lv_value> type any. * initialise init( io_tech_request_context->get_entity_type_name( ) ). if mv_db_tabname is not initial. * $select, grab fields to select if any lv_db_select = process_select( io_tech_request_context->get_select_entity_properties( ) ). lt_keys = io_tech_request_context->get_keys( ). * read association and keys process_nav_path( exporting it_nav_path = io_tech_request_context->get_navigation_path( ) it_source_keys = io_tech_request_context->get_source_keys( ) importing ev_navigating = lv_navigating changing cv_db_where = lv_db_where ). if lv_navigating = abap_false. * create data struct to grab converted keys create data lr_data like cs_entity. assign lr_data->* to <ls_data>. io_tech_request_context->get_converted_keys( importing es_key_values = <ls_data> ). * loop over keys to build where condition loop at lt_keys assigning <ls_key>. assign component <ls_key>-name of structure <ls_data> to <lv_value>. if sy-subrc = 0. lv_db_where = lv_db_where && lv_db_and && `( ` && <ls_key>-name && ` = '` && <lv_value> && `' )`. lv_db_and = ` and `. endif. endloop. endif. if lv_db_where is not initial. select single (lv_db_select) from (mv_db_tabname) into corresponding fields of cs_entity where (lv_db_where). endif. endif. mv_conv_keys = abap_false. endmethod.
get_entityset(), change
Now let’s put the logic in our get_entityset() method. Again we will create a new variable to determine if we are navigating. Next we call our new method process_nav_path() passing the required parameters. First we leave the check for our has_count(), if we have a count we will execute with our navigated OSQL where condition. Otherwise we check to see if we are navigating, if so execute the returned OSQL where condition, else continue as we have previously. Finally again we update our class attribute mv_conv_keys to false, check for source key conversion in our process_nav_path() method.
New modified method
method get_entityset. data: lv_db_where type string, lv_db_select type string, lv_db_orderby type string, lv_top type i, lv_skip type i, lv_navigating type abap_bool. * initialise init( exporting iv_entity_name = io_tech_request_context->get_entity_type_name( ) iv_max_top = iv_max_top ). if mv_db_tabname is not initial. * $top, $skip, process our paging process_paging( exporting io_tech_request_context = io_tech_request_context importing ev_top = lv_top ev_skip = lv_skip ). * $filter, grab our converted filter lv_db_where = io_tech_request_context->get_osql_where_clause_convert( ). * read association and keys process_nav_path( exporting it_nav_path = io_tech_request_context->get_navigation_path( ) it_source_keys = io_tech_request_context->get_source_keys( ) importing ev_navigating = lv_navigating changing cv_db_where = lv_db_where ). * check for $count if present just count the records * no need to order results, or select fields! if io_tech_request_context->has_count( ) = abap_true. * execute our select select count(*) up to lv_top rows into cs_response_context-count from (mv_db_tabname) where (lv_db_where). else. * $select, grab fields to select if any lv_db_select = process_select( io_tech_request_context->get_select_entity_properties( ) ). * $orderby grab our order lv_db_orderby = process_orderby( io_tech_request_context ). if lv_navigating = abap_true. * we are navigating, execute select with determined lv_db_where * from navigation! select (lv_db_select) from (mv_db_tabname) into corresponding fields of table ct_entityset where (lv_db_where) order by (lv_db_orderby). else. * execute our select select (lv_db_select) up to lv_top rows from (mv_db_tabname) into corresponding fields of table ct_entityset where (lv_db_where) order by (lv_db_orderby). if lv_skip > 0. delete ct_entityset from 1 to lv_skip. endif. endif. * $inlinecount, check for inline count and update if io_tech_request_context->has_inlinecount( ) = abap_true. cs_response_context-inlinecount = lines( ct_entityset ). endif. endif. endif. mv_conv_keys = abap_false. endmethod.
Time to test
Activate all changes and try some of the following examples. Note some key fields may be different depending on demo data created:
/sap/opu/odata/sap/ZFLIGHT_SRV/AirlineSet('UA')/ToFlightSchedules?$format=json
/sap/opu/odata/sap/ZFLIGHT_SRV/AirlineSet('UA')/ToFlightSchedules?$filter=AirportFrom eq 'FRA'&$format=json
/sap/opu/odata/sap/ZFLIGHT_SRV/AirlineSet('AZ')/ToFlightSchedules(AirlineId='AZ',ConnectionId='555')?$format=json
/sap/opu/odata/sap/ZFLIGHT_SRV/AirlineSet('AZ')/ToFlightSchedules/$count?$filter=CountryFrom eq 'IT'
/sap/opu/odata/sap/ZFLIGHT_SRV/AirlineSet('AZ')?$expand=ToFlightSchedules,ToFlightSchedules/ToFlights,ToFlightSchedules/ToFlights/ToPlane&$format=json
/sap/opu/odata/sap/ZFLIGHT_SRV/FlightSet(AirlineId='AA',ConnectionId='17',FlightDate=datetime'2016-01-13T00:00:00')/ToPlane?$format=json
Final Words
Here we are at the end of another blog in the series. Hopefully you have been able to follow along and have all the examples working. Either with this set of data or your own set that you have experimented with.
Remember to try and use some views as well as transparent tables, this way we can make use of some inner joins with in the view, to include data from related tables.
Stay tuned for another blog…
getEntitySetMethod -> passing 2 filter values
Hi experts,
i want to pass to the getEntitySet method of my service 2 filter values
?$filter=PAR1 eq '01'&$filter=PAR2 eq '02'
But how can I access both filters in my service implementation. In the input filter string only the last value is inserted (PAR2 eq '02').
thanks for support.
br,
christoph
Capturing Item level changes in the PR
Hi,
I have a requirement of Purchase Requisition. My requirement is PRs keep getting modified with new line items being added, or existing line item being changed (Eg. amount change). These PRs are then routed for approval. Now the approver would want to view the sequence of these line item changes/additions intertwined with all the approvals and rejections that have taken place till date in the header level.
currently, I am getting all the item level changes for a particular PR in cdpos table.But for a particular item number, I am not able to find changes specific to it.
Eg: 6/1/2016 line item 10 added by username
6/2/2016 PR approved by Username2
please advice.
Best Regards
Step-By-Step Procedure for creating Purchase Requisition using BOR interface.
This blog shows how to display and create PR using gateway services(BOR interface) in detail.
Business Object Repository(BOR) in Gateway Service:
It generally used to reduce the time required to create entity types in your data model, SAP Gateway Service Builder provideImport RFC/BOR Interface function with which you can import an existing data source and reuse this data to create new entity types with ease.
Step 1:Open Tcode SEGW and create project as shown below.
Provide project details.
Step 2:Create entity by importing BOR interface. For this right click on Data Model and choose Import -> RFC/BOR Interface.
Provide the details.
Step 3:Expand and select the following fields for creating the Purchase requisition and choose next.
Fields selected RequisitionItems(PREQ_ITEM, DOC_TYPE, MATERIAL, PLANT, QUANTITY, UNIT,
DELIV_DATE),Number,Return(TYPE,MESSAGE,LOGMSGNO).
Specify the key field NUMBER and choose finish.
For displaying (QUERY) Purchase Requisition using BOR interface.
Step 4: Now basic definition of data model is done successfully. As a next step we need to map the fields.
Navigate to service implementation and create the QUERY to display the Purchase requisition.
Step 5: In BOR select the GetDetail for displaying the Purchase requisition details.
Select the type as Business object Repository and choose tick box.
Step 6: Now map the fields accordingly by selecting the propose mapping button as shown in below screen.
Step 7:Fields are mapped accordingly. Check the project, save and generate the project.
For Creating Purchase Requisition using BOR interface.
Step 8:For creating purchase requisition similarly map the fields by importing the BOR interface.
Step 9: Select the BOR method (CreateFromData) as shown in below screen.
Select and proceed.
Step 10:Now similarly click on propose mapping button as shown below.
Mapping will be done according. Save and generate the project.
Testing the Service:
Step 11: Display Purchase requisition
Case1:
Goto Tcode /N/IWFND/MANIT_SERVICE register service.
Provide System Alias and Click on Get Service. Select Our Created Service and click on Add Selected Service.
Case 2:
Click on SAP Gateway Client.
Case 3:
Provide the following URL, Select GET and click on EXECUTE to get the sample XML of PR.
Step 12 :Create Purchase requisition
Case:1
Click on Use as Request and then select POST and EXECUTE it.
Purchase requisition got created.
Case 2:
Goto SE11 table and provide the Created PR number. So below screen shows that Purchase requisition is created successfully.
HCP oData Provisioning and X-CSRF-Token
Hi support,
I'm not able to call a "CREATE" or "UPDATE" oData service registered in "oData Provisioning service"...
I always receive a 403 HTTP error (the same as if I do not pass any CSRF Token...);
I'll try to explain my tests, could you please help me in some way?
I develop an oData Service (SEGW transaction) and, at first, I publish it using /IWFND/MAINT_SERVICE transaction;
SAP Gateway Client - Local service
- If I test both GET and POST call via SAP Gateway Client all works; I could not manually set "X-CSRF-Token : Fetch" header parameter in GET call, since the Gateway Client show a message saying: "CSRF Token is handled by SAP Gateway Client"; in fact, when I test POST call, X-CSRF-Token header parameter is set automatically by the Test Client;
ARC - Local service
If I test both GET and POST call via ARC (Advanced Rest Client, a Chrome plugin used to do REST calls), all works well; in this case I have to manually ask X-CSRF-Token to the system (doing a GET call with "X-CSRF-Token : Fetch" header parameter); the response would contain a valid X-XSRF-Token I can use in the next POST call;
ARC - oData provisioning
My next step was to register this service in oData Provisioning HCP service:
- GET calls works well; if I set the "X-CSRF-Token : Fetch" parameter, oData response has a CSRF token in the header parameters;
- If I do a POST call, I always obtain a 403 HTTP error (both if I pass the CSRF token or NOT); in the response header I see a "X-Csrf-token : required" header parameter...;
Considerations:
- My user has both GW_ADMIN and GW_USER role in oData Provisioning service;
- CSRF token returned by the GET call is, in some way, different from the one returned by the oData published locally (only numbers in it and longer);
- Trying to pass a CSRF token obtained doing a GET call in "local" service to the "Cloud" service obviously do not work :-)
- No log / error shown in oData Provisioning "Troubleshooting" section (obviously, no error also in the BACK-END system, since I'm not authorized to do a call and the system is not called at all);
- I'm using an HCP account (not a trial one);
Thanks to all,
BR
Manuel
Consume External OData in SAP Gateway
I have metadata service that looks like this...
<edmx:Edmxxmlns:edmx="http://schemas.microsoft.com/ado/2007/06/edmx"Version="1.0">
</edmx:Edmx>
This does not make it pass the parsing. I debugged and found in class /IWFND/CL_OCI_PARSER they are replacing certain schemas in the compose_unrecognized method.
DATA: ls_unrec TYPE ty_s_unrec .
* ls_unrec-actual = 'MaxLength="Max"'.
* ls_unrec-expected = 'MaxLength=""'.
* APPEND ls_unrec TO mt_unrecognized .
*
* ls_unrec-actual = 'MaxLength="MAX"'.
* ls_unrec-expected = 'MaxLength=""'.
* APPEND ls_unrec TO mt_unrecognized .
ls_unrec-actual = 'xmlns="http://schemas.microsoft.com/ado/2007/05/edm">'.
ls_unrec-expected = 'xmlns="http://schemas.microsoft.com/ado/2008/09/edm">'.
APPEND ls_unrec TO mt_unrecognized .
* Example: http://www.nerddinner.com/SERVICES/ODATA.SVC/$metadata
ls_unrec-actual = 'xmlns="http://schemas.microsoft.com/ado/2006/04/edm">'.
ls_unrec-expected = 'xmlns="http://schemas.microsoft.com/ado/2008/09/edm">'.
APPEND ls_unrec TO mt_unrecognized .
* Example: Azure market place services
ls_unrec-actual = 'http://schemas.microsoft.com/ado/2009/08/edm'.
ls_unrec-expected = 'http://schemas.microsoft.com/ado/2008/09/edm'.
APPEND ls_unrec TO mt_unrecognized .
Does anyone know if this could be updated, perhaps even made into a customizing table?
Thanks,
Alex
problem with URI in ODATA
Dear experts ,
i developed a ODATA service successfully. For that service i need to give plant , condition type and are single values simultaneously i need to pass a range table for Material number.
i am giving URI
/sap/opu/odata/SAP/YHKLL_SRV/PLANTSet?$filter=ConditionType eq 'PR00' and Werks eq '3000' and Material eq 'M16283' or Material eq 'M81018'
i am getting error 500 INTERNAL SERVER ERROR .
please correct my URI.
Thank you .
Catch a POST Payload.
Good afternoon fellow SAPers.
I am wondering if there's a posibility to keep a trace of the payloads sent to GW services. I know there's the transaction /IWBEP/TRACES, however this is an On - Demand trace and it has a period for when it can keep the Trace up.
Question is if there's a standar way to do the following.
My client requieres us to keep a log of the info sent from our Device to the backend, I need to figure out if there's a way to catch the payload and keep it on a file like XML for reference. Otherwise I could catch the POST Payload that we get from the method read_entry_data and convert it into a XML.
I know it's a weird requierement, but we want to keep a trace of the failed payloads to figure out some issues with the app.
With no further ado, I'm grateful for any ideas that you guys could have.
Cheers.
HCI - Odata Services (Beta) - oData endpoint
Hi all,
I need to create an OData service based on an existing OData service.
It should be possible according to this blog:Introduction to Creating OData Service in HANA Cloud Integration (beta)
I activate Odata Beta Service and I create my oData service (doing what described in this blog adapting it from SOAP to oData: Creating OData Service from SOAP using HCI (beta))
At the end of the procedure, when I try to access the created and deployed service constructing my endpoint (SAP HANA Cloud Integration (Internal, SAP HCI OEM)), I receive this error as a response:
HTTP Status 500 - while trying to invoke the method com.sap.gateway.core.ip.service.SecurityConfiguration.getSubjectsAndIssuers() of a null object loaded from local variable 'secConfig'
This is the URL called: https://*****-iflmap.hcisbt.eu1.hana.ondemand.com/gw/odata/SAP/Customer;v=1/
Namespace and service name should be correct (see screen) and also IFLMAP URL (same URL retrieved both from Eclipse and HCP cockpit);
Some considerations:
- From HCI monitor I could see my Integration Content deployed correctly; no logs at all;
- If I try to edit the Metadata of the oData service created, I see that NAMESPACE has a space at the beginning (see preceding screen)... If I try to remove it, system automatically put a space again; I try also tu add an encoded space in the endpoint URL, but same error...
- In the integration flow, staring point is an oData sender (system and connection to start) not editable and with no reference to an endpoint... All has been created automatically by the system.
Any suggestion? I do not know how to proceed...
Thank you so much,
Manuel