작성
·
145
0
package springbatch.batch.job.file;
import lombok.RequiredArgsConstructor;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepScope;
import org.springframework.batch.item.ItemProcessor;
import org.springframework.batch.item.database.JpaItemWriter;
import org.springframework.batch.item.database.builder.JpaItemWriterBuilder;
import org.springframework.batch.item.file.FlatFileItemReader;
import org.springframework.batch.item.file.builder.FlatFileItemReaderBuilder;
import org.springframework.batch.item.file.mapping.BeanWrapperFieldSetMapper;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import springbatch.batch.chunk.processor.FileItemProcessor;
import springbatch.batch.domain.Product;
import springbatch.batch.domain.ProductVO;
import javax.persistence.EntityManagerFactory;
@Configuration
@RequiredArgsConstructor
public class FileJobConfiguration {
private final JobBuilderFactory jobBuilderFactory;
private final StepBuilderFactory stepBuilderFactory;
private final EntityManagerFactory entityManagerFactory;
@Bean
public Job fileJob() {
return jobBuilderFactory.get("fileJob")
.start(fileStep1())
.build();
}
@Bean
public Step fileStep1() {
return stepBuilderFactory.get("fileStep1")
.<ProductVO, Product>chunk(10)
.reader(fileItemReader(null))
.processor(fileItemProcessor())
.writer(fileItemWriter())
.build();
}
@Bean
@StepScope
public FlatFileItemReader<ProductVO> fileItemReader(@Value("#{jobParameters['requestDate']}") String requestDate) {
return new FlatFileItemReaderBuilder<ProductVO>()
.name("flatFile")
.resource(new ClassPathResource("product_" + requestDate +".csv"))
.fieldSetMapper(new BeanWrapperFieldSetMapper<>())
.targetType(ProductVO.class)
.linesToSkip(1)
.delimited().delimiter(",")
.names("id","name","price","type")
.build();
}
@Bean
public ItemProcessor<ProductVO, Product> fileItemProcessor() {
return new FileItemProcessor();
}
@Bean
public JpaItemWriter<Product> fileItemWriter() {
return new JpaItemWriterBuilder<Product>()
.entityManagerFactory(entityManagerFactory)
.usePersist(true)
.build();
}
}
application.yml
spring:
profiles:
active: mysql
jpa:
hibernate:
ddl-auto: update
database-platform: org.hibernate.dialect.MySQL5InnoDBDialect
show-sql: true
open-in-view: false
properties:
hibernate.format_sql: true
---
spring:
config:
activate:
on-profile: mysql
datasource:
hikari:
jdbc-url: jdbc:mysql://localhost:3306/springbatch?useUnicode=true&character_set_server=utf8mb4
username: root
password: ----
driver-class-name: com.mysql.cj.jdbc.Driver
batch:
job:
names: ${job.name:NONE}
enabled: false
jdbc:
initialize-schema: always
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.2</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>spring-batch</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>spring-batch</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-batch -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-batch</artifactId>
<version>2.5.2</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.modelmapper</groupId>
<artifactId>modelmapper</artifactId>
<version>2.4.4</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.13</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.mysql/mysql-connector-j -->
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<version>9.0.0</version>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-oxm</artifactId>
<version>5.3.7</version>
</dependency>
<dependency>
<groupId>com.thoughtworks.xstream</groupId>
<artifactId>xstream</artifactId>
<version>1.4.20</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-quartz</artifactId>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.13</version>
</dependency>
<dependency>
<groupId>org.springframework.batch</groupId>
<artifactId>spring-batch-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
잘 작성한거 같은데, 디버그 중단점 걸어놓아도 안걸러지네요ㅠㅠ 원인을 모르겠습니다..
requestDate 부분이랑 fileItemReader이 동작을 안하는거 같습니다.
답변 1
-2
안녕하세요, 인프런 AI 인턴입니다.
seungwan37님의 문제를 살펴보니, fileItemReader
에서 requestDate
를 정상적으로 받아 엑셀 파일을 읽는 과정에서 문제가 발생하는 것 같습니다. @Value("#{jobParameters['requestDate']}") String requestDate
를 사용하여 jobParameters
에서 requestDate
를 받고 있으나, 해당 날짜에 맞는 엑셀 파일(product_20210101.csv
)이 ClassPath에 존재하는지 확인이 필요합니다.
또한, IDE의 디버그 중단점이 걸리지 않는 문제는 fileItemReader
에 대한 bean 생성 및 실행 과정에서 예상치 못한 오류 또는 requestDate
파라미터의 전달 문제로 인해 해당 코드 라인에 도달하지 못할 가능성이 있습니다.
다음의 확인 사항을 검토해보세요:
product_20210101.csv
파일이 프로젝트의 resources
폴더 안에 존재하는지 확인하세요. 파일 경로는 new ClassPathResource("product_" + requestDate +".csv")
에 의해 결정됩니다.requestDate=20210101
이 정상적으로 Job Parameters로 전달되는지 확인하세요. IDE 내에서 설정한 --job.name=fileJob requestDate=20210101
설정이 정확히 적용되었는지 다시 한 번 체크해보세요.jobParameters
가 정상적으로 출력되고 있는지 확인해보세요. 이를 통해 requestDate
파라미터가 정상적으로 전달되었는지도 확인할 수 있습니다.배치 Job의 디버깅 포인트를 설정할 때는, 해당 Step이 실행되기까지 전체적인 Flow를 이해하는 것이 중요합니다. Job Execution 시작점부터 fileItemReader
, fileItemProcessor
, fileItemWriter
까지 전체적인 실행 흐름에 따라 중단점을 걸어보며 단계별로 디버깅을 수행해보세요.
위 사항을 검토해도 문제가 해결되지 않는다면, 추가적으로 로그 출력 설정을 상세히 설정하여 해당 부분의 실행 과정을 로그를 통해 확인해보는 것도 좋은 방법입니다.
application.yml 파일과 동일한 경로에 엑셀파일도 존재하고,
SpringBatchApplication.main()에서 args파라미터 찍어보니
잘 나옵니다..!
게다가 교수님의 깃허브 프로젝트를 클론받아서 해당 강의 부분까지 다른 파일 삭제해서 실행해도 동일한 문제가 발생합니다..!