Plug-in Instance Management

For efficiency, a Cúram client application pools the minimum number of domain plug-in instances possible. This reduces the overhead involved in creating new plug-in instances each time their operations are invoked, but it does impose some restrictions on the way plug-ins can be written.

Domain plug-ins maintain state information: a reference to the domain and the active user's locale. Custom code can access this state information by calling the getDomain and getLocale methods and use it as required. The potential for concurrent access to plug-ins in typical multi-threaded servers impacts the way the plug-in instances (with their state information) are managed. If concurrent requests are received from users who are using different locales, then the same plug-in instance cannot be used when servicing these requests, as only one locale value can be set in a plug-in instance. However, as any Cúram application only supports a finite number of locales, maintaining a single plug-in instance for each locale is sufficient to avoid concurrency problems or synchronization overheads. This, of course, has to be multiplied by the number of domains, as the domain information also constitutes state. The result is that each domain in the domain hierarchy accesses a pool of plug-in instances specific to that domain and each pool contains one instance of each type of plug-in for each locale.

This instance management system is entirely driven by the plug-ins themselves. Each type of plug-in can implement its own instantiation strategy most appropriate to its needs. However, to avoid over-complicating instance management, the AbstractDomainPlugIn class (see Extending Existing Plug-ins) implements the single, consistent pooling strategy that balances efficiency against other considerations.

While it would be more efficient to dispense with the domain and locale state information and pass these values to the various converter and comparator methods, this poses several other problems that make this approach less desirable:

It is this latter point that is most important, successful upgrades depend on custom code that does not attempt to implement the plug-in interfaces from scratch. This is why such an approach cannot be supported.

The pooling strategy used means that there is one main limitation on how plug-ins can be written: plug-ins must not attempt to store any state information. In short, no customization should add fields to a plug-in class and attempt to store information in them; concurrent application requests will probably cause such a plug-in to fail intermittently or introduce obscure bugs.

Domain plug-in classes must also provide a default constructor (i.e., a constructor that takes no arguments). However, any Java class that does not explicitly define a default constructor will automatically have one defined for it if the default constructor of an ancestor class is visible. For custom plug-in classes that extend the plug-in classes and abstract plug-in classes provided with the out-of-the-box Cúram application, no explicit default constructor is required.