Custom generation strategy – how to enhance the generated data provider base classes
This article explains how I became interested in the service generation code and the means to alter it, to suit my own requirements.
A bit of history…
I have identified certain generic ABAP-level operations that I wish to be able to re-use for any resource in services that I implement.
The originals were implemented as code-per-service, which led to a lot of cutting & pasting and duplication.
To reduce these overheads and enforce a design pattern, I introduced a custom super class for my DPC base class, i.e. subclassed /IWBEP/CL_MGW_PUSH_ABS_DATA to ZCL_MGW_PUSH_ABS_DATA.
By changing the inheritance of my DPC base, injecting the new intermediate class into the family, I could inherit any new attributes, types or methods I implemented in ZCL_MGW_PUSH_ABS_DATA.
This was a good solution with one drawback – if the model was regenerated in SEGW, the DPC class is also regenerated. That regeneration would remove my inheritance so I would have to reapply it manually. Not too bad, as I know about this step – but what about in future when this went into another developer’s hands? I wanted a robust solution so I asked the Gateway product team if they could add this feature to Service Builder generation – otherwise I would need to implement a planned enhancement in the Service Builder code. They suggested I look at the Generation Strategy option and defined my own as a way of providing a solution.
“Great”, I replied, “where are the documentation and tools for this?”.
Well, the documentation was a no show (perhaps it exists somewhere, in German?) but Martin Bachmann did point me to the configuration area. From there I was able to figure out how to resolve my planned enhancement into a configuration option instead (with some code still needed).
Since there is nothing out there about this at the time of writing I thought it would be a good experience to share.
Service Builder…is configurable!
Yes, that’s right! It’s actually possible to change some of the Service Builder functionality by altering the plug-in elements.
Word of warning: this is not an activity that should be undertaken by someone without advanced developer skills. What I am doing here is a fairly lightweight change, but it would be possible to radically alter (and damage) your service builder installation and the service generation without due care and attention.
A bit of experimentation…
If you are still reading, you obviously like to live dangerously. 😎
To access the SEGW configuration, use transaction /IWBEP/SBS .
This is a cross client configuration area, so you have no fail-safe in a backup client.
- Make notes of all and any changes you make.
- Log changes in a transport (which may or may not need to go to your PRD environment).
- Revert any changes that you make on a trial and error basis and do not have a need for – you may be messing up something that you aren’t using but some else is.
There are various nodes that can be changed but the one that jumps out at me is the ‘Generation Strategies’ node – nice and obvious.
However, it belongs in the ‘DM plugins’ node set – what is the parent I am needing to work with? I’m pretty sure it’s /IWBEP/GEN based on it’s description but I also check the content of the ‘Generation Strategies’ node.
I’ve noticed the generation strategy as an option when creating a service but it’s always one choice – ‘0001’, so I’ve never really worried about it. Now, that single option helps me to confirm that I have the right node, because it only contains ‘0001’. I could be wrong but decide to carry on and revert my work if I’m wrong.
First step is to add a new strategy. I don’t pick ‘0002’ as that might conflict with a new SAP strategy. So I opt for ‘9000’, in the way I might for a custom dynpro (ah good times).
Note: this only makes a choice of ‘9000’ possible, it doesn’t actually have any further settings in this view.
Only one small change, but I can now check that I am on the right track. I chose ‘Create project’ in SEGW and find I now have two options for generation strategy.
I can choose my strategy, now how can I apply it?
Looking back at the DM plug-in setup for /IWBEP/GEN, it nominates class /IWBEP/CL_SBGN_PLUGIN as a delegate, so I’ll look at that.
I find the class has only two locally implemented methods, it’s constructor and CREATE_GENERATION_STRATEGY. The latter sounds promising
Strategy ‘0001’ creates an object to manage the generation and returns it. It seems logical that I can do the same with ‘9000’ and a different object in the return.
So, what will my replacement plug-in need to do when ‘9000’ is chosen?
Looking at ‘0001’ logic, the object type returned is an instance of /IWBEP/CL_SB_GEN_GENERATOR. I note that as another object that needs
Looking at /IWBEP/CL_SB_GEN_GENERATOR, I find method GENERATE_DPC. So far, all the method names have been very helpful! However, that is now invoking a further class.
DATA lo_dpc_generator TYPE REF TO /iwbep/cl_sb_gen_dpc_generator.
CREATE OBJECT lo_dpc_generator.
Within this second “DPC generator” class I find what I am looking for in method GENERATE_DPC_BASE_ABST_CLASS. Here is a hard-coded reference to the superclass name /IWBEP/CL_MGW_PUSH_ABS_DATA. That’s all I want to change.
I now know that I have to alter three levels of the default generation strategy to make mine work.
Back to the config of DM plugins: I opt to copy /IWBEP/CL_SBGN_PLUGIN and place the copy in the configuration (/IWBEP/CL_SBGN_PLUGIN is ‘final’ so it can only be copied – I would rather subclass it).
Update Sep 2014 – this is indeed a potential problem; I’ve used my custom strategy since an upgrade of IWBEP and I needed to redo the copy & mod of this class to accommodate some new parameters added to some framework methods. My logic was still OK but the other ‘decoupled’ methods of the class were out of date 🙁
I also make a copy of the original /IWBEP/GEN, comment it as such and deactivate it.
ZCL_SBGN_PLUGIN needs to return a custom generator object based on /IWBEP/CL_SB_GEN _GENERATOR when the strategy ‘9000’ is chosen.
Now I have a problem; I need to use the same class basis as /IWBEP/CL_SB_GEN_GENERATOR for the return parameter to work as the correct reference type, but inheritance doesn’t work as too many private methods are present, even though the class is not final.
My only option is to copy /IWBEP/CL_SB_GEN_GENERATOR into ZCL_SB_GEN_GENERATOR; I’ll change the GENERATE_DPC method later.
I add a new WHEN case for 9000 – ZCL_SBGN_PLUGIN now processes strategies 0001 and 9000.
if iv_gen_strat_version is supplied.
lv_gen_strat_version = iv_gen_strat_version.
lv_gen_strat_version = lc_gen_strat_version.
create object ro_gen_strategy
zcl_sb_gen_generator <=== custom type returned
is_gen_strategy = is_gen_strategy
iv_gen_strat_version = lv_gen_strat_version.
Next, I look at what is needed for /IWBEP/CL_SB_GEN_DPC_GENERATOR and how I can alter method GENERATE_DPC_BASE_ABST_CLASS.
This class isn’t final but it is heavily privatised. I subclass it to ZCL_SB_GEN_DPC_GENERATOR but that gives me very little benefit and not a lot of security against version changes in the IWBEP component. All of the private methods are redefined and replaced with copies of the originals.
Since almost everything in this inherited class is a copy, I can change GENERATE_DPC_BASE_ABST_CLASS without too much concern.
Addendum: I’ve since found that the regeneration of a “9000 service” dumps. The cause was hard to find but the fix was simple. The inheritance change is also referenced in the redefinitions preparation.
So this also needs changing to avoid such a dump (another ZCL_SB_GEN_DPC_GENERATOR method).
Now that I have the final Z class built, I can return to ZCL_SB_GEN_GENERATOR and change its GENERATE_DPC method.
That is all of the class building and config done, so I just need to verify that it all works.
Class injection has worked.
And my custom methods have all been inherited.
A few notes
- This could also be used for changes to model provider generation – currently I don’t have pressing need to change the MPC.
- Once a generation strategy is set, you cannot change it unless you delete and rebuild. I think this limitation might need to be changed by SAP if we are to use this feature.
- I could modify the generation code so that it composed the addtional methods in my base class or something similar, but I chose not to; this makes the maintenance simpler because it links to a non-composed class which can be tested and extended without touching the generation strategy code.
- The other generation plugins can be adapted to suit.
I hope this gives the reader some ideas about unlocking some of the power of a configurable builder tool.