【问题标题】:Corda query throws "com.fasterxml.jackson.databind.JsonMappingException: object is not an instance of declaring class"Corda 查询抛出“com.fasterxml.jackson.databind.JsonMappingException:对象不是声明类的实例”
【发布时间】:2020-10-14 14:44:21
【问题描述】:

我正在使用 example-cordapp 项目作为参考开发 cordapp。我已经能够向分类帐提交事务,甚至在节点上运行查询以查看它是否真的存在。但是,当我尝试从我的 Spring Boot 应用程序运行查询时,我收到了这个错误。

Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request 
processing failed; nested exception is 
org.springframework.http.converter.HttpMessageConversionException: JSON mapping problem: 
java.util.Collections$UnmodifiableRandomAccessList[0]->net.corda.core.contracts.StateAndRef["state"]- 
>net.corda.core.contracts.TransactionState["data"]- 
>com.mypackage.states.MyState["party"]; nested exception is 
com.fasterxml.jackson.databind.JsonMappingException: object is not an instance of declaring class 
(through reference chain: java.util.Collections$UnmodifiableRandomAccessList[0]- 
>net.corda.core.contracts.StateAndRef["state"]->net.corda.core.contracts.TransactionState["data"]- 
>com.mypackage.states.MyState["party"])] with root cause

java.lang.IllegalArgumentException: object is not an instance of declaring class
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_251]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_251]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~ 
[na:1.8.0_251]
at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_251]

这是请求代码

 @GetMapping(value = [ "/api/v1/states" ], produces = [MediaType.APPLICATION_JSON_VALUE])
fun getMyIOUs(): ResponseEntity<List<StateAndRef<MyState>>>  {
    val myStates = proxy.vaultQueryBy<MyState>().states
    return ResponseEntity.ok(myStates)
}

这是州代码

@BelongsToContract(com.sentinel.contract.SharingInformationContract::class)
class SharingInformationState(
    val party: Party,
    val dataOwnerId: Long,
    val dataBuyerId: Long,
    override val linearId: UniqueIdentifier = UniqueIdentifier()) : LinearState, QueryableState {

override val participants: List<AbstractParty> = listOf(party)


override fun generateMappedObject(schema: MappedSchema): PersistentState {
    return when (schema) {
        SharingInformationSchemaV1 -> SharingInformationSchemaV1.PersistentSharingInformation(
                party,
                dataOwnerId,
                dataBuyerId,
                linearId.id
        )
        else -> throw IllegalArgumentException("Unrecognised schema $schema")
    }
}

override fun supportedSchemas(): Iterable<MappedSchema> = listOf(SharingInformationSchemaV1)

}

互联网上关于这个问题的信息很少。有人建议它连接到类路径,那里有重复的东西,但我不知道如何检查。此外,此错误与派对类型无关。我曾尝试在聚会上添加@JsonIgnore,但随后它又抛出了另一个领域。该字段在映射模式中的持久性也无关紧要。我试过坚持而不坚持,它什么都没有改变。提前致谢!

【问题讨论】:

    标签: json spring spring-boot corda fasterxml


    【解决方案1】:

    我相信这是因为您缺少将 Corda 对象转换为 json 所需的 Corda Jackson 支持库。

    将此添加到 build.gradle 中的依赖项

    compile "net.corda:corda-jackson:$corda_release_version"
    

    https://github.com/corda/samples-java/blob/master/Advanced/auction-cordapp/client/build.gradle#L19

    另外,请确保您已配置 MappingJackson2HttpMessageConverter bean。

    @豆

    public MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter(){
        ObjectMapper mapper =  JacksonSupport.createDefaultMapper(partyAProxy());
        MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
        converter.setObjectMapper(mapper);
        return converter;
    }
    

    https://github.com/corda/samples-java/blob/master/Advanced/auction-cordapp/client/src/main/java/net/corda/samples/client/AppConfig.java#L48

    【讨论】:

    • 感谢您的建议!我真的很想念那个豆子。虽然,不幸的是,它仍然不起作用。我使用 Kotlin 插件版本 1.3.71 在 IDEA 2019 上工作。它会导致问题吗?据我阅读 Corda 取决于 1.2.71
    • 不太确定 Kotlin 插件是否有问题。您可以尝试看看这是否适合您:github.com/corda/samples-kotlin/tree/master/Advanced/…。这是我在答案中提到的示例的 kotlin 版本。
    • 如果上述方法有效,您可以确定 Kotlin 插件没有问题,您可能希望以此作为参考来验证您的代码。
    • 我决定检查我是否从节点得到了什么以及我得到了什么。所以节点返回了它应该返回的所有内容,但是由于某种原因,返回的类型没有被识别为应该的类型。例如,我尝试转换接收到的状态并得到:java.lang.ClassCastException: com.mypackage.states.SharingInformationState cannot be cast to com.mypackagel.states.SharingInformationState
    • 在您提供的示例中,Kotlin 的版本是 1.2.71。除了插件,版本是 gradle。 cordapp-example 适用于最新插件,但版本为 1.2.71
    【解决方案2】:

    java.lang.IllegalArgumentException: object is not an instance of declaring class 异常是通过对错误类型对象的反射调用方法时发生的情况。

    与杰克逊一起可能会发生,因为通用对您撒谎。这是一个例子:

    class A (val x: String)
    class B (val y: String)
    class C (val z: List<A>)
    
    ObjectMapper().writeValueAsString(C(listOf(B("x")) as List<A>))
    

    这会导致编译警告,但由于类型擦除,它会编译并最初运行。然而,我们在一个实际需要List&lt;A&gt; 的地方强行注入了List&lt;B&gt;。虽然类型擦除确实删除了相当多的信息,但它并没有完全删除。反射仍然可以用来确定C.z 实际上是List&lt;A&gt; 类型。 Jackson 使用此信息并尝试序列化 A 类型的对象,但在列表中找到 B 类型的对象并失败并显示给定消息。

    检查您的数据结构是否确实包含您期望的类型!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-08-01
      • 2017-05-05
      • 2021-11-15
      • 1970-01-01
      • 1970-01-01
      • 2017-07-03
      相关资源
      最近更新 更多