Quantcast
Channel: SCN : Blog List - ABAP Development
Viewing all articles
Browse latest Browse all 943

Persistent classes: single get( ) method instead of multiple get_xxx() methods calls

$
0
0

Dear mates,

 

Here is the next part of my blog related to OS functionality. You can find the beginning here:

 

Persistent classes: revival of a spirit. Query by range.

 

I presented the way how we can use local variables as more transparent way to create a query request.

 

As a result of IF_OS_CA_PERSISTENCY~GET_PERSISTENT_BY_QUERY method we have a table of OSREFTAB type.

 

So let's first consider how SAP proposes to process such references in DEMO_QUERY_SERVICE example:

 

LOOP AT connections ASSIGNING FIELD-SYMBOL(<connection>).          connection = CAST #( <connection> ).          result-carrid = connection->get_carrid( ).          result-connid = connection->get_connid( ).          APPEND result TO results.        ENDLOOP.

That's probably OK - but let's assume we have really pretty big number of attributes. The idea of numerous get_() method calls each time i want to read the full object structure didn't make me happy. I'm too lazy for it.

 

In my background there were several tasks when I used asXML serialization-deserialization and i decided to try it here:

 

The logic should be very simple:

 

  1. we serialize our object to asXML for object instance

 

When I tried to serialize CL_SPFLI_PERSISTENT instance i got nothing interesting:

<asx:abap version="1.0" xmlns:asx="http://www.sap.com/abapxml"><asx:values>  <STRUC href="#o52"/></asx:values><asx:heap xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:abap="http://www.sap.com/abapxml/types/built-in" xmlns:cls="http://www.sap.com/abapxml/classe//www.sap.com/abapxml/types/dictionary">  <cls:CL_SPFLI_PERSISTENT id="o52"/></asx:heap></asx:abap>

The reason of such a short file is that object must have IF_SERIALIZABLE_OBJECT interface to be serialized.

 

As I was going to use it for my own object I just created new Z class for SPFLI table but with this interface defined.

 

This time the result looked rather better:

<asx:abap version="1.0" xmlns:asx="http://www.sap.com/abapxml"><asx:values>  <STRUC href="#o52"/></asx:values><asx:heap xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:abap="http://www.sap.com/abapxml/types/built-in" xmlns:cls="http://www.sap.com/abapxml/classes/global" xmlns:dic="http://www.sap.com/abapxml/types/dictionary">  <cls:ZCL_SPFLI_PERSISTENT id="o52">   <ZCL_SPFLI_PERSISTENT>    <CARRID>UA</CARRID>    <CONNID>3517</CONNID>    <COUNTRYFR>DE</COUNTRYFR>    <CITYFROM>FRANKFURT</CITYFROM>    <AIRPFROM>FRA</AIRPFROM>    <COUNTRYTO>US</COUNTRYTO>    <CITYTO>NEW YORK</CITYTO>    <AIRPTO>JFK</AIRPTO>    <FLTIME>495</FLTIME>    <DEPTIME>10:40:00</DEPTIME>    <ARRTIME>12:55:00</ARRTIME>    <DISTANCE>6162.0</DISTANCE>    <DISTID>KM</DISTID>    <FLTYPE/>    <PERIOD>0</PERIOD>   </ZCL_SPFLI_PERSISTENT>  </cls:ZCL_SPFLI_PERSISTENT></asx:heap></asx:abap>

2. Well, now we need to think how we can fill SPFLI structure from XML. To see which file should I have I serialized SPFLI structure first:

<asx:abap version="1.0" xmlns:asx="http://www.sap.com/abapxml"><asx:values>  <STRUC>   <MANDT/>   <CARRID>UA</CARRID>   <CONNID>3517</CONNID>   <COUNTRYFR>DE</COUNTRYFR>   <CITYFROM>FRANKFURT</CITYFROM>   <AIRPFROM>FRA</AIRPFROM>   <COUNTRYTO>US</COUNTRYTO>   <CITYTO>NEW YORK</CITYTO>   <AIRPTO>JFK</AIRPTO>   <FLTIME>495</FLTIME>   <DEPTIME>10:40:00</DEPTIME>   <ARRTIME>12:55:00</ARRTIME>   <DISTANCE>6162.0</DISTANCE>   <DISTID>KM</DISTID>   <FLTYPE/>   <PERIOD>0</PERIOD>  </STRUC></asx:values></asx:abap>

lns:dic

3. Now we have asXML with object instance from one side, and we have asXML that we need to create .

There are several ways how to create it:

  • Parsing first one and renderring new one manually
  • Do the same over XSLT transormation

 

As I'm lazy i chose the last one. I'm not a big expert in XSLT so this is what actually I managed to create:

<xsl:transform version="1.0"  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"  xmlns:sap="http://www.sap.com/sapxsl"><xsl:strip-space elements="*"/><xsl:template match="/"><asx:abap  version="1.0"  xmlns:asx="http://www.sap.com/abapxml">  <asx:values>    <STRUCT>       <xsl:copy-of select="./*/*/*/*/*"/>    </STRUCT>  </asx:values>  </asx:abap></xsl:template></xsl:transform>

To my big surprise it worked:

So what I did I provided a new method for this operation:

 

class-methods TO_DATA    importing      !IO_OBJECT type ref to IF_SERIALIZABLE_OBJECT    changing      !CS_DATA type ANY .  method TO_DATA.     try.        " Object to asXml:serializable object        call transformation id          source struc = io_object          result xml data(lv_xml).        " asXml:serializable object to asXml:data        call transformation zcw_obj2struc          source xml lv_xml          result xml data(lv_xml_struc).        " asXml:data to data        call transformation id          source xml lv_xml_struc          result struct = cs_data.      catch cx_transformation_error into data(lo_cx).        if 1 eq 2.          " here you can go from the debugger          data(lo_output) = cl_demo_output=>new( ). " <-place the cursor here and press Shift+F12          lo_output->begin_section( 'Object to asXml:serializable object' ).          lo_output->write_xml( xml = lv_xml  ).          lo_output->begin_section( 'asXml:serializable object to asXml:data' ).          lo_output->write_xml( xml = lv_xml_struc  ).          lo_output->write_text( lo_cx->get_text( ) ).          lo_output->display( ).        endif.    endtry.  endmethod.

and finally this SAP code:

agent = ca_spfli_persistent=>agent.    TRY.        query_manager = cl_os_system=>get_query_manager( ).        query = query_manager->create_query(                  i_filter  = `AIRPFROM = PAR1 AND AIRPTO = PAR2` ).        connections =          agent->if_os_ca_persistency~get_persistent_by_query(                   i_query   = query                   i_par1    = airpfrom                   i_par2    = airpto ).        LOOP AT connections ASSIGNING FIELD-SYMBOL(<connection>).          connection = CAST #( <connection> ).          result-carrid = connection->get_carrid( ).          result-connid = connection->get_connid( ).          APPEND result TO results.        ENDLOOP.        cl_demo_output=>display( results ).      CATCH cx_root INTO exc.        cl_demo_output=>display( exc->get_text( ) ).    ENDTRY.

became more elegant to me:

 

types: begin of query_ts,    airpfrom type spfli-airpfrom,    airpto type spfli-airpto,  end of query_ts.  data: lt_results type table of spfli.  zcl_os_api=>select_by_query(      exporting        io_agent     =  zca_spfli_persistent=>agent   " Class-Specific Persistence Interface        is_selection = value query_ts(          airpfrom = p_from          airpto = p_to        )      importing        et_data = lt_results      ).

You probably think that such a technique will decrease overall performance sufficiently but that was a big surpsrise to me that trasnformation works really fast.

Also I think that XSLT transformation can be optimized somehow but here we need experts in this area to recieve an advise.

 

Will be glad to see your comments here. Critics is appreciated.

 

Petr.


Viewing all articles
Browse latest Browse all 943

Trending Articles



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