Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Corrected links that should have been relative instead of absolute.
Warning
titleWarning

This is a Draft

Background Information

Let me start out by saying this proposal doesn't propose that support be dropped for IMultithreaded interfaces. This proposal does propose that they should be marked as deprecated and over time as appropriate IMultithreaded channels should be rewritten to use IChannel insteadrefactored as Channels or Portlets. Eventually there might come a time when most current IMultithreadedChannel implementations have dropped IMultithreaded and we can simplify and improve the performance of uPortal by dropping support for this interface, but there are no near term plans to drop that support. Also, we need to make it clear that IMultithreaded* channels shouldn't be perceived as a better, faster more optimized way of developing a channel.

Advantages of Implementing the IMultithreaded* Interfaces

Reduces calls to class.instanceOf()

IMultithreaded* allows the running portal to minimize the number of calls to class.newInstance(), because this call happens once per channel class name and then, for IMultithreadeds, the instantiated class instance is stored in a static Map so that from then on it can be looked up by String class name. Map lookup, wrapper instantiation, and channel state object instantation do not add up to quite as much performance cost as does the class.instanceOf() excecution. However, the performance difference is negligible, may be outweighed by the additional runtime costs of IMultihreaded in channel state map synchronization and access costs, and all of this will be drowned out by the other costly operations involved in running the portal (executing transforms, database access, serializing the output, doing whatever valuable thing your channel does, etc.)

Drawbacks of Implementing the IMultithreaded* Interfaces

...

Channels implemented as IMultithreaded* are much more complex than normal IChannels with the same features. This is a serious problem in an open source project. It is a serious barrier to collaboration, and this reason alone is enough to warrant deprecation.

IMultithreaded re-invents Statics

...

IMulithreaded re-invents this. IMultithreaded asks the portal to guarantee that all boxes using this channel will be backed by the same IMultithreaded instance, such that the instance fields in that channel instance are shared across all usages of the channel. This is completely equivalent to writing an IChannel and placing those shared objects in static fields. It's an increasing best practice to avoid the use of static fields, which are well understood - it should be even more a best practice to avoid the use of an equivalent facility that is much less well understood.

...

IMultithreaded* channels also can't 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."

...

And these services can be shared. They can be grabbed from Factories using static initializers if they need to be shared statically. They can be grabbed from Spring if you'd like to declaratively configure them. They could even be grabbed from JNDI. Writing traditional IChannels, rather than IMultithreadeds, does not by any means mean that your channels cannot share the state and services they ought to share. Avoiding IMultithreaded does, however, help channels to avoid sharing state they don't need to share, state that just gets in the way.

Summary

What makes this even more clear-cut for me is that we haven't written a single channel that benefits from being implemented as IMultithreaded*There are no important advantages of IMultithreaded* to be had, and there are real costs of implementing this interface. It is clear that we should discourage implementation of channels as IMultithreaded*, and I think deprecating the interfaces is the clearest way to communicate this without ambiguity.

Proposal Implementation

  • Discourage use of these deprecated APIs
  • Refactor the core channels to implement IChannel* .
    • These framework channels implement one of the IMultithreaded* interfaces:
      • CGroupsManager (Patch attached to UP-1371)
      • CPortletAdapter (Patch attached to UP-1300)
      • CWebProxy (Patch attached to UP-1302)
      • CApplet (Patch attached to UP-1369)
      • CGenericXSLT (Patch attached to UP-1303)
      • CImage (Patch attached to UP-1367)
      • CInlineFrame (Patch attached to UP-1368)
      • CPersonAttributes (Patch attached to UP-1370)
  • Adopt a policy that no new channels implementing IMultithreaded*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"