diff --git a/client/rpc/src/integration-test/kotlin/net/corda/client/rpc/CordaRPCClientTest.kt b/client/rpc/src/integration-test/kotlin/net/corda/client/rpc/CordaRPCClientTest.kt index 850e8a057b..f47917197d 100644 --- a/client/rpc/src/integration-test/kotlin/net/corda/client/rpc/CordaRPCClientTest.kt +++ b/client/rpc/src/integration-test/kotlin/net/corda/client/rpc/CordaRPCClientTest.kt @@ -48,7 +48,6 @@ import org.junit.Before import org.junit.ClassRule import org.junit.Test import rx.subjects.PublishSubject -import java.io.File.pathSeparator import java.net.URLClassLoader import java.nio.file.Paths import java.util.* @@ -249,15 +248,12 @@ class CordaRPCClientTest : NodeBasedTest(listOf("net.corda.finance")) { @Test fun `additional class loader used by WireTransaction when it deserialises its components`() { val financeLocation = Cash::class.java.location.toPath().toString() - val classpathWithoutFinance = ProcessUtilities.defaultClassPath - .split(pathSeparator) - .filter { financeLocation !in it } - .joinToString(pathSeparator) + val classPathWithoutFinance = ProcessUtilities.defaultClassPath.filter { financeLocation !in it } // Create a Cash.State object for the StandaloneCashRpcClient to get node.services.startFlow(CashIssueFlow(100.POUNDS, OpaqueBytes.of(1), identity), InvocationContext.shell()).flatMap { it.resultFuture }.getOrThrow() val outOfProcessRpc = ProcessUtilities.startJavaProcess( - classpath = classpathWithoutFinance, + classPath = classPathWithoutFinance, arguments = listOf(node.internals.configuration.rpcOptions.address.toString(), financeLocation) ) assertThat(outOfProcessRpc.waitFor()).isZero() // i.e. no exceptions were thrown diff --git a/docs/source/tutorial-attachments.rst b/docs/source/tutorial-attachments.rst index 6f991d22d4..1956c9331a 100644 --- a/docs/source/tutorial-attachments.rst +++ b/docs/source/tutorial-attachments.rst @@ -27,11 +27,11 @@ Uploading and downloading To upload an attachment to the node, or download an attachment named by its hash, you use :doc:`clientrpc`. This is also available for interactive use via the shell. To **upload** run: -``>>> run uploadAttachment jar: /path/to/the/file.jar`` +``>>> run uploadAttachment jar: path/to/the/file.jar`` or -``>>> run uploadAttachmentWithMetadata jar: /path/to/the/file.jar, uploader: myself, filename: original_name.jar`` +``>>> run uploadAttachmentWithMetadata jar: path/to/the/file.jar, uploader: myself, filename: original_name.jar`` to include the metadata with the attachment which can be used to find it later on. Note, that currently both uploader and filename are just plain strings (there is no connection between uploader and the RPC users for example). diff --git a/docs/source/tutorial-test-dsl.rst b/docs/source/tutorial-test-dsl.rst index 91d788cfd6..f568ef6a84 100644 --- a/docs/source/tutorial-test-dsl.rst +++ b/docs/source/tutorial-test-dsl.rst @@ -99,7 +99,7 @@ Let's add a ``CommercialPaper`` transaction: } We can add a transaction to the ledger using the ``transaction`` primitive. The transaction in turn may be defined by -specifying ``input``-s, ``output``-s, ``command``-s and ``attachment``-s. +specifying ``input``s, ``output``s, ``command``s and ``attachment``s. The above ``input`` call is a bit special; transactions don't actually contain input states, just references to output states of other transactions. Under the hood the above ``input`` call creates a dummy transaction in the diff --git a/node/src/main/resources/build.properties b/node/src/main/resources/build.properties index f61271471e..f3f8ea80d3 100644 --- a/node/src/main/resources/build.properties +++ b/node/src/main/resources/build.properties @@ -12,4 +12,4 @@ # Note: sadly, due to present limitation of IntelliJ-IDEA in processing resource files, these constants cannot be # imported from top-level 'constants.properties' file -jolokiaAgentVersion=1.5.0 +jolokiaAgentVersion=1.6.0 diff --git a/samples/irs-demo/src/integration-test/kotlin/net/corda/irs/IRSDemoTest.kt b/samples/irs-demo/src/integration-test/kotlin/net/corda/irs/IRSDemoTest.kt index 9fd0c4740d..f8bdce5ddc 100644 --- a/samples/irs-demo/src/integration-test/kotlin/net/corda/irs/IRSDemoTest.kt +++ b/samples/irs-demo/src/integration-test/kotlin/net/corda/irs/IRSDemoTest.kt @@ -75,20 +75,18 @@ class IRSDemoTest : IntegrationTest() { isDebug = true, extraCordappPackagesToScan = listOf("net.corda.irs") )) { - val (nodeA, nodeB) = listOf( + val (controller, nodeA, nodeB) = listOf( + defaultNotaryNode, startNode(providedName = DUMMY_BANK_A_NAME, rpcUsers = rpcUsers), startNode(providedName = DUMMY_BANK_B_NAME, rpcUsers = rpcUsers), startNode(providedName = CordaX500Name("Regulator", "Moscow", "RU")) ).map { it.getOrThrow() } - val controller = defaultNotaryNode.getOrThrow() log.info("All nodes started") - val controllerAddrFuture = startSpringBootWebapp(IrsDemoWebApplication::class.java, controller, "/api/irs/demodate") - val nodeAAddrFuture = startSpringBootWebapp(IrsDemoWebApplication::class.java, nodeA, "/api/irs/demodate") - val nodeBAddrFuture = startSpringBootWebapp(IrsDemoWebApplication::class.java, nodeB, "/api/irs/demodate") - val (controllerAddr, nodeAAddr, nodeBAddr) = - listOf(controllerAddrFuture, nodeAAddrFuture, nodeBAddrFuture).map { it.getOrThrow().listenAddress } + val (controllerAddr, nodeAAddr, nodeBAddr) = listOf(controller, nodeA, nodeB).map { + startSpringBootWebapp(IrsDemoWebApplication::class.java, it, "/api/irs/demodate") + }.map { it.getOrThrow().listenAddress } log.info("All webservers started") diff --git a/samples/irs-demo/src/integration-test/kotlin/net/corda/test/spring/SpringDriver.kt b/samples/irs-demo/src/integration-test/kotlin/net/corda/test/spring/SpringDriver.kt index 8c0411d0a9..8c3f87900d 100644 --- a/samples/irs-demo/src/integration-test/kotlin/net/corda/test/spring/SpringDriver.kt +++ b/samples/irs-demo/src/integration-test/kotlin/net/corda/test/spring/SpringDriver.kt @@ -85,16 +85,14 @@ data class SpringBootDriverDSL(private val driverDSL: DriverDSLImpl) : InternalD } private fun startApplication(handle: NodeHandle, debugPort: Int?, clazz: Class<*>): Process { - val className = clazz.canonicalName - return ProcessUtilities.startJavaProcessImpl( - className = className, // cannot directly get class for this, so just use string + return ProcessUtilities.startJavaProcess( + className = clazz.canonicalName, // cannot directly get class for this, so just use string jdwpPort = debugPort, extraJvmArguments = listOf( "-Dname=node-${handle.p2pAddress}-webserver", "-Djava.io.tmpdir=${System.getProperty("java.io.tmpdir")}" // Inherit from parent process ), - classpath = ProcessUtilities.defaultClassPath, workingDirectory = handle.baseDirectory, arguments = listOf( "--base-directory", handle.baseDirectory.toString(), @@ -102,8 +100,7 @@ data class SpringBootDriverDSL(private val driverDSL: DriverDSLImpl) : InternalD "--corda.host=${handle.rpcAddress}", "--corda.user=${handle.rpcUsers.first().username}", "--corda.password=${handle.rpcUsers.first().password}" - ), - maximumHeapSize = null + ) ) } -} \ No newline at end of file +} diff --git a/testing/node-driver/src/main/kotlin/net/corda/testing/node/internal/DriverDSLImpl.kt b/testing/node-driver/src/main/kotlin/net/corda/testing/node/internal/DriverDSLImpl.kt index fd8782edcb..2230ded4fb 100644 --- a/testing/node-driver/src/main/kotlin/net/corda/testing/node/internal/DriverDSLImpl.kt +++ b/testing/node-driver/src/main/kotlin/net/corda/testing/node/internal/DriverDSLImpl.kt @@ -34,7 +34,6 @@ import net.corda.core.utilities.getOrThrow import net.corda.core.utilities.millis import net.corda.node.NodeRegistrationOption import net.corda.node.VersionInfo -import net.corda.node.internal.ConfigurationException import net.corda.node.internal.Node import net.corda.node.internal.StartedNode import net.corda.node.services.Permissions @@ -846,7 +845,7 @@ class DriverDSLImpl( it += extraCmdLineFlag }.toList() - return ProcessUtilities.startCordaProcess( + return ProcessUtilities.startJavaProcess( className = "net.corda.node.Corda", // cannot directly get class for this, so just use string arguments = arguments, jdwpPort = debugPort, @@ -859,13 +858,12 @@ class DriverDSLImpl( private fun startWebserver(handle: NodeHandleInternal, debugPort: Int?, maximumHeapSize: String): Process { val className = "net.corda.webserver.WebServer" writeConfig(handle.baseDirectory, "web-server.conf", handle.toWebServerConfig()) - return ProcessUtilities.startCordaProcess( + return ProcessUtilities.startJavaProcess( className = className, // cannot directly get class for this, so just use string arguments = listOf("--base-directory", handle.baseDirectory.toString()), jdwpPort = debugPort, extraJvmArguments = listOf("-Dname=node-${handle.p2pAddress}-webserver") + inheritFromParentProcess().map { "-D${it.first}=${it.second}" }, - workingDirectory = null, maximumHeapSize = maximumHeapSize ) } diff --git a/testing/node-driver/src/main/kotlin/net/corda/testing/node/internal/ProcessUtilities.kt b/testing/node-driver/src/main/kotlin/net/corda/testing/node/internal/ProcessUtilities.kt index ae2c0502ca..197122dda1 100644 --- a/testing/node-driver/src/main/kotlin/net/corda/testing/node/internal/ProcessUtilities.kt +++ b/testing/node-driver/src/main/kotlin/net/corda/testing/node/internal/ProcessUtilities.kt @@ -11,40 +11,32 @@ package net.corda.testing.node.internal import net.corda.core.internal.div +import java.io.File import java.nio.file.Path object ProcessUtilities { inline fun startJavaProcess( arguments: List, - classpath: String = defaultClassPath, + classPath: List = defaultClassPath, + workingDirectory: Path? = null, jdwpPort: Int? = null, - extraJvmArguments: List = emptyList() + extraJvmArguments: List = emptyList(), + maximumHeapSize: String? = null ): Process { - return startJavaProcessImpl(C::class.java.name, arguments, classpath, jdwpPort, extraJvmArguments, null, null) + return startJavaProcess(C::class.java.name, arguments, classPath, workingDirectory, jdwpPort, extraJvmArguments, maximumHeapSize) } - fun startCordaProcess( + fun startJavaProcess( className: String, arguments: List, - jdwpPort: Int?, - extraJvmArguments: List, - workingDirectory: Path?, - maximumHeapSize: String - ): Process { - return startJavaProcessImpl(className, arguments, defaultClassPath, jdwpPort, extraJvmArguments, workingDirectory, maximumHeapSize) - } - - fun startJavaProcessImpl( - className: String, - arguments: List, - classpath: String, - jdwpPort: Int?, - extraJvmArguments: List, - workingDirectory: Path?, - maximumHeapSize: String? + classPath: List = defaultClassPath, + workingDirectory: Path? = null, + jdwpPort: Int? = null, + extraJvmArguments: List = emptyList(), + maximumHeapSize: String? = null ): Process { val command = mutableListOf().apply { - add((System.getProperty("java.home") / "bin" / "java").toString()) + add(javaPath) (jdwpPort != null) && add("-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=$jdwpPort") if (maximumHeapSize != null) add("-Xmx$maximumHeapSize") add("-XX:+UseG1GC") @@ -54,7 +46,7 @@ object ProcessUtilities { } return ProcessBuilder(command).apply { inheritIO() - environment()["CLASSPATH"] = classpath + environment()["CLASSPATH"] = classPath.joinToString(File.pathSeparator) if (workingDirectory != null) { redirectError((workingDirectory / "$className.stderr.log").toFile()) redirectOutput((workingDirectory / "$className.stdout.log").toFile()) @@ -63,5 +55,7 @@ object ProcessUtilities { }.start() } - val defaultClassPath: String get() = System.getProperty("java.class.path") + private val javaPath = (System.getProperty("java.home") / "bin" / "java").toString() + + val defaultClassPath: List = System.getProperty("java.class.path").split(File.pathSeparator) } \ No newline at end of file diff --git a/tools/network-bootstrapper/src/main/kotlin/net/corda/bootstrapper/NetworkBuilder.kt b/tools/network-bootstrapper/src/main/kotlin/net/corda/bootstrapper/NetworkBuilder.kt index 6b4ee0220f..054a058c18 100644 --- a/tools/network-bootstrapper/src/main/kotlin/net/corda/bootstrapper/NetworkBuilder.kt +++ b/tools/network-bootstrapper/src/main/kotlin/net/corda/bootstrapper/NetworkBuilder.kt @@ -7,7 +7,6 @@ import net.corda.bootstrapper.notaries.NotaryCopier import net.corda.bootstrapper.notaries.NotaryFinder import java.io.File import java.util.concurrent.CompletableFuture -import java.util.concurrent.ConcurrentHashMap interface NetworkBuilder { @@ -23,7 +22,6 @@ interface NetworkBuilder { fun onNodePushed(callback: (PushedNode) -> Unit): NetworkBuilder fun onNodeInstance(callback: (NodeInstance) -> Unit): NetworkBuilder - fun withNodeCounts(map: Map): NetworkBuilder fun withNetworkName(networtName: String): NetworkBuilder fun withBasedir(baseDir: File): NetworkBuilder fun withBackend(backendType: Backend.BackendType): NetworkBuilder @@ -104,11 +102,6 @@ private class NetworkBuilderImpl : NetworkBuilder { return this } - override fun withNodeCounts(map: Map): NetworkBuilder { - nodeCounts = ConcurrentHashMap(map.entries.map { it.key.toLowerCase() to it.value }.toMap()) - return this - } - override fun withNetworkName(networtName: String): NetworkBuilder { this.networkName = networtName return this diff --git a/tools/network-bootstrapper/src/main/kotlin/net/corda/bootstrapper/cli/CommandLineInterface.kt b/tools/network-bootstrapper/src/main/kotlin/net/corda/bootstrapper/cli/CommandLineInterface.kt index 8ea71b8a43..5a385dbd6d 100644 --- a/tools/network-bootstrapper/src/main/kotlin/net/corda/bootstrapper/cli/CommandLineInterface.kt +++ b/tools/network-bootstrapper/src/main/kotlin/net/corda/bootstrapper/cli/CommandLineInterface.kt @@ -8,6 +8,7 @@ import net.corda.bootstrapper.context.Context import net.corda.bootstrapper.nodes.NodeAdder import net.corda.bootstrapper.nodes.NodeInstantiator import net.corda.bootstrapper.toSingleFuture +import net.corda.core.identity.CordaX500Name import net.corda.core.utilities.getOrThrow import java.io.File @@ -23,7 +24,6 @@ class CommandLineInterface { val (_, context) = NetworkBuilder.instance() .withBasedir(baseDir) .withNetworkName(networkName) - .withNodeCounts(parsedArgs.nodes) .onNodeBuild { builtNode -> println("Built node: ${builtNode.name} to image: ${builtNode.localImageId}") } .onNodePushed { pushedNode -> println("Pushed node: ${pushedNode.name} to: ${pushedNode.remoteImageName}") } .onNodeInstance { instance -> @@ -40,7 +40,7 @@ class CommandLineInterface { val (_, instantiator, _) = Backend.fromContext(context, cacheDir) val nodeAdder = NodeAdder(context, NodeInstantiator(instantiator, context)) parsedArgs.nodesToAdd.map { - nodeAdder.addNode(context, Constants.ALPHA_NUMERIC_ONLY_REGEX.replace(it.toLowerCase(), "")) + nodeAdder.addNode(context, Constants.ALPHA_NUMERIC_ONLY_REGEX.replace(it.key.toLowerCase(), ""), CordaX500Name.parse(it.value)) }.toSingleFuture().getOrThrow() persistContext(contextFile, objectMapper, context) } diff --git a/tools/network-bootstrapper/src/main/kotlin/net/corda/bootstrapper/cli/CommandParsers.kt b/tools/network-bootstrapper/src/main/kotlin/net/corda/bootstrapper/cli/CommandParsers.kt index 9eb7305bd5..3bf543f6da 100644 --- a/tools/network-bootstrapper/src/main/kotlin/net/corda/bootstrapper/cli/CommandParsers.kt +++ b/tools/network-bootstrapper/src/main/kotlin/net/corda/bootstrapper/cli/CommandParsers.kt @@ -20,11 +20,9 @@ open class CliParser { @Option(names = ["-b", "--backend"], description = ["The backend to use when instantiating nodes"]) var backendType: Backend.BackendType = Backend.BackendType.LOCAL_DOCKER - @Option(names = ["--nodes"], split = ":", description = ["The number of each node to create. NodeX:2 will create two instances of NodeX"]) - var nodes: MutableMap = hashMapOf() - @Option(names = ["--add", "-a"]) - var nodesToAdd: MutableList = arrayListOf() + @Option(names = ["--add"], split = ":", description = ["The node to add. Format is :. Eg; \"Node1:O=Bank A, L=New York, C=US, OU=Org Unit, CN=Service Name\""]) + var nodesToAdd: MutableMap = hashMapOf() fun isNew(): Boolean { return nodesToAdd.isEmpty() diff --git a/tools/network-bootstrapper/src/main/kotlin/net/corda/bootstrapper/gui/BootstrapperView.kt b/tools/network-bootstrapper/src/main/kotlin/net/corda/bootstrapper/gui/BootstrapperView.kt index d9eaee3e04..750185e254 100644 --- a/tools/network-bootstrapper/src/main/kotlin/net/corda/bootstrapper/gui/BootstrapperView.kt +++ b/tools/network-bootstrapper/src/main/kotlin/net/corda/bootstrapper/gui/BootstrapperView.kt @@ -21,6 +21,7 @@ import net.corda.bootstrapper.baseArgs import net.corda.bootstrapper.context.Context import net.corda.bootstrapper.nodes.* import net.corda.bootstrapper.notaries.NotaryFinder +import net.corda.core.identity.CordaX500Name import org.apache.commons.lang3.RandomStringUtils import org.controlsfx.control.SegmentedButton import tornadofx.* @@ -70,7 +71,6 @@ class BootstrapperView : View("Corda Network Builder") { } } - val nodeCount = controller.foundNodes.map { it.id to it.count }.toMap() val result = NetworkBuilder.instance() .withBasedir(controller.baseDir.get()) .withNetworkName(networkName) @@ -81,7 +81,6 @@ class BootstrapperView : View("Corda Network Builder") { .onNodeInstancesRequested(controller::addInstanceRequests) .onNodeInstance(controller::addInstance) .withBackend(selectedBackEnd) - .withNodeCounts(nodeCount) .withBackendOptions(backendParams) .build() @@ -118,6 +117,10 @@ class BootstrapperView : View("Corda Network Builder") { enableWhen { controller.networkContext.isNotNull } action { templateChoiceBox.selectionModel.selectedItem?.let { nodeToAdd -> + + val textInputDialog = TextInputDialog("O=Bank A, L=New York, C=US, OU=Org Unit, CN=Service Name") + textInputDialog.title = "X500 of node to add" + val x500ToUse = textInputDialog.showAndWait().orElseGet { null } val context = controller.networkContext.value runLater { val (_, instantiator, _) = Backend.fromContext( @@ -125,7 +128,7 @@ class BootstrapperView : View("Corda Network Builder") { File(controller.baseDir.get(), Constants.BOOTSTRAPPER_DIR_NAME)) val nodeAdder = NodeAdder(context, NodeInstantiator(instantiator, context)) controller.addInstanceRequest(nodeToAdd) - nodeAdder.addNode(context, nodeToAdd).handleAsync { instanceInfo, t -> + nodeAdder.addNode(context, nodeToAdd, x500ToUse?.let { CordaX500Name.parse(it) }).handleAsync { instanceInfo, t -> t?.let { GuiUtils.showException("Failed", "Failed to add node", it) } @@ -263,10 +266,6 @@ class BootstrapperView : View("Corda Network Builder") { compareValues(o1.nodeType.toString() + o1.templateId, o2.nodeType.toString() + o2.templateId) * -1 }) - fun clear() { - networkContext.set(null) - } - fun clearAll() { networkContext.set(null) foundNodes.clear() diff --git a/tools/network-bootstrapper/src/main/kotlin/net/corda/bootstrapper/nodes/NodeAdder.kt b/tools/network-bootstrapper/src/main/kotlin/net/corda/bootstrapper/nodes/NodeAdder.kt index 4de0d53ebe..c90ea6e3ac 100644 --- a/tools/network-bootstrapper/src/main/kotlin/net/corda/bootstrapper/nodes/NodeAdder.kt +++ b/tools/network-bootstrapper/src/main/kotlin/net/corda/bootstrapper/nodes/NodeAdder.kt @@ -2,17 +2,18 @@ package net.corda.bootstrapper.nodes import net.corda.bootstrapper.containers.instance.InstanceInfo import net.corda.bootstrapper.context.Context +import net.corda.core.identity.CordaX500Name import java.util.concurrent.CompletableFuture class NodeAdder(val context: Context, val nodeInstantiator: NodeInstantiator) { - fun addNode(context: Context, nodeGroupName: String): CompletableFuture { + fun addNode(context: Context, nodeGroupName: String, x500ToAdd: CordaX500Name?): CompletableFuture { return synchronized(context) { val nodeGroup = context.nodes[nodeGroupName]!! val nodeInfo = nodeGroup.iterator().next() val currentNodeSize = nodeGroup.size - val newInstanceX500 = nodeInfo.groupX500!!.copy(commonName = nodeInfo.groupX500.commonName + (currentNodeSize)).toString() + val newInstanceX500 = x500ToAdd?.toString() ?: nodeInfo.groupX500!!.copy(commonName = nodeInfo.groupX500.commonName + (currentNodeSize)).toString() val newInstanceName = nodeGroupName + (currentNodeSize) val nextNodeInfo = nodeInfo.copy( instanceX500 = newInstanceX500, diff --git a/tools/network-bootstrapper/src/main/kotlin/net/corda/bootstrapper/nodes/NodeBuilder.kt b/tools/network-bootstrapper/src/main/kotlin/net/corda/bootstrapper/nodes/NodeBuilder.kt index 9b55321cdd..bf67ee336a 100644 --- a/tools/network-bootstrapper/src/main/kotlin/net/corda/bootstrapper/nodes/NodeBuilder.kt +++ b/tools/network-bootstrapper/src/main/kotlin/net/corda/bootstrapper/nodes/NodeBuilder.kt @@ -21,10 +21,10 @@ open class NodeBuilder { val copiedNodeConfig = copiedNode.copiedNodeConfig val nodeDir = copiedNodeConfig.parentFile if (!copiedNodeConfig.exists()) { - throw IllegalStateException("There is no nodeConfig for dir: " + copiedNodeConfig) + throw IllegalStateException("There is no nodeConfig for dir: $copiedNodeConfig") } val nodeConfig = ConfigFactory.parseFile(copiedNodeConfig) - LOG.info("starting to build docker image for: " + nodeDir) + LOG.info("starting to build docker image for: $nodeDir") val nodeImageId = localDockerClient.buildImageCmd() .withDockerfile(File(nodeDir, "Dockerfile")) .withBaseDirectory(nodeDir)