6

Tôi đang gặp vấn đề lạ với một ứng dụng là một ứng dụng khởi động mùa xuân.TransactionRequiredException: không có giao dịch nào đang được tiến hành trong khi đang sử dụng JPAItemWriter

chi tiết đây:

Ứng dụng này có một công việc hàng loạt mùa xuân trong đó sử dụng JpaItemWriter cho thực hiện ghi vào cơ sở dữ liệu.

Ngoài ra, các ứng dụng được cấu hình để sử dụng hibernate

cấu hình ItemWriter như sau:

@Bean(name = "itemWriter") 
    @StepScope 
    public ItemWriter<Record> itemWriter() { 
     JpaItemWriter<Record> itemWriter = new JpaItemWriter<>(); 
     itemWriter.setEntityManagerFactory(emf); 
     return itemWriter; 
    } 

Công việc hàng loạt đã từng làm việc tuyệt vời, nhưng thời gian gần đây chúng tôi nâng cấp Jenkins của chúng tôi để Jenkins (2.73.3) . Sau đó, các mã được xây dựng và triển khai sử dụng Jenkins mới này bắt đầu ném các lỗi sau khi công việc hàng loạt cùng được điều hành:

2017-12-03 16:09:44.720 DEBUG - testservice - - jobLauncher-3 - org.springframework.batch.item.database.JpaItemWriter:97 - Writing to JPA with 4 items. 
2017-12-03 16:09:44.733 DEBUG - testservice - - jobLauncher-3 - org.springframework.batch.item.database.JpaItemWriter:109 - 4 entities merged. 
2017-12-03 16:09:44.733 DEBUG - testservice - - jobLauncher-3 - org.springframework.batch.item.database.JpaItemWriter:110 - 0 entities found in persistence context. 
2017-12-03 16:09:44.743 WARN - testservice - - jobLauncher-3 - com.shared.domain.error.BatchExceptionHandler:63 - [test-service]999999999(Dn9lM4c)ExhaustedRetryException: Unable to locate ErrorDetail for Id ExhaustedRetryException. Details: 
org.springframework.retry.ExhaustedRetryException: Retry exhausted after last attempt in recovery path, but exception is not skippable.; nested exception is javax.persistence.TransactionRequiredException: no transaction is in progress 
     at org.springframework.batch.core.step.item.FaultTolerantChunkProcessor$5.recover(FaultTolerantChunkProcessor.java:403) ~[spring-batch-core-3.0.7.RELEASE.jar!/:3.0.7.RELEASE] 
     at org.springframework.retry.support.RetryTemplate.handleRetryExhausted(RetryTemplate.java:473) ~[spring-retry-1.1.5.RELEASE.jar!/:?] 
     at org.springframework.retry.support.RetryTemplate.doExecute(RetryTemplate.java:333) ~[spring-retry-1.1.5.RELEASE.jar!/:?] 
     at org.springframework.retry.support.RetryTemplate.execute(RetryTemplate.java:201) ~[spring-retry-1.1.5.RELEASE.jar!/:?] 

Các cơ sở mã tương tự khi xây dựng và triển khai sử dụng Old Jenkins (. Jenkins ver 1,646) , công việc hoạt động tốt.

Trong cả hai trường hợp, ứng dụng sẽ được triển khai trên phiên bản EC2 (AWS) có cùng AMI. Vì vậy, không có sự khác biệt trong máy chủ mà họ đang chạy trên.

Ngoài ra, tôi đã kiểm tra phiên bản Java và phiên bản maven được sử dụng để tạo mã trên cả hai phiên bản của Jenkins và chúng giống nhau.

Maven phiên bản và phiên bản Java:

Apache Maven 3.0.4 (r1232337; 2012-01-17 08:44:56+0000) 
Maven home: /opt/maven/apache-maven-3.0.4 
Java version: 1.8.0_72, vendor: Oracle Corporation 
Java home: /usr/java/jdk1.8.0_72/jre 
Default locale: en_US, platform encoding: UTF-8 

các phiên bản khác:

SpringBoot: 1.4.7.RELEASE 
HibernateVersion: 5.2.3.Final 

Sự khác biệt duy nhất là Jenkins cũ đang chạy trên AWS RHEL và cái mới đang chạy trên CentOS7.

Tôi thậm chí đã kiểm tra các lọ được tạo trong cả hai trường hợp và không có gì có vẻ khác biệt.

Hiện nay không chắc chắn làm thế nào để tiếp tục khắc phục vấn đề này

Edited:

tôi đã gỡ lỗi từ xa của mã được tạo ra bởi cả Jenkins, sau đây là những quan sát thực hiện.

Các cuộc gọi JpaItemWriter "EntityManagerFactoryUtils.getTransactionalEntityManager" và trong phương thức "emHolder" là null trong một trường hợp và có giá trị hợp lệ trong trường hợp khác.

public static EntityManager doGetTransactionalEntityManager(
       EntityManagerFactory emf, Map<?, ?> properties, boolean synchronizedWithTransaction) throws PersistenceException { 

      Assert.notNull(emf, "No EntityManagerFactory specified"); 

      EntityManagerHolder emHolder = 
        (EntityManagerHolder) TransactionSynchronizationManager.getResource(emf); 

// This line returns a valid emHolder 
// But in case of the code which is not working, it is returning a 
// null value 
EntityManagerHolder emHolder = 
        (EntityManagerHolder) TransactionSynchronizationManager.getResource(emf); 

Không chắc chắn tại sao NamedThreadLocal> ("Tài nguyên giao dịch") không có thực thểMangerHolder trong một trường hợp nhưng không phải trong trường hợp khác.

Cập nhật

Sau khi gỡ lỗi hơn những gì tôi thấy trong trường hợp của mã mà không hoạt động công việc hàng loạt mùa xuân sử dụng "DataSourceTransactionManager" nhưng trong trường hợp khác, nó sử dụng JpaTransactionManager.

+0

Tạo sự khác biệt của các tạo phẩm được tạo ra. –

+0

@ JensSchauder Tôi đã làm một khác biệt bằng cách sử dụng ngoài so sánh và không có gì là khác nhau, ngoại trừ số phiên bản –

+0

Bạn đang tạo ra một lọ chất béo, hoặc một cuộc chiến tranh? Bạn có chắc là Jenkins đang kéo các phụ thuộc giống nhau ở cả hai nơi? Bạn có chỉ định phiên bản chính xác của phụ thuộc trong poms của bạn không? Nếu không có khả năng một bản dựng có thể chứa các phiên bản phụ thuộc khác nhau. – PaulNUK

Trả lời

1

tôi đã có thể giải quyết vấn đề của tôi bây giờ, đây là những phát hiện của tôi:

Có vẻ như có một sự khác biệt trong thứ tự mà các hạt cà phê được tạo ra trong cả hai trường hợp.

Tôi đã có một trình quản lý JpaTransaction bean được định nghĩa trong các lớp cấu hình của tôi. Bean này không bao giờ được tạo bằng mã được tạo bằng cách sử dụng Jenkins 2.0.

Mùa xuân đang tạo bean quản lý giao dịch proxy trong lớp "org.springframework.batch.core.configuration.annotation.SimpleBatchConfiguration" và trình quản lý giao dịch này không hoạt động tốt với JpaItemWriter.

Tôi đã xem một vé JIRA thảo luận vấn đề với SimpleBatchConfiguration.

https://jira.spring.io/browse/BATCH-2294

Sau khi tôi thêm đậu JpaTransaction cùng trong lớp BatchConfiguration tôi, vấn đề biến mất.

Các vấn đề liên quan