読者です 読者をやめる 読者になる 読者になる

tohnamanブログ

東村山に生息するWindows好きな太っちょオヤジプログラマのブログ

Spring Batch その6

Java Spring Batch

今回もSpring Batch です。


Spring Batch その1~その5で、概要からJob作成・実行まで書きましたが、出来上がったモノに不満があると思います

  • DEBUGログが邪魔
  • csvファイルのパスがハードコーディング
  • 成功後の再実施で一意制約違反エラーで失敗する

などなど。なので、今回から数回に分けて、この問題に対応します。

今回はログ整理で、方針は

  • 開発用のログとしてコンソール出力のみとする
  • DEBUGは邪魔なので基本はINFOのみとする
  • SQLを出力する
  • ログライブラリはlog4j2を採用する

では、早速行ってみよう!

pomの修正(差分のみ)

  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-log4j2</artifactId>
  </dependency>

log4j2を追加

  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-batch</artifactId>
    <exclusions>
      <exclusion>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-logging</artifactId>
      </exclusion>
    </exclusions>
  </dependency>

springはlogbackを採用しているので、log4j2とバッティングしないように、
logbackに依存しているライブラリを排除する

log4j2.xml

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="OFF">
  <Appenders>
    <Console name="CONSOLE_APPENDER" target="SYSTEM_OUT">
      <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%-5p] (%-10t) (%40.40C:%L) - %m%n"/>
    </Console>
  </Appenders>

  <Loggers>
    <Root level="INFO">
      <AppenderRef ref="CONSOLE_APPENDER"/>
    </Root>
    <Logger name="jp.tokyo.higashimurayama.tohnaman.batch" level="DEBUG" additivity="false">
      <AppenderRef ref="CONSOLE_APPENDER"/>
    </Logger>
  </Loggers>
</Configuration>

batchパッケージをDEBUGにしているのはSQL出力の為ですが、何故か、この設定にするとSQLが出力するんです。
気持ち悪いけど一旦このままにして、別途調査するだ!

一応、これで方針に沿ったログが出力されるけど、もう一歩踏み込んでおく

Job開始・終了ログ用のリスナーの準備

public class LogListener implements JobExecutionListener {

  private static final Logger LOGGER = LoggerFactory.getLogger(LogListener.class);

  @Override
  public void beforeJob(JobExecution jobExecution) {
    LOGGER.info("\n----- はじめ -----");
  }

  @Override
  public void afterJob(JobExecution jobExecution) {
    LOGGER.info("\n----- おわり -----");
  }
}

Job開始・終了時に簡単なしるしを出力する

Batch用ApplicationContextの修正

@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
@PropertySource("classpath:/application.properties")
@Import({ DataSourceConfig.class, MyBatisConfig.class })
public class BatchContext {

  @Bean
  public LogListener logListener() {
    return new LogListener();
  }
}

LogListenerのBean定義を追加する

Csv2dbJob01Configの修正

@Atowired
private LogListener logListener;

@Bean
public Job csv2dbJob() {
  // @formatter:off
  return jobBuilderFactory
      .get("csv2dbJob")
      .listener(logListener)
      .flow(csv2dbStep())
      .end()
      .build();
  // @formatter:on
}

LogListener フィールドを追加しJobで使用するように修正

ログ

2017-01-14 20:10:13.607 [INFO ] (main      ) (ntext.support.AbstractApplicationContext:581) - Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@543788f3: startup date [Sat Jan 14 20:10:13 JST 2017]; root of context hierarchy
2017-01-14 20:10:14.342 [WARN ] (main      ) (ationClassEnhancer$BeanMethodInterceptor:348) - @Bean method ScopeConfiguration.stepScope is non-static and returns an object assignable to Spring's BeanFactoryPostProcessor interface. This will result in a failure to process annotations such as @Autowired, @Resource and @PostConstruct within the method's declaring @Configuration class. Add the 'static' modifier to this method to avoid these container lifecycle issues; see @Bean javadoc for complete details.
2017-01-14 20:10:14.355 [WARN ] (main      ) (ationClassEnhancer$BeanMethodInterceptor:348) - @Bean method ScopeConfiguration.jobScope is non-static and returns an object assignable to Spring's BeanFactoryPostProcessor interface. This will result in a failure to process annotations such as @Autowired, @Resource and @PostConstruct within the method's declaring @Configuration class. Add the 'static' modifier to this method to avoid these container lifecycle issues; see @Bean javadoc for complete details.
2017-01-14 20:10:14.553 [INFO ] (main      ) (.jdbc.datasource.DriverManagerDataSource:133) - Loaded JDBC driver: org.sqlite.JDBC
2017-01-14 20:10:15.349 [INFO ] (main      ) (springframework.jmx.export.MBeanExporter:431) - Registering beans for JMX exposure on startup
2017-01-14 20:10:15.570 [INFO ] (main      ) (ository.support.JobRepositoryFactoryBean:183) - No database type set, using meta data indicating: SQLITE
2017-01-14 20:10:15.664 [INFO ] (main      ) (ch.core.launch.support.SimpleJobLauncher:195) - No TaskExecutor has been set, defaulting to synchronous executor.
2017-01-14 20:10:15.794 [INFO ] (main      ) (.core.launch.support.SimpleJobLauncher$1:133) - Job: [FlowJob: [name=csv2dbJob]] launched with the following parameters: [{param=2}]
2017-01-14 20:10:15.880 [INFO ] (main      ) (ohnaman.batch.core.listeners.LogListener:14) - 
----- はじめ -----
2017-01-14 20:10:15.980 [INFO ] (main      ) (amework.batch.core.job.SimpleStepHandler:146) - Executing step: [csv2dbStep]
2017-01-14 20:10:17.907 [DEBUG] (main      ) (pache.ibatis.logging.jdbc.BaseJdbcLogger:145) - ==>  Preparing: insert into MST_ADDRESS (ID, ZIP, OFFICE_FLG, DELETE_FLG, PREF_NAME, PREF_KANA, CITY_NAME, CITY_KANA, TOWN_NAME, TOWN_KANA, TOWN_MEMO, AZA_NAME, AZA_KANA, MEMO, OFFICE_NAME, OFFICE_KANA, OFFICE_ADDRESS, NEW_ID, REGIST_DATE) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) 
2017-01-14 20:10:17.923 [DEBUG] (main      ) (pache.ibatis.logging.jdbc.BaseJdbcLogger:145) - ==> Parameters: 189000000(Integer), 1890000(String), 0(Integer), 0(Integer), 東京都(String), トウキョウト(String), 東村山市(String), ヒガシムラヤマシ(String), (String),  (String), (該当なし)(String), (String), (String), (String), (String), (String), (String), null, null
2017-01-14 20:10:17.924 [DEBUG] (main      ) (pache.ibatis.logging.jdbc.BaseJdbcLogger:145) - ==> Parameters: 189000200(Integer), 1890002(String), 0(Integer), 0(Integer), 東京都(String), トウキョウト(String), 東村山市(String), ヒガシムラヤマシ(String), 青葉町(String), アオバチョウ(String), (String), (String), (String), (String), (String), (String), (String), null, null
2017-01-14 20:10:17.924 [DEBUG] (main      ) (pache.ibatis.logging.jdbc.BaseJdbcLogger:145) - ==> Parameters: 189855000(Integer), 1898550(String), 1(Integer), 0(Integer), 東京都(String), トウキョウト(String), 東村山市(String), ヒガシムラヤマシ(String), 青葉町(String), アオバチョウ(String), (String), (String), (String), (String), 国立療養所 多磨全生園(String), コクリツリヨウヨウジヨ タマゼンシヨウエン(String), 青葉町4丁目1?1(String), null, null
2017-01-14 20:10:17.925 [DEBUG] (main      ) (pache.ibatis.logging.jdbc.BaseJdbcLogger:145) - ==> Parameters: 189851100(Integer), 1898511(String), 1(Integer), 0(Integer), 東京都(String), トウキョウト(String), 東村山市(String), ヒガシムラヤマシ(String), 青葉町(String), アオバチョウ(String), (String), (String), (String), (String), 東京都 多摩北部医療センター(String), トウキヨウト タマホクブイリヨウセンタ?(String), 青葉町1丁目7?1(String), null, null
2017-01-14 20:10:17.925 [DEBUG] (main      ) (pache.ibatis.logging.jdbc.BaseJdbcLogger:145) - ==> Parameters: 189000100(Integer), 1890001(String), 0(Integer), 0(Integer), 東京都(String), トウキョウト(String), 東村山市(String), ヒガシムラヤマシ(String), 秋津町(String), アキツチョウ(String), (String), (String), (String), (String), (String), (String), (String), null, null
2017-01-14 20:10:17.926 [DEBUG] (main      ) (pache.ibatis.logging.jdbc.BaseJdbcLogger:145) - ==> Parameters: 189001100(Integer), 1890011(String), 0(Integer), 0(Integer), 東京都(String), トウキョウト(String), 東村山市(String), ヒガシムラヤマシ(String), 恩多町(String), オンタチョウ(String), (String), (String), (String), (String), (String), (String), (String), null, null
2017-01-14 20:10:17.927 [DEBUG] (main      ) (pache.ibatis.logging.jdbc.BaseJdbcLogger:145) - ==> Parameters: 189000300(Integer), 1890003(String), 0(Integer), 0(Integer), 東京都(String), トウキョウト(String), 東村山市(String), ヒガシムラヤマシ(String), 久米川町(String), クメガワチョウ(String), (String), (String), (String), (String), (String), (String), (String), null, null
2017-01-14 20:10:17.928 [DEBUG] (main      ) (pache.ibatis.logging.jdbc.BaseJdbcLogger:145) - ==> Parameters: 189858500(Integer), 1898585(String), 1(Integer), 0(Integer), 東京都(String), トウキョウト(String), 東村山市(String), ヒガシムラヤマシ(String), 久米川町(String), クメガワチョウ(String), (String), (String), (String), (String), 山崎製パン (株) 武蔵野第二工場(String), ヤマザキセイパン (カブ) ムサシノダイニコウジヨウ(String), 久米川町1丁目53?1(String), null, null
2017-01-14 20:10:17.928 [DEBUG] (main      ) (pache.ibatis.logging.jdbc.BaseJdbcLogger:145) - ==> Parameters: 189001300(Integer), 1890013(String), 0(Integer), 0(Integer), 東京都(String), トウキョウト(String), 東村山市(String), ヒガシムラヤマシ(String), 栄町(String), サカエチョウ(String), (String), (String), (String), (String), (String), (String), (String), null, null
2017-01-14 20:10:17.929 [DEBUG] (main      ) (pache.ibatis.logging.jdbc.BaseJdbcLogger:145) - ==> Parameters: 189002100(Integer), 1890021(String), 0(Integer), 0(Integer), 東京都(String), トウキョウト(String), 東村山市(String), ヒガシムラヤマシ(String), 諏訪町(String), スワチョウ(String), (String), (String), (String), (String), (String), (String), (String), null, null
2017-01-14 20:10:17.929 [DEBUG] (main      ) (pache.ibatis.logging.jdbc.BaseJdbcLogger:145) - ==> Parameters: 189002600(Integer), 1890026(String), 0(Integer), 0(Integer), 東京都(String), トウキョウト(String), 東村山市(String), ヒガシムラヤマシ(String), 多摩湖町(String), タマコチョウ(String), (String), (String), (String), (String), (String), (String), (String), null, null
2017-01-14 20:10:17.930 [DEBUG] (main      ) (pache.ibatis.logging.jdbc.BaseJdbcLogger:145) - ==> Parameters: 189002200(Integer), 1890022(String), 0(Integer), 0(Integer), 東京都(String), トウキョウト(String), 東村山市(String), ヒガシムラヤマシ(String), 野口町(String), ノグチチョウ(String), (String), (String), (String), (String), (String), (String), (String), null, null
2017-01-14 20:10:17.930 [DEBUG] (main      ) (pache.ibatis.logging.jdbc.BaseJdbcLogger:145) - ==> Parameters: 189852000(Integer), 1898520(String), 1(Integer), 0(Integer), 東京都(String), トウキョウト(String), 東村山市(String), ヒガシムラヤマシ(String), 野口町(String), ノグチチョウ(String), (String), (String), (String), (String), 日機装 株式会社 東村山製作所(String), ニツキソウ カブシキガイシヤ ヒガシムラヤマセイサクジヨ(String), 野口町2丁目16?2(String), null, null
2017-01-14 20:10:17.931 [DEBUG] (main      ) (pache.ibatis.logging.jdbc.BaseJdbcLogger:145) - ==> Parameters: 189001200(Integer), 1890012(String), 0(Integer), 0(Integer), 東京都(String), トウキョウト(String), 東村山市(String), ヒガシムラヤマシ(String), 萩山町(String), ハギヤマチョウ(String), (String), (String), (String), (String), (String), (String), (String), null, null
2017-01-14 20:10:17.931 [DEBUG] (main      ) (pache.ibatis.logging.jdbc.BaseJdbcLogger:145) - ==> Parameters: 189002400(Integer), 1890024(String), 0(Integer), 0(Integer), 東京都(String), トウキョウト(String), 東村山市(String), ヒガシムラヤマシ(String), 富士見町(String), フジミチョウ(String), (String), (String), (String), (String), (String), (String), (String), null, null
2017-01-14 20:10:17.934 [DEBUG] (main      ) (pache.ibatis.logging.jdbc.BaseJdbcLogger:145) - ==> Parameters: 189001400(Integer), 1890014(String), 0(Integer), 0(Integer), 東京都(String), トウキョウト(String), 東村山市(String), ヒガシムラヤマシ(String), 本町(String), ホンチョウ(String), (String), (String), (String), (String), (String), (String), (String), null, null
2017-01-14 20:10:17.935 [DEBUG] (main      ) (pache.ibatis.logging.jdbc.BaseJdbcLogger:145) - ==> Parameters: 189850100(Integer), 1898501(String), 1(Integer), 0(Integer), 東京都(String), トウキョウト(String), 東村山市(String), ヒガシムラヤマシ(String), 本町(String), ホンチョウ(String), (String), (String), (String), (String), 東村山市役所(String), ヒガシムラヤマシヤクシヨ(String), 本町1丁目2?3(String), null, null
2017-01-14 20:10:17.935 [DEBUG] (main      ) (pache.ibatis.logging.jdbc.BaseJdbcLogger:145) - ==> Parameters: 189855500(Integer), 1898555(String), 1(Integer), 0(Integer), 東京都(String), トウキョウト(String), 東村山市(String), ヒガシムラヤマシ(String), 本町(String), ホンチョウ(String), (String), (String), (String), (String), 東村山税務署(String), ヒガシムラヤマゼイムシヨ(String), 本町1丁目20?22(String), null, null
2017-01-14 20:10:17.936 [DEBUG] (main      ) (pache.ibatis.logging.jdbc.BaseJdbcLogger:145) - ==> Parameters: 189002300(Integer), 1890023(String), 0(Integer), 0(Integer), 東京都(String), トウキョウト(String), 東村山市(String), ヒガシムラヤマシ(String), 美住町(String), ミスミチョウ(String), (String), (String), (String), (String), (String), (String), (String), null, null
2017-01-14 20:10:17.936 [DEBUG] (main      ) (pache.ibatis.logging.jdbc.BaseJdbcLogger:145) - ==> Parameters: 189002500(Integer), 1890025(String), 0(Integer), 0(Integer), 東京都(String), トウキョウト(String), 東村山市(String), ヒガシムラヤマシ(String), 廻田町(String), メグリタチョウ(String), (String), (String), (String), (String), (String), (String), (String), null, null
2017-01-14 20:10:18.305 [INFO ] (main      ) (ohnaman.batch.core.listeners.LogListener:19) - 
----- おわり -----
2017-01-14 20:10:18.401 [INFO ] (main      ) (.core.launch.support.SimpleJobLauncher$1:136) - Job: [FlowJob: [name=csv2dbJob]] completed with the following parameters: [{param=2}] and the following status: [COMPLETED]
2017-01-14 20:10:18.401 [INFO ] (main      ) (ntext.support.AbstractApplicationContext:982) - Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@543788f3: startup date [Sat Jan 14 20:10:13 JST 2017]; root of context hierarchy
2017-01-14 20:10:18.406 [INFO ] (main      ) (springframework.jmx.export.MBeanExporter:449) - Unregistering JMX-exposed beans on shutdown

ログがきれいになりました。

完成したモノをGitHubここ に置いています。
前回までのモノを初回リリースとしてまとめています。


今回は、ここまで