04-04-2012 12:26 PM
Hello!
this is my first post ever, so please be gentle with me
i have the following question:
i want to create a function module, which is RFC-able and all it should do is import the method name which i will call dynamically and the parameter table which is necessary to call the method with the correct parameters.
defining the method name as an importing parameter type string for the function module is possible, so whenever the user choses to e.g. press the button logon i will import the proper method name (e.g. LOGON).
2nd i need the parameters which is of type abap_parmbind_tab and here the system (in the SE37) cries that generic types are not allowed for RFC function modules and i have absoluteley no idea of how i can fix this matter.
so in short: is it in general possible to create such a RFC function module which will call dynamically the method + the correct parameters via abap_parmbind_tab?
thanks a lot in advance,
dominik
04-04-2012 1:20 PM
Hi Dominik,
I really liked your idea
I think in your case it won't be possible to include abap_parmbind_tab type parameters.
VALUE of the type REF TO DATA. And references are not allowed in RFC FMs.
What I think can be done.
1) get the list of all the methods which are wrapping in the RFC FM.
2) add all the parameter of all the method in you FM interface ( Nor referecne type )
3) In the FM based on the FM name passed populate the local variables ABAP_PARMBIND_TAB and make the dynamic call
http://help.sap.com/saphelp_nw70/helpdata/en/08/d27c03b81011d194f60000e8353423/content.htm
04-04-2012 1:54 PM
I've done exactly what you required, and encountered the same problem. To resolve it I converted the value into hexadecimal before calling the RFC. Within the RFC, I convert the hex value back to whatever type the parameter requires.
04-05-2012 2:59 PM
I was wrong. This is what you need: cl_abap_container_utilities=>fill_container_c
It returns a string, and then you have to convert that into a table of fixed length characters, so you can rebuild the string at the other end, and then use read_container_c to recover that data. Which could even be a structure or a table..
04-05-2012 4:31 PM
Hello,
I think this is a problem every developer has to face when he/she tries to use dynamic elements with RFC!
Matthew Billingham wrote:
... you have to convert that into a table of fixed length characters, so you can rebuild the string at the other end ...
Imo defining the return table of "fixed length characters" will always be a problem - something i faced a few weeks back
BR,
Suhas
04-06-2012 8:01 AM
Not a problem.
You've converted your data into a string. You cut the string into, say, 256 character portions, so it'll fit into a table of CHAR256. For the last slice, you record how many bytes of the field are actually used.
I.e. assume your string is 'abcdefghijklm', and your table is CHAR8. Then you end up with
abcdefgh
ijklm
To recover the string, you just need the table with these chars, and 5, so you get the length of the string right. This is pretty much the same as what's done for sending binary data as MIME.
Believe me, it works - I've done it! (I should say that using cl_abap_container_utilities was Otto Gold's idea.).
matt
10-09-2012 1:39 PM
I am afraid that I must confirm the problem with the fixed length. I learnt the hard way (one of the tools I`ve built does not work over RFC at one of our customers despite the fact it worked just fine on my internal systems). I am researching the problem now and to me the XML option (CALL TRANSFORMATION ID) sounds like the best thing we can do.
I am sorry for misleading recommendation, Matt, the container operation thing is not safe.
Hope this helps other people too, I have seen tons of questions about the topic in last hours.
For further information about the XML option I recommend and the contribution and the feedback thread:
http://scn.sap.com/thread/53916
http://scn.sap.com/docs/DOC-10106
I haven`t tested it in production environment yet, but originally used the string container for "any structure" and some structures just didn`t work out.
Cheers Otto
10-19-2012 9:28 AM
So why doesn't it work at your customer? I've used the same technique with one of my clients and it is fine. I'm taking a standard table with records comprising flat fields. I don't know its structure until runttime, but need to pass the data to an RFC FM (along with the typing information).
I've a container structure defined in the data dictionary:
RECORD_NUMBER INT4
COMPONENT_NUMBER INT4
CHAR_REC_NUMBER INT4
CHAR_DATA CHAR255
RECORD_LENGTH INT4
Then I use this code where <t_data> is a generic table and <s_data> is type any, but is a non-deep structure:
ls_container is type the container structure, and lt_container is a standard table of it.
* Convert each line to a string, then convert into the container format
LOOP AT <t_data> ASSIGNING <s_data>.
ls_container-record_number = sy-tabix.
DO.
ls_container-component_number = sy-index.
ASSIGN COMPONENT ls_container-component_number OF STRUCTURE <s_data> TO <field>.
IF sy-subrc IS NOT INITIAL.
EXIT.
ENDIF.
cl_abap_container_utilities=>fill_container_c( EXPORTING im_value = <field> IMPORTING ex_container = l_converted ).
DO.
ls_container-char_rec_number = sy-index.
l_len = STRLEN( l_converted ).
IF l_len LT c_container_width.
ls_container-record_length = l_len.
ls_container-char_data = l_converted.
INSERT ls_container INTO TABLE lt_container.
EXIT.
ENDIF.
ls_container-record_length = c_container_width.
ls_container-char_data = l_converted(c_container_width).
INSERT ls_container INTO TABLE lt_container.
l_converted = l_converted+c_container_width.
IF l_converted IS INITIAL.
EXIT.
ENDIF.
ENDDO.
ENDDO.
ENDLOOP.
At the receiving end, I decode it_data - which is my table of the container structure type. l_record is a string.
* Convert the data from the interface into the right format
sort it_data by record_number component_number char_rec_number.
loop at it_data into ls_data.
if ls_data-record_length gt 0.
concatenate l_record ls_data-char_data(ls_data-record_length) into l_record.
endif.
at end of component_number. " New component
assign component ls_data-component_number of structure <s_outdata> to <field>.
cl_abap_container_utilities=>read_container_c( exporting im_container = l_record
importing ex_value = <field> ).
clear l_record.
endat.
at end of record_number.
insert <s_outdata> into table <t_outdata>.
endat.
endloop.
<t_outdata> is a table of the same structure as <t_data>. (likewise <s_outdata> and <s_data> ).
06-04-2012 1:11 PM
just wanted to finish my thread off. maybe it is helpful for others.
what we have done is following:
it may sound a little bit 'dirty' but a big advantage is that we do not have to deploy the RFC all the time whenever we change something in it.
i do not know how much performance we will lose with this - if you are interested i can set up some measurements (which i will be able to do in 2 weeks).
10-10-2012 6:25 PM
Hello Dominik,
I know its not nice to re open a closed discussion. But, since you are calling methods dynamically and your RFC is generic, how would you handle object instantiation?. Some objects might implement a singleton, others may not, would this not be an issue?.
Please do correct me if I am getting wrong somewhere.
Thanks,
Venkat.
10-10-2012 9:03 PM
only purpose is to pass the import parameters through to another FM which is representing our 'Main' Function.
Ok , So I missed this point. So you would be creating another FM where the actual object instantiation and the method call would happen. This FM would be application specific I would assume. It would be more like "An Object - message interface".- Sort of theoretical OO programming, where Objects listen and react to messages .
Thanks,
Venkat.