The Curse of Frankenstein
Writing another book for SAP Press – Part 2 of 3
Winter of Dis-Contents
CDS View Annotations
When it comes to SAP Press books the rule is to focus on “how” to do whatever subject is being discussed, and the philosophical side of “why” you are doing it in the first place is discouraged. I found this out the hard way as in my original draft some years ago I gave each side equal weighting, and as a result had to ditch large chunks.
I was unreasonably upset at the time; to me “how” and “why” go hand in hand; however, in retrospect this is not such a harsh imposition. The obvious solution to the problem occurred to me straight away – publish all the text I had to delete from the book in blogs on SCN. This I did, and all was well with the world.
So, when drafting a second edition naturally there were loads of philosophical thoughts that sprang to mind whilst writing about the huge jumps in technology that have occurred in SAP world over the last two years.
This time I did not do a “nice try, goodbye, don’t waste my time” attempt to put such things inside the book, I kept them to one side, and thought that when the book comes out that would be a good time to put them in one or two blogs. That time is now, as John Parr would say. Whilst I am at it, I will also add anything in general I had to delete from the book.
I cannot speak for the rest of the world, but here in Australia clearly UI5/Gateway is being adopted by a multitude of organisations both government and commercial. In a world where every single person seems to be glued to their mobile device that does make me so surprised I drop dead on the spot.
In real life (i.e. at work) I am supposed to be working on this pretty much full time now (as well as the other two things I am supposed to be working full time on) and I would like to quote Graham Robinson from his speech at the Australian SAP User group conference the other day:-
“I don’t know everything about Gateway. I do know more than I knew last week, and this time next week I will know still more”.
Naturally I am in the exact same boat – I may well be further along the journey than some, enough so that I can write a chapter on the subject in my book, but I am nowhere near as advanced as Graham, and I am still learning all the time. Hopefully we all are, every day, and not just about programming, if I wanted to get all deep and meaningful.
In the book I used – because it was easy – the example of an embedded Gateway system i.e. one were everything was in the ERP system. That is not actually very realistic as I would hazard a guess that very few companies use the ERP system for every single thing in their business. As just one example the market for CRM systems seems to have exploded recently (at least in Australia) and that would be outside of the ERP system.
So generally you would have a “Henry Hub” system outside of your SAP ERP system which is the Gateway server. You might say “obviously yes, you foolish fool, oh you most foolish of fools, you Clown Prince of Foolish Fools, why even mention it?” It is to bring up the most common argument against Gateway, one that can stop your project dead before it even begins.
The argument may not make sense once you look into it, but like many arguments that does not stop it being devastatingly effective. It goes like this:-
“Gateway works by exposing a service as a URL. Anyone can type in a URL anywhere in the world, so therefore anyone can view/modify your data”.
If you think about it that cannot be right – nobody in their right minds would deploy UI5 applications if that were true, and it is possible that some organisations are not run by obvious madmen.
My initial experience whilst testing UI5 applications is that whilst there is a security problem it is the opposite one to that mentioned. That is, if I type in the URL in a browser, or call it up from Eclipse or whatever, contact is not made with the ERP system. This is due to something called CORS. It leaves me breathless.
So actually you have to fight, for your right, to access data using a “third party”. This is not the place to go into the details, if the internet cannot help you, and there is a fair bit that has been written on this subject (e.g. one billion different people all posting questions on the forums about CORS and they cannot access any data) then you could do worse than looking at the SAP Press book on Gateway. I am reading it at the moment.
The chapter on shared memory had to go out the window as it was no longer “new” enough, and the pace of HANA adoption has been so fast, much to SAP’s delight, that the whole concept is irrelevant to an ever increasing number of SAP customers.
However just in case you are not moving to HANA in the near future, and shared memory is still a useful (or potentially useful) solution to some performance problems you are having, I have a “gotcha” warning.
This is good in two ways; firstly because it solves an actual problem I encountered in an actual productive environment and secondly because it allows me to talk about evil robots being sent back through time to kill the mother of the saviour of all humanity.
In this case the evil being faced by the human race takes the form of short dumps in production when shared memory is in use. This is an actual problem I had, I will tell you what causes it and how to solve it, and as an added bonus you get to thwart SkyNet at the same time.
I loved the idea of shared memory, which is sort of like a buffer on steroids, buffering the sort of data you cannot normally buffer, and thus dramatically reducing database access and improving system performance.
One problem I came across was, when the system wide shared memory area was full, fatal exceptions start getting raised. I could catch these in my custom programs but for whatever reason a lot of standard SAP programs that make use of shared memory have no error handling at all. So when the memory is full the dumps were not coming from my Z programs, but rather from assorted standard SAP programs. There is nothing you can do in such case except for getting BASIS to increase the size of the shared memory area, or stop using shared memory yourself.
If that problem gets solved, next up is that what happens is that the shared memory is stored separately on each application server. So if a user changes the data – the material master in this example – then you need to invalidate the shared memory on every application server, so the next read on any given is forced to got to the database to get the updated data prior to storing this in shared memory once again.
For each shared memory class (ends with SHMO) there is a standard method called INVALIDATE_AREA which does precisely this for a given application server. So in the business transaction event after the material master is saved, I loop through all the application servers, calling an RFC function module on that server to delete that specific material (the one being changed) from shared memory.
If that fails then it is time for the sledgehammer approach, and invalidate the entire shared memory area for that object on that server. That is done via the INVALIDATE_AREA method, but I was getting short dumps saying “SYSTEM_SHM_AREA_OBSOLETE”.
It transpires that I needed to set one parameter when calling that method, invoking the terminator in order to stop my short dumps.
Here is an extract from the code at the end of my RFC function to remove one (or all) records from shared memory for the material object.
* If we get here we could not delete the single record that has been
* updated, so we have to use the sledgehammer approach and
* delete everything. That’s better than the slightest risk of
* having wrong data in shared memory
zcl_material_master_shmo=>invalidate_area( terminate_changer = abap_false ).”See Below
* TERMINATE_CHANGER – the default value of this is ABAP_TRUE. The SAP documentation says this:-
* Once this method is executed and ABAP_TRUE is passed to TERMINATE_CHANGER, all programs
* where there are still exclusive locks for the invalidated area instance versions are
* terminated with the runtime error SYSTEM_SHM_AREA_OBSOLETE.
* So a program has gotten a hold of the shared memory object 0.1 seconds before the material
* master record was changed, and still has a lock on it. I think causing the program to short
* dump is a bit extreme, if we pass in ABAP_FALSE then whatever program it is will finish
* dealing with the “old” data, release the lock, and next time it wants to access shared memory
* again (two seconds time maybe) the current version of the shared object will be accessed
I am sure some people will get hung up on the specific example (material) but that is the least important thing in the world. In this case I am buffering some aspects of the material which are performance killers to get back database wise, like texts and characteristics, neither of which change more than once every six months, if that.
The point is, I had short dumps because I was using shared memory, and handling the applications server invalidation myself, because you have to, and now I don’t get dumps any more.
CDS View Annotations
I feel the need burning inside of me to expand on a story I mention in my book about CDS views.
I was sitting in Las Vegas merrily listening to an SAP TechEd presenter talking about how to put lots of UI specific annotations inside a CDS view. Who should be sat next to me but SAP Mentor and author James Wood. He asked me “should all this stuff be in the model?”
My initial response was “of course not”. In the MVC paradigm the CDS view corresponds to the model (despite its name) and models have no business telling the view what to do, that would violate the separation of concerns would it not?
However after thinking about this a lot, and comparing the concept with what I have been doing with ALV reports inside the SAP GUI I have modified my position. My new opinion could best be expressed by paraphrasing famous UK academic D.P. Gumby.
D.P.Gumby in his many guises
Question : Should UI type things like “this field is editable” or “you can drill down on this field” or “sort the result list by this field” be in the model?
Answer : NO! NO! NO! NO! NO! NO! NO! NO! NO! NO! NO! NO! NO! NO! NO! NO! NO! NO! NO! NO! NO! NO! NO! NO! NO! NO! NO! NO! NO! NO! NO! NO! NO! NO! NO! NO! NO! NO! NO! NO! NO! NO! NO! NO! NO! NO! NO! NO! YES! YES! This should be in the model! Get in the Model! GET IN! GET IN! GET IN THE MODEL!
When it comes to the ALV inside the SAP GUI the “view” is generally something like CL_SALV_TABLE which has the job of presenting the data, but it could equally be an earlier technology like REUSE_ALV_GRID or CL_GUI_ALV_GRID and I want to be able to swap view technology on a whim without affecting the model. In my base model class interface ZIF_BC_MODEL I have assorted attributes and methods like FILL_EDITABLE_FIELDS and FILL_HOTSPOT_FIELDS, which the model populates with the fields it can deal with e.g. the model only has the code to drill down on certain fields, and can only change certain fields, so it needs to declare this.
Some of these model based tables are more semantic e.g. FILL_HIDDEN_FIELDS or FILL_TECHNICAL_FIELDS to say whether a field is not important enough to be shown by default, or should not be shown at all. Changing the texts also falls into this category. Once again, is it the views place to decide such things? Or in the same way that a CDS view is a model, should a view be like a model, playing dumb and concentrating on looking pretty?
I have decided I am going to hammer the flowers that represent this sort of information into the vase that is the view with my sledgehammer shouting “GET IN” repeatedly.
So if I am currently doing just that with a view which is an ALV grid of whatever sort, why in the world would I want to treat an application where the vie is a UI5 front end any differently? The so called “Get Smart Templates” act rather like the various ALV classes/functions (though some would kill me for saying so) and are controlled from the CDS view in the same way the ALV is controlled from your SAP GUI application.
Right Lads, Back on Your Heads
“You are old, Father William,” the young man said,
“And your hair has become very white;
And yet you incessantly stand on your head –
Do you think, at your age, it is right?”
“In my youth,” Father William replied to his son,
“I feared it might injure the brain;
But, now that I’m perfectly sure I have none,
Why, I do it again and again.”
So, let us turn this on its head – what if I wanted to do something free energy crazy, something radical, something as cool as a cucumber stuffed with liquid nitrogen?
What if I wanted to do an ALV type report based on a CDS view? This is important because the flavour of the month inside the SAP development department is the CDS view and all other SAP technologies like BOPF and the like must dance around the mighty CDS in a circle paying homage, throwing flowers and sacrificing their first born child.
Based on cast iron logic like that, naturally for a new SAP GUI report, I want to use a CDS view as a data source.
There is even a class for such a beast, you call CL_SALV_GUI_TABLE_IDA=>CREATE_FOR_CDS_VIEW and naturally you can set various settings just as in a standard ALV report, naturally using a different sort of coding than anything that has gone before.
Now it would be a touch on the bonkers side, would it not, if there were annotations in the CDS view, to effectively duplicate that code inside the ABAP coding?
Normally, when I create a concrete model class for my ALV reports, I inherit from ZCL_BC_MODEL and redefine the methods where I want editable fields or what have you, by providing a hard coded list.
Are you being Annotation Serviced?
SAP provide a class called CL_DD_DDL_ANNOTATION_SERVICE. It is not documented – of course – but it is fairly easy to get your head around it via experimentation, and it is more fun that way.
After playing around a bit, I decided that method GET_ANNOS was the simplest – you input the CDS view name, and both the header annotations and field annotations come back. There are more annotations returned at the field level than the ones you defined, as you get some text descriptions being derived from the DDIC data element.
In return table ELEMENT_ANNOS you get a list of fields and any annotations that may have been applied to them e.g. how important they are, position in the list and such forth. There are a lot of standard annotations which have exact equivalents in the ALV world, such as hiding fields.
SAP has a guideline that whatever you do, under no circumstances, ever, ever, don’t go making up your own annotations. This is rather like “you can go through any door in this palace except this one, and by the way it’s unlocked” or “you can eat from any tree in this garden except the apple tree”.
So after about three seconds I added an annotation to my CDS view for one of the fields called “@ZMonster.Evil: true”. I wondered if this would get a syntax error i.e. do SAP enforce their own rules. Naturally they do not, so this generated OK, and furthermore my new annotation showed up in the results list when I called the above mentioned method of the annotation hunting class.
That implies that if there was not actually an existing standard annotation which did the equivalent of a ALV setting, such as making a field technical or whatever, you could just decide on your own annotation convention, specific to yourself, though that would be VERY NAUGHTY. You would be best advised changing back to the standard at such point SAP does decide to provide a standard annotation for whatever is currently missing. In actual fact the current list of existing annotations is huge, so there probably is not much missing. If SAP did create a standard annotation starting with a “Z” they should be slapped round the face with a wet fish.
So my next ALV type experiment would be taking a current report I have that runs in the SAP GUI using an ALV, one that has columns which can be drilled down on, some hidden, some with different names than usual, and a specific sort order and so on, re-write the data access as a CDS view, and put annotations in that view.
My good old model up until now has been creating a hard coded list of what fields are drill-down fields or in some other way special. These lists are set up during construction of the model, and later find their way into the view class, along with the data table which the model read from the database using its database access class.
As there is a dedicated persistency layer class I could just change that to read a CDS view instead of the current set of tables being read. Then, back in the main model, I could replace the hard coding by using the annotation hunting class to get the sort order, column order, new names when required and so on. The end result would still be several tables with the exact same information before, ready to make their journey to the view.
In good old OO style, the coding for the controller and view classes would not have to change one iota, as the external interface of the model class has not changed, just the internal implementation, which is always supposed to be top secret, to allow just this sort of thing.
I notice there are annotations which say what fields are supposed to be used as selection fields. When a “smart” template in the Web IDE finds these annotations it builds a selection screen area at the top of the screen based on those values.
In theory I could also build a dynamic selection screen in the SAP GUI in the same way. What puts me off is the idea that we have gone back to the bad old “logical database” days where everything seemed to work by black magic. When I first saw a custom program written using a logical database I could not work out where the selection screen was coming from, or how the data was getting retrieved, or basically anything. We stopped using logical database things circa 2000 in our own developments and I think SAP have declared them obsolete. I suppose with a CDS view it is a bit more transparent where the rules are coming from.
In any event, in a future blog I will report the outcome of this experiment. In the meantime if anyone thinks I am barking at the moon mad for even considering this, please let me know.
That is about long enough for one blog, I will publish another in a few weeks with some more material which did not really fit into an SAP Press book on programming, because it was too abstract / philosophical or whatever.
“CL_DD_DDL_ANNOTATION_SERVICE. It is not documented – of course”
As far as I know, it is, at least in upcoming 7.51.
First appearance and an example in the current documentation.
I was referring to the good old habit people have of going into the class via SE24 and pressing the "Class Documentation" button.
A lot of developers do not like to document classes/ function modules / data elements / tables and so forth,so the documentation inside SAP is somewhat patchy. Of course us customer types are just as bad, if not worse. I have a user exit such then when I release my own transports I get a warning if I have not documentation them within SAP. It is painful, but how can I keep the moral high ground otherwise?
My favourite function module documentation is when you press "function module documentation" and get the description "this function module is being documented, to comply with SAP standards" and that is all.
In my 7.50 system, you can go into SE24 and press “Class Documentation” button for CL_DD_DDL_ANNOTATION_SERVICE ...
I am on a 7.50 system, but only SP01, which may, and probably does, make a difference. I tried logging on in both English and German, and no result for the "class documentation" button either time.
The reason I try in German is that once when I got the "documentation is not available in language EN" for a function, I logged out and logged back in using language DE. I then pressed the documentation button and this time the documentation came up - in English.
"may, and probably does, make a difference. "