Move Web API from CordaPluginRegistry to new class WebPluginRegistry (#864)

Move Web API from CordaPluginRegistry to new class WebPluginRegistry
This commit is contained in:
szymonsztuka 2017-06-20 15:29:35 +01:00 committed by GitHub
parent 4dc06ed25b
commit 4195adfb7b
15 changed files with 85 additions and 39 deletions

View File

@ -9,17 +9,16 @@ import java.util.function.Function
* to extend a Corda node with additional application services. * to extend a Corda node with additional application services.
*/ */
abstract class CordaPluginRegistry { abstract class CordaPluginRegistry {
/**
* List of lambdas returning JAX-RS objects. They may only depend on the RPC interface, as the webserver should @Suppress("unused")
* potentially be able to live in a process separate from the node itself. @Deprecated("This is no longer in use, moved to WebServerPluginRegistry class in webserver module",
*/ level = DeprecationLevel.ERROR, replaceWith = ReplaceWith("net.corda.webserver.services.WebServerPluginRegistry"))
open val webApis: List<Function<CordaRPCOps, out Any>> get() = emptyList() open val webApis: List<Function<CordaRPCOps, out Any>> get() = emptyList()
/**
* Map of static serving endpoints to the matching resource directory. All endpoints will be prefixed with "/web" and postfixed with "\*. @Suppress("unused")
* Resource directories can be either on disk directories (especially when debugging) in the form "a/b/c". Serving from a JAR can @Deprecated("This is no longer in use, moved to WebServerPluginRegistry class in webserver module",
* be specified with: javaClass.getResource("<folder-in-jar>").toExternalForm() level = DeprecationLevel.ERROR, replaceWith = ReplaceWith("net.corda.webserver.services.WebServerPluginRegistry"))
*/
open val staticServeDirs: Map<String, String> get() = emptyMap() open val staticServeDirs: Map<String, String> get() = emptyMap()
@Suppress("unused") @Suppress("unused")

View File

@ -12,6 +12,14 @@ UNRELEASED
* The node driver has moved to net.corda.testing.driver in the test-utils module * The node driver has moved to net.corda.testing.driver in the test-utils module
Milestone 13
------------
* Web API related collections ``CordaPluginRegistry.webApis`` and ``CordaPluginRegistry.staticServeDirs`` moved to
``net.corda.webserver.services.WebServerPluginRegistry`` in ``webserver`` module.
Classes serving Web API should now extend ``WebServerPluginRegistry`` instead of ``CordaPluginRegistry``
and they should be registered in ``resources/META-INF/services/net.corda.webserver.services.WebServerPluginRegistry``.
Milestone 12 Milestone 12
------------ ------------

View File

@ -623,7 +623,8 @@ The example CorDapp has the following directory structure:
│ │   └── resources │ │   └── resources
│ │   ├── META-INF │ │   ├── META-INF
│ │   │   └── services │ │   │   └── services
│ │   │   └── net.corda.core.node.CordaPluginRegistry │   │   │   ├── net.corda.core.node.CordaPluginRegistry
│   │ │ └── net.corda.webserver.services.WebServerPluginRegistry
│ │   ├── certificates │ │   ├── certificates
│ │   │   ├── readme.txt │ │   │   ├── readme.txt
│ │   │   ├── sslkeystore.jks │ │   │   ├── sslkeystore.jks
@ -665,7 +666,8 @@ The example CorDapp has the following directory structure:
│   └── resources │   └── resources
│   ├── META-INF │   ├── META-INF
│   │   └── services │   │   └── services
│   │   └── net.corda.core.node.CordaPluginRegistry    │   │   ├── net.corda.core.node.CordaPluginRegistry
   │ │ └── net.corda.webserver.services.WebServerPluginRegistry
│   ├── certificates │   ├── certificates
│   │   ├── readme.txt │   │   ├── readme.txt
│   │   ├── sslkeystore.jks │   │   ├── sslkeystore.jks
@ -808,7 +810,8 @@ Service Provider Configuration File
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
If you are building a CorDapp from scratch or adding a new CorDapp to the cordapp-tutorial project then you must provide If you are building a CorDapp from scratch or adding a new CorDapp to the cordapp-tutorial project then you must provide
a reference to your sub-class of ``CordaPluginRegistry`` in the provider-configuration file in located in the ``resources/META-INF/services`` directory. a reference to your sub-class of ``CordaPluginRegistry`` or ``WebServerPluginRegistry`` (for Wep API) in the provider-configuration file
located in the ``resources/META-INF/services`` directory.
Re-Deploying Your Nodes Locally Re-Deploying Your Nodes Locally
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

View File

@ -43,7 +43,8 @@ structure:
│ └── resources │ └── resources
│ ├── META-INF │ ├── META-INF
│ │ └── services │ │ └── services
│ │ └── net.corda.core.node.CordaPluginRegistry │ │ ├── net.corda.core.node.CordaPluginRegistry
│ │ └── net.corda.webserver.services.WebServerPluginRegistry
│ ├── certificates │ ├── certificates
│ │ ├── sslkeystore.jks │ │ ├── sslkeystore.jks
│ │ └── truststore.jks │ │ └── truststore.jks
@ -60,9 +61,20 @@ structure:
Defining a plugin Defining a plugin
----------------- -----------------
You can specify the web APIs and static web content for your CorDapp by subclassing You can specify the transport options (between nodes and between Web Client and a node) for your CorDapp by subclassing
``net.corda.core.node.CordaPluginRegistry``: ``net.corda.core.node.CordaPluginRegistry``:
* The ``customizeSerialization`` function allows classes to be whitelisted for object serialisation, over and
above those tagged with the ``@CordaSerializable`` annotation. For instance, new state types will need to be
explicitly registered. In general, the annotation should be preferred. See :doc:`serialization`.
The fully-qualified class path of each ``CordaPluginRegistry`` subclass must be added to the
``net.corda.core.node.CordaPluginRegistry`` file in the CorDapp's ``resources/META-INF/services`` folder. A CorDapp
can register multiple plugins in a single ``net.corda.core.node.CordaPluginRegistry`` file.
You can specify the web APIs and static web content for your CorDapp by implementing
``net.corda.webserver.services.WebServerPluginRegistry`` interface:
* The ``webApis`` property is a list of JAX-RS annotated REST access classes. These classes will be constructed by * The ``webApis`` property is a list of JAX-RS annotated REST access classes. These classes will be constructed by
the bundled web server and must have a single argument constructor taking a ``CordaRPCOps`` object. This will the bundled web server and must have a single argument constructor taking a ``CordaRPCOps`` object. This will
allow the API to communicate with the node process via the RPC interface. These web APIs will not be available if the allow the API to communicate with the node process via the RPC interface. These web APIs will not be available if the
@ -73,13 +85,9 @@ You can specify the web APIs and static web content for your CorDapp by subclass
is not started. is not started.
* The static web content itself should be placed inside the ``src/main/resources`` directory * The static web content itself should be placed inside the ``src/main/resources`` directory
* The ``customizeSerialization`` function allows classes to be whitelisted for object serialisation, over and The fully-qualified class path of each ``WebServerPluginRegistry`` class must be added to the
above those tagged with the ``@CordaSerializable`` annotation. For instance, new state types will need to be ``net.corda.webserver.services.WebServerPluginRegistry`` file in the CorDapp's ``resources/META-INF/services`` folder. A CorDapp
explicitly registered. In general, the annotation should be preferred. See :doc:`serialization`. can register multiple plugins in a single ``net.corda.webserver.services.WebServerPluginRegistry`` file.
The fully-qualified class path of each ``CordaPluginRegistry`` subclass must be added to the
``net.corda.core.node.CordaPluginRegistry`` file in the CorDapp's ``resources/META-INF/services`` folder. A CorDapp
can register multiple plugins in a single ``net.corda.core.node.CordaPluginRegistry`` file.
Installing CorDapps Installing CorDapps
------------------- -------------------

View File

@ -1,10 +1,10 @@
package net.corda.bank.plugin package net.corda.bank.plugin
import net.corda.bank.api.BankOfCordaWebApi import net.corda.bank.api.BankOfCordaWebApi
import net.corda.core.node.CordaPluginRegistry import net.corda.webserver.services.WebServerPluginRegistry
import java.util.function.Function import java.util.function.Function
class BankOfCordaPlugin : CordaPluginRegistry() { class BankOfCordaPlugin : WebServerPluginRegistry {
// A list of classes that expose web APIs. // A list of classes that expose web APIs.
override val webApis = listOf(Function(::BankOfCordaWebApi)) override val webApis = listOf(Function(::BankOfCordaWebApi))
} }

View File

@ -1,2 +0,0 @@
# Register a ServiceLoader service extending from net.corda.node.CordaPluginRegistry
net.corda.bank.plugin.BankOfCordaPlugin

View File

@ -0,0 +1,2 @@
# Register a ServiceLoader service extending from net.corda.webserver.services.WebServerPluginRegistry
net.corda.bank.plugin.BankOfCordaPlugin

View File

@ -1,10 +1,10 @@
package net.corda.irs.plugin package net.corda.irs.plugin
import net.corda.core.node.CordaPluginRegistry
import net.corda.irs.api.InterestRateSwapAPI import net.corda.irs.api.InterestRateSwapAPI
import net.corda.webserver.services.WebServerPluginRegistry
import java.util.function.Function import java.util.function.Function
class IRSPlugin : CordaPluginRegistry() { class IRSPlugin : WebServerPluginRegistry {
override val webApis = listOf(Function(::InterestRateSwapAPI)) override val webApis = listOf(Function(::InterestRateSwapAPI))
override val staticServeDirs: Map<String, String> = mapOf( override val staticServeDirs: Map<String, String> = mapOf(
"irsdemo" to javaClass.classLoader.getResource("irsweb").toExternalForm() "irsdemo" to javaClass.classLoader.getResource("irsweb").toExternalForm()

View File

@ -1,2 +0,0 @@
# Register a ServiceLoader service extending from net.corda.core.node.CordaPluginRegistry
net.corda.irs.plugin.IRSPlugin

View File

@ -0,0 +1,2 @@
# Register a ServiceLoader service extending from net.corda.webserver.services.WebServerPluginRegistry
net.corda.irs.plugin.IRSPlugin

View File

@ -15,15 +15,17 @@ import net.corda.core.serialization.SerializationCustomization
import net.corda.vega.analytics.CordaMarketData import net.corda.vega.analytics.CordaMarketData
import net.corda.vega.analytics.InitialMarginTriple import net.corda.vega.analytics.InitialMarginTriple
import net.corda.vega.api.PortfolioApi import net.corda.vega.api.PortfolioApi
import net.corda.webserver.services.WebServerPluginRegistry
import java.util.function.Function import java.util.function.Function
/** /**
* [SimmService] is the object that makes available the flows and services for the Simm agreement / evaluation flow * [SimmService] is the object that makes available the flows and services for the Simm agreement / evaluation flow.
* It also enables a human usable web service for demo purposes - if available. * It is loaded via discovery - see [CordaPluginRegistry].
* It is loaded via discovery - see [CordaPluginRegistry] * It is also the object that enables a human usable web service for demo purpose
* It is loaded via discovery see [WebServerPluginRegistry].
*/ */
object SimmService { object SimmService {
class Plugin : CordaPluginRegistry() { class Plugin : CordaPluginRegistry(), WebServerPluginRegistry {
override val webApis = listOf(Function(::PortfolioApi)) override val webApis = listOf(Function(::PortfolioApi))
override val staticServeDirs: Map<String, String> = mapOf("simmvaluationdemo" to javaClass.classLoader.getResource("simmvaluationweb").toExternalForm()) override val staticServeDirs: Map<String, String> = mapOf("simmvaluationdemo" to javaClass.classLoader.getResource("simmvaluationweb").toExternalForm())
override fun customizeSerialization(custom: SerializationCustomization): Boolean { override fun customizeSerialization(custom: SerializationCustomization): Boolean {

View File

@ -0,0 +1,2 @@
# Register a ServiceLoader service extending from net.corda.webserver.services.WebServerPluginRegistry
net.corda.vega.services.SimmService$Plugin

View File

@ -3,10 +3,10 @@ package net.corda.webserver.internal
import com.google.common.html.HtmlEscapers.htmlEscaper import com.google.common.html.HtmlEscapers.htmlEscaper
import net.corda.client.rpc.CordaRPCClient import net.corda.client.rpc.CordaRPCClient
import net.corda.core.messaging.CordaRPCOps import net.corda.core.messaging.CordaRPCOps
import net.corda.core.node.CordaPluginRegistry
import net.corda.core.utilities.loggerFor import net.corda.core.utilities.loggerFor
import net.corda.nodeapi.ArtemisMessagingComponent import net.corda.nodeapi.ArtemisMessagingComponent
import net.corda.webserver.WebServerConfig import net.corda.webserver.WebServerConfig
import net.corda.webserver.services.WebServerPluginRegistry
import net.corda.webserver.servlets.* import net.corda.webserver.servlets.*
import org.apache.activemq.artemis.api.core.ActiveMQNotConnectedException import org.apache.activemq.artemis.api.core.ActiveMQNotConnectedException
import org.eclipse.jetty.server.* import org.eclipse.jetty.server.*
@ -203,9 +203,9 @@ class NodeWebServer(val config: WebServerConfig) {
return connection.proxy return connection.proxy
} }
/** Fetch CordaPluginRegistry classes registered in META-INF/services/net.corda.core.node.CordaPluginRegistry files that exist in the classpath */ /** Fetch WebServerPluginRegistry classes registered in META-INF/services/net.corda.webserver.services.WebServerPluginRegistry files that exist in the classpath */
val pluginRegistries: List<CordaPluginRegistry> by lazy { val pluginRegistries: List<WebServerPluginRegistry> by lazy {
ServiceLoader.load(CordaPluginRegistry::class.java).toList() ServiceLoader.load(WebServerPluginRegistry::class.java).toList()
} }
/** Used for useful info that we always want to show, even when not logging to the console */ /** Used for useful info that we always want to show, even when not logging to the console */

View File

@ -0,0 +1,24 @@
package net.corda.webserver.services
import net.corda.core.messaging.CordaRPCOps
import java.util.function.Function
/**
* Implement this interface on a class advertised in a META-INF/services/net.corda.webserver.services.WebServerPluginRegistry file
* to create web API to connect to Corda node via RPC.
*/
interface WebServerPluginRegistry {
/**
* List of lambdas returning JAX-RS objects. They may only depend on the RPC interface, as the webserver lives
* in a process separate from the node itself.
*/
val webApis: List<Function<CordaRPCOps, out Any>> get() = emptyList()
/**
* Map of static serving endpoints to the matching resource directory. All endpoints will be prefixed with "/web" and postfixed with "\*.
* Resource directories can be either on disk directories (especially when debugging) in the form "a/b/c". Serving from a JAR can
* be specified with: javaClass.getResource("<folder-in-jar>").toExternalForm()
*/
val staticServeDirs: Map<String, String> get() = emptyMap()
}

View File

@ -3,7 +3,7 @@ package net.corda.webserver.servlets
import kotlinx.html.* import kotlinx.html.*
import kotlinx.html.stream.appendHTML import kotlinx.html.stream.appendHTML
import net.corda.core.messaging.CordaRPCOps import net.corda.core.messaging.CordaRPCOps
import net.corda.core.node.CordaPluginRegistry import net.corda.webserver.services.WebServerPluginRegistry
import org.glassfish.jersey.server.model.Resource import org.glassfish.jersey.server.model.Resource
import org.glassfish.jersey.server.model.ResourceMethod import org.glassfish.jersey.server.model.ResourceMethod
import java.io.IOException import java.io.IOException
@ -15,7 +15,7 @@ import javax.servlet.http.HttpServletResponse
* Dumps some data about the installed CorDapps. * Dumps some data about the installed CorDapps.
* TODO: Add registered flow initiators. * TODO: Add registered flow initiators.
*/ */
class CorDappInfoServlet(val plugins: List<CordaPluginRegistry>, val rpc: CordaRPCOps): HttpServlet() { class CorDappInfoServlet(val plugins: List<WebServerPluginRegistry>, val rpc: CordaRPCOps): HttpServlet() {
@Throws(IOException::class) @Throws(IOException::class)
override fun doGet(req: HttpServletRequest, resp: HttpServletResponse) { override fun doGet(req: HttpServletRequest, resp: HttpServletResponse) {