diff --git a/.idea/compiler.xml b/.idea/compiler.xml
index d8ab87d54d..687b740285 100644
--- a/.idea/compiler.xml
+++ b/.idea/compiler.xml
@@ -184,4 +184,4 @@
-
\ No newline at end of file
+
diff --git a/settings.gradle b/settings.gradle
index 3fc5753e21..f9a1119927 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -43,6 +43,7 @@ include 'tools:loadtest'
include 'tools:graphs'
include 'tools:bootstrapper'
include 'tools:dbmigration'
+include 'tools:notaryhealthcheck'
include 'example-code'
project(':example-code').projectDir = file("$settingsDir/docs/source/example-code")
include 'samples:attachment-demo'
diff --git a/tools/notaryhealthcheck/build.gradle b/tools/notaryhealthcheck/build.gradle
new file mode 100644
index 0000000000..3d0ac39e2b
--- /dev/null
+++ b/tools/notaryhealthcheck/build.gradle
@@ -0,0 +1,62 @@
+import net.corda.plugins.Cordform
+
+apply plugin: 'java'
+apply plugin: 'kotlin'
+apply plugin: 'idea'
+apply plugin: 'net.corda.plugins.quasar-utils'
+apply plugin: 'net.corda.plugins.publish-utils'
+apply plugin: 'net.corda.plugins.cordapp'
+apply plugin: 'net.corda.plugins.cordformation'
+apply plugin: 'maven-publish'
+
+dependencies {
+ compile "org.jetbrains.kotlin:kotlin-stdlib-jre8:$kotlin_version"
+ testCompile "junit:junit:$junit_version"
+
+ // Corda integration dependencies
+ cordaCompile project(path: ":node:capsule", configuration: 'runtimeArtifacts')
+ cordaCompile project(':core')
+ cordaCompile project(':client:jfx')
+ cordaCompile project(':client:rpc')
+ cordaCompile project(':node-driver')
+ compile group: 'mysql', name: 'mysql-connector-java', version: '6.0.6'
+ compile group: 'io.dropwizard.metrics', name: 'metrics-graphite', version: '3.2.5'
+
+}
+
+idea {
+ module {
+ downloadJavadoc = true // defaults to false
+ downloadSources = true
+ }
+}
+
+publishing {
+ publications {
+ jarAndSources(MavenPublication) {
+ from components.java
+ artifactId 'notaryhealthcheck'
+
+ artifact sourceJar
+ artifact javadocJar
+ }
+ }
+}
+
+task runTest(type: JavaExec) {
+ classpath = sourceSets.main.runtimeClasspath
+ main = 'net.corda.notarytest.MainKt'
+}
+
+task deployHealthCheck(type: Cordform, dependsOn: 'jar') {
+ definitionClass = 'net.corda.notarytest.HealthCheckCordform'
+}
+
+jar {
+ manifest {
+ attributes(
+ 'Automatic-Module-Name': 'net.corda.notarytest'
+ )
+ }
+}
+
diff --git a/tools/notaryhealthcheck/src/main/kotlin/net/corda/notarytest/HealthCheckCordform.kt b/tools/notaryhealthcheck/src/main/kotlin/net/corda/notarytest/HealthCheckCordform.kt
new file mode 100644
index 0000000000..ee26a4f9ea
--- /dev/null
+++ b/tools/notaryhealthcheck/src/main/kotlin/net/corda/notarytest/HealthCheckCordform.kt
@@ -0,0 +1,44 @@
+package net.corda.notarytest
+
+import net.corda.cordform.CordformContext
+import net.corda.cordform.CordformDefinition
+import net.corda.core.identity.CordaX500Name
+import net.corda.node.services.Permissions.Companion.all
+import net.corda.node.services.config.NotaryConfig
+import net.corda.testing.node.User
+import net.corda.testing.node.internal.demorun.*
+import java.nio.file.Paths
+
+fun main(args: Array) = HealthCheckCordform().deployNodes()
+
+val notaryDemoUser = User("demou", "demop", setOf(all()))
+
+// This is not the intended final design for how to use CordformDefinition, please treat this as experimental and DO
+// NOT use this as a design to copy.
+class HealthCheckCordform : CordformDefinition() {
+ init {
+ nodesDirectory = Paths.get("build", "nodes")
+ node {
+ name(CordaX500Name("R3 Notary Health Check", "London", "GB"))
+ p2pPort(10002)
+ rpcPort(10003)
+ rpcUsers(notaryDemoUser)
+ }
+ node {
+ name(CordaX500Name("Notary Service 0", "London", "GB"))
+ p2pPort(10009)
+ rpcPort(10010)
+ notary(NotaryConfig(validating = false))
+ extraConfig = mapOf(
+ "mysql" to mapOf(
+ "jdbcUrl" to "jdbc:mysql://notary-10.northeurope.cloudapp.azure.com:3306/corda?rewriteBatchedStatements=true&useSSL=false",
+ "username" to "",
+ "password" to "",
+ "autoCommit" to "false"
+ )
+ )
+ }
+ }
+
+ override fun setup(context: CordformContext) {}
+}
diff --git a/tools/notaryhealthcheck/src/main/kotlin/net/corda/notarytest/Main.kt b/tools/notaryhealthcheck/src/main/kotlin/net/corda/notarytest/Main.kt
new file mode 100644
index 0000000000..8a6de73657
--- /dev/null
+++ b/tools/notaryhealthcheck/src/main/kotlin/net/corda/notarytest/Main.kt
@@ -0,0 +1,26 @@
+package net.corda.notarytest
+
+import net.corda.client.rpc.CordaRPCClient
+import net.corda.core.messaging.CordaRPCOps
+import net.corda.core.messaging.startFlow
+import net.corda.core.utilities.NetworkHostAndPort
+import net.corda.nodeapi.internal.config.User
+import net.corda.node.services.Permissions
+import net.corda.notarytest.flows.HealthCheckFlow
+
+fun main(args: Array) {
+ val addresses = listOf(NetworkHostAndPort("localhost", 10003))
+
+ val notaryDemoUser = User("demou", "demop", setOf(Permissions.all()))
+
+ addresses.parallelStream().forEach {
+ val c = CordaRPCClient(it).start(notaryDemoUser.username, notaryDemoUser.password)
+ healthCheck(c.proxy)
+ }
+ println("ok")
+}
+
+fun healthCheck(rpc: CordaRPCOps) {
+ val notary = rpc.notaryIdentities().first()
+ rpc.startFlow(::HealthCheckFlow, notary).returnValue.get()
+}
diff --git a/tools/notaryhealthcheck/src/main/kotlin/net/corda/notarytest/flows/HealthCheckFlow.kt b/tools/notaryhealthcheck/src/main/kotlin/net/corda/notarytest/flows/HealthCheckFlow.kt
new file mode 100644
index 0000000000..f87b00f216
--- /dev/null
+++ b/tools/notaryhealthcheck/src/main/kotlin/net/corda/notarytest/flows/HealthCheckFlow.kt
@@ -0,0 +1,38 @@
+package net.corda.notarytest.flows
+
+import co.paralleluniverse.fibers.Suspendable
+import net.corda.core.contracts.CommandData
+import net.corda.core.contracts.Contract
+import net.corda.core.contracts.ContractState
+import net.corda.core.flows.FlowLogic
+import net.corda.core.flows.NotaryFlow
+import net.corda.core.flows.StartableByRPC
+import net.corda.core.identity.AbstractParty
+import net.corda.core.identity.Party
+import net.corda.core.transactions.LedgerTransaction
+import net.corda.core.transactions.TransactionBuilder
+
+@StartableByRPC
+open class HealthCheckFlow(val notaryParty: Party) : FlowLogic() {
+
+ class DoNothingContract : Contract {
+ override fun verify(tx: LedgerTransaction) {}
+ }
+
+ data class DummyCommand(val dummy: Int = 0) : CommandData
+
+ @Suspendable
+ override fun call(): Unit {
+
+ data class State(override val participants: List) : ContractState
+
+ val state = State(listOf(ourIdentity))
+
+ val stx = serviceHub.signInitialTransaction(TransactionBuilder(notaryParty).apply {
+ addOutputState(state, "net.corda.notarytest.flows.HealthCheckFlow\$DoNothingContract")
+ addCommand(DummyCommand(), listOf(ourIdentity.owningKey))
+ })
+
+ subFlow(NotaryFlow.Client(stx))
+ }
+}
\ No newline at end of file