07-25-2014 1:13 PM
This is really a tricky problem, maybe only old ABAP developers know a solution... for this...
FORM routine STRUKTUR_ANLEGEN that contains a Userexit Call
EXIT_SAPFV45S_001
See note 548205
In this case coding is very old, so we have a function module call that is part of this 'old' construction' with global table VBAP VBAK etc...
and EXIT has not enough parameters to implement program logic because logic of return table XSTB depends on VKORG and VTWEG value of VBAK..
So I can only use two approaches:
1. Use 'dirty' assigns in userexit function
2. Use an implicit enhancement point at beginning of form routine STRUKTUR_ANLEGEN and copy complete code to change program behavior before adding a check 1 = 0.
Both approaches are not 'nice' but the secon approach seems to be the nicer one because I have access to all variables...
But now there's a serious problem because my code starts directly after FORM statement and before variables...
To substitute local variables with other named ones and in coding is no problem..
But there are varables defined with
LOCAL: structure,
*vbap,
tvak.
But an obsolete LOCAL definition can only be made directly after a FORM statement, but as a part of an enhancement point implementation it technically seems to be a part of a mthod... so system throws an error that LOCAL is only allowed directly after FORM ..
Is there a way to implement LOCAL logic using other ABAP expressions ?
BR
Thomas
07-25-2014 1:52 PM
Hi
No I don't think, but you can try this:
A) Create a new include Z.........
B) in this include define your form ZZ_STRUKTUR_ANLEGEN_NEW (you can call how you prefer of course)
B) Create an implicit enhancement point in include FV45SFST (the system allows to insert an enhancement at the end of include definition): here insert your include
INCLUDE Z.............
D) Create an implicit enhancement point in form STRUKTUR_ANLEGEN, here insert the calling for your new routine and skip the standard code:
PERFORM ZZ_STRUKTUR_ANLEGEN_NEW.
CHECK 1 = 2.
Now you should have a new form where you can insert all code you need: LOCAL statament too
Max
07-25-2014 2:29 PM
My 2 cents ...
What i understand from the SAP documentation that the LOCAL keyword creates a buffer for the global variable so that their values are not changed unnecessarily in the procedure.
So i was thinking if we can try to assign these global variable to formal params of a Z-class method via "pass by value". Here is a small code snippet (plagiarised from SAP example )
What are your thoughts about it?
BR,
Suhas
07-25-2014 2:48 PM
Hi
Why to use a global variable defined in a local class?
It would be enough a new local variable defined in the routime, but then it needs to replace "old" variable with a new one in all points where it's used.
If I've understood Thomas want to copy all code of the routine in order to insert his modification, because it can't place an enhancement in the middle of a form.
The LOCAL statament but also all local declarations will be a problem, because it has to define all again (the enhancement is before the declaration), but if you can use a new form (as copy of old one), the development will be easier
Max
07-25-2014 3:11 PM
Why to use a global variable defined in a local class?
I was trying to show that LOCAL statement behaves in the same way as "pass-by-value". That's why i wrote this code to see if the results in the SAP sample coding match that of my code.
If I've understood Thomas want to copy all code of the routine in order to insert his modification, because it can't place an enhancement in the middle of a form.
I think i got the requirement wrong then I thought Thomas wanted to use these LOCAL variables to do some processing.
BR,
Suhas
PS - Did i mention that i hate global variables? I kinda broke-up with them since i started coding in OO.
07-25-2014 3:30 PM
I thought that too
but then I thought if he needs to define some variable by LOCAL statement, he'll have to define all local variables too: it's really dirty job.
Max
07-25-2014 5:49 PM
It could be that easy if SAP would only allow a IF ... ELSE in first enhancement point and an ENDIF at the end...
Then this problem would just mean copying complete code one conditional function call and one IF ELSE END ...statement
Because this is no modification, SAP doesn't seem to have too many trust in 'extern' developers, being able to replace their code too easily
because if something goes wrong they (devs) could post it here an search for a solution provider or even write an OSS message....
Idea with form routine at the end seems possible at first sight ... and needs a lot of form parameters ( all local variables)....
but it is still like the magic bullet of JFK.. or like old times with GOTO statements forward backward and an EXIT at the end....
In german: Spaghetticode
will try it as soon as I will get budget for this
Thanks
07-25-2014 6:02 PM
Hi,
It's never a good idea to copy SAP code, I believe... and, if I understand you correctly, that's an awful lot of copied code, with enhancement points and so on...
I would go for explicit enhancement at the beginning of form, but what i would try to do is pass all the data I need (or references to it) to a singleton class and retrieve it from singleton class inside user exit... A better (in terms of seeing where the values come from) variant of export to memory/import from memory, in other words.
cheers
Jānis
07-25-2014 6:17 PM
Yes
Good idea, I didn't think that, but a problem could be if it needs to have the data (not managed in exit interface) elaborated by part of code before the exit (I mean the part of code betwenn the beginning of the form and the exit)
Max
07-25-2014 6:31 PM
Yes, but getting and passing references by GET REFERENCE OF, and then dereferencing using ASSIGN when you need the data, should allow to solve that - even for stuff defined locally in STRUKTUR_ANLEGEN, I believe? About the stuff localized using LOCAL in STRUKTUR_ANLEGEN - that one I'm not sure about Needs trying out...
Alternatively, if you don't need any local data of STRUKTUR_ANLEGEN, enhance the Module Pool (implicit at the end of some important include) with Get_VBAK_And_Other_Useful_Stuff subroutine and call it from the exit
cheers
Jānis
07-25-2014 8:28 PM
Ok so I have to make clear what functional thing should be implemented:
This FORM routine performs a BOM explosion for a root material using different possible parameters... and creates customer order positions out of these bill of material positions.
But now we have here a very customer specific bill of material (very special and not usable with SAP standard functionality) that contains assembled materials. For these assembled and not produced materials no order position should be created.. so just have to delete some BOM explosion results
Program uses a parameter with value A = simple BOM explosion B = multilevel/multihierarchical BOM explosion and E (use customer exit)
Specification is quite simple: BOM explosion should exactly be executed like using parameter B.. but should then be extended by my logic to reduce table xstb by deleting positions that contain an assembled material.... so that customer order does not create a position for these..
Because there are some additional code lines before BOM explosion module when using B, I can not use Exit directly without copying this code into function module also... here I have to do dirty assignments to get all this working.. so I thought it could be easier to use a full code copy enhancement replace method... and here I meet my LOCAL friends.... that make it impossible to simply copy SAP code and add a function module to reduce xstb...
By the way trying to solve this using suggested FORM method above -> I will run into trouble with all the other enhancement point definitions.... grrrr
I only want to reduce entries of table xstb ..... using B logic and a logic using vbak-vkorg and vbak-vtweg and some other values from bill of material position data....
At the end I may really have to choose dirty assignment solution...with parameter value 'E' for USER_EXIT, but I really don't know how to copy logic lines of B before BOM explosion into EXIT....
Small concept big problem
07-25-2014 11:16 PM
Good good....I've tried it and it works...
but the last little problem: it's it needs to use local data, the enhancement point it's at the beginning of form, so it can't use local variables they aren't defined yet
Max
07-25-2014 11:30 PM
By the way trying to solve this using suggested FORM method above -> I will run into trouble with all the other enhancement point definitions.... grrrr
They are a part of a code, you need to copy in your new form if the enhancement is active in your system
07-26-2014 12:39 AM
Getting a reference via dynamic assign like the red marked stuff in the following example is perhaps stretching it too far already, but will also work, I believe... It needs sy-subrc checks, just in case the SAP enhancements/definitions disappear...
REPORT zjbtst1 .
CLASS lcl_memory DEFINITION CREATE PRIVATE.
PUBLIC SECTION.
CLASS-METHODS get_instance
RETURNING value(ro_instance) TYPE REF TO lcl_memory .
METHODS: set IMPORTING i_ref TYPE REF TO data,
get RETURNING value(r_data) TYPE string .
PRIVATE SECTION.
CLASS-DATA so_instance TYPE REF TO lcl_memory.
DATA: m_ref TYPE REF TO data.
ENDCLASS.
CLASS lcl_memory IMPLEMENTATION.
METHOD get_instance.
IF so_instance IS NOT BOUND.
CREATE OBJECT so_instance.
ENDIF.
ro_instance = so_instance.
ENDMETHOD.
METHOD set .
m_ref = i_ref .
ENDMETHOD .
METHOD get .
FIELD-SYMBOLS <l_data> TYPE any .
ASSIGN m_ref->* TO <l_data> .
r_data = <l_data> .
ENDMETHOD .
ENDCLASS.
START-OF-SELECTION .
PERFORM test1 .
FORM test1 .
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""$"$\SE:(1) Form TEST1, Anfang *$*$-Start: (1)---------------------------------------------------------------------------------$*$*
ENHANCEMENT 1 ZJBTEST_BEGIN. "active version
FIELD-SYMBOLS <fs> type any .
data: l_ref type ref to data .
assign ('L_VAR') to <fs> .
get REFERENCE OF <fs> into l_ref .
lcl_memory=>get_instance( )->set( l_ref ) .
ENDENHANCEMENT.
*$*$-End: (1)---------------------------------------------------------------------------------$*$*
DATA: l_string TYPE string VALUE 'Test Test 1' .
DATA: l_ref_int TYPE REF TO data.
ENHANCEMENT-POINT ZJBTST SPOTS ZJBTST1 .
*$*$-Start: ZJBTST------------------------------------------------------------------------------$*$*
ENHANCEMENT 1 ZJBTST1. "active version
data l_var type string value 'Test test 2' .
l_var = |Changed | && l_var .
ENDENHANCEMENT.
*$*$-End: ZJBTST------------------------------------------------------------------------------$*$*
PERFORM test2 .
GET REFERENCE OF l_string INTO l_ref_int .
lcl_memory=>get_instance( )->set( l_ref_int ) .
PERFORM test2 .
ENDFORM .
FORM test2 .
DATA: l_string TYPE string .
l_string = lcl_memory=>get_instance( )->get( ).
WRITE: / l_string .
ENDFORM .
07-26-2014 8:21 AM
Hi
Yes you're right.....I've never noticed and thought that as It can't use a variable before its definition (we'll have a sintax error), but after starting program all variables are loaded in memory, so they are readily available: it doesn't matter where they are defined.
Good good very good job
Thank you very much
Max
07-26-2014 9:12 AM
You're welcome. Unrelated to this stuff, but right about now I really wish SAP had sneaked in a simple way, via kernel call or something, for a method to get its own parameter bindings (abap_parmbind_tab from type pool ABAP)... I guess I'm getting used that so much is possible in ABAP
cheers
Jānis
07-25-2014 9:04 PM
With all that is going on there, the safest and most practical option is simply to go for a repair. Get the object key and make the changes in as minimal a fashion as you can.
It's still done with the modification assistant, and so is picked up during upgrades and support package implementations.
It's what I would do.
07-25-2014 10:02 PM
Hello, you're perfectly right.. from a developers perspective...
but you will surely also know ,, what the persistent issue is about this..
1. Getting modification acknowledged by customer. SAP support may deny support ... in case of OSS etc etc ...
2. We (as solution provider) will have to take it as a part of our maintenance agreement
In 16 years of development I've seen all kinds of customer attitude toward mods...
From "No way .." to "Is there still some original code ?.. Who cares about!"
I will only ask customer to choose a mod, if I'm convinced I can't deliver it as an enhancement or an exit...
Will have to check back options with customer , so until now I thank you all...
I will surely report complete result ... hopefully already during next week..
BR
Thomas
07-26-2014 7:39 AM
SAP Support may deny support for anything with an implicit enhancement, dynamic assigns up the call stack, or any kind of user exit. The support comes back when you reverse or switch off the exit.
You'll also have to take any enhancement or user exit as a solution provider.
Ultimately, the customer have to decide whether they really want this functionality. I think in all my 17 years I've never seen an implementation that didn't have some kind of direct modification. At least they're better than copies of standard programs!
Another approach that occurs to me, when you need data not available through the interface, is to make an enhancement/use an exit in the place where the data is present, and store it, perhaps as static attributes of a class.
08-04-2014 10:45 AM
Ok, I've made some checks and there are a lot more global variables that are mixed up terribly and are not considered to be a part of the standard user exit in this form routine...
Tried all kind of tricks with enhancements and result is:
Use a simple call function in a 7 line mod and implement a restrictive conditional call and an own active/inactive switch logic....
Use standard result table XSTB of BOM Explosion as IMPORT and EXPORT and implement table content reduction logic.... in function module..
Worst case is somebody will have to do one more SPAU decision ...
Sometimes this old SAP codes are ......really woooahhh...
I hope SAP still has some young employees that know what purpose all this global variable mixups in SD code have..
This is sureley a question of long story telling nights.... during mentoring...
So I've proposed a modification in this case....
let's wait and see...
Now I will have to describe logic and prepare a specification, because this decision is taken during my holiday.....
BR
Thomas