Quantcast
Channel: ABAP Development
Viewing all articles
Browse latest Browse all 948

ABAP Trapdoors: CALL TRANSFORMATION id(ontwork)

$
0
0

Welcome to another ABAP Trapdoors article - the first one posted using my new SCN user. If you are intersted in the older articles, you can find a link list at the bottom of this post.

 

I've been using asXML for some years now as a convenient way to serialize and deserialize arbitrary ABAP data structures. Some time ago, I learned about IF_SERIALIZABLE_OBJECT and its use to include class instances (aka objects) in an asXML representation as well. A few days ago, I decided to use this technique in a current development project. At the same time, I was trying to use CL_DEMO_OUTPUT_STREAM instead of classic lists as suggested by the online documentation, and since I was supposedly familiar with the basics of using transformations, I focused rather on the usage of this new output technology. I hacked together a small demo programm like this one:

 

REPORT z_test_serialize.
CLASS lcl_serializable_thingy DEFINITION CREATE PUBLIC.  PUBLIC SECTION.    INTERFACES if_serializable_object.    METHODS constructor      IMPORTING        i_foo TYPE string.    METHODS get_foo      RETURNING        VALUE(r_foo) TYPE string.  PRIVATE SECTION.    DATA g_foo TYPE string.
ENDCLASS.
CLASS lcl_serializable_thingy IMPLEMENTATION.  METHOD constructor.    g_foo = i_foo.  ENDMETHOD.  METHOD get_foo.    r_foo = g_foo.  ENDMETHOD.
ENDCLASS.
CLASS lcl_main DEFINITION CREATE PRIVATE.  PUBLIC SECTION.    CLASS-METHODS run.
ENDCLASS.
CLASS lcl_main IMPLEMENTATION.  METHOD run.    DATA: lr_stream        TYPE REF TO cl_demo_output_stream,          l_foo_in        TYPE string,          lr_first_thingy  TYPE REF TO lcl_serializable_thingy,          l_xml_data      TYPE string,          lr_second_thingy TYPE REF TO lcl_serializable_thingy,          l_foo_out        TYPE string.    lr_stream = cl_demo_output_stream=>open( ).    SET HANDLER cl_demo_output_html=>handle_output FOR lr_stream.    lr_stream->write_text( iv_text = 'XML Serialization of ABAP Objects Instances'                            iv_format = if_demo_output_formats=>heading                            iv_level  = 1 ).    l_foo_in = |Hello, this is Foo Bar calling from { sy-sysid } client { sy-mandt }.|.    lr_stream->write_data( iv_name  = 'Input Data'                          ia_value  = l_foo_in                          iv_format = if_demo_output_formats=>nonprop ).    CREATE OBJECT lr_first_thingy      EXPORTING        i_foo = l_foo_in.    CALL TRANSFORMATION id      SOURCE instance = lr_first_thingy      RESULT xml      = l_xml_data.    lr_stream->write_data( iv_name  = 'XML Serialization'                          ia_value  = l_xml_data                          iv_format = if_demo_output_formats=>nonprop ).    CALL TRANSFORMATION id      SOURCE xml      = l_xml_data      RESULT instance = lr_second_thingy.    l_foo_out = lr_second_thingy->get_foo( ).    lr_stream->write_data( iv_name  = 'Output Data'                          ia_value  = l_foo_out                          iv_format = if_demo_output_formats=>nonprop ).    lr_stream->close( ).  ENDMETHOD.
ENDCLASS.
START-OF-SELECTION.  lcl_main=>run( ).

Instead of the expected output (some text, an XML representation of the instance and the same text again), I got - a shortdump. The reference lr_second_thingy was not set after the second transformation - so the deserialization must somehow be broken, right? The debugger quickly revealed that the string variable that was supposed to contain the serialized instance was empty - so it's the serialization that must be broken, then, and not the deserialization? Well, they both are, in a way. To cut straight to the point, here is the faulty code:

 

    CALL TRANSFORMATION id      SOURCE instance = lr_first_thingy      RESULT xml      = l_xml_data.    lr_stream->write_data( iv_name  = 'XML Serialization'                          ia_value  = l_xml_data                          iv_format = if_demo_output_formats=>nonprop ).    CALL TRANSFORMATION id      SOURCE xml      = l_xml_data      RESULT instance = lr_second_thingy.

And here is the corrected version:

 

    CALL TRANSFORMATION id      SOURCE instance = lr_first_thingy      RESULT XML        l_xml_data.    lr_stream->write_data( iv_name  = 'XML Serialization'                          ia_value  = l_xml_data                          iv_format = if_demo_output_formats=>nonprop ).    CALL TRANSFORMATION id      SOURCE XML        l_xml_data      RESULT instance = lr_second_thingy.

Yup, the difference is a single character - or two characters in this case. Without the equals sign, XML is treated as a keyword to denote a variable containing the raw XML data. With the equals sign, something else happens that I have yet to find a sensible and practical use for - at least when used with the identity transformation. You can spot this issue if you use the pretty printer to convert the keywords to upper case - and if you notice the tiny difference between xml and XML.

 

Older ABAP Trapdoors articles


Viewing all articles
Browse latest Browse all 948

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>