2

I have a following handle within my flow:

.handle(Jpa.retrievingGateway(this.sourceEntityManagerFactory)
                    .entityClass(DocumentHeader.class)
                    .jpaQuery("from DocumentHeader d where d.modifiedDate > :modified")
                    .parameterExpression("modified", "payload")
                    .maxResults(maxResults), e -> e.id("retrieveDocumentHeader"))
            .channel(Channels.DOCUMENT_HEADER.name())

I would like to do something in case the jpa query returns no results. Do I need to implement an advice for that? If so, how can I get the information that the query returned empty results?

UPDATE

Following Artem's suggestion, I came up with the following:

    @Bean
public Advice returnEmptyResultForAdvice() {
    ExpressionEvaluatingRequestHandlerAdvice advice = new ExpressionEvaluatingRequestHandlerAdvice();
    advice.setOnFailureExpressionString("new java.util.ArrayList(0)");
    advice.setReturnFailureExpressionResult(true);
    return advice;
}

And the gateway:

.handle(Jpa.retrievingGateway(this.sourceEntityManagerFactory)
                    .entityClass(DocumentHeader.class)
                    .jpaQuery("from DocumentHeader d where d.modifiedDate > :modified")
                    .parameterExpression("modified", "payload")
                    .maxResults(maxResults), e -> e.id("retrieveDocumentHeader")
                    .advice(this.advices.returnEmptyResultForAdvice()).requiresReply(true))

But it gives me the following error:

2020-08-13 19:13:57.474 ERROR 5552 --- [ask-scheduler-1] o.s.integration.handler.LoggingHandler   : org.springframework.integration.handler.ReplyRequiredException: No reply produced by handler 'retrieveDocumentHeader', and its 'requiresReply' property is set to true....]

UPDATE2

I did some more debugging of ExpressionEvaluatingRequestHandlerAdvice

protected Object doInvoke(ExecutionCallback callback, Object target, Message<?> message) {
    try {
        Object result = callback.execute();
        if (this.onSuccessExpression != null) {
            this.evaluateSuccessExpression(message);
        }

        return result;
    } catch (RuntimeException var7) {
        Exception actualException = this.unwrapExceptionIfNecessary(var7);
        if (this.onFailureExpression != null) {
            Object evalResult = this.evaluateFailureExpression(message, actualException);

It never throws an exception so I guess that's why the failure expression is not being invoked?

Blink
  • 1,408
  • 13
  • 21

2 Answers2

3

This feature is not implemented yet: https://jira.spring.io/browse/INT-3333

However you can catch with the ExpressionEvaluatingRequestHandlerAdvice a ReplyRequiredException when you add this advice into that e (endpoint configurer) and its requiresReply(true) option.

Then that ExpressionEvaluatingRequestHandlerAdvice may have an onFailureExpression and returnFailureExpressionResult to return for example an empty list.

UPDATE

I take my ExpressionEvaluatingRequestHandlerAdvice suggestion back. We have code there like this:

Object result = callback.execute();
if (this.onSuccessExpression != null) {
    evaluateSuccessExpression(message);
}
return result;

The callback.execute() returns null for us and and we don't care about that and just return it as is. The ReplyRequiredException is thrown a bit later. So, this one does meet our null reply requirements.

I suggest you to implement your own AbstractRequestHandlerAdvice with checking a result of the callback.execute() isntead.

Artem Bilan
  • 113,505
  • 11
  • 91
  • 118
  • Thanks for suggestion. Could you please take a look at the UPDATE in my post? – Blink Aug 13 '20 at 17:18
  • Can you place a break point in the `ExpressionEvaluatingRequestHandlerAdvice` to be sure how that `onFailureExpression` is evaluated and and what is going on next? – Artem Bilan Aug 13 '20 at 19:33
  • So the expression is evaluated correctly during bootstrap but I have no idea where else should I put a breakpoint to debug it when the gateway is executed? Any idea? – Blink Aug 14 '20 at 12:14
  • hi Artem, any idea how to debug it further? If I won't be able to solve it soon I'm thinking about switching to a normal handle with spring data repository. – Blink Aug 19 '20 at 07:25
  • Ok. I’ll debug it today. Sounds like that advice is not applied... – Artem Bilan Aug 19 '20 at 12:15
  • See an UPDATE in my answer. – Artem Bilan Aug 20 '20 at 00:54
1

Example advice:

@Bean
public Advice verifyEmptyResult() {
    return new AbstractRequestHandlerAdvice() {
        @Override
        protected Object doInvoke(ExecutionCallback callback, Object target, Message<?> message) {
            Object executed = callback.execute();
            if (executed == null)
                return new ArrayList<>();
            else
                return executed;
        }
    };
}
Blink
  • 1,408
  • 13
  • 21