Though there is exactly 1 parameter for Service i am always hitting argument mismatch when using spring with kotlin combination.
i have also debugged
org.springframework.remoting.support.RemoteInvocation.invoke method
i could see it is passing exactly 1 argument and correct targetObject. But invoke(targetObject, this.arguments); resulted in parameter mismatch.
Source Code:
https://github.com/c-nnooka/RabbitMqRemotingKotlin
Exception
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 Details:
interface IJobQueryService{
fun findJobById(args : QueryJobArgs) : QueryJobResponse
}
interface IJobService : IJobQueryService
Service Implementation Details:
class JobController(val jobQueryService: IJobQueryService) : IJobService{
override fun findJobById(args: QueryJobArgs): QueryJobResponse {
return jobQueryService.findJobById(args)
}
}
BeanConfiguration: (Note: Not specifying complete configuration for simplicity)
@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;
}
Invocation Details
val jobservice = applicationContext.getBean(IJobService::class.java)
println("Remoting Is On => " + jobservice.findJobById(QueryJobArgs().apply { job = Job().apply { id = 1 } } ))
The problem that you try to transport JSON over the network.
Therefore an
AmqpClientInterceptorwraps yourQueryJobArgsinto theRemoteInvocationobject and already that one is serialized to the JSON like:Pay attention to the
__TypeId__=org.springframework.remoting.support.RemoteInvocationheader. This one is used on the consumer side to deserialize a content to theRemoteInvocation. But since there is no an (automatic) info for theargumentsto be deseriailized to theQueryJobArgsthey remains as aLinkedHashMap. ThereforeCaused by: java.lang.Throwable: argument type mismatch.As a workaround I suggest you to come back to the
SimpleMessageConverterwhich will use a standard Java serialization mechanism.UPDATE
OK! You know I've hacked this with the JSON as well.
So, I did this:
And injected this
objectMapperinto all theJacksonconverters presented in yourRabbitConfig. Now it works as expected I assume:Also I removed all the modifications related to the
messageHandlerMethodFactory. Doesn't look like it is involved in the RPC. However you may need it for some other stuff. Different story though...