user2041176
user2041176

Reputation: 35

How do i send response back to Gateway interface?

im currently getting this error :

 DestinationResolutionException: 
     no output-channel or replyChannel header available .  

I have a file gateway that is injected in a controller

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

and a router that send messages to respective channels

@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();
}

Here my transformer bean , converts message to string and sends to contract.input channel , i can see in my logs that message arrives contract,input channel , however after response in handler method i get:

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

Transformer:

@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();
}

Below is the service activator to send message back to router.output , however i encounter that exception above .

@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;
}

My aim here is to get message back to FileGateway interface after response .

Upvotes: 0

Views: 328

Answers (1)

Artem Bilan
Artem Bilan

Reputation: 121272

The gateway is a request-reply component and for correlation between them a replyChannel header with a TemporaryReplyChannel is populated during sending a message into a requestChannel.

This is clearly explained in the Reference Manual.

So, even if you provide that replyChannel = "output" and use it somewhere downstream, a replyChannel must preserve in the headers.

Your problem code is here in the @Transformer:

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

You build a new message and don't copy request header to curry that replyChannel.

Unlike many other components (e.g. @ServiceActivator), a transformer doesn't copy headers into a reply message if a Message instance is returned from the transformation function.

So, you need to consider to add into your code over there this: copyHeaders(request.getHeaders())

Upvotes: 1

Related Questions