Rayyan
Rayyan

Reputation: 173

Spring Integration JpaInboundChannelAdapterSpec Update method

Why isn't there an equivalent updateSQL() (as in JdbcPollingChannelAdapter) for JpaInboundChannelAdapterSpec? Please confirm if manual persist through handle() should be called to update polled records as NOT to pick the same again?

UPDATE enter image description here

    @Bean
    public JpaInboundChannelAdapterSpec dBJpaInboundSpec() {

        return Jpa.inboundAdapter(entityManagerFactory)
                    .entityClass(XYZ.class)
                    .jpaQuery("SELECT a FROM XYZ a WHERE a.status is null")
                    // trick to update the polled record
                    .deleteAfterPoll(true)
                    .maxResults(maxMessagesPerPoll);
    }

    @Bean
    public PollerSpec dBPollerSpec() {

        return Pollers.fixedDelay(Duration.ofMinutes(pollInterval))
                    .maxMessagesPerPoll(maxMessagesPerPoll)
                    .transactional()
                    .advice(loggingAdvice);
    }

2022-10-21 20:05:57,559 [scheduling-2              ] ERROR o.s.i.h.LoggingHandler - b46f904d98859f6f org.springframework.messaging.MessagingException: nested exception is org.springframework.dao.InvalidDataAccessResourceUsageException: could not execute statement; SQL [n/a]; nested exception is org.hibernate.exception.SQLGrammarException: could not execute statement, failedMessage=GenericMessage [payload=[REMOVED_FOR_OBVIOUS_REASONS], headers={REMOVED_FOR_OBVIOUS_REASONS}]
    at org.springframework.integration.endpoint.AbstractPollingEndpoint.pollForMessage(AbstractPollingEndpoint.java:427)
    at org.springframework.integration.endpoint.AbstractPollingEndpoint.lambda$createPoller$4(AbstractPollingEndpoint.java:348)
    at org.springframework.integration.util.ErrorHandlingTaskExecutor.lambda$execute$0(ErrorHandlingTaskExecutor.java:57)
    at org.springframework.core.task.SyncTaskExecutor.execute(SyncTaskExecutor.java:50)
    at org.springframework.integration.util.ErrorHandlingTaskExecutor.execute(ErrorHandlingTaskExecutor.java:55)
    at org.springframework.integration.endpoint.AbstractPollingEndpoint.lambda$createPoller$5(AbstractPollingEndpoint.java:341)
    at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:54)
    at org.springframework.scheduling.concurrent.ReschedulingRunnable.run(ReschedulingRunnable.java:95)
    at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:539)
    at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
    at java.base/java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:304)
    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)
    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
    at java.base/java.lang.Thread.run(Thread.java:833)
Caused by: org.springframework.dao.InvalidDataAccessResourceUsageException: could not execute statement; SQL [n/a]; nested exception is org.hibernate.exception.SQLGrammarException: could not execute statement
    at org.springframework.orm.jpa.vendor.HibernateJpaDialect.con

Upvotes: 0

Views: 163

Answers (1)

Artem Bilan
Artem Bilan

Reputation: 121177

I think it is not implement like you'd expect just because JPA is not just about DB, but persistent entity state in the memory. So, if you just did an update on the entity, then downstream logic is going to deal with that updated data - not an original you have polled from persistent layer before.

Yes, it is better to do such an update already after processing in this case manually.

I also always recommend a trick with an org.hibernate.annotations.SQLDelete where you indeed can specify an UPDATE query. That JpaInboundChannelAdapterSpec has this option then:

/**
 * If set to 'true', the retrieved objects are deleted from the database upon
 * being polled. May not work in all situations, e.g. for Native SQL Queries.
 * @param deleteAfterPoll Defaults to 'false'.
 * @return the spec
 */
public JpaInboundChannelAdapterSpec deleteAfterPoll(boolean deleteAfterPoll) {

Upvotes: 1

Related Questions