Application Development Discussions
Join the discussions or start your own on all things application development, including tools and APIs, programming models, and keeping your skills sharp.
cancel
Showing results for 
Search instead for 
Did you mean: 

dynamic method call over RFC function module

Former Member
0 Kudos

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

10 REPLIES 10

Private_Member_49934
Contributor
0 Kudos

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

More on this here

http://help.sap.com/saphelp_nw70/helpdata/en/08/d27c03b81011d194f60000e8353423/content.htm

matt
Active Contributor
0 Kudos

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.

matt
Active Contributor
0 Kudos

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..

0 Kudos

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

matt
Active Contributor
0 Kudos

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

OttoGold
Active Contributor
0 Kudos

Hi , friends,

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

matt
Active Contributor
0 Kudos

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> ).

Former Member
0 Kudos

just wanted to finish my thread off. maybe it is helpful for others.

what we have done is following:

  • created a RFC FM.
  • only purpose is to pass the import parameters through to another FM which is representing our 'Main' Function.
  • there we unwrap our import parameters and call the proper methods.

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).

0 Kudos

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.

0 Kudos

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.