我正在使用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
此外,请确保您配置了MappingJackson2HttpMessageConverter
Bean。
@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
的对象,并失败并显示给定消息。
检查您的数据结构是否确实包含您期望的类型!