Open jjansenvr opened 1 year ago
Currently, handling an outputstream is handled in iaf-ladybug/IbisDebuggerAdvice.debugProvideOutputStream by the following code:
/**
* Provides advice for {@link IOutputStreamingSupport#provideOutputStream(PipeLineSession session, IForwardTarget next)}
*/
public MessageOutputStream debugProvideOutputStream(ProceedingJoinPoint proceedingJoinPoint, PipeLineSession session) throws Throwable {
if (!isEnabled()) {
return (MessageOutputStream)proceedingJoinPoint.proceed();
}
String correlationId = getCorrelationId(session);
if (log.isDebugEnabled()) log.debug("debugProvideOutputStream thread id ["+Thread.currentThread().getId()+"] thread name ["+Thread.currentThread().getName()+"] correlationId ["+correlationId+"]");
if (proceedingJoinPoint.getTarget() instanceof ISender) {
ISender sender = (ISender)proceedingJoinPoint.getTarget();
// Use WriterPlaceHolder to make the contents that is later written to the MessageOutputStream appear as input of the Sender
WriterPlaceHolder writerPlaceHolder = ibisDebugger.senderInput(sender, correlationId, new WriterPlaceHolder());
MessageOutputStream resultStream = (MessageOutputStream)proceedingJoinPoint.proceed();
String resultMessage = handleMessageOutputStream(writerPlaceHolder, resultStream);
ibisDebugger.senderOutput(sender, correlationId, resultMessage);
return resultStream;
}
if (proceedingJoinPoint.getTarget() instanceof IPipe) {
IPipe pipe = (IPipe)proceedingJoinPoint.getTarget();
PipeLine pipeLine = pipe instanceof AbstractPipe ? ((AbstractPipe)pipe).getPipeLine() : new PipeLine();
// Use WriterPlaceHolder to make the contents that is later written to the MessageOutputStream appear as input of the Pipe
WriterPlaceHolder writerPlaceHolder = ibisDebugger.pipeInput(pipeLine, pipe, correlationId, new WriterPlaceHolder());
MessageOutputStream resultStream = (MessageOutputStream)proceedingJoinPoint.proceed();
String resultMessage = handleMessageOutputStream(writerPlaceHolder, resultStream);
ibisDebugger.pipeOutput(pipeLine, pipe, correlationId, resultMessage);
return resultStream;
}
log.warn("Could not identify outputstream provider ["+proceedingJoinPoint.getTarget().getClass().getName()+"] as pipe or sender");
return (MessageOutputStream)proceedingJoinPoint.proceed();
}
In this code, an input and an output checkpoint is created within the context of the calling pipe or sender. This yields the nested pattern.
I would like to suggest two alternative checkpoint generating methods: provideOutputStreamToPipe() and provideOutputStreamToSender(). These methods should return a Function<MessageOuputStream,MessageOuputStream> that can be used to give ladybug control over the returned outputStream. The above code would then become:
String correlationId = getCorrelationId(session);
if (log.isDebugEnabled()) log.debug("debugProvideOutputStream thread id ["+Thread.currentThread().getId()+"] thread name ["+Thread.currentThread().getName()+"] correlationId ["+correlationId+"]");
if (proceedingJoinPoint.getTarget() instanceof ISender) {
ISender sender = (ISender)proceedingJoinPoint.getTarget();
Function<MessageOutputStream,MessageOutputStream> outputStreamDebugger = ibisDebugger.provideOutputStreamToSender(sender, correlationId);
MessageOutputStream resultStream = (MessageOutputStream)proceedingJoinPoint.proceed();
return outputStreamDebugger.apply(resultStream);
}
if (proceedingJoinPoint.getTarget() instanceof IPipe) {
IPipe pipe = (IPipe)proceedingJoinPoint.getTarget();
PipeLine pipeLine = pipe instanceof AbstractPipe ? ((AbstractPipe)pipe).getPipeLine() : new PipeLine();
Function<MessageOutputStream,MessageOutputStream> outputStreamDebugger = ibisDebugger.provideOutputStreamToPipe(pipe, correlationId);
MessageOutputStream resultStream = (MessageOutputStream)proceedingJoinPoint.proceed();
return outputStreamDebugger.apply(resultStream);
}
Ladybug could then display the contents of the messageOutputStream as the result of the current pipe/sender, and as the input of the next pipe/sender. If the messageOutputStream was null, the contents could be ignored.
The ladybug does not handle the input of streaming processing in the same way as non streaming, this is where it is not easy to understand for a developer or maintainer.
Functionally the flow is the same so it should look the same