Supply energy to ABAP Web Services in SAP Web AS 6.20
Introduction
ABAP Web Services (SOAP runtime) is a very powerful technology and with few tips it becomes also more flexible and robust. Virtual Interfaces introduced in SAP Web AS 6.40 provide great
benefits but if you cannot upgrade now then continue to read this weblog.
There are other weblogs on this topic and I suggest to read the followings:
“BSP – a Developer’s Journal Part XIII: Developing ABAP Web Services” by Thomas Jung
“Real Web Services with REST and ICF” by DJ Adams
Headaches due to XML Schemas?
SAP Web AS 6.20 automatically serialize XML to ABAP and vice versa. It is a great feature but what
about if you need more flexibility?
Attributes are not supported and element names are linked to the ABAP dictionary objects.
So, in projects you will normally have to code structures and tables type starting with ZV* (for sales)
and then you will have XML elements called ZV* (not so nice).
It is also quite difficult to produce XML elements completely in lower case (especially the 1st char).
Take the ABAP+XSLT medicine
Do you know ABAP? Do you know XSLT?
If Yes, you can produce XML messages also according to most complicated schema.
Invoke the XSLT processor in your RFC in order to create also the most complex XML document.
Then, move it to an export parameter of type STRING.
So easy?
You are not so lucky and that’s why you will need to continue reading my weblog…
The HTTP handler of the SOAP processor replace <, > and other special chars.
Test it and tell me what happened to your well formatted data…
Here is How-to solve the issue (you will also win a nice SOAP log)
STEP 1 – a new SOAP runtime Class Handler
– in SE24 create a new class handler extending HTTP_EXT_SOAPHANDLER_RFC or coping it
– update method IF_HTTP_EXTENSION~HANDLE_REQUEST
with the following code:
METHOD if_http_extension~handle_request .
-
Begin of insert
DATA: o_conv TYPE REF TO cl_abap_conv_in_ce,
l_crequest_len TYPE i,
l_crequest TYPE string,
l_cresponse_len TYPE i,
l_cresponse TYPE string.
DATA: l_uuid TYPE sysuuid_c.
DATA: l_uuid_string TYPE string.
DATA: l_log_file_path TYPE string VALUE ”. “<– Insert the path where log has to be written
DATA: l_log_file_name TYPE string.
DATA: l_log_file_sep_req_begin TYPE string.
DATA: l_log_file_sep_req_end TYPE string.
DATA: l_log_file_sep_res_begin TYPE string.
DATA: l_log_file_sep_res_end TYPE string.
l_log_file_sep_req_begin = ‘*** Incoming SOAP – Begin **********************************************’.
l_log_file_sep_req_end = ‘*** Incoming SOAP – End **********************************************’.
l_log_file_sep_res_begin = ‘*** Outgoing SOAP – Begin **********************************************’.
l_log_file_sep_res_end = ‘*** Outgoing SOAP – End **********************************************’.
-
Log – Get GUID
CALL FUNCTION ‘SYSTEM_UUID_C_CREATE’
IMPORTING
uuid = l_uuid.
-
Log – Build file name
l_uuid_string = l_uuid.
CONCATENATE l_log_file_path
sy-uname
‘_’
l_uuid_string
‘.log’
INTO l_log_file_name.
-
End of insert
DATA: soap_proc TYPE REF TO csoaprequestprocessor.
DATA: rfc_plugin TYPE REF TO csoaprequestpluginrfc.
DATA: if_plugin TYPE REF TO isoaprequestplugin.
DATA: request TYPE xstring.
DATA: response TYPE xstring.
DATA: errstrg TYPE string.
DATA: errcode TYPE string.
CREATE OBJECT soap_proc.
CREATE OBJECT rfc_plugin.
if_plugin = rfc_plugin.
IF soap_proc IS INITIAL
OR if_plugin IS INITIAL.
CONCATENATE csoapconstants=>sc_soap_fault_maj_srvr
csoapconstants=>sc_soap_fault_min_int
INTO errcode SEPARATED BY ‘.’.
CALL METHOD csoaptools=>create_simple_string_fault
EXPORTING
faultcode = errcode
faultstring = ‘Cannot allocate request handler’
IMPORTING
stringfault = errstrg. “#EC NOTEXT
CALL METHOD server->response->set_header_field(
name = ‘Content-Type’
value = ‘text/xml’ ).
CALL METHOD server->response->set_cdata( data = errstrg ).
EXIT.
ENDIF.
request = server->request->get_data( ).
-
Begin of insert
-
Convert into STRING
o_conv = cl_abap_conv_in_ce=>create( input = request ).
o_conv->read( IMPORTING data = l_crequest len = l_crequest_len ).
-
Log request
CALL TRANSFORMATION (‘INDENT’)
SOURCE XML l_crequest
RESULT XML l_crequest.
OPEN DATASET l_log_file_name FOR OUTPUT IN TEXT MODE ENCODING UTF-8.
TRANSFER l_log_file_sep_req_begin TO l_log_file_name.
TRANSFER l_crequest TO l_log_file_name.
TRANSFER l_log_file_sep_req_end TO l_log_file_name.
-
End of insert
CALL METHOD soap_proc->process_request
EXPORTING
request = request
plugin = if_plugin
IMPORTING
response = response
EXCEPTIONS
processing_failure = 1.
IF sy-subrc NE 0.
CALL METHOD server->response->set_status(
code = ‘500’
reason = ‘Soap document processing failed’ ).
ENDIF.
CALL METHOD server->response->set_header_field(
name = ‘Content-Type’
value = ‘text/xml; charset=utf-8’ ).
-
Begin of insert
-
Step 1 – Convert into STRING
o_conv = cl_abap_conv_in_ce=>create( input = response ).
o_conv->read( IMPORTING data = l_cresponse len = l_cresponse_len ).
-
Step 2 – Replace special STRINGs
REPLACE ALL OCCURENCES OF
‘<?xml version=”1.0″ encoding=”iso-8859-1″?>’
IN l_cresponse WITH ”.
-
Step 3 – Replace special characters
REPLACE ALL OCCURENCES OF ‘<‘ IN l_cresponse WITH ‘<‘.
REPLACE ALL OCCURENCES OF ‘>’ IN l_cresponse WITH ‘>’.
REPLACE ALL OCCURENCES OF ‘”‘ IN l_cresponse WITH ‘”‘.
REPLACE ALL OCCURENCES OF ”’ IN l_cresponse WITH ””.
-
Step 4 – Convert back to XSTRING
DATA: oref TYPE REF TO cl_abap_conv_out_ce.
DATA: slen TYPE i.
DATA: xlen TYPE i.
CALL METHOD cl_abap_conv_out_ce=>create
EXPORTING
encoding = ‘UTF-8’
endian = ‘ ‘ “– or: ‘L’, ‘B’
RECEIVING
conv = oref.
slen = strlen( l_cresponse ).
CALL METHOD oref->write
EXPORTING
n = slen
data = l_cresponse
IMPORTING
len = xlen.
response = oref->get_buffer( ).
-
Step 5 – Log
CALL TRANSFORMATION (‘INDENT’)
SOURCE XML l_cresponse
RESULT XML l_cresponse.
TRANSFER l_log_file_sep_res_begin TO l_log_file_name.
TRANSFER l_cresponse TO l_log_file_name.
TRANSFER l_log_file_sep_res_end TO l_log_file_name.
-
End of insert
CALL METHOD server->response->set_data( data = response ).
ENDMETHOD.
Now attach the CLASS HANDLER created in STEP 1 to this new service:
STEP 3 – the Web Service (RFC)
Create a simple RFC enabled function module that export the parameter RESPONSE of TYPE STRING.
<BR/>Enjoy invoking your Web Service and do not forget to have a look to the produced log file
(it is called <USER>_;<GUID>.log in the directory of your SAP Web AS file system)
<BR/>
WSDL Generation
Unfortunately no utility can be made available to produce a WSDL describing a response XML schema that
is not known by the system.
Take a while and learn WSDL language, you need to write it manually (if you have the XML schema it’s easy).
Happy SOAP to you…
Sergio





