배치 서비스 약간 수정 - nhnacademy-be10-WannaB/wannab-wiki GitHub Wiki

UserSpend 코드

@Getter
@AllArgsConstructor
public class UserSpend {
    @Getter
    private Long userId;
    private int totalBookPriceSum;
    private int totalDiscountAmountSum;

    public UserSpend() {
    }

    public UserSpend(Long userId, Long totalBookPriceSum, Long totalDiscountAmountSum) {
        this.userId = userId;
        this.totalBookPriceSum = totalBookPriceSum.intValue();
        this.totalDiscountAmountSum = totalDiscountAmountSum.intValue();
    }

    public int getActualSpent() {
        return totalBookPriceSum - totalDiscountAmountSum;
    }

}

  1. 생성자 중복 정의
  2. Getter 중복 정의
@Getter
@NoArgsConstructor
@AllArgsConstructor
public class UserSpend {
    
    private Long userId;
    private int totalBookPriceSum;
    private int totalDiscountAmountSum;

    public int getActualSpent() {
        return totalBookPriceSum - totalDiscountAmountSum;
    }

}
  • 이렇게 수정

yml

spring:
  application:
    name: batchservice
  lifecycle:
    timeout-per-shutdown-phase: 30s
  cloud:
    discovery:
      enabled: false
    config:
      enabled: false

dbcp2:
  datasource:
    url: jdbc:h2:mem:testdb
    driver-class-name: org.h2.Driver
    username: sa
    password: ""
    initial-size: 5
    max-total: 5
    max-idle: 5
    min-idle: 5

server:
  port: 10396
  shutdown: graceful

eureka:
  client:
    enabled: false
    
# Order Payment
order:
  api:
    url: http://localhost:10392

# Book
book:
  api:
    url: http://localhost:10390

# Coupon
coupon:
  api:
    url: http://localhost:10388

안쓰는 것들 삭제

spring:
  application:
    name: batchservice
  lifecycle:
    timeout-per-shutdown-phase: 30s
  cloud:
    discovery:
      enabled: false
    config:
      enabled: false

dbcp2:
  datasource:
    url: jdbc:h2:mem:testdb
    driver-class-name: org.h2.Driver
    username: sa
    password: ""
    initial-size: 5
    max-total: 5
    max-idle: 5
    min-idle: 5
    between-eviction-millis: 300000
    min-evictable-idle-millis: 600000
    num-tests-per-eviction-run: 3

server:
  port: 10396
  shutdown: graceful

eureka:
  client:
    enabled: false

  • 유레카에 등록이 되어야하나?
  • 우리는 사실 필요없긴한데 그래도 등록하는게 좋을것같긴하다 여러 의미로
    • 유레카 대시보드로 확인할 수도 있고
    • 지금은 따로 요청이나 이런건 없지만 요청을 주고받을수도 있을테니까
    • rest api 로 상태를 체크할수도 있을테니까

DBCP2 설정 추가

@Getter @Setter
@Configuration
@ConfigurationProperties(prefix = "dbcp2.datasource")
public class DataSourceConfig {

    private String driverClassName;
    private String url;
    private String username;
    private String password;
    private Integer maxIdle;
    private Integer maxTotal;
    private Integer initialSize;
    private Integer minIdle;
    private Long betweenEvictionMillis;
    private Long minEvictableIdleMillis;
    private Integer numTestsPerEvictionRun;

    @Bean
    public DataSource dataSource() {
        BasicDataSource basicDataSource = new BasicDataSource();

        basicDataSource.setDriverClassName(driverClassName);
        basicDataSource.setUrl(url);
        basicDataSource.setUsername(username);
        basicDataSource.setPassword(password);
        basicDataSource.setMaxIdle(maxIdle);
        basicDataSource.setMaxTotal(maxTotal);
        basicDataSource.setInitialSize(initialSize);
        basicDataSource.setMinIdle(minIdle);

        basicDataSource.setValidationQuery("SELECT 1");
        basicDataSource.setTestOnReturn(true);
        basicDataSource.setTestOnBorrow(true);
        basicDataSource.setTestWhileIdle(true);

        basicDataSource.setDurationBetweenEvictionRuns(Duration.ofMinutes(betweenEvictionMillis));
        basicDataSource.setMinEvictableIdle(Duration.ofMinutes(minEvictableIdleMillis));
        basicDataSource.setNumTestsPerEvictionRun(numTestsPerEvictionRun);

        return basicDataSource;
    }
}

기본으로 설정된 Job이 없는에러

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'jobLauncherApplicationRunner' defined in class path resource [org/springframework/boot/autoconfigure/batch/BatchAutoConfiguration.class]: Job name must be specified in case of multiple jobs
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1806)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:600)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:522)
	at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:337)
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:335)
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:975)
	at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:971)
	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:625)
	at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:146)
	at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:755)
	at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:456)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:335)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1364)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1353)
	at shop.wannab.batchserver.BatchserverApplication.main(BatchserverApplication.java:10)
Caused by: java.lang.IllegalArgumentException: Job name must be specified in case of multiple jobs
	at org.springframework.util.Assert.isTrue(Assert.java:111)
	at org.springframework.boot.autoconfigure.batch.JobLauncherApplicationRunner.afterPropertiesSet(JobLauncherApplicationRunner.java:115)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1853)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1802)
	... 16 common frames omitted

코드 보니 스케쥴러로 실행하는거같은데

@Component
@RequiredArgsConstructor
@EnableScheduling
public class BatchScheduler {

    private final JobLauncher jobLauncher;
    private final Job updateUserGradeJob;
    private final Job updateUserStateJob;

    // TODO : 변경 필요
    @Scheduled(cron = "0 */2 * * * ?")
    public void runUpdateUserGradeJob() throws Exception {
        JobParameters params = new JobParametersBuilder()
                .addLong("time", System.currentTimeMillis())
                .toJobParameters();

        jobLauncher.run(updateUserGradeJob, params);
    }

    // TODO : 변경 필요
    @Scheduled(cron = "0 1/2 * * * ?")
    public void runUpdateUserStateJob() throws Exception {
        JobParameters params = new JobParametersBuilder()
                .addLong("time", System.currentTimeMillis())
                .toJobParameters();

        jobLauncher.run(updateUserStateJob, params);
    }
}

yml에 추가

  batch:
    job:
      enabled: false

Batch schedule yml로 빼기

batch:
  schedule:
    update-user-grade: "0 0 0 1 * ?"
    update-user-state: "0 0 1 1 * ?"
@Getter @Setter
@Component
@ConfigurationProperties(prefix = "batch.schedule")
public class BatchScheduleProperties {
    private String updateUserGrade;
    private String updateUserState;
}

  • yml 값을 configuration properties로 주입받고
@Slf4j
@Component
@RequiredArgsConstructor
@EnableScheduling
public class BatchScheduler implements SchedulingConfigurer {

    private final JobLauncher jobLauncher;
    private final Job updateUserGradeJob;
    private final Job updateUserStateJob;
    private final BatchScheduleProperties scheduleProperties;

    public void runUpdateUserGradeJob() {
        JobParameters params = new JobParametersBuilder()
                .addLong("time", System.currentTimeMillis())
                .toJobParameters();
        try {
            jobLauncher.run(updateUserGradeJob, params);
        } catch (Exception e) {
            log.error("runUpdateUserGradeJob Error : {}", e.getMessage());
        }

    }

    public void runUpdateUserStateJob() {
        JobParameters params = new JobParametersBuilder()
                .addLong("time", System.currentTimeMillis())
                .toJobParameters();
        try{
            jobLauncher.run(updateUserStateJob, params);
        } catch (Exception e){
            log.error("runUpdateUserStateJob Error : {}", e.getMessage());
        }

    }

    @Override
    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
        taskRegistrar.addCronTask(this::runUpdateUserGradeJob, scheduleProperties.getUpdateUserGrade());
        taskRegistrar.addCronTask(this::runUpdateUserStateJob, scheduleProperties.getUpdateUserState());
    }
}
  • 여기에서 의존성 주입받고 configureTask를 통해서 값을 설정해줌
  • 원래 IOException을 명시적으로 던져야하는데 SneakyThrows로 일단 통과시킴