From e8914b9e18279931c708d5c4054b800e127ffe8a Mon Sep 17 00:00:00 2001 From: Parth Shukla Date: Sun, 3 Jan 2021 16:09:50 +0530 Subject: [PATCH 1/2] resolves #4, resolves #9, resolves #10, resolves #11 fixes for various issues based on testing with obligation cordapp --- build.gradle | 2 +- bundle-rest-embedded/build.gradle | 2 +- .../b180/cordaptor/corda/ReflectionUtils.kt | 3 ++- .../cordaptor/rest/CordaTypesSerializers.kt | 22 +++++++++++++++++++ .../b180/cordaptor/rest/GenericSerializers.kt | 5 ++++- .../tech/b180/cordaptor/rest/KoinModule.kt | 1 + .../b180/cordaptor/rest/CordaTypesTest.kt | 17 ++++++++++++++ tar/build.gradle | 10 +++++++++ 8 files changed, 58 insertions(+), 4 deletions(-) diff --git a/build.gradle b/build.gradle index 7f8ed93..ecea353 100644 --- a/build.gradle +++ b/build.gradle @@ -136,7 +136,7 @@ configure(moduleProjects) { } signing { - required { version.endsWith('SNAPSHOT') } + required { !version.endsWith('SNAPSHOT') } sign publishing.publications.maven } } diff --git a/bundle-rest-embedded/build.gradle b/bundle-rest-embedded/build.gradle index fe986fa..21673a6 100644 --- a/bundle-rest-embedded/build.gradle +++ b/bundle-rest-embedded/build.gradle @@ -3,7 +3,7 @@ apply plugin: 'net.corda.plugins.cordapp' cordapp { targetPlatformVersion 7 - minimumPlatformVersion 7 + minimumPlatformVersion 6 workflow { // must be kept in sync with koin.properties name "cordaptor-embedded-bundle" diff --git a/corda-common/src/main/kotlin/tech/b180/cordaptor/corda/ReflectionUtils.kt b/corda-common/src/main/kotlin/tech/b180/cordaptor/corda/ReflectionUtils.kt index 6accea7..0c876dd 100644 --- a/corda-common/src/main/kotlin/tech/b180/cordaptor/corda/ReflectionUtils.kt +++ b/corda-common/src/main/kotlin/tech/b180/cordaptor/corda/ReflectionUtils.kt @@ -2,6 +2,7 @@ package tech.b180.cordaptor.corda import net.corda.core.flows.FlowLogic import kotlin.reflect.KClass +import kotlin.reflect.full.allSupertypes /** * Unpacks reflection data about a flow class to determine its return type. @@ -12,7 +13,7 @@ import kotlin.reflect.KClass * FIXME log details of failed type discovery */ fun determineFlowResultClass(flowClass: KClass>): KClass { - val flowLogicType = flowClass.supertypes.find { it.classifier == FlowLogic::class } + val flowLogicType = flowClass.allSupertypes.find { it.classifier == FlowLogic::class } ?: throw AssertionError("Flow class $flowClass does not seem to extend FlowLogic") val flowLogicReturnType = flowLogicType.arguments.firstOrNull()?.type diff --git a/rest-endpoint/src/main/kotlin/tech/b180/cordaptor/rest/CordaTypesSerializers.kt b/rest-endpoint/src/main/kotlin/tech/b180/cordaptor/rest/CordaTypesSerializers.kt index 1d89dfe..90de9cd 100644 --- a/rest-endpoint/src/main/kotlin/tech/b180/cordaptor/rest/CordaTypesSerializers.kt +++ b/rest-endpoint/src/main/kotlin/tech/b180/cordaptor/rest/CordaTypesSerializers.kt @@ -27,6 +27,7 @@ import java.math.BigDecimal import java.math.RoundingMode import java.security.PublicKey import java.security.cert.X509Certificate +import java.time.Duration import java.time.Instant import java.time.format.DateTimeFormatter import java.util.* @@ -208,6 +209,27 @@ class JavaInstantSerializer : CustomSerializer, } } +/** + * Serializer for an [Duration] representing it as a JSON string value formatted as an ISO-8601 timestamp. + * + * @see DateTimeFormatter.ISO_INSTANT + */ +class JavaDurationSerializer : CustomSerializer, + SerializationFactory.DelegatingSerializer( + delegate = SerializationFactory.StringSerializer, + my2delegate = { this.toString() }, + delegate2my = { Duration.parse(it) } + ) { + + override fun generateSchema(generator: JsonSchemaGenerator): JsonObject { + return mapOf( + "type" to "string", + "format" to "date-time" + ).asJsonObject() + } +} + + /** * Serializer for an [AbstractParty] representing it as a JSON object containing its X.500 name. * diff --git a/rest-endpoint/src/main/kotlin/tech/b180/cordaptor/rest/GenericSerializers.kt b/rest-endpoint/src/main/kotlin/tech/b180/cordaptor/rest/GenericSerializers.kt index 871e611..33b6677 100644 --- a/rest-endpoint/src/main/kotlin/tech/b180/cordaptor/rest/GenericSerializers.kt +++ b/rest-endpoint/src/main/kotlin/tech/b180/cordaptor/rest/GenericSerializers.kt @@ -174,7 +174,7 @@ class ListSerializer private constructor( when (parameterizedType.rawType) { Collection::class.java -> ::newArrayList List::class.java -> ::newArrayList - else -> throw AssertionError("Don't know how to make instances of ${parameterizedType.rawType}") + else -> ::instantiationNotSupported } } else { throw AssertionError("Don't know how to make instances of ${collectionType.observedType}") @@ -195,6 +195,9 @@ class ListSerializer private constructor( // FIXME instantiate an array of a certain type via Java reflection fun newArray(items: List<*>): Array = TODO("Deserialization of arrays is not supported yet") + //catch all for types that do not need to be created from JSON + fun instantiationNotSupported(items: Any) = SerializationException("Type not supported") + fun iteratorOfAnArray(c: Any?) = c?.let { (c as Array<*>).iterator() } ?: throw AssertionError("Null instead of an array - unsafe code in the parent serializer") fun iteratorOfACollection(c: Any?) = c?.let { (c as Collection<*>).iterator() } diff --git a/rest-endpoint/src/main/kotlin/tech/b180/cordaptor/rest/KoinModule.kt b/rest-endpoint/src/main/kotlin/tech/b180/cordaptor/rest/KoinModule.kt index c5ac336..0b27d47 100644 --- a/rest-endpoint/src/main/kotlin/tech/b180/cordaptor/rest/KoinModule.kt +++ b/rest-endpoint/src/main/kotlin/tech/b180/cordaptor/rest/KoinModule.kt @@ -89,6 +89,7 @@ class RestEndpointModuleProvider : ModuleProvider { single { CordaTimeWindowSerializer(get()) } bind CustomSerializer::class single { JsonObjectSerializer() } bind CustomSerializer::class single { CordaOpaqueBytesSerializer() } bind CustomSerializer::class + single { JavaDurationSerializer() } bind CustomSerializer::class single { CordaFlowInstructionSerializerFactory(get()) } bind CustomSerializerFactory::class single { CordaAmountSerializerFactory(get()) } bind CustomSerializerFactory::class diff --git a/rest-endpoint/src/test/kotlin/tech/b180/cordaptor/rest/CordaTypesTest.kt b/rest-endpoint/src/test/kotlin/tech/b180/cordaptor/rest/CordaTypesTest.kt index a1d89ba..1084c4c 100644 --- a/rest-endpoint/src/test/kotlin/tech/b180/cordaptor/rest/CordaTypesTest.kt +++ b/rest-endpoint/src/test/kotlin/tech/b180/cordaptor/rest/CordaTypesTest.kt @@ -23,6 +23,7 @@ import tech.b180.cordaptor.corda.CordaNodeState import tech.b180.cordaptor.kernel.lazyGetAll import java.math.BigDecimal import java.math.RoundingMode +import java.time.Duration import java.time.Instant import java.util.* import kotlin.reflect.full.allSuperclasses @@ -275,6 +276,22 @@ class CordaTypesTest : KoinTest { assertEquals(OpaqueBytes("TEST".toByteArray(Charsets.UTF_8)), serializer.fromJson(""""VEVTVA=="""".asJsonValue())) } + + @Test + fun `test java duration serialization`() { + val serializer = getKoin().getSerializer(Duration::class) + + assertEquals("""{"type":"string","format":"date-time"}""".asJsonObject(), + serializer.generateRecursiveSchema(getKoin().get())) + + // "PT4H" is string for duration of 4 hours + assertEquals("PT4H", + serializer.toJsonString(Duration.ofHours(4))) + + assertEquals(Duration.ofHours(4), + serializer.fromJson("PT4H".asJsonValue())) + } + } data class TestFlowParam(val intParam: Int) diff --git a/tar/build.gradle b/tar/build.gradle index 149b653..59b7b4c 100644 --- a/tar/build.gradle +++ b/tar/build.gradle @@ -1,3 +1,4 @@ +import org.apache.tools.ant.filters.*; configurations { // trimming down Corda's transitive dependencies not requried for Corda RPC client to work implementation.exclude group: 'org.hibernate' @@ -57,6 +58,15 @@ task dist(type: Tar, dependsOn: [ ':corda-rpc-client:jar', ':local-cache:jar', ' } } + eachFile { file -> + // make sure scripts have UNIX endings + if (file.name.endsWith(".sh") || file.name.endsWith(".conf")) { + filter(FixCrLfFilter.class, + eol:FixCrLfFilter.CrLf.newInstance("lf")) + } + } + + into "lib", { from configurations.runtimeClasspath.files } From 7e47c27702f953e63eb6c6f3ca9f0e0d71138be7 Mon Sep 17 00:00:00 2001 From: Parth Shukla Date: Tue, 5 Jan 2021 17:52:42 +0530 Subject: [PATCH 2/2] pr comment fixes --- .../kotlin/tech/b180/cordaptor/rest/CordaTypesSerializers.kt | 4 ++-- .../test/kotlin/tech/b180/cordaptor/rest/CordaTypesTest.kt | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/rest-endpoint/src/main/kotlin/tech/b180/cordaptor/rest/CordaTypesSerializers.kt b/rest-endpoint/src/main/kotlin/tech/b180/cordaptor/rest/CordaTypesSerializers.kt index 90de9cd..1a4caf0 100644 --- a/rest-endpoint/src/main/kotlin/tech/b180/cordaptor/rest/CordaTypesSerializers.kt +++ b/rest-endpoint/src/main/kotlin/tech/b180/cordaptor/rest/CordaTypesSerializers.kt @@ -210,7 +210,7 @@ class JavaInstantSerializer : CustomSerializer, } /** - * Serializer for an [Duration] representing it as a JSON string value formatted as an ISO-8601 timestamp. + * Serializer for an [Duration] representing it as a JSON string value formatted as an ISO-8601 duration format. * * @see DateTimeFormatter.ISO_INSTANT */ @@ -224,7 +224,7 @@ class JavaDurationSerializer : CustomSerializer, override fun generateSchema(generator: JsonSchemaGenerator): JsonObject { return mapOf( "type" to "string", - "format" to "date-time" + "format" to "iso-8601-duration" ).asJsonObject() } } diff --git a/rest-endpoint/src/test/kotlin/tech/b180/cordaptor/rest/CordaTypesTest.kt b/rest-endpoint/src/test/kotlin/tech/b180/cordaptor/rest/CordaTypesTest.kt index 1084c4c..15d697a 100644 --- a/rest-endpoint/src/test/kotlin/tech/b180/cordaptor/rest/CordaTypesTest.kt +++ b/rest-endpoint/src/test/kotlin/tech/b180/cordaptor/rest/CordaTypesTest.kt @@ -281,7 +281,7 @@ class CordaTypesTest : KoinTest { fun `test java duration serialization`() { val serializer = getKoin().getSerializer(Duration::class) - assertEquals("""{"type":"string","format":"date-time"}""".asJsonObject(), + assertEquals("""{"type":"string","format":"iso-8601-duration"}""".asJsonObject(), serializer.generateRecursiveSchema(getKoin().get())) // "PT4H" is string for duration of 4 hours