There are various optional references to icons which may be contributed by a plug-in. Most icons should be transparent GIFs unless stated otherwise in the table below. Here is a set of potential locations for contributing icons:
Context | Recommended Size in Pixels | Remarks |
---|---|---|
Plug-in icon appearing in the common About dialog | 16x16 | Transparent GIF |
Bitmap for plug-in specific 2nd-level About dialog | None | May be also JPG or PNG file |
Perspective icon in Select Perspective dialog | 16x16 | Transparent GIF |
Header icon contributed by perspective | Height: 35. Width: depends on space required for toolbar and view listbox. | May be also JPG or PNG file |
Icon representing an item in tree or table | 16x16 | Transparent GIF |
Icon for command for an item (context menu or toolbar in detail view) | 16x16 | Transparent GIF |
The Pluggable UI relies heavily on dedicated class loaders. Whereas the code for a normal web application is only loaded via the basic WebappClassLoader provided by Software AG Runtime, this class loader is only used for loading the classes resembling the PluggableUI base with the underlying Application Designer. The respective classes are loaded from the following directories below <RuntimeWebAppsDir>\PluggableUI:
WEB-INF/classes WEB-INF/lib/*.jar
In addition, locations holding common or shared class or jar files are searched by the WebappClassLoader when attempting to resolve references to required classes.
Any code contributed by a plug-in is loaded by a corresponding instance of the PlugInWebappClassLoader from the following directories below <RuntimeWebAppsDir>\PluggableUI
plugInDir/classes plugInDir/lib/*.jar
If resolution fails, the PlugInWebappClassLoader
for the current plug-in will delegate class loading to the
PlugInWebappClassLoaders for other plug-ins in the order
as listed as <requiredPlugin>
in the
plugin.xml of the current plug-in recursively. Finally, if
resolution via required plug-ins fails, the
PlugInWebappClassLoader will delegate class loading to the
WebappClassLoader.
The following picture illustrates the scenario of the LifeCycleManagement plug-in (representing any other 3rd party plug-in) that depends on the CentraSiteControl plug-in and the PluggableUI base infrastructure.
The AdapterPlugInClassLoader is used by ApplicationDesigner when resolving references to adapter classes found in layout definitions. The AdapterPlugInClassLoader will never load classes itself. Instead, it will ask all known PlugInWebappClassLoaders in an unspecified order whether they can load a required class.
Warning: You must avoid having the same adapter classes in more than one plug-in! Otherwise, various classloading related issues (ClassCastException, ClassNotFoundException, …) will result. Under normal conditions, fulfilling this restriction should not cause any problems. |
In general, you should avoid having multiple locations contributing the same classes within the graph of locations spanned by the required plug-ins.
Normally, when executing the HTTP requests on behalf of a single Application Designer session, there is no parallel execution in multiple threads (unless the code contributed by a plug-in starts a thread on its own). Hence, access to objects or properties having a scope restricted to the session context does not require any synchronization.
However, when using global / static variables, this is no longer true: multiple active user sessions may be processed in parallel.
Avoid usage of global variables. They may lead to the following issues:
Synchronization is required otherwise non-reproducible race conditions will result.
Memory leakages: if global collections that grow for each session are used.
Global references to JAXR-based RegistryObjects: a RegistryObject contains a reference to the JAXR-based Connection (including the underlying credentials) which had been used to load it. When resolving a secondary reference either of the following may happen:
If the connection is still open: credentials of another user will be used, thus causing a security hole.
If the connection is no longer open: a corresponding exception will be thrown ("trying to use a closed connection").
All adapter classes of a plug-in should not be just subclasses of com.softwareag.cis.server.Adapter. Instead, they should be derived from one of the following classes:
com.softwareag.cis.plugin.adapter.util.CommonAdapter - for a plug-in that does not depend on CentraSite Control
com.centrasite.control.adapters.BaseAdapter - for a plug-in that depends on CentraSite Control
BaseAdapter
is a subclass of
CommonAdapter
and thus inherits certain properties.
Among those is the implicit registration of all adapters as "known
adapters" in the current session context. However, under certain
circumstances it may happen that adapters for nested pages displayed using a
SUBCISPAGE or ROWTABSUBPAGES control
are not automatically deregistered when closing e.g. an activity displayed in
the CONTENT frame on the right hand side of the workplace.
This may lead to subsequent NullPointerExceptions.
Normally, de-registration is accomplished within the
destroy()
method in
CommonAdapter
. Hence, be careful when overriding this
method in a subclass to call super.destroy()
. In
addition, you should override the endProcess()
method
in the adapter for the container layout, which should perform at least the
following actions:
call super.endProcess()
call CommonAdapter.removeKnownAdapter (subPageAdapter)
for each subPageAdapter