Wednesday, October 13, 2010

Perl, RFC, ABAP and Macros

Summary

Perl, RFC, ABAP and Macros - what do they have to do with it all?

Macros - Just call me old fashioned ... But I love 'em!

By Piers Harding

09 Jun 2004

Macros

In my earlier SAP years, I used to go from project to project, and was forever finding that I wanted to do the same things that I did last time - programming wise. I quickly grew tired of this repetitiveness - so something just had to be done about it. It became a bit of a game - how could I alter the way I had to program, and record all those little juicy code snipets, for anything from updating the screen status bar, to speeding up DATA declarations? My answer was to have a personal program INCLUDE, and to accumulate the knowledge and experience in code fragments housed in MACROS. Before I knew it, an interesting side effect occurred - I had started creating my own version of ABAP - for example: I didn't like the "REFRESH" command , so I reinvented it as "zap".

define zap.
  free &1. clear &1.
end-of-definition.
    
data: xtab like tab512 occurs 0 with header line.
    
    
zap xtab.

See - that was four less key strokes! And, it just sounds like what I want to do to an internal table. So, I would merrily accumulate these macros (I have approx 100), as I went from project to project. Each place I went to got the benefit of the macros that I had built up from the last place, and I took with me the new ones as they evolved. This was always an agreement that I made with the management, and they were usually quite happy when I explained that it would mean that I would code faster/be more productive as a result. (I'm sure we could get into "Holy Wars" over what this means in terms of IP, and also the issue of ABAP just not looking universal anymore, but I'll leave that discussion as an exercise for the reader :-). )

Perl

Now, as a Perl programmer the three tenets of Perl - "laziness, impatience and hubris" - are dear to my heart, and Macros play right into this.

Macros don't just save you time, by reducing the typing you have to do for repetitive tasks, they also allow you to define new actions and grammar in a programming language, like this:

define uc.
  translate &1 to upper case.
end-of-definition.
    
data: x type string value 'the quick brown fox'.
    
* convert to upper case
uc x.

or:

define cat.
  concatenate &1 &2 into &1.
end-of-definition.
    
data: x type string value 'the quick brown fox ',
      y type string value 'jumped over the lazy do'.
    
* concatenate two strings together
cat x y.

These time-saving devices have also allowed me to bring ABAP just that little bit closer to other more "natural" languages that I like programming with, while also gaining (a little) satisfaction by further obliterating it's COBOLesque roots.

RFC Requests and Macros

But - that is not the main thrust of this spiel - what I really wanted to show was how you can further push the boundaries of ABAP, by using RFC, and the "smoke and mirrors" quality of Macros, to bind other programming languages to your applications.

The example detailed below is a functioning Application Server that is RFC enabled. It just so happens that the Server is written in Perl, but there is no reason why it couldn't be Python, or Ruby, or any number of other programming languages - it was just easier (for me) to do it in Perl.

The Server provides the functionality of executing the various snippets of Perl code passed to it, but it is the Macros that hide away all the unpleasant verbosity of translating those RFC requests, into what looks like a new set of commands in the ABAP language. For instance, you can execute an arbitrary snippet of code:

perl_string = 'print "Hello + return!\n"; "the return bit";'.
  pexec_return perl_string result_string.
  write: /01 result_string.

and result_string will have "the return bit" in it, as it is the last evaluation in the Perl code block. "Well - what is the use of that?" I hear you say. Well - take a look at another example of what we can do:

method_name = 'MIME::Base64::encode_base64'.
  pstring_table = 'my piece of text'.
  append pstring_table.
  pstatic_method method_name pstring_table result_table.
  loop at result_table.
    write: /01 'base64 encoded string: ', result_table.
  endloop.

This piece of code allowed a static method name (encode_base64) from a Perl package (Mime::Base64) to be called, passing it an arbitrary list of parameters, and receiving an arbitrary list of results - in this case, specifically calling a function that base64 encoded a string. I now have a means of base64 encoding ABAP strings in any of my programs (if I really wanted that - your mileage may vary).

But even that is not the extent of the point that I'm trying to make here - CPAN has literally thousands of packages and libraries that could be useful in your code, and now they are all available! Also, because of other Macros available in this Perl Server, you can execute code blocks in various ways, perform Perl style regular expressions, instantiate Perl objects, call instance methods, and delete objects.

Note: to obtain the full details of what commands/macros are available and how they operate, please refer to the macro INCLUDE file (it is documented), and the test Report referenced in the What you need section.

Additionally, this is functionally no different from how the outbound communication with the SAP NetWeaver JAVA application server works, as it relies on the Registered RFC interface for communication with the JVM.

However - where Perl (and certain other languages) differs (and I think excels) is that Perl has a very universal set of data types (scalars, and arrays) and uses the concept of coercing values into the appropriate form for a given context (e.g. changing a string to an int if doing a numeric comparison, etc.), making it very easy to represent it inside another language - in this case, ABAP.

Making It Happen

The whole set of examples are available for you to try. There are two main components to this. First, you need to set up and run the Perl server, and second, you need to create the program INCLUDE containing the macros, and the test Executable ABAP program. You can download the code for steps 1, 3, and 4.

What You Need

  1. Perl Server (Registered RFC) -> code. Save this to a file called perl.pl.

  2. Ensure that you have the Perl module SAP::Rfc installed - you can get this from CPAN at search.cpan.org.

  3. ABAP Macros INCLUDE -> macro include. Upload this to an ABAP program include ZIBPERLMACROS.

  4. ABAP Test Report -> report code. Upload this to an Executable ABAP program called ZTEST_PERL.

  5. Create a registered RFC DESTINATION in transaction SM59 called 'PERL' with a TPNAME of 'perl' - these can be changed by reading the notes in the macro file, and using the switches associated with the program perl.pl.

  6. Run the Perl Server - you can discover the program options by running: perl perl.pl -h. You will most likely need to run it something like this: perl -MURI -MMIME::Base64 perl.pl -d -g -s -n

    Note: the "-MURI -MMIME::Base64" switches are only necessary for the running of the ABAP Test Report - they load the appropriate Perl packages that the tests rely on (URI and MIME::Base64). You would use similar options to load other libraries that you wanted to access from ABAP.

  7. Now execute the test Report program ZTEST_PERL.

The environment I used for developing this was:

  • RedHat 9

  • Perl 5.8.0

  • SAP::Rfc 1.31

  • SAP: NetWeaver 4 evaluation system, should work with R/3 4.x+

Output

If you are running the test suite, then you can expect output like this from the Perl Server:

Mon Jun  7 09:06:10 2004: Debugging is switched on...
Mon Jun  7 09:06:10 2004: VERSION: 1.31
Mon Jun  7 09:06:10 2004: START
Mon Jun  7 09:06:14 2004: Running do_exec_perl...
Mon Jun  7 09:06:14 2004: call type is: E
Mon Jun  7 09:06:14 2004: Command is: #print "Hello!\n";#
Hello!
Mon Jun  7 09:06:14 2004: Finished iteration - returning...
    
    
Mon Jun  7 09:06:14 2004: Running do_exec_perl...
Mon Jun  7 09:06:14 2004: call type is: ER
Mon Jun  7 09:06:14 2004: Command is: #print "Hello + return!\n"; "the return bit";#
Hello + return!
Mon Jun  7 09:06:14 2004: Exec result is: the return bit
Mon Jun  7 09:06:14 2004: Finished iteration - returning...
....

The test Report output should look something like this:

What Now?

A lot of the focus with SAP seems to be (to me) on how to make SAP more "open", and accessible to the rest of the (Computing) world, but why shouldn't we look for ways in which SAP (or more specifically - R/3) can be extended by bringing in applications from the outside.

In this example, I have hopefully shown how this can be achieved, as I have opened SAP up to the potential of the extensive code base of the Perl community. However - it is not just Perl that has something to offer. There are many other communities built up around programming languages that also have large application resources available - so why not these too?

Appendix

The code samples referred to above: perl.pl, zibperlmacros and ztest_perl can be downloaded from:

No comments:

Tutorials on SAP-ABAP

Adobe Interactive Forms Tutorials

Business Server Pages (BSP)

Userexits/BADIs

Web Dynpro for ABAP (Step by step procedure for web dynpro,Tutorials on Web Dynpro,)

ALV Tutorials

Blog Archive

goodsites