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