The logical structure of the standard module is defined by
the contents of the file
module.xml which comprises
one or more top-level
rootspace definitions along with their
(If you are familiar with accessors, transports
and transreptors in NetKernel 3, these are now unified as types of
endpoints in NetKernel 4.)
The logical structure defined by the module is created when a module is
The logical structure of a module is defined by an XML document. The root element module must have the attribute version with the value "2.0" (to distinguish it from the module definition used in NetKernel 3). The direct children of the root are the meta, system and one or more rootspace elements.
A module must have one meta element. The meta element has two required child elements - identity and info. The identity element contains two required child elements, uri, which is the module's globally unique URI identifier and version, the module's current version number.
The info element contains two required child elements, name and description, both should contain human readable text which will be displayed as part of the module presentation in NetKernel tools and reports.
A module may have a system element.
If the child element dynamic is present then NetKernel monitors
module.xml and all of the module's Java class files for changes.
When a change is detected NetKernel re-commissions the module.
The child element classloader contains a single child element exports with one or more match elements. Each match elements contain a regular expression that specifies one or more Java classes exported by the module.
Each module uses its own custom classloader that loads and manages Java classes for any space it defines (rootspace or normal space). The module classloader is able to selectively export classes for importation by other module classloaders.
If the child element jvm is present then this module will only be commissioned if NetKernel is running on a JVM version equal to or higher than the version specified by this tag. If it is not an error will be reported at boot.
A common design pattern uses one public rootspace per module.
There are many examples of this in NetKernel itself including the service
library modules such as
A module with one private rootspace may seem nonsensical as no
external requests could enter that space.
However, if that rootspace hosts a transport then it
is a fulcrum module and can issue
when the transport detects an event external to NetKernel and the application.
A less common but import module design uses a single public rootspace
and several private rootspaces which create separate address regions.
These separate regions can contain resources that differ in access restrictions
(secure or not secure), or have other distinct characteristics.
The optional attribute public controls whether spaces outside of the module can import the rootspace. If a rootspace is public (the default) then it can be statically imported by any space in any module and the wormhole accessor can dynamically import the space. If it is private then it can only be imported by other spaces in its own module. To make a rootspace visible only in its own module, set the public attribute to false:
The optional attribute name specifies a human readable name displayed by the Visualizer and other system tools. If the name attribute is not provided then the kernel constructs a name from the XPath location of the space within the application structure and the module's identifier.
If the optional private-filter attribute is present and set to
"true", then the private-filtering space is inserted and all
space elements marked "private" are not exposed outside of the rootspace.
If the private-filter attribute is present and set to "false", then
all space elements, regardless of their marked visibility are
exposed outside of the rootspace.
If the attribute is missing, then the rootspace scans its
module.xml file search for private tags.
If any are found, then the private-filtering space is inserted, otherwise
it is omitted.
An endpoint is marked as private by instantiating it with a <private> tag. In this example we import layer1 but ensure that it's functionality will not be exposed outside the importing module:
The optional attribute uri specifies an identifier for the rootspace. If the rootspace is public then the identifier must be globally unique. If the rootspace is private then the identifier must be unique within the module. If omitted, the rootspace takes on an identifier derived from the containing module's uri (specified in /module/meta/identity/uri). The first space will have the same uri as the module and subsequent space elements will have the module's uri with an index number appended after a colon (":").