Как отправить ответ обратно в интерфейс шлюза?

В настоящее время я получаю эту ошибку:

 DestinationResolutionException: 
     no output-channel or replyChannel header available .  

У меня есть файловый шлюз, который внедрен в контроллер

@MessagingGateway
public interface FileGateway {
    @Gateway(requestChannel = "router.input", replyChannel = "output")
    FileRequestResponse requestFile(FileRequestRequest fileFetchRequest);
}

и маршрутизатор, который отправляет сообщения на соответствующие каналы

@Bean
IntegrationFlow routeFileRequest() {
    return IntegrationFlows.from("router.input")
            .<FileRequestRequest, FileType>route(m -> m.getParameters().getFileType(), m -> m
                    .channelMapping(FileType.CONTRACT, "contract.transform")
                    .channelMapping(FileType.INVOICE, "invoice.tranform"))
            // .channelMapping(FileType.USAGE, "usageChannel"))
            .get();
}

Здесь мой bean-компонент-трансформер преобразует сообщение в строку и отправляет в канал contract.input, я вижу в своих журналах, что сообщение приходит, контракт, входной канал, однако после ответа в методе обработчика я получаю:

org.springframework.messaging.core.DestinationResolutionException:
    no output-channel or replyChannel header available. 

Трансформатор:

@Transformer(inputChannel = "contract.transform", outputChannel = "contract.input")
public Message<String> transformContractMessage(Message<FileRequestRequest> request) {
    /**
     *
     *  @param request
     *  @return contractId
     */
    FileRequestRequest frr = request.getPayload();

    return MessageBuilder.
            withPayload(request.
                    getPayload().getContractId()).
            setHeader("fileType", "CONTRACT").build();
}

Ниже приведен активатор службы для отправки сообщения обратно на router.output, однако я обнаружил это исключение выше.

@ServiceActivator(inputChannel = "contract.input" ,outputChannel = "output")
public FileRequestResponse res(Message<String> message){
    log.info(" Retrieving File With Contract ID {} ",message.getPayload());
    ContractRsp contractResponse = contractFetchService.retrieveContract(message.getPayload());
    log.info(" Contract File Received {} ",contractResponse);

    return FileRequestResponse.builder().build();
}
@Bean
public DirectChannel output(){
    DirectChannel channel = new DirectChannel();

    return channel;
}

Моя цель здесь - вернуть сообщение в интерфейс FileGateway после ответа.


person user2041176    schedule 27.09.2019    source источник


Ответы (1)


Шлюз - это компонент запроса-ответа, и для корреляции между ними заголовок replyChannel с TemporaryReplyChannel заполняется во время отправки сообщения в requestChannel.

Это четко объясняется в Справочнике. Руководство.

Таким образом, даже если вы предоставите этот replyChannel = "output" и используете его где-то ниже по течению, replyChannel должен сохраниться в заголовках.

Код вашей проблемы находится здесь, в @Transformer:

return MessageBuilder.
        withPayload(request.
                getPayload().getContractId()).
        setHeader("fileType", "CONTRACT").build();

Вы создаете новое сообщение и не копируете заголовок запроса для его replyChannel.

В отличие от многих других компонентов (например, @ServiceActivator), преобразователь не копирует заголовки в ответное сообщение, если из функции преобразования возвращается экземпляр Message.

Итак, вам нужно подумать о том, чтобы добавить в свой код вот это: copyHeaders(request.getHeaders())

person Artem Bilan    schedule 27.09.2019
comment
Что ж, вам нужно вернуть из этого метода преобразователя просто payload или сообщение, но с скопированными заголовками запроса. - person Artem Bilan; 27.09.2019