...
They require the channel programmer to code the channel to remove objects from the state map when a user's session is removed. This easily results in a channel that leaks memory if implemented incorrectly. It also moves into custom code garbage collection that would otherwise be performed by the Java runtime environment's garbage collector. That is, with IChannels, when a user's session goes out of scope, the IChannel instances used to support that session also go out of scope and become available for garbage collection. IMultithreadeds never go out of scope (are stored in a ChannelFactory static map) and so custom code is required by the channel developer to remove from an internal Map the ChannelState instance representing a particular usage of the IMultithreaded. There was a bug for some time in uPortal wherein the appropriate session ending events were not propogated in certain exceptional conditions, leading IMultithreadeds reliant upon this event propogation to accumulate state in their maps ("leaking memory"). The framework bug blocking event propogation has since been resolved, but the experience highlights the unnecessary dependency of IMultithreadeds on event propogation to accomplish something IChannels accomplish more naturally.
Less Diagnostic Information
IMultithreaded* channel's channels also can't print out expose much useful information in their toString() methods to let us know what is going on when a
channel fails to render. IChannels can provide all the relevant information needed to diagnose a rendering failure including which user
the problem occurred with and what the publish/subscribe id of the channel is. The IMultithreaded* interfaces would need to be modified to have a method
toString(uid) that would take the user's session/uid as a parameter in order to print out the same useful information, and then code using this method would need to be aware that it was using an IMultithreaded and the appropriate key. This highlights that "IMultithreadeds are weird, not behaving like normal Java objects."
More, not less, object creation
...
Additional locking and unlocking, synchronization costs
With normal IChannels, each box a user sees in a portal is backed by an IChannel object instance which includes the state for that one box. With IMultithreadeds, the IChannel for each box is just a wrapper for a single IMultithreaded instance shared across all users. That IMultithreaded includes a state Map with uid keys into the Map to find the appropriate state to service a particular box (uid corresponds one to one with wrapper IChannel reference).
This creates a synchronization problem inside the IMultithreaded implementation. Access to the Map must be synchronized such that one channel usage doesn't add to or delete from the Map concurrently with another's accessing the Map. So synhronization is required, which adds locking and unlocking costs. Implementing the same functionality with an IChannel avoids this locking and unlocking, since there is no shared Map of channel states.
Sharing the Map also creates a slim theoretical potential for insteresting bugs, wherein one user's channel instance incorrectly accesses the backing state map and uses another user's channel state information. Such a bug is less feasible to introduce to traditional IChannels, since they do not share state across usages.
What IMultithreaded does to ChannelFactory
...
- Discourage use of these deprecated APIs
- Refactor the core channels to implement IChannel* .
- These framework channels implement one of the IMultithreaded* interfaces:
- CGroupsManager
- CPortletAdapter
- CWebProxy
- CApplet
- CGenericXSLT
- CImage
- CInlineFrame
- CPersonAttributes
- These framework channels implement one of the IMultithreaded* interfaces:
- Adopt a policy that no new channels will be accepted into the framework (uPortal source tree) if they implement IMultithreaded*
- Propose a presentation for JA-SIG Vancouver conference "Why IMultithreaded is Deprecated and How to Refactor Your Channels away from IMultithreaded"