Search code examples
springspring-integrationspring-integration-dsl

Spring Integration JPA Gateway: act on empty result


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?


Solution

  • 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.