Merged in mnesbit-plugin-framework (pull request #522)

Document on plugin loading framework.
This commit is contained in:
Matthew Nesbit 2016-11-23 17:21:52 +00:00
commit 8b94325039
3 changed files with 107 additions and 5 deletions

View File

@ -0,0 +1,98 @@
The Corda Plugin Framework
==========================
The intention is that Corda is a common platform, which will be extended
by numerous application extensions (CorDapps). These extensions will
package together all of the Corda contract code, state structures,
protocols/flows to create and modify state as well as RPC extensions for
node clients. Details of writing these CorDapps is given elsewhere
:doc:`creating-a-cordapp`.
To enable these plugins to register dynamically with the Corda framework
the node uses the Java ``ServiceLoader`` to locate and load the plugin
components during the ``AbstractNode.start`` call. Therefore,
to be recognised as a plugin the component must:
1. Include a default constructable class extending from
``net.corda.core.node.CordaPluginRegistry`` which overrides the relevant
registration methods.
2. Include a resource file named
``net.corda.core.node.CordaPluginRegistry`` in the ``META-INF.services``
path. This must include a line containing the fully qualified name of
the ``CordaPluginRegistry`` implementation class. Multiple plugin
registries are allowed in this file if desired.
3. The plugin component must be on the classpath. In the normal use this
means that it should be present within the plugins subfolder of the
node's workspace.
4. As a plugin the registered components are then allowed access to some
of the node internal subsystems.
5. The overridden properties on the registry class information about the different
extensions to be created, or registered at startup. In particular:
a. The ``webApis`` property is a list of JAX-RS annotated REST access
classes. These classes will be constructed by the embedded web server
and must have a single argument constructor taking a ``ServiceHub``
reference. This reference provides acccess to functions such as querying
for states through the ``VaultService`` interface, or access to the
``NetworkMapCache`` to identify services on remote nodes. The framework will
provide a database transaction in scope during the lifetime of the web
call, so full access to database data is valid. Unlike
``servicePlugins`` the ``webApis`` cannnot register new protocols, or
initiate threads. (N.B. The intent is to move the Web support into a
separate helper process using the RPC mechanism to control access.)
b. The ``staticServeDirs`` property maps static web content to virtual
paths and allows simple web demos to be distributed within the CorDapp
jars. (N.B. The intent is to move the Web support into a separate helper
process using the RPC mechanism to control access.)
c. The ``requiredFlows`` property is used to declare new protocols in
the plugin jar. Specifically the property must return a map with a key
naming each exposed top level flow class and a value which is a set
naming every parameter class that will be passed to the flow's
constructor. Standard ``java.lang.*`` and ``kotlin.*`` types do not need
to be included, but all other parameter types, or concrete interface
implementations need declaring. Declaring a specific flow in this map
white lists it for activation by the ``FlowLogicRefFactory``. White
listing is not strictly required for ``subFlows`` used internally, but
is required for any top level flow, or a flow which is invoked through
the scheduler.
d. The ``servicePlugins`` property returns a list of classes which will
be instantiated once during the ``AbstractNode.start`` call. These
classes must provide a single argument constructor which will receive a
``PluginServiceHub`` reference. These singleton instances are regarded
as trusted components and can be used for a number of purposes.
i. Firstly, they can call ``PluginServiceHub.registerFlowInitiator`` and
register flows that will be initiated locally in response to remote flow
requests.
ii. Second, the service can hold a long lived reference to the
PluginServiceHub and to other private data, so the service can be used
to provide Oracle functionality. This Oracle functionality would
typically be exposed to other nodes by flows which are given a reference
to the service plugin when initiated (as defined by the
``registerFlowInitiator`` call). The flow can then call into functions
on the plugin service singleton. Note, care should be taken to not allow
flows to hold references to plugin services, or fields which are not
also ``SingletonSerializeAsToken``, otherwise Quasar suspension in the
``StateMachineManager`` will fail with exceptions. An example oracle can
be seen in ``NodeInterestRates.kt`` in the irs-demo sample.
iii. The final
use case for service plugins is that they can spawn threads, or register
to monitor vault updates. This allows them to provide long lived active
functions inside the node, for instance to initiate workflows when
certain conditions are met.
e. The ``registerRPCKryoTypes`` function allows custom Kryo serialisers
to be registered and whitelisted for the RPC client interface. For
instance new state types passed to flows started via RPC will need
to be explicitly registered. This will be called at various points on
various threads and needs to be stable and thread safe.

View File

@ -49,6 +49,7 @@ Read on to learn:
persistence
node-administration
corda-configuration-files
corda-plugins
node-services
.. toctree::
@ -66,7 +67,7 @@ Read on to learn:
tutorial-contract-clauses
tutorial-test-dsl
tutorial-clientrpc-api
flow-state-machines
protocol-state-machines
oracles
tutorial-attachments
event-scheduling

View File

@ -7,11 +7,14 @@ you can upload and download attachments, access a REST API and so on.
Logging
-------
Logs are stored to the logs subdirectory of the node directory and are rotated from time to time. You can
In the default configuration logs are stored to the logs subdirectory of the node directory and are rotated from time to time. You can
have logging printed to the console as well by passing the ``--log-to-console`` command line flag. Corda
uses the log4j2 framework to manage its logging, so you can also configure it in more detail by writing
a custom logging configuration file and passing ``-Dlog4j.configurationFile=my-config-file.xml`` on the
command line as well.
uses the SL4J logging façade which is configured with the log4j2 binding framework to manage its logging,
so you can also configure it in more detail by writing a custom log4j2 logging configuration file and passing ``-Dlog4j.configurationFile=my-config-file.xml``
on the command line as well. The default configuration is copied during the build from ``config/dev/log4j2.xml``, or for the test sourceSet from ``config/test/log4j2.xml``.
In corda code a logger is typically instantiated via the ``net.corda.core.utilities.loggerFor`` utility method which will create an SL4J ``Logger`` with a name based on the type parameter.
Also, available in ``net.corda.core.utilities``, are extension methods to take a lazily evaluated logging lambda for trace and debug level, which will not evaluate the lambda if the LogLevel threshold is higher.
Database access
---------------