A simple middleware for RFC/HTTP
When I first experienced* GOOGLE’s ANDROID*, I was puzzled ’bout how to communicate with SAP without having to install something in my device…so,I look for some http client interfaces which could help me…simple and fast…
When my search failed, I decide to create my own http service to call ANY function in SAP system via HTTP, without having the restriction of RFC’s enabled ones.
I wish to share my experience, hoping it’ll be helpful to someone…
Access to SICF transaction and declare a new service; insert the service user which will be used by default to access to your system.
In the tab ‘Handler List’ insert your+ Z class+ which implement the IF_HTTP_EXTENSION interface(create it if doesn’t already exist using SE24).
Save and activate the service.
Insert the following code in the IF_HTTP_EXTENSION~HANDLE_REQUEST method:
set extended check off.
type-pools ABAP.
data PARA_TAB type ABAP_FUNC_PARMBIND_TAB.
data: aus_para_tab type table of abap_func_parmbind,
aus_line type abap_func_parmbind.
data PARA_LINE like line of PARA_TAB.
data AREA(4) type C.
data OBJECT(30) type C.
types: begin of import,
name type string,
value type string,
end of import,
begin of tables,
name type string,
row type string,
field type string,
value type string,
end of tables.
-
…
data: fbname_resp(200) type c.
data: outsstr type string.
data: outdoc type xstring,
indoc type xstring.
data: fbname(40) type c.
data: fb_response type string.
data: xform(50) type c.
data: xprog(50) type c.
data: tagtype type i.
data: exception type string.
data: nsattrib type string.
data: response type string.
data: header type string.
data: xmlheader type string.
data: begindoc type string.
data: enddoc type string.
data: beginfault type string.
data: endfault type string.
data: faultcode type string.
data: faultstring type string.
data: fault_detail type string.
data: detail_name type string.
data: detail_msg type string.
data: dummy type string.
data: sy_subrc(2) type c.
data: tagname type string,
value type string,
xmlns type string,
attname type string,
attval type string,
attribcnt type i,
i type i.
data: raise_exception type c.
data: content_type type string.
data: templ_http_hdr type string,
templ_body type string.
data: cdata type string.
*&-Retrieving of characer data
cdata = server->request->get_cdata( ).
*{ INSERT SVIK909215 1
*data acca. while acca eq space. endwhile.
*} INSERT
if not cdata is initial.
data:miniparser type ref to cl_ixml_mini_parser.
data:minidom type ref to if_ixml_mini_dom.
data rc type sy-subrc.
data: nodename type string.
data: node type ref to IF_IXML_MINI_NODE,
newnode type ref to if_ixml_mini_node,
nodeleaf type ref to if_ixml_mini_node,
nvalue type ref to if_ixml_mini_node,
nodetab type ref to if_ixml_mini_node,
noderow type ref to if_ixml_mini_node,
nodefield type ref to if_ixml_mini_node,
funname type string,
timport type table of import,
ttables type table of tables,
simport type import,
stables type tables,
rowindex(3) type n.
data: responsexml type string,
viewname type DD02L-TABNAME,
tdfies type table of ddfield,
sdfies type ddfield,
valfield type char200.
DATA: ITERATOR TYPE REF TO IF_IXML_MINI_DFS_ITER.
CREATE OBJECT MINIPARSER.
CALL METHOD MINIPARSER->PARSE_STRING
EXPORTING
STREAM = CDATA
IMPORTING
DOM = MINIDOM.
iterator = minidom->get_dfs_iterator( ).
while rc eq 0.
nodename = iterator->get_name( ).
node = iterator->get_node( ).
case nodename.
when ‘CALL_FUNCTION’.
call method node->get_attribute
exporting
index = 1
importing
value = funname.
when ‘EXPORTING’.
*&-
*&- GESTIONE PARAMETRI IMPORTING
*&-
newnode = node->get_first_child( ).
simport-name = newnode->get_name( ).
nvalue = newnode->get_first_child( ).
if not nvalue is initial.
simport-value = nvalue->get_value( ).
endif.
append simport to timport.
nodeleaf = newnode.
while 1 = 1.
clear nodeleaf.
nodeleaf = newnode->get_next( ).
if nodeleaf is initial.
exit.
endif.
simport-name = nodeleaf->get_name( ).
simport-value = nodeleaf->get_value( ).
append simport to timport.
newnode = nodeleaf.
endwhile.
when ‘TABLES’.
*&-
*&- GESTIONE TABLES
*&-
nodetab = node->get_first_child( ).
while 1 = 1. “tab
rowindex = 1.
if nodetab is initial. exit. endif.
stables-name = nodetab->get_name( ).
noderow = nodetab->get_first_child( ).
while 1 = 1 .”is initial.
stables-row = rowindex.
if noderow is initial. exit. endif.
nodefield = noderow->get_first_child( ).
while 1 = 1.
if nodefield is initial. exit. endif.
stables-field = nodefield->get_name( ).
nvalue = nodefield->get_first_child( ).
if not nvalue is initial.
stables-value = nvalue->get_value( ).
endif.
append stables to ttables.
nodefield = nodefield->get_next( ).
endwhile.
add 1 to rowindex.
noderow = noderow->get_next( ).
endwhile.
nodetab = nodetab->get_next( ).
endwhile.
endcase.
rc = iterator->advance( ).
endwhile.
data: texc type table of rsexc,
sexc type rsexc,
texp type table of rsexp,
sexp type rsexp,
timp type table of rsimp,
simp type rsimp,
tcha type table of rscha,
scha type rscha,
tpara type table of rstbl,
spara type rstbl.
data datatype type ref to data.
data: funcname type RS38L-NAME.
funcname = funname.
CALL FUNCTION ‘FUNCTION_IMPORT_INTERFACE’
EXPORTING
funcname = funcname
-
INACTIVE_VERSION = ‘ ‘
-
IMPORTING
-
GLOBAL_FLAG =
-
REMOTE_CALL =
-
UPDATE_TASK =
-
EXCEPTION_CLASSES =
tables
exception_list = texc
export_parameter = texp
import_parameter = timp
CHANGING_PARAMETER = tcha
tables_parameter = tpara
-
P_DOCU =
-
EXCEPTIONS
-
ERROR_MESSAGE = 1
-
FUNCTION_NOT_FOUND = 2
-
INVALID_NAME = 3
-
OTHERS = 4
.
IF sy-subrc <> 0.
-
MESSAGE ID SY-MSGID TYPE SY-MSGTY NUMBER SY-MSGNO
-
WITH SY-MSGV1 SY-MSGV2 SY-MSGV3 SY-MSGV4.
ENDIF.
field-symbols: ‘ into responsexml.
CALL FUNCTION ‘DD_NAMETAB_TO_DDFIELDS’
EXPORTING
-
KEYFIELDS = ‘X’
-
NULLABLE = ‘X’
tabname = viewname
-
IMPORTING
-
SUBRC =
tables
ddfields = tdfies
.
looP AT tdfies into sdfies.
concatenate ‘.
read table tpara into spara with key parameter = para_line-name.
if sy-subrc eq 0.
if not spara-dbstruct is initial.
viewname = spara-dbstruct.
elseif not spara-typ is initial.
typen = spara-typ.
CALL FUNCTION ‘DD_TTYP_GET’
EXPORTING
-
GET_STATE = ‘M ‘
-
LANGU = SY-LANGU
-
PRID = 0
ttyp_name = typen
-
WITHTEXT = ‘ ‘
-
TRACELEVEL = 0
IMPORTING
DD40V_WA_A = dd40wa
-
DD40V_WA_N =
-
GOT_STATE =
-
TABLES
-
DD42V_TAB_A =
-
DD42V_TAB_N =
-
EXCEPTIONS
-
ILLEGAL_VALUE = 1
-
OP_FAILURE = 2
-
OTHERS = 3
.
IF sy-subrc <> 0.
-
MESSAGE ID SY-MSGID TYPE SY-MSGTY NUMBER SY-MSGNO
-
WITH SY-MSGV1 SY-MSGV2 SY-MSGV3 SY-MSGV4.
ENDIF.
viewname = dd40wa-rowtype.
endif.
endif.
if not [] is initial.
concatenate responsexml ‘<‘ para_line-name ‘>
‘ into responsexml.
CALL FUNCTION ‘DD_NAMETAB_TO_DDFIELDS’
EXPORTING
-
KEYFIELDS = ‘X’
-
NULLABLE = ‘X’
tabname = viewname
-
IMPORTING
-
SUBRC =
tables
ddfields = tdfies
.
loop at <CALL_FUNCTION name=”<functionname>”></p><p>* <EXPORTING></p><p> </p><p> </p><p> ….</p><p> </p><p> </p><p> </p><p> </p><p> </p><p> </p><p> </row></p><p> </NAMETAB1></p><p> ….</p><p> < /NAMETABn></p><p> </p><p>The server should invoke the function and answer with a similar format:</p><p><CALL_FUNCTION name=”<functionname>”></p><p> </p><p> </p><p> </p><p> ….</p><p> </p><p> </p><p> </p><p> </p><p> </p><p> </p><p> </row></p><p> </NAMETAB1></p><p> ….</p><p> < /NAMETABn>*
…Just as if you call a function from ABAP code…
Cordiali saluti,
Ignacio.
Best Regards and thanks again
Paolo
Regards, Andreas
In this case,of course, one should implements major changes to the service: https, limit access via mapped (device) user, etc...
Like all service of this kind, I think should be a developer's tool, so I can't understand why should'nt access to no-RFC enabled FM...
regards
Paolo