Corda查询抛出"com.fasterxml.jackson.databind.JsonMappingException:对象不是声明类的实例"



我正在使用example-cordapp项目作为参考来开发cordapp。我已经能够将交易提交到账本,甚至在节点上运行查询以查看它是否真的存在。但是,当我尝试从我的 Spring 启动应用程序运行查询时,出现此错误。

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,但随后它会扔到另一个领域。映射架构中此字段的持久性也无关紧要。我试过坚持和不坚持,它什么也改变不了。提前感谢!

我相信这是因为您缺少将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

此外,请确保您配置了MappingJackson2HttpMessageConverterBean。

@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

异常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<A>的地方强行注入了List<B>。虽然键入擦除确实会删除相当多的信息,但它并没有完全删除。反射仍可用于确定C.z实际上是List<A>型。Jackson 使用此信息并尝试序列化类型A的对象,但在列表中找到类型B的对象,并失败并显示给定消息。

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

最新更新