Where I live in the United States, it is nearly time for the Christmas Holidays. Any day now we will have the first snow of the season. People are busy putting up lights and Christmas trees. The shopping centers are full of eager shoppers. Given this is the season for sharing of gifts, what better time could there be for exploring the new ABAP Shared Memory functionality in WebAS 640.
Now you might be saying to yourself, that we already have access to shared memory areas via the import and export statements. What could be so special about this new functionality? Well first of all, this is read access to shared memory without the need to copy it into user session memory. Second the new shared memory is implemented through ABAP Objects. Therefore you are provided with robust tools to interact with shared memory through code. You also have good administrative tools to monitor and support these memory areas. This is what I want to focus on today. We will look at how to create a shared memory class, but I will really focus on what I have seen to be some of the major advantages to this new technology.
Creating our Root Class
All of the data we want to store or expose through the shared memory area has to be contained in a Root Class. Later when we work with our shared memory, you will see that all we are really doing is getting a pointer to an instance of this root class. We then access or manipulate the data through this class. We will start off quite simply by creating a normal ABAP Class from SE80. We will name it ZCL_SDN_SHARED_ROOT.
Now we have to define that this class will be a Shared Memory Class. To do that we just have to select Shared Memory-Enabled from the General Data area of our class properties.
That’s it. We now have a shared memory root class. For this class to be useful, it’s going to need to be able to supply some data. For that reason, let’s create a private attribute called message of type string.
Now we can create two public methods that will be used to access this message attribute(GET_MESSAGE and SET_MESSAGE). The GET_MESSAGE will have a string returning parameter and the SET_MESSAGE will have a string importing parameter. Right now all these methods are going to do is to read and write our private attribute. Of course I could have just exposed my message attribute as a public attribute. However I wanted to show that one of the advantages of the shared memory class is the ability to add logic on read and write. Later we will add just such logic.
Creating the Shared Memory Area
Next up we have to create a Shared Memory Area. This Area is another ABAP Class. It will become the information broker for your root classes. It will control access to the instances of the root class. That’s right, you might have multiple versions of the root class alive at once. Therefore the Area manages these versions. For instance you might have a reader working with the active version while a separate writer is building a new version. This ability to version, which comes from the Area object, is one of the other major advantages of the shared memory technology.
To create our Area we go to transaction SHMA. We are going to name our area class ZCL_SDN_SHARED_AREA.
From the top part of the following screen we fill in the Basic Properties. All we are going to do right now in here is assign our root class to the area. We also have the ability to set certain other parameters. The first makes the shared memory area Client Specific. If you are familiar with the basic SAP concept of Clients within a System Instance, this should be self explanatory. Next up is the Aut. AreaStrucuring. We will look at this option a little later in the weblog. Finally there is transaction area. This option allows you to tie your shared memory area to a data base object. This allows you to propagate shared memory values across multiple application servers. But proper Propagation, Invalidation, and Preloading of Shared memory areas across multiple Application Servers could probably be a weblog by itself. For today we will learn to walk before we run.
The bottom half of the screen has some additional attributes. For now we will leave all values at their default. Therefore we won’t have multiple versions. Nor will we have any type of Auto Start for our memory area. There also will not be any limits set.
If we return to SE80, we can now see that we have two classes that really make up our shared memory: the area class and the root class.
Our Area class is generated for us, but it still might be interesting to look at some of its Public methods. These are methods we are going to program against to read, write and update our shared memory.
We are ready to write our first program. This program will get read access to our shared memory area. We can then access the GET_MESSAGE method of our root class to write out our message attribute.
If you ran the read program you got a short dump, right. That’s because our shared memory area doesn’t exist yet. Later we will learn how we can turn on Auto Initialization so that on the first read request the memory area is created. For now let’s just write a program to do that. This program will create an instance of the root object. It will then write to the message attribute and set the root back into the area.
After you run this write program, you can go back to the first and now you should get results without the short dump.
Shared Memory Monitor
Before we move on to more advanced techniques, let’s take a minute to look at the monitoring and administration tools for shared memory. If you successfully ran the write and then the read program, you should be able to see your area and root instance in these tools. You start off by going to transaction SHMM. From the first screen of the monitoring tool, we can see all of shared memory areas. We can also see memory usage, number of instances, number of versions, and the status breakdown of the versions. As you can see our new little shared memory area isn’t taking up much space.
If we double click on the area, we can drill down farther and see all the instances of root classes within the area. We only have our once instance (the default instance). From these screens you delete either an instance or the whole memory area. You can also see the structure of the root class and the public attributes of the class. Overall the tools that you would need to keep track of where you shared memory is allocated are all here.
As you saw from the example earlier, we got a short dump when we tried to read from the unloaded memory area. Wouldn’t it be much nicer if the memory area could automatically preload itself on the first read attempt. Well that’s exactly what we are going to do now. To do this we are first going to have to add the interface, IF_SHM_BUILD_INSTANCE, to our root class.
This should add one new public static method to our root class called BUILD. This is where we are going to put the initialization code for our shared memory instance.
Basically we will copy in the code from our earlier write program into this BUILD method. We will just change the initial message, so that we can tell the difference.
Now we need to change that attributes of our area. Always remember to go to SHMM and delete any existing Shared Areas after you make changes here. First we will set the Aut. AreaStructuring in the basic properties of the shared area.
Now we also must supply the name of our constructor class. This is our root class where we just implemented the IF_SHM_BUILD_INSTANCE. This field entry will check and make sure that the class you supply has this interface. We also have to set if we want to Auto start on just the read request or also every invalidation.
Now we are ready for a new read program. This read program is only slightly different. When we issue the attach_for_read on an initial memory area, this should trigger our BUILD method. Now this build activity happens Asynchronously in another work processes. Unfortunately the attach_for_read doesn’t wait for this BUILD work to complete. Therefore we have to account for this and add a wait to our read program if the initial attach fails.
Updating Data in Shared Memory
We have looked at how to write initial data into our shared memory. But remember our write program created a new instance of the root class. We also need to be able to update the data in an existing instance. To do that we will use the attach_for_update. Because the update might trigger the BUILD method as well if the shared area is initial, we have to account for the Asynchronous activity again. Then we try to get a pointer to the existing root instance. If one doesn’t exist, we just create one.
Now while I was writing this weblog, I noticed some interesting attributes on the attach_for_update that aren’t there on the attach for read. They were attach_mode and wait_time. It looks as though maybe SAP plans to do the wait logic for us. I decided to give these new options a try:
All I got was this very interesting short dump. I guess I will just have to wait a little longer for this functionality. Maybe Support Stack 10 will have it.
In this section I wanted to demonstrate the power of shared objects based upon their OO implementation. Instead of just accessing a memory area, you are accessing an ABAP class. That means that this shared memory area can also contain logic to manipulate the data as it is read. For this demonstration, I will append a random number between 1 and 100 to the end of the message in the GET_MESSAGE method. I have just been dying for an excuse to use the new Random Number classes in 640 anyway. The following is the code for the new GET_MESSAGE method.
The following are the new results:
I was going to close out the weblog with an example of how I could use OO events in my shared memory class. I thought it would be really neat to have two consumers of a shared memory area. One would write and the other would register for an ON_Update event. When the first program wrote an update, the second program’s event handler would respond to this update and popup a message. Unfortunately I received the following message as soon as I added an event to the root class.
Now my German is a little rusty, but I get the feeling it is telling me I can’t use events in shared memory classes. I can understand that there would be serious technical problems to get a shared memory event to work right, but it sure would be nice! Perhaps we have something to look forward to in NetWeaver 05.