I am trying to build a flow that starts with a Http.inboundGateway -> Does Several Things like Store the request data to a Database, Does Header Enrichment, Send to AMQP and returns with a Status of the flow (Successful / Failed).
I have a few things I am struggling with and am not able to figure out.
1.) Logging the Request and Response.
I have managed to log the request that the Http.inboundGateway received (See below. Not sure if that is the right way to do it but it works. Please suggest of there is a better way to do it). That said, I am not able to get a hold of the Response message that is sent to the client and also am kind of out of ideas about how to calculate the Transaction time of the flow and log it to the log file. It would be super useful IF there was a way for me to print Statistics after every transactions like "Received : 5, Success : 4, Failed : 1, Average Transaction Time : 250ms ..etc"
@Bean
public IntegrationFlow httpInboundGateway()
{
return IntegrationFlows.from(Http.inboundGateway("/httplistner")
.requestMapping(requestMapping -> requestMapping.methods(HttpMethod.POST))
.mappedRequestHeaders("*"))
.transform(new ObjectToStringTransformer())
.wireTap(flow -> flow.handle(message -> logger.info(">> Received Request from Caller.\nHeaders : "+message.getHeaders() + "\nPay Load : "+message.getPayload())))
.channel(httpRequestChannel())
.get();
}
2.) How to add log statements to a Spring DSL Flow?
I want to be able to add log statements (For Debugging) to my Integration DSL definitions so I can look at the log file and understand what happened and what went wrong. As of now, I could NOT been able to find a way to do it other than adding ".wireTap" in the middle of the flow as shown in the definition above. Please suggest if there is a better / correct way to do it.
3.) Customizing the Response sent by "Http.inboundGateway".
I could not figureout how to customize the HTTP Response that the Http.inboundGateway sends back to the clients after the flow is finished. How can I do it, or can you point me to documentation where I can read and understand how to do it? I am looking to use Spring DSL.
The same is true for Error responses also. As you can see, I have NOT added an Error Channel to my Http.inboundGateway. So if an error happens now in its current configuration, the client gets a 500 and the full stack trace. How do I get a hold of the error message and be able to buiold a custom response based on the error and send that to the client. Example : Id they sent me XML payload and the XML is malformed, I want to be able to send them a HTTP 400 with some detail in the Response indicating that their Request Data is not well formed.
The trick for capturing output is log()
followed by a "bridge to nowhere" - named because it has no output channel - so the framework sends the result back to the gateway.
Here you go...
@SpringBootApplication
public class So41990546Application {
public static void main(String[] args) {
SpringApplication.run(So41990546Application.class, args);
}
@Bean
public IntegrationFlow flow() {
return IntegrationFlows.from(Http.inboundGateway("/foo")
.requestMapping(requestMapping -> requestMapping.methods(HttpMethod.POST))
.mappedRequestHeaders("*")
.requestPayloadType(String.class))
.log(Level.INFO, m -> "Inbound: " + m.getPayload())
.<String, String>transform(String::toUpperCase)
.log(Level.INFO, m -> "Outbound: " + m.getPayload())
.bridge(e -> e.id("Bridge.to.nowhere"))
.get();
}
@Bean
public IntegrationFlow errorsFlow() {
return IntegrationFlows.from(Http.inboundGateway("/errors")
.requestMapping(requestMapping -> requestMapping.methods(HttpMethod.POST))
.mappedRequestHeaders("*")
.requestPayloadType(String.class)
.errorChannel("errors.input"))
.log(Level.INFO, m -> "Inbound: " + m.getPayload())
.transform("1 / 0")
.log(Level.INFO, m -> "Outbound: " + m.getPayload())
.bridge(e -> e.id("Another.bridge.to.nowhere"))
.get();
}
@Bean
public IntegrationFlow errors() {
return f -> f.transform("'Error: ' + payload.cause.message")
.enrichHeaders(b -> b.header(HttpHeaders.STATUS_CODE, 400))
.log(Level.INFO) // log the whole message so we can see the status code
.bridge(e -> e.id("Another.b.t.n"));
}
}
.log
was added in 1.2 and uses a wiretap underneath.
EDIT
If you use a named channel...
@Bean
public IntegrationFlow flow() {
return IntegrationFlows.from(Http.inboundGateway("/foo")
.requestMapping(requestMapping -> requestMapping.methods(HttpMethod.POST))
.mappedRequestHeaders("*")
.requestPayloadType(String.class))
.channel(namedChannel())
.log(Level.INFO, m -> "Inbound: " + m.getPayload())
.<String, String>transform(String::toUpperCase)
.log(Level.INFO, m -> "Outbound: " + m.getPayload())
.bridge(e -> e.id("Bridge.to.nowhere"))
.get();
}
public MessageChannel namedChannel() {
return new DirectChannel();
}
and enable metrics, as described in the documentation you can get all kinds of stats from that channel which will include average elapsed time for the downstream flow.