cancel
Showing results for 
Search instead for 
Did you mean: 

Singleton class problem ... a session issue?

matteo_montalto
Contributor
0 Kudos

Hi all gurus,

basically, I need to trasport an user selection, made via a multiple-chose popup, into a standard method underlying.

In order to do so, as in other scenarios I did, I created a specific singleton class, with a single attribute (which represents the user selection).

I defined a get and a set method to access the attribute and everything goes fine until we just set the variable .

Now the problem... In the place in which I have to get the value, I simply instanciate the class... and that's empty. Debugging I've seen that my factory() method creates the instance as no instance result available. That's a really strange problem.

Any possible explanation for such an issue? My guess is that after the user selection (which correctly assign a value to the class attribute) a new application is lauched by the standard and that could imply that a new session is started. And as far as I understood, each singleton class in OO ABAP lives in a session.

That should explain why in the get() point an active instance is not found, and a new one is instanciated.

This is an huge problem for the requirement I have to implement; could anyone suggest an alternative approach or a workaround?

Thanks, suggestions will be highly appreciated

Accepted Solutions (1)

Accepted Solutions (1)

former_member184578
Active Contributor
0 Kudos

Hi,

Use Shared Memory Object. You can check this article http://scn.sap.com/docs/DOC-27396

Or, Create a temporary data base table and store the data temporarily ,fetch it and delete it after use.

Hope this helps u.,

Regards,

Kiran

matteo_montalto
Contributor
0 Kudos

Thanks Kiran,

I tried to adapt my developments using a Shared Memory Object... here are the results (and doubts, of course 😞

- i tried first to define the Shared Memory Area setting the "Binding" option to "User session"... and it didn't work with the same problems I had with the singleton class; everything's good but in the point in which I should retrieve the attribute value... there's no active instance of the class. Probably, the point in which I need to read the value is on a new session opened by the standard process

- i switched then the "Binding" property of the SMA to "Application Server" and, gladly, it works now the value is correctly retrieved in the point in which I have to get it.

BUT...

my doubts are now about concurrency. As this SMA process is used in a particular point that is, specifically, the creation of a document in SRM... what happens if two or more users are at the same time approaching this part of the process? Will they "share" the same attribute of the class, or will they have distinguished process so that each user has it's own SMA?

As I understood in previous works I did using singleton classes, each user had its own class instance so there's no problem.

But seeing the catch() clauses in using SMA, my fear is that ALL users share the same, unique memory area... and that would not be good as the set/get stack should be considered for each user approaching the system or the sequentiality would not be guaranteed if cuncurrent operations are performed.

Could anyone help me a bit on this point? Suggestions will be highly appreciated

former_member184578
Active Contributor
0 Kudos

Hi,

No need to worry about different users. For each user there will be a different instance of SHMA. The problem is if the application opens in different application server( may happen in Production server due to load balancing) . You can check the comment from thomas on the same where I mentioned in the next part of this article http://scn.sap.com/docs/DOC-27397

So, Storing data in a temporary database table is more good.

Hope this helps u.,

Regards,

Kiran

matteo_montalto
Contributor
0 Kudos

Hi Kiran,

that's different from what I've seen in debug. Trying to describe what I did:

- logged in simultaneously with two different username, say User A and User B, from my pc;

- i triggered the popup for the User A, and seen via debug that the value chosen (say, "1") has been stored via SHMA; after that, I simply kept the process in temporary stuck and in the meanwhile...

- i triggered the popup for the User B. B choose value "9" and that's correctly stored via SHMA;

- after that, back to User A. When it's time to get the value, I'd expect to get "1"... instead, I get "9"!!!

That's why I thought that SHMA shares the same, unique instance between different users... or maybe the problem is that I was working with both users with a single client pc?

The scenario of different application server could be a no-problem in our context.

Thanks again

former_member184578
Active Contributor
0 Kudos

Hi,

Yes. The latest version of the SHM instance will be active.( sorry about my previous statement which is confusing, for each user different versions will be created and at runtime one version is active). Let say user A set the attr of SHM to 5 and later user B set it to 10. If you read SHM the value wil be 10.

Here note that While user A is writing the value to SHM ,User B cannot set the value due to Locks.

So, I find no problem here. When user A is running application he will set the value ( say 5) and get it. ( then locks will be released) and when user B is running he will set the value ( say 10 ) and get it from SHM.

From your scenario, I guess you are setting the value to SHM when user selects the check box( in onSelect of Check box) ?  Instead, in OnSave you read the check box and set the value to SHM and read the SHM in your main View.

Or why don't you create a context attribute in the component controller and pass the data via component controller ( mapping )

Regards,

Kiran

matteo_montalto
Contributor
0 Kudos

Hi Kiran, the above solution might be a problem for us as we've got basically two "checkpoints", in example:

1) point in which we SET the SMA for a specific user (you're right, it's associated to the checkbox selection by the user);

2) point in which we GET the SMA to have the selected value.

If several users approach point 1) simultaneously, what will happen? I guess the first one trying to access the SMA gets the lock, while the others are stuck'd. So we should manage explicitly a routine that keeps on trying to get the lock... seems quite dirty.

Of course, the main problem remains how to avoid the case that you well described:

"Let say user A set the attr of SHM to 5 and later user B set it to 10. If you read SHM the value wil be 10."

This could be avoided if we can guarantee that the user that gets the lock first KEEP IT until the GET() phase is over. I mean:

- get the lock;

- write;

- don't release the lock;

- .....

- read from SMA to get the value;

- release the lock;

This could assure concurrency and correctness, don't you think? The main problem remains a sort of "polling" algorithm that we have to implement to manage the case in which:

- user A has got the lock;

- user B tries to get the lock and gets an error;

then we should do a sort of (horrible) polling in which user B tries to get the lock.

Well... it seems there's no clean solution to the task.

For what concerns the DB table... it has been considered a "dirty" solution so it's the last option that would be considered.

For what concerns Component Controller... I could do that, but the point in which I have to GET that value is a method of a class, specifically /SAPSRM/CL_PDO_BO_SC, method GET_DEFAULT_PROCESS_TYPE, in which (seen in debug) I have absolutely no reference to any WD Compcontroller entity ( otherwise I could solve the problem by raising a popup directly from this method, but there's no reference of any WD element ).

former_member184578
Active Contributor
0 Kudos

Hi,

Interesting scenario. I seek some clarification. Why you SET the SHM in the checkbox selection.

I assume, You have a popup screen with some check boxes corresponding to some entries, and you need to get the selected entries when the pop up is closed.

So what I suggested was, instead of setting the SHM in the onSelect of Check box, set the selected entries to SHM in the onSave or ( Close ) of popup and get it.

Or is it a different scenario.?

If you set the SHM in onSelect of Checkbox, this may result in serious problem. Let say, user A select checkbox 1 and you set to SHM and user wait for some time ( may be he wants to have coffee ) mean time if user B selects check box 2 then this will be updated to SHM. Then when user Save and Close the POP up and you try to read it, you will get check box 2 entry.

I don't completely accept that storing to DB is dirty solution. If there is no other work around you have to use DB. Just create a temporary DB, save and delete. And from Thomas comment it is the good way.

Regards,

Kiran

matteo_montalto
Contributor
0 Kudos

Hi Kiran,

you're right, a better approach should be the one you described... But as the "Ok" button is associated to an action which is proper of the caller WD View, I just simplified by setting the value @ checkbox selection time.
Anyway, the problem would not be avoided even if we SET the SHM at the closure of the popup.

Let's say, user A triggers the selection popup and sets a value for SHM (say, value "A"). After a fraction of time, user B sets SHM to "B".

In the meantime, execution flow proceed for user A; specifically, at the GET time, he *could* get from the SHM the value "B" which has been set by user B.

And that breaks the rules we'd like to impose.

The only thing I could think to overcome this problem is to get an exclusive lock on the SHM from the moment we try to SET till the time in which we GET. Obviously, in such a case evental users which cuncurrently would access the popup will have to WAIT until the SHM lock has been released.

Seems not a great way of managing the task, however there's no alternative solution (except the DB table which is considered, as told, a last-chance, "dirty" solution... ok, you don't agree, neither I in a certain sense, however that's what they told us ).

I'd like to further investigate the CompController mapping way, but as far as I've seen in debug, there's no reference of the overlying WD interface in the method in which I'd like to GET the value.

My first intention was to trigger the popup directly from the method /SAPSRM/CL_PDO_BO_SC -> GET_DEFAULT_PROCESS_TYPE. But I don't have any reference of the WD layer in that method, so I don't know how to get the API controller reference there ((tipically, in WD development, we could retrieve it by the get_api method from the component controller:

e.g;

lo_api_controller  WD_COMP_CONTROLLER->wd_get_api( ). )

former_member184578
Active Contributor
0 Kudos

Hi,

There wont be much execution time. If you write the SET to SHM in on Close of Pop up (or on Save ) you can set and get it, which is in the flow, Even mean time if other user tries to SET the SHM, they can't as the lock exists. So both users cant SET at a time and hence there will be difference in execution time.

And the Idea of keeping other user wait till the read of first user is fine but not sure whether you can achieve this, because if you don't detach commit of write i guess it wont update!! not sure, You can give a try.

But this wont make the other user to make wait as it will throw a short dump.

So you catch the lock exception and use a wait statement.

keep the access of SHM in endless loop.

Do ( infinite condition )

* attach for write

  

   EXIT " if no lock success.

catch

       cx_shm_read_lock_active

       cx_shm_change_lock_active

        cx_shm_exclusive_lock_active

WAIt for 5 secs.

EndDO

Hope this helps u.,

Regards,

Kiran

Answers (0)