Spring singleton bean - фоновая нить; Нет EntityManager с фактической ошибкой транзакции - PullRequest
0 голосов
/ 10 мая 2018

Программа предназначена для частого запуска фоновых потоков и загрузки входящих DataEvents на удаленный сервер.

@Scope(value = ConfigurableBeanFactory.SCOPE_SINGLETON)
@Singleton
@Component
public class RWDataUploader {

    protected org.slf4j.Logger log = LoggerFactory.getLogger(RWDataUploader.class);

    @PersistenceContext(type = PersistenceContextType.TRANSACTION)
    private EntityManager em;

    protected EntityManager getEntityManager() {
        return em;
    }

    private final Object objectUploaderMonitor = new Object();

    private boolean isActive = true;
    private int errorCount = 0;
    private long sleepTime = 20000l;
    private Timer bgProcessTimer;

    @PostConstruct
    public void init() {
        log.info("RWDataUploadClient initilized {} ", RWDataUploader.this);
         TimerTask task = new TimerTask() {
            @Override
            public void run() {
                log.info("Staring Upload process...");
                RWDataUploader.this.startUpload();
                bgProcessTimer.cancel();
            }
        };
        bgProcessTimer = new Timer("Upload process");
        bgProcessTimer.scheduleAtFixedRate(task, 10000, 3000); // start with a delay
    }

    @PreDestroy
    public void close() {
        stopUpload();
        log.info("RWDataUploadClient closed {} ", RWDataUploader.this);
    }

    public void stopUpload() {
        isActive = false;
        synchronized (objectUploaderMonitor) {
            objectUploaderMonitor.notify();
        }
    }

    public void startUpload() {
        while (isActive) {
            synchronized (objectUploaderMonitor) {
                try {
                    uploadTxnToServer();
                    log.debug("UploadTxnToServer Done Sleeping for next cycle " + sleepTime);
                    objectUploaderMonitor.wait(sleepTime);
                } catch (Exception ex) {
                    errorCount++;
                    log.error("Exception at ObjectUploaderMonitor.wait " + ex.getMessage() , ex); 
                    if (errorCount == 1) {
                        isActive = false; 
                    }
                }
            }
        }
        log.info("Uploader client is stopped");
    }


    @Transactional
    private void uploadTxnToServer() {
        List<RWDataEvent> openDevnts = getPendingDataEvents();
        for (RWDataEvent openDevnt : openDevnts) {
            log.info("Uploaded DE {} ", openDevnt);
            // logic Upload event to remote server
            // upload done
            openDevnt.setProcessedStatusCode("UPLOADED");
            em.merge(openDevnt);
        }
    }

    private List<RWDataEvent> getPendingDataEvents() {
        Query nq = em.createNamedQuery("RWDataEvent.findByProcessedStatusCode");
        nq.setParameter("processedStatusCode", "WAIT_UPLOAD");
        return nq.getResultList();
    }

}  

Получение следующей ошибки при выполнении

ОШИБКА crrcuploader.RWDataUploader - Исключение в ObjectUploaderMonitor.wait Нет EntityManager с фактической транзакцией, доступной для текущего потока - не может надежно обработать вызов «слияния».springframework.orm.jpa. SharedEntityManagerCreator.java: 106) в com.retailwave.rwos.compartment.uploader.RWDataUploader.startUpload (RWDataUploader.java:82) в com.retailwave.rwos.compartment.uploader.RWDataUploader $ 1.run (RWDataUploader.java:57)

1 Ответ

0 голосов
/ 10 мая 2018

Без перестройки все. Используйте TransactionTemplate для выполнения кода в транзакции.

Вы должны использовать метод execute и поместить в него реализацию.

...