1

虽然服务只有 1 个参数,但在将 spring 与 kotlin 组合使用时,我总是遇到参数不匹配。我还调试 org.springframework.remoting.support.RemoteInvocation.invoke了方法,我可以看到它恰好传递了 1 个参数和正确的 targetObject。但invoke(targetObject, this.arguments); 导致参数不匹配。

源代码:

https://github.com/c-nnooka/RabbitMqRemotingKotlin

例外

Caused by: **java.lang.Throwable: argument type mismatch**
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_161]
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:1.8.0_161]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.8.0_161]
    at java.lang.reflect.Method.invoke(Method.java:498) ~[?:1.8.0_161]
    at org.springframework.remoting.support.RemoteInvocation.invoke(RemoteInvocation.java:215) ~[spring-context-5.0.4.RELEASE.jar:5.0.4.RELEASE]
    at org.springframework.remoting.support.DefaultRemoteInvocationExecutor.invoke(DefaultRemoteInvocationExecutor.java:39) ~[spring-context-5.0.4.RELEASE.jar:5.0.4.RELEASE]
    at org.springframework.remoting.support.RemoteInvocationBasedExporter.invoke(RemoteInvocationBasedExporter.java:78) ~[spring-context-5.0.4.RELEASE.jar:5.0.4.RELEASE]
    at org.springframework.remoting.support.RemoteInvocationBasedExporter.invokeAndCreateResult(RemoteInvocationBasedExporter.java:114) ~[spring-context-5.0.4.RELEASE.jar:5.0.4.RELEASE]
    at org.springframework.amqp.remoting.service.AmqpInvokerServiceExporter.onMessage(AmqpInvokerServiceExporter.java:80) ~[spring-amqp-2.0.2.RELEASE.jar:2.0.2.RELEASE]
    at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.doInvokeListener(AbstractMessageListenerContainer.java:1457) ~[spring-rabbit-2.0.2.RELEASE.jar:2.0.2.RELEASE]
    at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.actualInvokeListener(AbstractMessageListenerContainer.java:1348) ~[spring-rabbit-2.0.2.RELEASE.jar:2.0.2.RELEASE]
    at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.invokeListener(AbstractMessageListenerContainer.java:1324) ~[spring-rabbit-2.0.2.RELEASE.jar:2.0.2.RELEASE]
    at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.executeListener(AbstractMessageListenerContainer.java:1303) ~[spring-rabbit-2.0.2.RELEASE.jar:2.0.2.RELEASE]
    at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.doReceiveAndExecute(SimpleMessageListenerContainer.java:785) ~[spring-rabbit-2.0.2.RELEASE.jar:2.0.2.RELEASE]
    at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.receiveAndExecute(SimpleMessageListenerContainer.java:769) ~[spring-rabbit-2.0.2.RELEASE.jar:2.0.2.RELEASE]
    at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.access$700(SimpleMessageListenerContainer.java:77) ~[spring-rabbit-2.0.2.RELEASE.jar:2.0.2.RELEASE]
    at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer$AsyncMessageProcessingConsumer.run(SimpleMessageListenerContainer.java:1010) ~[spring-rabbit-2.0.2.RELEASE.jar:2.0.2.RELEASE]
    at java.lang.Thread.run(Thread.java:748) ~[?:1.8.0_161]
    at org.springframework.remoting.support.RemoteInvocationUtils.fillInClientStackTraceIfPossible(RemoteInvocationUtils.java:45) ~[spring-context-5.0.4.RELEASE.jar:5.0.4.RELEASE]
    at org.springframework.remoting.support.RemoteInvocationResult.recreate(RemoteInvocationResult.java:156) ~[spring-context-5.0.4.RELEASE.jar:5.0.4.RELEASE]
    at org.springframework.amqp.remoting.client.AmqpClientInterceptor.invoke(AmqpClientInterceptor.java:78) ~[spring-amqp-2.0.2.RELEASE.jar:2.0.2.RELEASE]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185) ~[spring-aop-5.0.4.RELEASE.jar:5.0.4.RELEASE]
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212) ~[spring-aop-5.0.4.RELEASE.jar:5.0.4.RELEASE]
    at com.sun.proxy.$Proxy108.findJobById(Unknown Source) ~[?:?]

接口细节:

interface IJobQueryService{

    fun findJobById(args : QueryJobArgs) : QueryJobResponse

}

interface IJobService : IJobQueryService

服务实施细节:

class JobController(val jobQueryService: IJobQueryService) : IJobService{


    override fun findJobById(args: QueryJobArgs): QueryJobResponse {
        return jobQueryService.findJobById(args)
    }


}

BeanConfiguration:(注意:为简单起见未指定完整配置)

    @Bean
    fun rmsExporter(rabbitTemplate: RabbitTemplate):AmqpInvokerServiceExporter {
        val exporter = AmqpInvokerServiceExporter();
        exporter.amqpTemplate = rabbitTemplate;
        exporter.service = JobController(JobQueryProvider());
        exporter.serviceInterface = IJobService::class.java
        exporter.messageConverter = producerJackson2MessageConverter()
        return exporter;
    }

    @Bean
    fun rmxProxy(rabbitTemplate: RabbitTemplate) : AmqpProxyFactoryBean {
        val proxy = AmqpProxyFactoryBean();
        proxy.amqpTemplate = rabbitTemplate;
        proxy.serviceInterface = IJobService::class.java
        proxy.routingKey = "rms.webservice.api"
        return proxy;
    }

调用详细信息

val jobservice  = applicationContext.getBean(IJobService::class.java)

println("Remoting Is On => " +  jobservice.findJobById(QueryJobArgs().apply { job = Job().apply { id = 1 } } ))
4

1 回答 1

2

您尝试通过网络传输 JSON 的问题。

因此,AmqpClientInterceptor将您包装QueryJobArgsRemoteInvocation对象中,并且已经将其序列化为 JSON,例如:

(Body:'{"methodName":"findJobById","parameterTypes":["com.example.rabbiitmqremoting.args.job.QueryJobArgs"],"arguments":[{"job":{"id":1,"createdBy":null}}],"attributes":null}' MessageProperties [headers={__TypeId__=org.springframework.remoting.support.RemoteInvocation}, contentType=application/json, contentEncoding=UTF-8, contentLength=167, deliveryMode=PERSISTENT, priority=0, deliveryTag=0])

注意__TypeId__=org.springframework.remoting.support.RemoteInvocation标题。这个用于消费者端将内容反序列化为RemoteInvocation. 但是由于没有(自动)信息arguments可以反序列化到它们,所以QueryJobArgs它们仍然是LinkedHashMap. 因此Caused by: java.lang.Throwable: argument type mismatch

作为一种解决方法,我建议您回到SimpleMessageConverter将使用标准 Java 序列化机制的那个。

更新

好的!你知道我也用 JSON 破解了这个。

所以,我这样做了:

@Autowired
lateinit var objectMapper: ObjectMapper

@PostConstruct
fun init() {
    this.objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY)
}

并将其注入objectMapperJackson您的RabbitConfig. 现在它按预期工作,我假设:

Hellow From RMS
Remoting Is On => com.example.rabbiitmqremoting.response.QueryJobResponse@151bf776

我还删除了与messageHandlerMethodFactory. 看起来它不涉及 RPC。但是,您可能需要它来处理其他一些事情。不同的故事虽然...

于 2018-04-13T18:28:40.790 回答