All context nodes created at design time default to being singletons. So one might think that using them is always a good idea. Unfortunately, the workbench only offers this setting for historical reasons.
During the time while Web Dynpro was being created, the almighty designers thought that having singletons will improve performance and hence all nodes should be singletons unless a developer explicitly switches this feature off. Over time though (and several projects later that utilized Web Dynprio) we learned that using singletons is usually a bad idea. Let me explain why we came to this conclusion.
Some UI Elements Don’t Work With Singleton Nodes
Those are all ui elements that iterate over context elements and display the structure of the sub nodes. The most prominent example is the Tree. In case a context node is a singleton, expanding another parent tree node will make the old sub tree to vanish.
Some UI Elements Work, But Behave Strangly
Best example are ui elements that display multiple context elements of the same node at the same time. Those are the Table, MultiPane, DropdownByIndex, etc. One might be tempted to add sub nodes to the “main” context node to structure data or to add additional data like readOnly, enabled, etc. While doing this the developer needs to be aware that forgetting to switch off the singleton feature can lead to strange effects. It’s best explained using a table.
Suppose you have a table ui element that binds to a context node called DATA. In order to supply additional data for an editable field a sub node SUPPLEMENT is created. It contains an attribute READ_ONLY (among others). Node DATA has a supply function and since the business logic supplies both the data and the control info, the supply function fills the content of the SUPPLEMENT sub nodes as well for all elements. This increases performance. By mistake or simply by not recognizing it the developer leaves the singleton feature switched on at the SUPPLEMENT node.
Now the problems begin. (1) After starting the application, the readOnly settings are not properly applied. It only seems to be correct for a few rows. (2) After switching the leadSelection, nothing changes. (3) After trying to change the value of the readOnly attribute it only works for the first row.
What happened? The singleton setting caused all of the problems. (1) Some rows might have been marked editable by the business logic. So the error is not detected. (2) The error already started within the supply function. By supplying the child node of the next context element, the previous child node gets invalidated. Even worse, later on the renderer loops over the context elements as well, which invalidates all child nodes again. Since the child nodes have no supply function, the correct values will never be restored. Switching the leadSelection has no further effect, since things got already broken during the first run. (3) By only changing the readOnly setting of the first row, the renderer still accesses the correct information as it renders the table from top to bottom. It will fail for any other row since during rendering the first row the child node of any other row will be invalidated.
The solution is simple again: Just switch off the singleton feature at the SUPPLEMENT node and everything will start working properly.
Saving Detail Data Can Become Difficult
Suppose you have a node DATA and a node DETAIL_DATA, which happens to be a child node of DATA. The content of DATA is displayed as a table, while the content of DETAIL_DATA is displayed as a form (just for differentiating both – could be as well a second table or any other combination of ui elements). Node DETAIL_DATA is a singleton node.
If a user enters data into the form and switches the leadSelection at the same time, the data entered into the form will be lost. There are mechanisms to prevent this, but they are not active by default. Let me explain the reason why the data gets lost.
Since DETAIL_DATA happens to be a singleton node, it exists only once. More specifically, it only exists for the element of DATA that has the leadSelection. Before the user entered the data into the form, the leadSelection was at a certain element. By switching the leadSelection, the node presenting the form data gets deleted and a new node is created for the element that holds the new leadSelection. This happens well before any application coding is called. Hence, it is impossible for an application developer to prevent the loss of data.
Right after this side effect had been detected, a countermeasure was implemented. UI elements, that allow a user to switch the leadSelection, got a new property selectionChangeBehaviour. This property can be set to “manual”, which means that the runtime won’t switch the leadSelection automatically, but gives the application developer the change to save the entered data and to change the leadSelection afterwards.
Since the default value of this attribute is not “manual” due to compatibility to existing applications, developers unware of this scenario might forget to make this setting while working with singleton nodes, which leads to the described effect. Applications that do not use singleton nodes don’t need to set this attribute to “manual” since the other instance of the child node won’t vanish and its content can be accessed at all times.
One Component Deletes the Data of Another Component
This happens whenever context mapping is done across the border of a component. Actually, doing something like this is a bad thing as well, which I will explain in another blog. Sometimes though, it cannot be avoided and if that was the case, using Singletons might lead to strange effects – especially in conjuction with the master-detail problem described above.
Suppose you have a table with a detail form as described in the previous scenario. Using the selectionChangeBehavior will save your own component from losing the data and will allow you to act beforehand. In case your component is supposed to be reusable and you don’t know who will be using it, you will have to think ahead and provide an event to which the outside component can subscribe to preserve its part of the data. Most developers of reusable components are not aware of this problem and hence have to rewrite parts of their components after detecting the cause. Unfortunately, that won’t be all. Developers already integrating the affected component will have to rewrite parts of their coding as well.
Of course, switching off singleton will solve the issue as well and should be done unless there is very convincing demand to use this feature.
Using Singletons Can Decrease Performance
Huh? Yep, because it comes down to performance vs. memory used. Singletons allow you to save memory. Saving memory has a possibility to increase performance in certain circumstances, but usually it’s not the case – especially not if memory was not the bottleneck.
Mostly, discussions about using singletons and performance neclet the time it takes to resupply affected child nodes. There, in most cases the data is retrieved from a heavy weight business logic that has to perform a database select. Even if the data was buffered inside of a series of internal tables, real world applications have to transform this data to be presented at the user interface. Of course this can take alot of time – usually more time than just to cache the ui representation of the data within the controller. At the end, such a caching algorithm can easily be achieved by switching off the singleton flags.
The second performance related aspect is that invalidating the child nodes that existed below the element holding the previous leadSelection after a leadSelection change also takes it time. It’s not much though, but it still counts.
Errors Caused By Singletons Are Difficult To Detect
An application that uses a component that has singleton nodes has a high chance to behave properly, if each singleton node had a supply function. Nonetheless, taking into account what has been said above, using singleton nodes can lead to strange effects, like lost data and side effects integrating different components. Moreover, a developer might receive complaints about the poor performance of his or her application without being aware of the origin of the problem.
All of these problems are very difficult to detect as they do not happen inside of a single method, but result from the interaction of different coding pieces surrounded by the special behaviour of the singleton nodes. While debugging, the affected nodes might have proper content due to the existance of the supply function. Since you can’t (and should not be enforced to) debug the Web Dynpro runtime, the only option for a developer is to guess the places where breakpoints should be set to make sense out of the effects he or she is experiencing.
Without any offense, this is an approach doctors follow while trying to understand the origin of certain symptoms. They use their knowledge and experience – and guess. If they need more evidence, they send a person to a specialist. With enough evidence some medicine is prescribed or the person is sent to a hospital for “repair”. If the medicine turns out to have no effect, the next iteration starts.
Unlike humans, computers allow us to debug a problem. Moreover, with a proper design in the beginning, the guessing can be reduced significantly later on when it comes to maintain the product. Switching off the singleton feature helps reducing the guessing and lowers maintaince costs in the long run.
Singletons Make Sense, If..
… you really aim for a performance gain after having conducted a thourough performance analysis e.g. using se30 or the performance trace available in sicf and you came to the conclusion that the benefits gained outweigh the drawbacks caused. Of course, before enabling the flag, you have verified that none of the issues mentioned above apply to your scenario or you have taken appropriate countermeasures like adding supply functions, using the selectionChangeBehavior attribute of affected ui elements and providing events to reusable components.
The first thing after creating a context node is to switch off the singleton checkbox. It will save you alot of trouble.