Spring integration - channel adapter vs. gateway (

2019-07-25 11:49发布

问题:

I'm confused about the difference of Channel Adapters and Gateways in spring integration. As stated in https://stackoverflow.com/a/29992267/467944 by @gary-russell channel adapters are un-diirectional while gateways are bi-directional. If this is the case, why there is a amqp inbound gateway as well as an amqp outbound gateway?

What I'm trying to accomplish in the end is the following:

  1. Http request received within a controller
  2. place message on amqp queue
  3. consumer consumes messages and put result to result queue
  4. result arrives at controller

so I'd guess I need a gateway with an interface which is called from the controller and puts the payload to the amqp queue (configured as its request channel) while it listens for its answer on the its reply-channel. However with that configuration I always end up with a

MessageDeliveryException: Dispatcher has no subscribers for channel 'application.fromRabbit'

where fromRabibbit is my reply-queue.

回答1:

You should always show configuration when asking questions like this.

Dispatcher has no subscribers...

This is a configuration error where you have not wired up your integration flow correctly.

There are two types of gateways in Spring Integration -

Gateways to interface with external systems

These provide request/reply semantics with external systems.

Inbound gateways are for server-side request/reply where the server receives a request, performs some processing and returns a reply.

Outbound gateways are the client-side equivalent where the client sends a request and waits for a reply. With AMQP, we have an async version where the reply comes back on a different thread.

Messaging Gateways

These interface-based gateways provide a gateway (usually request/reply but a method with a void result is one-way) from Java code (rather than some external system).

This enables legacy java code to use an integration-based flow.

So you might have...

controller -> gateway -> transformer(optional) -> amqp-outbound-gateway

...this is a common pattern and works well.

The server side might be

amqp-inbound-gateway -> service-activator

Show your code/config and someone can help debug your configuration problem.



回答2:

Thank you @gary-russell for the insights. I think I have the correct config now:

<?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:int="http://www.springframework.org/schema/integration"
       xmlns:int-amqp="http://www.springframework.org/schema/integration/amqp"
       xmlns:rabbit="http://www.springframework.org/schema/rabbit"
       xsi:schemaLocation="http://www.springframework.org/schema/integration/amqp http://www.springframework.org/schema/integration/amqp/spring-integration-amqp.xsd
        http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd
        http://www.springframework.org/schema/rabbit http://www.springframework.org/schema/rabbit/spring-rabbit.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">


    <!-- 'CLIENT' SIDE CONFIG -->
    <int:channel id="clientToRabbit" />
    <int:channel id="clientFromRabbit" />
    <int:gateway id="uppercaseGateway" service-interface="com.example.queuing.UpperCaseService" default-request-channel="clientToRabbit" />
    <int-amqp:outbound-gateway request-channel="clientToRabbit"  amqp-template="amqpTemplate" exchange-name="si.test.exchange" routing-key="si.test.binding" />


    <!-- 'SERVER' SIDE CONFIG -->
    <int:channel id="serverFromRabbit" />
    <int:channel id="serverToRabbit" />
    <int-amqp:inbound-gateway request-channel="serverFromRabbit" reply-channel="serverToRabbit" queue-names="si.test.queue" amqp-template="amqpTemplate" connection-factory="connectionFactory" />
    <int:service-activator input-channel="serverFromRabbit" output-channel="serverToRabbit" ref="upperCaseService" method="toUpperCase" />


    <!-- Infrastructure -->
    <rabbit:connection-factory id="connectionFactory" host="localhost" />

    <rabbit:template id="amqpTemplate" connection-factory="connectionFactory" />

    <rabbit:admin connection-factory="connectionFactory" />

    <rabbit:queue name="si.test.queue" />
    <rabbit:direct-exchange name="si.test.exchange">
        <rabbit:bindings>
            <rabbit:binding queue="si.test.queue" key="si.test.binding" />
        </rabbit:bindings>
    </rabbit:direct-exchange>
</beans>