camel-spring与jms的远程处理-不明确的方法调用

ss2ws0br  于 2021-07-13  发布在  Java
关注(0)|答案(0)|浏览(197)

我试图理解基于camel的bean和spring远程处理。
我创建了两个项目:
其中一个充当带有嵌入式activemq的服务器
另一个充当客户端,使用camel-spring远程代理使用接口。
服务器端接口是deliveryservice,它由deliveryserviceimpl类实现,该类有两个重载了不同方法签名的方法。使用下面列出的代码,独立服务器运行时不会出现任何问题。
方法实现并从客户端调用。

String updateDelivery(String address);
     String updateDelivery(String address, String zipCode);

在客户端,包含接口,并将其注入到实际调用方法的bean中。下面是它的xml配置。

<camel:proxy id="deliveryService" serviceInterface="com.remote.client.DeliveryService" serviceUrl="direct:input"/>

    <bean id="deliveryInfo" class="com.remote.client.UpdateDeliveryDetailsFromClient">
       <property name="deliveryService" ref="deliveryService" />
    </bean>

现在,当我执行客户机时,我看到服务器端正在被调用,但正在接收 Ambiguous method invocation 例外。

org.apache.camel.component.bean.AmbiguousMethodCallException: Ambiguous method invocations possible: [public java.lang.String com.springremote.srvr.DeliveryServiceImpl.updateDelivery(java.lang.String), public java.lang.String com.springremote.srvr.DeliveryServiceImpl.updateDelivery(java.lang.String,java.lang.String)] on the exchange: Exchange[ID-thirumurthi-HP-1615077478318-0-1]

根据文档,我希望camel beanprocesser能够调用正确的方法。
通过一点挖掘,我注意到当使用多个参数调用接口时,客户端无法转换。下面是客户端日志

TIME STARTED : ======> 2021-03-06T22:14:12.142636200
22:14| INFO | CamelLogger.java 158 | client side log :ID-thirumurthi-HP-1615097652037-0-2 ==  Renton
... the result updating address : Renton
22:14| INFO | CamelLogger.java 158 | client side log :ID-thirumurthi-HP-1615097652037-0-4 ==  [Ljava.lang.Object;@6f70a21b
... the result updating address zip both : [Ljava.lang.Object;@6f70a21b

我有几个问题:
在客户端,我在updatedeliverydetailsfromclient.java类中自动连接了deliveryservice接口,但是spring无法解析它,因为bean在其中 <camel:proxy.. . 有没有办法使用@autowired注解在这里注入bean?
当调用方法具有不同的方法签名时,为什么camel不能在这里识别正确的bean方法我可以尝试其他选项,如在camel头中指定方法名称或直接调用方法。)
注意:当我尝试在接口中使用一个方法时,流工作正常。
详细的日志异常在底部。

服务器项目代码

package com.springremote.srvr;
public interface DeliveryService {

     String updateDelivery(String address);
     String updateDelivery(String address, String zipCode);
}
package com.springremote.srvr;
import org.apache.camel.Handler;
public class DeliveryServiceImpl implements DeliveryService{

    @Override
    public String updateDelivery(String address) {
        return "<< SERVER >> : Delivery Info updated with address ONLY : "+address;
    }

    @Override
    public String updateDelivery(String address, String zipCode) {
        return "<< SERVER>> :Delivery Info updated with address & zip :"+address +" & " + zipCode;
    }  
}

spring dsl上下文xml(file:context-springremote-server.xml)

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:broker="http://activemq.apache.org/schema/core"
    xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://camel.apache.org/schema/spring
http://camel.apache.org/schema/spring/camel-spring.xsd
http://activemq.apache.org/schema/core
http://activemq.apache.org/schema/core/activemq-core.xsd">

    <import resource="activemq-broker.xml" />
    <bean id="deliveryService" class="com.springremote.srvr.DeliveryServiceImpl" />

  <!--  Don't use org.apache.activemq.camel.component.ActiveMQComponent since this is part of older activemq-camel dependency and doesn't working with camel 3.0+ -->
    <bean id="activemq" class="org.apache.camel.component.activemq.ActiveMQComponent">
        <property name="brokerURL" value="tcp://localhost:61616" />
    </bean>
    <camelContext id="camel" xmlns="http://camel.apache.org/schema/spring">
        <route>
            <from uri="activemq:queue:example" />
            <log message="serverside log => ${header.camelFileName} = ${body}" />
            <to uri="bean:deliveryService" /> 
        </route>
    </camelContext>
</beans>

activemq-borker.xml文件

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:broker="http://activemq.apache.org/schema/core"
       xsi:schemaLocation="
         http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
         http://activemq.apache.org/schema/core http://activemq.apache.org/schema/core/activemq-core.xsd">

    <!-- setup a real ActiveMQ broker which listen on port 61616 -->
    <broker:broker useJmx="false" persistent="false" brokerName="myBroker">
        <broker:transportConnectors>
            <broker:transportConnector name="tcp" uri="tcp://localhost:61616"/>
        </broker:transportConnectors>
    </broker:broker>
</beans>

我在类路径中有一个log4j.properties文件。
我使用main()方法用下面的代码执行了这个服务器。这一切如期而至。

package com.springremote.srvr;
import org.apache.camel.main.Main;
import org.apache.camel.spring.SpringCamelContext;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class DeliveryServiceServerUsingCamel3Main {

    public static void main(String[] args) {
        Main mainapp= new Main();
        ApplicationContext context = new ClassPathXmlApplicationContext(
                "context-springremote-server.xml");
        SpringCamelContext camelContext = (SpringCamelContext)context.getBean("camel");
        mainapp.addConfiguration(camelContext);     
        try {
            mainapp.run();
        } catch (Exception e) {
            e.printStackTrace();
        }       
    }
}

客户端代码

package com.remote.client;
public interface DeliveryService {
     String updateDelivery(String address);
     String updateDelivery(String address, String zipCode);
}
package com.remote.client;
import org.springframework.beans.factory.annotation.Autowired;
public class UpdateDeliveryDetailsFromClient {
    // Didn't include the getter setter method here.
    DeliveryService deliveryService;

    public String updateDelivery(String updateInfo) {
        return this.getDeliveryService().updateDelivery(updateInfo);
    }

    public String updateDelivery(String address, String zipCode) {
        return this.getDeliveryService().updateDelivery(address,zipCode);
    }
}

上下文文件名delivery-service-client-remote-context.xml

<!-- <beans tag not included, it is mostly the same as in the server side context.xml-->    
    <bean id="activemq" class="org.apache.camel.component.activemq.ActiveMQComponent">
        <property name="brokerURL" value="tcp://localhost:61616"/>
    </bean>
    <camel:proxy id="deliveryService" serviceInterface="com.remote.client.DeliveryService" serviceUrl="direct:input"/>

    <bean id="deliveryInfo" class="com.remote.client.UpdateDeliveryDetailsFromClient">
       <property name="deliveryService" ref="deliveryService" />
    </bean>

    <camelContext id="camel" xmlns="http://camel.apache.org/schema/spring">
        <route>
            <from uri="direct:input" />
            <log message="client side log : ${body}"/>
            <to uri="activemq:queue:example" />
        </route>
    </camelContext>
</beans>

调用接口方法的独立客户端代码

package com.remote.client;
import java.time.LocalDateTime;
import org.apache.camel.ProducerTemplate;
import org.apache.camel.impl.engine.DefaultProducerTemplate;
import org.apache.camel.spring.SpringCamelContext;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class DeliveryServiceClientMainSeperateVM {

    public static void main(String[] args) throws Exception{

       ApplicationContext appContext = new ClassPathXmlApplicationContext("delivery-service-client-remote-context.xml");
        SpringCamelContext camelContext = (SpringCamelContext)appContext.getBean("camel");
        try {
            System.out.println("STARTED @ : ======> "+LocalDateTime.now());
            camelContext.start();          

            UpdateDeliveryDetailsFromClient shipmentReceiver = camelContext.getRegistry().lookupByNameAndType("deliveryInfo",UpdateDeliveryDetailsFromClient.class);
            String updateStatus = shipmentReceiver.updateDelivery("Renton");
            System.out.println("... the result updating address : " + updateStatus);
            updateStatus = shipmentReceiver.updateDelivery("Renton","98055");
            System.out.println("... the result updating address zip both : " + updateStatus);
            Thread.sleep(15000);
            System.out.println("STOPPED @ : ========> "+LocalDateTime.now());
        } finally {
            camelContext.stop();
        }    
    }
}

日志详细信息:

org.apache.camel.component.bean.AmbiguousMethodCallException: Ambiguous method invocations possible: [public java.lang.String com.springremote.srvr.DeliveryServiceImpl.updateDelivery(java.lang.String), public java.lang.String com.springremote.srvr.DeliveryServiceImpl.updateDelivery(java.lang.String,java.lang.String)] on the exchange: Exchange[ID-thirumurthi-HP-1615077478318-0-1]
    at org.apache.camel.component.bean.BeanInfo.chooseBestPossibleMethodInfo(BeanInfo.java:871)
    at org.apache.camel.component.bean.BeanInfo.chooseMethodWithMatchingBody(BeanInfo.java:800)
    at org.apache.camel.component.bean.BeanInfo.chooseMethod(BeanInfo.java:634)
    at org.apache.camel.component.bean.BeanInfo.createInvocation(BeanInfo.java:286)
    at org.apache.camel.component.bean.BeanInfo.createInvocation(BeanInfo.java:186)
    at org.apache.camel.component.bean.AbstractBeanProcessor.process(AbstractBeanProcessor.java:129)
    at org.apache.camel.component.bean.BeanProcessor.process(BeanProcessor.java:55)
    at org.apache.camel.component.bean.BeanProducer.process(BeanProducer.java:41)
    at org.apache.camel.processor.SendProcessor.process(SendProcessor.java:134)
    at org.apache.camel.processor.errorhandler.RedeliveryErrorHandler$RedeliveryState.run(RedeliveryErrorHandler.java:476)
    at org.apache.camel.impl.engine.DefaultReactiveExecutor$Worker.schedule(DefaultReactiveExecutor.java:185)
    at org.apache.camel.impl.engine.DefaultReactiveExecutor.scheduleMain(DefaultReactiveExecutor.java:59)
    at org.apache.camel.processor.Pipeline.process(Pipeline.java:87)
    at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:228)
    at org.apache.camel.impl.engine.DefaultAsyncProcessorAwaitManager.process(DefaultAsyncProcessorAwaitManager.java:78)
    at org.apache.camel.support.AsyncProcessorSupport.process(AsyncProcessorSupport.java:40)
    at org.apache.camel.component.jms.EndpointMessageListener.onMessage(EndpointMessageListener.java:129)
    at org.springframework.jms.listener.AbstractMessageListenerContainer.doInvokeListener(AbstractMessageListenerContainer.java:736)
    at org.springframework.jms.listener.AbstractMessageListenerContainer.invokeListener(AbstractMessageListenerContainer.java:696)
    at org.springframework.jms.listener.AbstractMessageListenerContainer.doExecuteListener(AbstractMessageListenerContainer.java:674)
    at org.springframework.jms.listener.AbstractPollingMessageListenerContainer.doReceiveAndExecute(AbstractPollingMessageListenerContainer.java:318)
    at org.springframework.jms.listener.AbstractPollingMessageListenerContainer.receiveAndExecute(AbstractPollingMessageListenerContainer.java:257)
    at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.invokeListener

暂无答案!

目前还没有任何答案,快来回答吧!

相关问题