cancel
Showing results for 
Search instead for 
Did you mean: 

OK - I got a really interesting question down in ABAP General and NW AppSer

former_member181923
Active Participant
0 Kudos

This one is so interesting that I thought I'd draw a little extra attention to it here.

See:

or:

Any and all <i><b>informed</b></i> opinion welcome.

Accepted Solutions (0)

Answers (11)

Answers (11)

Former Member
0 Kudos

????

And people complain about FUNCTIONAL Consultants being incomprehensible.

What on earth do you guys talk about in a bar after work (assuming you ever get any time off anyway).

Cricket / Golf / Football or even your next door neigbours dogs. ?.

Maybe because most abappers seem to possess at least one of the following

1) listening to their own music on Ipods etc and totally shutting themselves off from " Normal Office Interaction".

2) Male, over 50 years old and still wearing a "Pony Tail".

There's plenty of life outside programming - even if the daytime challenge is still interesting.

Functional guys can at at least sleep in their own beds at night (at least a few days a week) and usually have the opportunity to mix / interact with all sorts of people outside their immediate area.

One Abapper I know (The "Ipod listening type plus the mandatory over 50's pony tail") hasn't said a social word to ANYBODY outside work for at least 9 months.

This guy might be the greatest gift to SAP ABAP but I'm sure I'd hate to be stuck on a long plane journey - London to Sydney for example sat next to this guy.

Each to their own --but there are plenty of better ways of passing your working days and letting your life slip by.

( Nothing wrong with technical discussions in the technical areas but this IS the COFFEE FORUM).

Cheers

Jimbo

former_member181923
Active Participant
0 Kudos

Hi James -

Pleasure to make your acquaintance.

It's clear you weren't paying close attention to SDN during the two or three months prior to the creation of "The Coffee Corner".

As an SDNer who was at least partially responsible for the creation of the "Coffee Corner" (for all the wrong reasons - heh heh heh), I feel I'm within my rights to say that the Coffee Corner was designed to be a place with many different "corners" of its own.

IOW, if folks want to discuss their extramural interests, there'e a "Coffee Corner corner" for that.

And by the same token, if folks want to discuss SAP-related stuff that really doesn't belong on the blog page or the Forums (because these folks want "point-free" serious discussions of interesting topics), there's a "Coffee Corner corner" for that.

So - how about this?

I won't criticize you or anyone else here for the kind of interest in sports that characterizes prolonged adolescence.

And in return, you might leave off criticizing a very valuable function of the Coffee Corner:

point-free discussion of SAP-related technical topics that are tinged with at least a little controversy and have broader implications for the SAP community over and above the technical.

Best regards

djh

stephenjohannes
Active Contributor
0 Kudos

James,

Part of the appeal of the coffee corner is the fact for us developer types we can ask some very general questions disguised as a rant about technical issues. These issues normally don't fit anywhere else here, because they cross several boundaries and question that the system is designed properly. These conversations are usually the most interesting to pay attention to, vs 1000s of post on how to write a piece of code, which you can usually search for.

As far as ABAP developers not doing anything else or being antisocial, let's face it developers in general are "wired" differently than the general population. I find this also true for basis guys. The social issue may just be a case of your situation. Honestly though headphones are the only way to get the code done at times. You need to drown out the interaction in order to focus on fixing the issue.

I would say beyond the coding aspect, you have the Xbox 360, PS3, and wii for starters for things to do beyond coding :). I personally watch baseball(Go Cards!), and play fantasy baseball as a hobby.

So it's not bad, but I don't think on SDN I am going to start discussing whether the Cards even have a chance at winning the central in the coffee corner. It's way off topic and there are other places where I talk sports. I think you need to keep in mind that most people come ot SDN for their SAP related discussions. However anyone who wants to start a baseball thread, I would join in.

Take care,

Stephen

former_member181923
Active Participant
0 Kudos

hahaha (as Chris Solomon would say) ...

Here's why I'm laughing.

When I first posted this thread to CC, you all thought it was just Crazy Dave making a "mountain out of a molehill" again.

Well I've been at this new shop only two months, and sure enough, it's quite possible (even likely) that they've hit the same limitation on the "SHARED BUFFER" construct in multi-appserver contexts.

And believe me - this is not an inexperienced or unprofessional shop - it's very very ABAP OO, etc.

It's just that for them (just like for me last year), the limitation is never a "gotcha" until you move from single-server DEV and QA instances to multi-server PROD instances.

So maybe the "molehill" wasn't such a small one after all ...

former_member181923
Active Participant
0 Kudos

No - I'm not "back" - but I did want to circle back and close two loops in this thread before leaving.

First -

I wanted to confirm Thomas Jung's expectations that when you have a legitimate reason to use EXPORT DATABASE statements (and also direct statements against INDX-type tables, e.g. "DELETE FROM's"), then the places you need to use them <u><i><b>will</b></i></u> allow them to be committed by SAP's natural end-of-LUW commits, without having to worry about coding your own commits that might interfere with the work that SAP has queued up.

In my case, I needed to use an EXPORT DATABASE to an INDX-type table and a DELETE FROM an INDX-type table in an exit within the XQSM function group. And it was important that these actions were committed before the process progressed to a later BAdI and a later XMBC exit.

They were, in fact committed in exactly the way one would expect.

Second -

I had an interesting off-line exchange with Julius and I wanted to clarify why you have to be careful about context id.

Suppose that inside the XQSM exit called from a MIGO dialog process, you get your user's current context id. Then when a BAdI is involed by an SAP update process that follows this MIGO dialog process, the context id returned in this BAPI is not the same as the context id returned in the dialog process.

And therefore, you cannot use context-id as part of a hash-key for the srtfd column of an INDX-type table, because it will be different in the dialog process nad the BAdI.

What I wound up doing is defining a row with RELID IX and in the srtfd column of this row, using a hash of sy-datum and sy-uname.

But in this row, I also put sy-datum and sy-uname into the AEDAT and USERA fields so that I can do a SELECT SINGLE on this row and get the srtfd to use in storing further rows.

So long as I make sure to do appropriate deletes (so that there is always only one row with relid IX and user name and system date), this will work fine.

And again, the only reason one has to do all this extra work is because clients typically (and correctly) don't "advance number" MSEG mblnrs, inasmuch as advance numbering can lead to gaps in auditability.

So in the absence of a unique MBLNR that one knows "up front", you have to find other ways to make sure that your EXPORT DATABASE keys are properly unique.

OK - enough said.

More than enough, more than likely.

KKilhavn
Active Contributor
0 Kudos

Thanks for returning to give us another update.

I don't mind reading many words as long as they are as interesting as these. Hopefully I will never need to apply this new knowledge But it is interesting nonetheless, much more interesting than the copy&pasted text from online help that is too common. Besides, if I ever have to face such a problem, I may be lucky and recall that this was once discussed on SDN. Perhaps I should put a watch on this thread so I know where to find it?

Until next time (just wait, you will soon be feeling the crave for the daily ABAP fix), be well.

former_member181923
Active Participant
0 Kudos

heh heh heh ...

What is the obvious problem in the above approach for geting an integer value for the srtfd key column in each custom INDX-type table row?

Note: it's a problem that can EASILY be fixed ... it's not a "show-stopper", just a silly oversight.

Boy, do I feel stupid!

Former Member
0 Kudos

Hi David,

I'll take a shot in the dark... does it have something to do with two super users who travel to Las Vegas for the TechEd BOF sessions and return as one?

Cheers,

Julius

former_member181923
Active Participant
0 Kudos

This is really cool: the <b>export to database</b> statement with a given key value for ID <i><b>replaces</b></i> what's already in the table for the same key value.

To see that this is true, copy the system table INDX to a custom table called ZINDX_QM (so you won't have to change the code below.) Activate this custom table.

Then run the following code twice as follows:

1) the first time, leave the value of wa_stuff as it is declared, i.e.:

"This is some stuff"

2) the second time, change the value of wa_stuff to:

"This is some stuff - pass 2."

You'll see that the second value has replaced the first value in the custom table.

So the export to database statement actually does <b>a "replace", not an "append"</b>, if the key value is already in the table.


REPORT  ZFOO.

type-pools: thfb.

TABLES:
  zindx_qm.


DATA:
  context_id             TYPE thfb_context_id,
  cntxt_user_dt(60)      TYPE c,
  cntxtud_s              TYPE string,
  rtrnd_hash             TYPE i,
  rtrnd_hash_n(22)       TYPE n,
  rtrnd_hash_c(22)       TYPE c,
  wa_zindx_qm            TYPE zindx_qm,
  v_chk_cnt              TYPE i,
  wa_stuff(40)           TYPE c VALUE 'This is some stuff - pass 1'.


CALL FUNCTION 'TH_GET_CONTEXT_ID'
  IMPORTING
    CONTEXT_ID       = context_id.

CONCATENATE context_id
            sy-datum
            sy-uname
       INTO cntxt_user_dt.

cntxtud_s = cntxt_user_dt.

CALL FUNCTION 'LCRDB_STRING_HASH'
  EXPORTING
    TEXT =  cntxtud_s
  IMPORTING
    HASH =  rtrnd_hash.

rtrnd_hash_n = rtrnd_hash.
rtrnd_hash_c = rtrnd_hash_n.

wa_zindx_qm-aedat = sy-datum.
wa_zindx_qm-usera = sy-uname.
wa_zindx_qm-pgmid = sy-repid.

EXPORT wa_stuff
  TO DATABASE zindx_qm(mo)
  ID rtrnd_hash_c
  FROM wa_zindx_qm.

CLEAR wa_stuff.
*
IMPORT wa_stuff TO wa_stuff
  FROM DATABASE zindx_qm(mo)
  ID rtrnd_hash_c.

WRITE: / wa_stuff.

Also, the second cool thing is that the "relid" (area) field of the custom table actually makes coding multiple storage statements much easier. To see why this is so, just compare what's been commented out in the following BAdI method with what's replaced it:


method IF_EX_INSPECTIONLOT_UPDATE~CREATE_IN_UPDATE.

* 11/10: new export statements from XSQM exit
*EXPORT gt_outtab        TO DATABASE zindx_qm(tb) ID rtrnd_hash_c.
*EXPORT s7_tab_mseg      TO DATABASE zindx_qm(ms) ID rtrnd_hash_c.
*EXPORT v_cntr_recursion TO DATABASE zindx_qm(rc) ID rtrnd_hash_c.

* 11/10 - original decs/imports before switch to database exports from shared buffer exports
*v_memkey(60)      TYPE c,
*v_memkey2(64)     TYPE c,
*v_memkey3(65)     TYPE c,
*v_memkey4(65)     TYPE c,
*v_memkey5(65)     TYPE c,
*v_memkey6(65)     TYPE c,
*IMPORT gt_outtab        TO gt_outtab        FROM SHARED BUFFER indx(st) ID v_memkey.  now tb
*IMPORT s7_tab_mseg      TO s7_tab_mseg      FROM SHARED BUFFER indx(st) ID v_memkey2. now ms
*IMPORT v_cntr_recursion TO v_cntr_recursion FROM SHARED BUFFER indx(st) ID v_memkey3. now rc
*IMPORT v_do_exit        TO v_do_exit        FROM SHARED BUFFER indx(st) ID v_memkey4. now de
*IMPORT wa_zzqa02        TO wa_zzqa02        FROM SHARED BUFFER indx(st) ID v_memkey5. now wz
*IMPORT i_zzqa02         TO i_zzqa02         FROM SHARED BUFFER indx(st) ID v_memkey6. now iz

* for context id typing
TYPE-POOLS:
  thfb.

DATA:
  context_id             TYPE thfb_context_id,
  cntxt_user_dt(60)      TYPE c,
  cntxtud_s              TYPE string,
  rtrnd_hash             TYPE i,
  rtrnd_hash_n(22)       TYPE n,
  rtrnd_hash_c(22)       TYPE c,
  wa_zindx_qm            TYPE zindx_qm,
  v_chk_cnt              TYPE i.

DATA:
  v_do_exit         TYPE c,
  v_cntr_recursion  TYPE i,
  v_itab_cnt        TYPE i,
  v_index           TYPE i,
  v_mapl_cnt        TYPe i.

DATA:
  s_qals            TYPE qals,
  s7_tab_mseg       TYPE STANDARD TABLE OF mseg,
  wa_mseg           TYPE mseg,
  gt_outtab         TYPE STANDARD TABLE OF zzmseg_qm_2007,
  wa_zzqm           TYPE zzmseg_qm_2007,
  wa_zzqa02         TYPE zzqa02_prueflos,
  i_zzqa02          TYPE STANDARD TABLE of zzqa02_prueflos,

  wa_zqm_lottrck    TYPE zqm_lottrck,

  wa_mapl TYPE mapl,

  v_mtart           TYPE mtart,
  v_qmatv           TYPE qmatv.

DATA:
  v_cnt_wyt3        TYPE i,
  v_debug           TYPE i.

  CALL FUNCTION 'TH_GET_CONTEXT_ID'
    IMPORTING
    CONTEXT_ID       = context_id.

  CONCATENATE context_id
              sy-datum
              sy-uname
         INTO cntxt_user_dt.

  cntxtud_s = cntxt_user_dt.

  CALL FUNCTION 'LCRDB_STRING_HASH'
    EXPORTING
      TEXT =  cntxtud_s
    IMPORTING
      HASH =  rtrnd_hash.

  rtrnd_hash_n = rtrnd_hash.
  rtrnd_hash_c = rtrnd_hash_n.

* ***********************************************************************
*  CONCATENATE 'DEXIT'
*               sy-uname
*               sy-datum
*               context_id
*          INTO v_memkey4.
*  IMPORT v_do_exit TO v_do_exit FROM SHARED BUFFER indx(st) ID v_memkey4.
  IMPORT v_do_exit TO v_do_exit
    FROM DATABASE zindx_qm(de)
    ID rtrnd_hash_c.
* ***********************************************************************


* ***********************************************************************
*  CONCATENATE 'CRCSN'
*              sy-uname
*              sy-datum
*              context_id
*         INTO v_memkey3.
*  IMPORT v_cntr_recursion TO v_cntr_recursion FROM SHARED BUFFER indx(st) ID v_memkey3.
  IMPORT v_cntr_recursion TO v_cntr_recursion
    FROM DATABASE zindx_qm(rc)
    ID rtrnd_hash_c.
* ***********************************************************************

* ***********************************************************************
*  CONCATENATE sy-uname
*              sy-datum
*              context_id
*         INTO v_memkey.
*  IMPORT gt_outtab TO gt_outtab FROM SHARED BUFFER indx(st) ID v_memkey.
  IMPORT gt_outtab TO gt_outtab
    FROM DATABASE zindx_qm(tb)
    ID rtrnd_hash_c.
* ***********************************************************************

  DESCRIBE TABLE gt_outtab LINES v_itab_cnt.

  IF v_do_exit = 'N'.

    v_do_exit = 'Y'.

*   **********************************************************************
*    EXPORT v_do_exit FROM v_do_exit TO SHARED BUFFER indx(st) ID v_memkey4.
    EXPORT v_do_exit FROM v_do_exit TO DATABASE zindx_qm(de) ID rtrnd_hash_c.
*   **********************************************************************

*   **********************************************************************
*    CONCATENATE 'SQALS'
*                sy-uname
*                sy-datum
*                context_id
*           INTO v_memkey5.
*    IMPORT wa_zzqa02 TO wa_zzqa02 FROM SHARED BUFFER indx(st) ID v_memkey5.
    IMPORT wa_zzqa02 TO wa_zzqa02
      FROM DATABASE zindx_qm(wz)
      ID rtrnd_hash_c.
*   **********************************************************************

    IF v_cntr_recursion < v_itab_cnt.
*   **********************************************************************
*    CONCATENATE 'TQALS'
*                sy-uname
*                sy-datum
*                context_id
*           INTO v_memkey6.
*      IMPORT i_zzqa02 TO i_zzqa02 FROM SHARED BUFFER indx(st) ID v_memkey6.
      IMPORT i_zzqa02 TO i_zzqa02
        FROM DATABASE zindx_qm(iz)
        ID rtrnd_hash_c.
*   **********************************************************************
    ENDIF.

    APPEND wa_zzqa02 TO i_zzqa02.

*   **********************************************************************
*    EXPORT i_zzqa02 FROM i_zzqa02 TO SHARED BUFFER indx(st) ID v_memkey6.
    EXPORT i_zzqa02 FROM i_zzqa02 TO DATABASE zindx_qm(iz) ID rtrnd_hash_c.
*   **********************************************************************

    IF v_cntr_recursion = 0.
      CALL FUNCTION 'ZZQA02_ASSIGN_BDC' IN BACKGROUND TASK.
    ENDIF.

    EXIT.

  ENDIF.

*   **********************************************************************
*  CONCATENATE 'MSEG'
*              sy-uname
*              sy-datum
*              context_id
*         INTO v_memkey2.
*  IMPORT s7_tab_mseg TO s7_tab_mseg FROM SHARED BUFFER indx(st) ID v_memkey2.
  IMPORT s7_tab_mseg TO s7_tab_mseg
    FROM DATABASE zindx_qm(ms)
    ID rtrnd_hash_c.
*   **********************************************************************

  v_index = v_itab_cnt - v_cntr_recursion + 1.

  READ TABLE gt_outtab INTO wa_zzqm INDEX v_index.

  READ TABLE s7_tab_mseg INTO wa_mseg INDEX v_index.

  IF    wa_mseg-bwart <> '101'
    AND wa_mseg-bwart <> '103'.
    EXIT.
  ENDIF.

  IF  wa_mseg-werks <> '2000'.
    EXIT.
  ENDIF.

  SELECT
  SINGLE mtart
    FROM mara
    INTO v_mtart
   WHERE matnr = wa_mseg-matnr.

  SELECT
  SINGLE qmatv
   FROM  marc
   INTO  v_qmatv
  WHERE  matnr = wa_mseg-matnr
    AND  werks = wa_mseg-werks.

  IF    v_mtart <> 'ROH'
    AND v_qmatv <> 'X'.
    EXIT.
  ENDIF.

  s_qals = insplot.

*  v_lifnr_save = s_qals-lifnr.

  CALL FUNCTION 'QPBU_LOT_DELETE'
     EXPORTING
     I_QALS        = s_qals.

   s_qals-lifnr   = wa_zzqm-zzlifnr.
   s_qals-pplverw = '5'.
   s_qals-stat19  = 'X'.

  SELECT
  SINGLE plnty
         plnnr
         plnal
         zkriz
         zaehl
    FROM mapl
    INTO (s_qals-plnty,
          s_qals-plnnr,
          s_qals-plnal,
          s_qals-zkriz,
          s_qals-zaehl)
   WHERE matnr = wa_mseg-matnr
     AND werks = wa_mseg-werks
     AND lifnr = wa_zzqm-zzlifnr.

  v_do_exit = 'N'.
*   **********************************************************************
*  EXPORT v_do_exit FROM v_do_exit TO SHARED BUFFER indx(st) ID v_memkey4.
  EXPORT v_do_exit FROM v_do_exit TO DATABASE zindx_qm(de) ID rtrnd_hash_c.
*   **********************************************************************

  v_cntr_recursion = v_cntr_recursion - 1.
*   **********************************************************************
*  EXPORT v_cntr_recursion FROM v_cntr_recursion TO SHARED BUFFER indx(st) ID v_memkey3.
  EXPORT v_cntr_recursion FROM v_cntr_recursion TO DATABASE zindx_qm(rc) ID rtrnd_hash_c.
*   **********************************************************************

  wa_zzqa02-prueflos = s_qals-prueflos.
*   **********************************************************************
*  CONCATENATE 'SQALS'
*              sy-uname
*              sy-datum
*              context_id
*         INTO v_memkey5.
*  EXPORT wa_zzqa02 FROM wa_zzqa02 TO SHARED BUFFER indx(st) ID v_memkey5.
  EXPORT wa_zzqa02 FROM wa_zzqa02 TO DATABASE zindx_qm(wz) ID rtrnd_hash_c.
*   **********************************************************************

  SELECT COUNT( * )
    FROM mapl
    INTO v_mapl_cnt
   WHERE matnr = wa_mseg-matnr
     AND werks = wa_mseg-werks
     AND plnty = 'Q'
     AND plnnr <> '99999999'.

  IF v_mapl_cnt = 1.
    wa_mapl-matnr = wa_mseg-matnr.
    wa_mapl-werks = wa_mseg-werks.
    wa_mapl-plnty = 'Q'.
    wa_mapl-plnnr = '99999999'.
    wa_mapl-plnal = '01'.
    wa_mapl-zkriz = '0000001'.
    wa_mapl-zaehl = '00000001'.
    wa_mapl-lifnr = 'ZZZZZZZZZZ'.
    wa_mapl-datuv = sy-datum.

    INSERT INTO mapl VALUES wa_mapl.

  ENDIF.

  CALL FUNCTION 'QPBU_LOT_INSERT'
     EXPORTING
       QALS_NEW       = s_qals.

  IF wa_zzqm-zzltno IS INITIAL.
    EXIT.
  ENDIF.

  wa_zqm_lottrck-zzltno   = wa_zzqm-zzltno.
  wa_zqm_lottrck-werk     = wa_mseg-werks.
  wa_zqm_lottrck-prueflos = s_qals-prueflos.
  wa_zqm_lottrck-mblnr    = s_qals-mblnr.
  wa_zqm_lottrck-mjahr    = s_qals-mjahr.
  wa_zqm_lottrck-zeile    = s_qals-zeile.

  INSERT
    INTO zqm_lottrck
  VALUES wa_zqm_lottrck.

ENDMETHOD.

former_member181923
Active Participant
0 Kudos

Just a little technical follow-up regarding key structure of custom INDX-type tables when using them to replace shared buffer exports with database exports.

In the custom exit I wrote with shared buffer exports, I used context id as part of the memory ID string (along with username, date, and a field indicating the type of data being stored.) I did this to take into account the fact that a superuser might have two MIGO sessions open at the same time, doing goods receipts in each one (for some crazy reason - who knows why?)

But since context-id is 40 bytes, it's clear that you can't fit it directly into the 22-byte SRTFD key of your custom INDX-type table.

So here's what I did to get around this:

First, I coded the following hash call to give me the context id hashed as a 22-byte character field which can be used for SRTFD in my custom ZINDX_QM table:


type-pools: thfb.

DATA:
  context_id             TYPE thfb_context_id,
  cntxt_id_s             TYPE string,
  rtrnd_hash             TYPE i,
  rtrnd_hash_n(22)       TYPE n,
  rtrnd_hash_c(22)       TYPE c.

CALL FUNCTION 'TH_GET_CONTEXT_ID'
  IMPORTING
    CONTEXT_ID       = context_id.

cntxt_id_s = context_id.

CALL FUNCTION 'LCRDB_STRING_HASH'
  EXPORTING
    TEXT =  cntxt_id_s
  IMPORTING
    HASH =  rtrnd_hash.

rtrnd_hash_n = rtrnd_hash.
rtrnd_hash_c = rtrnd_hash_n.

(You can run this code directly in a zfoo program - add a WRITE to see for yourself that rtrnd_hash_c is a 22-byte zero-filled char field containing the integer returned from the hash.)

Next, I created this custom index on my custom INDX-type table ZINDX_QM:

[code]

AEDAT - date

USERA - username

RELID - "area" of ZINDX_QM - to distinguish between types of data being stored

SRTFD - key (to hold hashed context id)

[code]

This gives me exactly the same capability that I had with the longer concatenated memory id in the shared buffer export statements, and of course, because it's a relatively unique index (up to multiple lines in cluster, i.e. column SRTF2) and a small table, I'm gonna get performance that's probably gonna be about the same as shared buffer on exports, imports, and delete's.

If anyone thinks this is overkill and can think of a better way, please help me out by letting me know.

Regards

djh

former_member181923
Active Participant
0 Kudos

Actually, you can have your cake and eat it to by making the table key field a hash of the concatenation of context id, datum, and uname.

Former Member
0 Kudos

could any one tell me how to post a question?

Former Member
0 Kudos

Congratulations : you just succeeded to post a question !

thomas_jung
Developer Advocate
Developer Advocate
0 Kudos

I got a direct email via this thread from Julius:

<i>My understanding is that SAP strongly recommends not to use destination NONE for RFC calls.

Or where you trying to bait David for a left hook?

I hope that you are not offended by me asking that and questioning your "trick", but I was curious.</i>

I don't know of any way to answer this email except back in the forum thread since there was no contact information.

First I want to say that I hope that no one thinks that David and I are having some knock out, drag down fight here. I am trying to help him with a problem and at the same time we are having a friendly (at least I hope so) intellectual discussion. I find this kind of thing fun and I suspect that David does as well.

I would never, ever knowingly give someone bad information for any reason - and certainly not in some effort to win a discussion.

To that point, where exactly did you hear that using Destination NONE was a strongly recommended against?

Destination NONE isn't an unsupported feature. It is a powerful concept that can be abused if not used properly, but that doesn't mean it should be completely avoided. In fact the documentation for STARTING NEW TASK explicity describes the functionality of Desintation NONE:

If the destination is not specified and also not defined via the addition KEEPING TASK of the statement RECEIVE, then the destination "NONE" is used implicitly. When using destination "NONE", a new main mode is opened for the current user session. In a main mode generated with STARTING NEW TASK, system field sy-modno has the value 0. The asynchronous RFC does not support communication with external systems or programs in other programming languages.

Former Member
0 Kudos

Hello Thomas,

If you click on "reply", then it resolves the email address of the sender.

I was curious to know why you mentioned it as a "trick" => hence "left hook". The jovial "boxing" comments... tempted me to ask whether you were trying to explore further options. And my question was about the option. That you do not aim left hooks at David is nice for David

My understanding is that if a function call leaves it's function group, then new authorization requirements kick in (if active).

To me, it makes sense to activate authority-checks where these would otherwise lead to no checks. But to use programming techniques which then require the respective authority for the end user, might not make sense either.

So I was curious to know why you mentioned it. The "outbound" recommendations I refered to for 2004 and 2004s (destination NONE and SPACE). But I see that it has changed for 7.10 as it is not mentioned (I only checked that now).

It would be great to know if something has changed there? If my understanding is incorrect, then take a swing

Cheers,

Julius

thomas_jung
Developer Advocate
Developer Advocate
0 Kudos

>I was curious to know why you mentioned it as a "trick"

By trick I only meant that it was a programming approach that was a bit unusual, although not inappropriate at all.

Not sure I understand what you are getting at with the discussion of authority-checks and how that is any different when using destination NONE.

What "outbound" recommendations are you refering to? Where are they? The section of the documentation that I copied in about destination NONE is from the inline help of a 7.0 SP13 system. I can't say if something has changed because I'm not familiar with the information you are referencing.

KKilhavn
Active Contributor
0 Kudos

I don't have anything to contribute to the discussion of facts, I have just been enjoying following it and wanted to say thank you to the two of you, Thomas and David. It has been nice to learn something about a completely new topic - it can even be used to partly justify the hours spent here in SDN

However, it's really too bad that this discussion isn't in ABAP General (that would be my guess as to where it belongs) where it started, for the benefit of the audience there. I'm naive enough to believe quite a few people would find it inspiring. Personally I don't follow the discussions in that forum, so for myself it is great to read it here, but still...

Former Member
0 Kudos

Hi Thomas,

It is an optional check when using that programming technique. Also rather unusual, hence my curiosity mail about your statement (and intention not to muddle up the thread with a side track).

The recommendations I referred to are <a href="http://help.sap.com/saphelp_nw70/helpdata/en/b6/3457423e080f53e10000000a155106/frameset.htm">here</a> for example.

Cheers,

Julius

thomas_jung
Developer Advocate
Developer Advocate
0 Kudos

>and intention not to muddle up the thread with a side track

I think muddled threads are the norm in the Coffee Corner. That is part of what I like about the coffee corner, like real world conversations it is OK for things to take off into unexpected directions.

>The recommendations I referred to are here for example

Those recommendations are specific to qRFC. The use case I was describing is quite different from the typical qRFC. We just want an Asynchronous RFC (aRFC). Actually if you don't specify a destination, destination NONE is automatically used when you have the addition STARTING NEW TASK. I still like to explicity state DESTINATION NONE just because I feel that the usage scenario becomes clearer.

former_member181923
Active Participant
0 Kudos

Totally agree with Thomas - this thread is starting to feel exactly like what a coffee-corner thread should feel like. Sometimes, the connections between things are serendipitous in surprising ways.

Anyway, in the spirit of this "multiplex" thread, I just wanted to reply to NXO and say that my objection to the shared buffer export statement is NOT the appearance of the word "SHARED" in it - I agree with Thomas that the buffer is shared in a meaningful sense.

<u><i><b>Rather, my objection is that this statement is one of the "exceptions to the rule" in ABAP.</b></i></u>

In other words, the "general" rule for ABAP is that if a statement works on 1-WAS, it will work on n-WASs. How can anyone argue that this is not the "general" rule? If this weren't the "general" rule, then SAP would be unable to claim (with a straight face) that the ABAP language is scaleable to multi-servers.

So, assuming this viewpoint is correct, the relevant question is what SAP should do about the "exceptions" to this "general" rule - the shared bufffer export statement and others to which Thomas has alluded in this thread.

And my claim is not a big deal - just that SAP should mark these "exceptions" with a selected keyword like "SINGLE-WAS".

In particular, if a statement only works properly on 1-WAS, but doesn't throw a run-time error on an n-WAS client, then it should have the keyword "SINGLE-WAS" in it, like:

EXPORT .... TO <b>SINGLE-WAS</b> SHARED BUFFER ...

That way, the situation is transparently clear, and requires no more than the usual level of infrastructure understanding on the part of the ABAP programmer.

Of course, if an ABAP programmer used a statement like the above and didn't check to see whether a given client was multi or single WAS, then oh well ... I mean agree that SAP can only go so far to keep folks from shooting themselves in the feet.

ChrisSolomon
Active Contributor
0 Kudos

@NXO hahaha

@David

As you wrote...

<i>"In other words, the "general" rule for ABAP is that if a statement works on 1-WAS, it will work on n-WASs. How can anyone argue that this is not the "general" rule? If this weren't the "general" rule, then SAP would be unable to claim (with a straight face) that the ABAP language is scaleable to multi-servers." -from the desk of David Halitsky</i>

I guess this is where I kinda struggle with this whole discussion. What I have always liked most about ABAP is that I consider it abstracted enough that I don't HAVE to worry about those issues (ie. 1-server vs. n-servers). The lower level foundation of the language handles that all rather nicely for me. I can focus more on writing the most fantastical, mind-blowing code possible and leave that "down to the metal" business alone. (KIDDING! haha)

But I do agree with you....the ONLY time this becomes an issue is at times with the "exceptions".....which are perfectly pointed out in both the "SHARED" statement as well at the RFC call additional "DESTINATION" parameter. In those cases, it really is where you are "steering" the processing with either "hey, run/store this EXACTLY on this app server and no where else" (or in the case with the DESTINATION addition....directing it where ever you like....even back onto yourself with the "NONE" value as Thomas explained quite well).

So yeh, David....I see these kinds of things as "exception syntax"....for the rest of it, I just let ABAP do it's thing. haha

Former Member
0 Kudos

Dear Thomas, David, Christopher (and Sree - are you still there?)...

Thank you for your statements that contributors to SDN can, and are welcome to, post "unexpected directions" to main threads in your Coffee Corner threads.

I am okay with "serendipity"; in fact, I love it!

I would also like to welcome 'sree' to SDN!

My contribution is however less of an "unexpected direction", but rather an "aspect" of the solution which I think should be considered.

[...]

<i> "(or in the case with the DESTINATION addition....directing it where ever you like....even back onto yourself with the "NONE" value..."</i>

For the expected result, from the view of the developer, you can send the task + destination where ever you like... in this case saving it into the context of 1-EXIT when triggered by the user on 1-WAS.

=> So, David does not have to stuff his table full of data and the program flow is just fine.

From the view of the end user, they might be able to stuff your MSEG table full of widgets from where ever they like... in this case saving themselves into the context of N-EXITS when triggered on N-WAS from N-...

I understand that it is just one of several aspects to be considered when writing co-ordinated code. So, unusual developers might want to consider it in their choice of programming technique.

I also understand NXOs views on end users...

Kind regards,

Julius

ChrisSolomon
Active Contributor
0 Kudos

David, are you the guy that went behind God and told him that the trees should look more "tree-ish" ? (JOKING!)

(*just trying to lighten the mood as always)

former_member583013
Active Contributor
0 Kudos

David:

Excuse me...But you shouldn't do cross-posting...

Greetings,

Blag.

former_member181923
Active Participant
0 Kudos

Thomas (Jung) was kind enough to answer this down in ABAP General, but the implications of his answer are really really ugly.

I'm gonna have to pretend it's still 1973 and build a custom z-table that I can put stuff into and take stuff out of.

Can't believe SAP has allowed this hole to exist in its thinking and its architecture!!!!

thomas_jung
Developer Advocate
Developer Advocate
0 Kudos

What hole are you extactly refering to?

Do you really want the shared memory buffers to cross over multiple application servers? You should certainly consider the implications before answering yes. Think about the performance hit you would take in trying to synchronize shared buffers on a multitude of application servers (across the network). If you went with asynchronous approach (which is possible by using Shared Memory Objects) this also wouldn't work for your problem because the update process might execute before the data reaches the corresponding application server.

That is partially why update work process data gets qued into the database before the update process begins anyway. The other benefit besides scalability is recoverability. Updates can be recorvered and repeated (even partially completed ones).

I'm not sure what your total process flow is, but normally when you want to get data into the update process you send it there directly by passing it into the interface of an Update function module.

When using update processes, real time performance usually isn't the highest priority. The update is asynchronous anyway - so realibility and scalability is the highest concern.

thomas_jung
Developer Advocate
Developer Advocate
0 Kudos

<i>>I'm gonna have to pretend it's still 1973 and build a custom z-table that I can put stuff into and take stuff out of.</i>

On that subject alone...

Well I wasn't even born yet in 1973, but I still have been know to architect things that use a custom table to "put stuff into and take stuff out of". From an architectural standpoint this still has some very valid usages. There are different types of caching that require different lifetimes and different usage patterns and shared memory is just one of those types.

Take server cookies for example. In stateless applications they are excellent way to persist entire data objects without consuming precious physical memory. Often when creating a stateless application I balance the usage of both shared memory objects (for information that it makes sense to share between different user sessions) and server cookies (for information specific to a particular user session).

former_member181923
Active Participant
0 Kudos

Thomas -

Thanks for taking the time to tease this one out.

Regarding "total process flow", SAP has defined the situation - not me.

If you want to pop anything custom from the MIGO GR screen, you've got to use an exit in XSQM - a dialog-side process.

But if you want to be sure that your update is synchronized with the MSEG update done by MIGO GR, you've got to use an exit in XMBC (or a BAdI, which would still have the same problem.)

So maybe the "hole" is actually in the way SAP has implemented dialog processes and update processes.

I remember in the mature days of CICS, plenty of shops had a whole region devoted to front-end screen handling and another whole region devoted to VSAM/IDMS updating.

There didn't seem to be ANY problem in "synchronizing" data flow between them.

And that's all you really have here.

Anyway, thanks very much again for the authoritative answer - at least I know for sure there's a solution at the end of the tunnel (two or three days of careful recoding.)

Regards

djh

dkh

former_member181923
Active Participant
0 Kudos

Thomas -

Re "precious physical memory" ...

Now that sounds like you were very much around in 1973.

These days, I am hard pressed to see why any amount of memory can possibly be "precious", given how fast swap-pack IO has gotten ...

Regards

djh

thomas_jung
Developer Advocate
Developer Advocate
0 Kudos

Not at all. You really think any amount of memory can be possible? There are still plenty of people that run on 32-bit architecture. That alone is a limiting factor that you aren't taking into consideration. Also how do you economically scale internet facing applications with 10,000+ concurrent users.

I'm not sure what swap-pack IO and neither is Google evidently.

Former Member
0 Kudos

going back 70's, this thread looks like Ali vs Foreman ABAP fight

thomas_jung
Developer Advocate
Developer Advocate
0 Kudos

>So maybe the "hole" is actually in the way SAP has implemented dialog processes and update processes.

I wouldn't go there. For you to say that, you obviously don't understand how important that is to the rock-solid nature of the AS-ABAP architecture. This is the very foundation of why R/3 became successful!

>I remember in the mature days of CICS, plenty of shops had a whole region devoted to front-end screen handling and another whole region devoted to VSAM/IDMS updating.

There didn't seem to be ANY problem in "synchronizing" data flow between them.

You obviously don't understand the differences here either. We are talking about client/server here as well as adaptive computing frames. It isn't as simply as doing a synchronization within a heterogenious environment. I've seen systems with 30+ application servers. It also isn't really a technical problem. You can of course build your own cross application server buffer sync by using CALL FUNCTION ... DESTINATION, but what is that going to do to your performance? Also why consume memory in the buffer of every single application server in your cluster? Memory may be cheap, but I don't by into your supposition that it is an endless resource to be wasted.

>two or three days of careful recoding

Really? Just to switch from a memory buffer to a DB based on. Have you even tried the suggestion of EXPORT TO DATABASE? It seems just as likely to work as your Custom DB approach as they both would require a COMMIT WORK.

Former Member
0 Kudos

Round five, Thomas is winning by points.

former_member181923
Active Participant
0 Kudos

Thomas -

Theoretical argumentation aside for the moment, I see a real potential "showstopper" if I'm reading you correcrly - a showstopper whether I use EXPORT TO DATABASE or my own custom Z-table.

As you point out, to use either approach, I've got to issue that COMMIT from within the dialog-side exit in XQSM.

Now I'm <i>pretty</i> sure that SAP has nothing of its own que'd up for update at the point inside XSQM when the exit fires. Because SAP doesn't begin to update until the user hits the main MIGO save button, and the user can't get there without first "OK'ng" off the subscreen I call in XQSM.

So - it would <i>seem</i> like a COMMIT inside the XQSM exist would be safe enough - but what do you think? Would I risk a commit where SAP doesn't want one?

Thanks for any advice you can offer on this point.

Regards

djh

thomas_jung
Developer Advocate
Developer Advocate
0 Kudos

Commits inside an exit always make me nervous. I would first try it without and see if the built in commit comes soon enough that it would work.

The more I think about it the built in commit work should do the trick. The Update Function Modules will not execute until after the commit work is issued:

From the online help:

<i>The actual execution is triggered by the statement COMMIT WORK. The formal parameters of the function module receive the values of the actual parameters from table VBLOG. A function module that is registered several times will also be excuted several times with the respective parameter values.

If a COMMIT WORK statement is not executed after registration of a function module during execution of the current program, the function module is not executed and is deleted from table VBLOG at the end of the program.</i>

If that doesn't work then you might try this trick. Put the logic you want to write into the DATABASE Buffer in a function module. Call the function module with STARTING NEW TASK ... DESTINATION NONE and do the commit work within the function module. This should keep the commit from disrupting the running process of the SAP Program you are within.

former_member181923
Active Participant
0 Kudos

Thomas -

Thank you very much for your last post - it makes sense to me and gives me confidence that the DATABASE export has a reasonable chance of working.

Also, thank your for the time you have taken helping on this issue. True generosity of spirit cannot be disguised even by the most acerbic of posting styles - and you certainly have both.

Regarding the "theoretical issue", I think there may be one point on which we might agree.

You yourself brought up scaleability in one of your responses, and in doing so I think you may have missed one forest for some very valid trees.

To me, true scaleability implies that if a programming language statement works on a 1-WAS system, it should work on an n-WAS system.

So I would be totally happy if SAP would add the key-word SINGLE-WAS to the shared buffer export statement:

EXPORT gt_outtab TO SINGLE-WAS SHARED BUFFER indx(st) ID v_memkey.

much as SAP added the IN LEGACY TEXT MODE to OPENs of app server files.

If SAP were to do this, they would be in an intellectually coherent and defensible position.

But in the absence of this key-word addition, I still (respectfully) think that SAP is in a less-than-defensible position regarding the export shared buffer programming construct.

And please believe me, I do mean "respectfully" with no sarcasm.

Any day I get a chance to learn something from you is a red-letter day on my calendar.

Best regards

djh

Former Member
0 Kudos

Excellent understanding gentlemen ! You two win a free entrance to Community Day in Buenos Aires

Former Member
0 Kudos

I've seen people stuff so much in memory using EXPORT that it's caused dumps.

I believe there's a limit to how much you can allocate to it, irrespective of the physical memopry on the machine.

former_member181923
Active Participant
0 Kudos

Well presumably this wouldn't be a problem with the EXPORT DATABASE that Thomas has suggested.

One thing that puzzles me though - when you export to SHARED BUFFER

you use "INDX(st)".

Does this mean that "SHARED BUFFER" is really just an area in the system INDX table?

If so, then the SINGLE-WAS restriction on SHARED BUFFER amounts to saying that there is only one INDX table per WAS and that only this WAS can update it.

Is this correct?

Or is the similarity of the INDX(st) key-word to the EXPORT DATABASE key-word just a coincidence?

suresh_datti
Active Contributor
0 Kudos

INDX is a database cluster & it shouldn't matter which WAS is being used to update.

~Suresh

thomas_jung
Developer Advocate
Developer Advocate
0 Kudos

>Does this mean that "SHARED BUFFER" is really just an area in the system INDX table?

Nope the Shared Buffer is a memory area on the application server. The INDX specification simply describes which data dictionary object should be use to create the line structure of the object in memory. Here are more details from the online help:

When storing the data, the system creates a memory table in the application buffer, whose line structure is defined with dbtab. For dbtab, you have to specify a data base table from the ABAP dictionary that has the same structure as structure if stored in the data base table. The line area ar, the work area wa, the optional client cl and the identification wa have the same significance for the memory table, as if stored in a data base table with the exception that the length of the identification is limited to id 59 resp. 62 characters depending on whether the addition CLIENT is specified or not.

thomas_jung
Developer Advocate
Developer Advocate
0 Kudos

>true scaleability implies that if a programming language statement works on a 1-WAS system, it should work on an n-WAS system.

I'm sorry but I just don't see it that way. It isn't like the command doesn't work at all when you have a multiple AS system. It works just fine when used as intended - a caching mechanism or communication within the same process stack. Just because it doesn't work the way you think it should, doesn't mean it isn't scalable.

There are plenty of constructs that don't work in a stateless BSP application (persistent objects, transational services, EXPORT to Shared Memory/Buffer). Do this mean the language isn't scaleable? Not at all.

former_member181923
Active Participant
0 Kudos

Hi Suresh -

Good to see your "by-line" here.

I interpret your answer as follows.

If someone chooses to export to database INDX (rather than a custom cluster, which is what SAP advises), then the actual system table INDX is used and is therefore accessible to all WAS's.

But if someone chooses to export to shared buffer INDEX(st), then the system creates a true buffer in memory, as per Thomas' last explanation. And this is the case in which the single-WAS limitation applies.

Best regards

djh

former_member181923
Active Participant
0 Kudos

Thomas -

Thanks for clarifying the purpose of the INDX(st) keyword on the shared buffer export statement. Very much appreciated.

djh

former_member181923
Active Participant
0 Kudos

Thomas -

Re scaleability of programming language constructs.

I think this is an area where there can be legitimate disagreement.

But I want to be sure we identify the exact point on which we may disagree.

What I was trying to say is that:

if:

a language is, IN GENERAL, scaleable to multi-processor systems,

then:

the grammarians of the language have an obligation to somehow identify (with appropriate keywords, for example)

So I'm not saying that SAP should eliminate the shared buffer statement because it doesn't scale.

And I'm not saying that SAP should necessarily scale this statement.

All I'm saying is that any non-scaleable statement should be identified as such - not in the documentation, but in the syntax of the statement itself.

I know you've already spent a lot of your valuable time in this this thread, but if you a moment more, I'm really curious what your arguments are against this last proposition.

Regards

djh

former_member181923
Active Participant
0 Kudos

Sorry! That if/then got really kluged-up. It should have been:

if:

a language is, IN GENERAL, scaleable to multi-processor systems,

then:

the grammarians of the language have an obligation to somehow identify (with appropriate keywords, for example) any statement of the languahe that is not so scaleable.

thomas_jung
Developer Advocate
Developer Advocate
0 Kudos

Careful that you draw a distinction between multi-processor/multi-core and multiple server clusters; these are two very different things architecturally speaking. ABAP is very much muti-processor/multi-core capable and the these commands work just fine in single/multi processor and core environments.

What we are talking about is vastly different. We are talking about clusters of servers communicating across the network. Separate (often physical) servers with their own memory space. I'm trying to think of any programming language that has special syntax when working in a multi-server cluster, but I haven't been able to think of any.

Of course even if we did implement such syntax, how would you want it to function - synchronous or asynchronous? I think in either scenario it would still not be appropriate for your problem and I struggle to find a good use case outside of the one you have experienced.

former_member181923
Active Participant
0 Kudos

Hi Thomas -

You wrote:

<i>First I want to say that I hope that no one thinks that David and I are having

some knock out, drag down fight here. I am trying to help him with a problem

and at the same time we are having a friendly (at least I hope so) intellectual

discussion. I find this kind of thing fun and I suspect that David does as well.</i>

Couldn't agree more. You <i>are</i> helping me with the immediate problem at hand, and I <i>do</i> find the more abstract discussion very interesting. Not sure why Chris thinks the mood needs lightening - maybe it's just that he's seen me get into it with folks here on matters having to do with SDN sociology. But this discussion, of course, has nothing to do with SDN sociology and I certainly don't feel like either of us are in anything but an equanimitable mood.

That being said, I think that I didn't make my point about syntax clear - maybe because the post got garbled. You just wrote:

<i>I'm trying to think of any programming language that has special syntax when working in a multi-server cluster, but I haven't been able to think of any.</i>

But actually - what I wanted/suggested was just the opposite:

1) The initial assumption should be that ABAP <i><b>is</b></i> for the most part a "multi-server cluster" language.

2) So the only statements that need special key-words are the ones that are single-server-only, e.g. the shared buffer export statement.

This may not change your opinion of the proposition, but I just wanted to clarify, because it looks like you were giving your opinion on a position I actually hadn't taken.

Thanks again for taking the time, Thomas

djh

Former Member
0 Kudos

Is what you're saying, in a nutshell, that SHARED is a bit misleading in this case? If so, I concur.

thomas_jung
Developer Advocate
Developer Advocate
0 Kudos

>that SHARED is a bit misleading in this case

No SHARED is still a fine description because the data in that buffer is shared by all work processes on that application server or all internal modes of the same user session. The primary function for these buffers remains for caching.

Former Member
0 Kudos

But it's not shared across all servers. At least one person seems to have interpreted it to mean that, or the question wouldn't have been asked.

Perhaps

SLIGHTLY SHARED SORT OF

might have been more appropriate?