Spring Batch 코드를 만들 때, 보통 아래와 같은 코드를 이용해서 jobParameter를 전달받습니다.
1 2 |
String maxCountParams = chunkContext.getStepContext().getStepExecution() .getJobParameters().getString("maxCount"); |
물론 배치를 실행할 때, argument를 주게 되겠죠.
1 |
classpath:jobs/dormant/sendmail/batch-job.xml maxCount=1 |
그런데 말입니다…
maxCount=1 숫자입니다. 그렇다면, 아래와 같은 코드도 가능하지 않을까요?
1 |
long maxCountParams = chunkContext.getStepContext().getStepExecution().getJobParameters().getLong("maxCount"); |
실제로 JobParameters는 getLong(), getString(), getDate(), getDouble() 메소드를 지원합니다.
심지어 defaultValue까지 지정할 수 있게 되어있습니다.
JobParameters.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
public long getLong(String key){ Object value = parameters.get(key).getValue(); return value==null ? 0L : ((Long)value).longValue(); } public long getLong(String key, long defaultValue){ if(parameters.containsKey(key)){ return getLong(key); } else{ return defaultValue; } } public String getString(String key){ JobParameter value = parameters.get(key); return value==null ? null : value.toString(); } public String getString(String key, String defaultValue){ if(parameters.containsKey(key)){ return getString(key); } else{ return defaultValue; } } public double getDouble(String key){ return ((Double)parameters.get(key).getValue()).doubleValue(); } public double getDouble(String key, double defaultValue){ if(parameters.containsKey(key)){ return getDouble(key); } else{ return defaultValue; } } public Date getDate(String key){ return (Date)parameters.get(key).getValue(); } public Date getDate(String key, Date defaultValue){ if(parameters.containsKey(key)){ return getDate(key); } else{ return defaultValue; } } |
하지만 위에서 argument를 준 것처럼 maxCount=1 이라고 주면, 아래와 같은 오류를 리턴합니다.
1 2 3 4 5 |
ERROR 2015-07-24 17:52:33 [main] o.s.batch.core.step.AbstractStep.execute - Encountered an error executing the step java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Long at org.springframework.batch.core.JobParameters.getLong(JobParameters.java:59) ~[spring-batch-core-2.1.7.RELEASE.jar:na] |
실제로 JobParameters를 생성하는 곳을 보면 아래와 같이 파싱합니다.
즉, argument를 줄 때, (long)maxCount=1 이라고 줘야 정상적으로 long type으로 파싱하게 됩니다.
(왜 다른 instance variable은 public인데, double만 private일까요…-ㅅ-)
DefaultJobParametersConverter.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
public static final String DATE_TYPE = "(date)"; public static final String STRING_TYPE = "(string)"; public static final String LONG_TYPE = "(long)"; private static final String DOUBLE_TYPE = "(double)"; public JobParameters getJobParameters(Properties props) { if (props == null || props.isEmpty()) { return new JobParameters(); } JobParametersBuilder propertiesBuilder = new JobParametersBuilder(); for (Iterator<Entry<Object, Object>> it = props.entrySet().iterator(); it.hasNext();) { Entry<Object, Object> entry = it.next(); String key = (String) entry.getKey(); String value = (String) entry.getValue(); if (key.endsWith(DATE_TYPE)) { Date date; try { date = dateFormat.parse(value); } catch (ParseException ex) { String suffix = (dateFormat instanceof SimpleDateFormat) ? ", use " + ((SimpleDateFormat) dateFormat).toPattern() : ""; throw new IllegalArgumentException("Date format is invalid: [" + value + "]" + suffix); } propertiesBuilder.addDate(StringUtils.replace(key, DATE_TYPE, ""), date); } else if (key.endsWith(LONG_TYPE)) { Long result; try { result = (Long) parseNumber(value); } catch (ClassCastException ex) { throw new IllegalArgumentException( "Number format is invalid for long value: [" + value + "], use a format with no decimal places"); } propertiesBuilder.addLong(StringUtils.replace(key, LONG_TYPE, ""), result); } else if (key.endsWith(DOUBLE_TYPE)) { Double result = parseNumber(value).doubleValue(); propertiesBuilder.addDouble(StringUtils.replace(key, DOUBLE_TYPE, ""), result); } else if (StringUtils.endsWithIgnoreCase(key, STRING_TYPE)) { propertiesBuilder.addString(StringUtils.replace(key, STRING_TYPE, ""), value); } else { propertiesBuilder.addString(key, value); } } return propertiesBuilder.toJobParameters(); } |
argument를 줄 때, 따로 type을 지정하지 않으면 모두 String으로 파싱됩니다.
그 때, getLong() 등의 다른 type getter를 이용하면 오류가 발생합니다.
그래서 혹시라도 jenkins job을 설정할 때, 실수할 여지가 있는 코드보다는 차라리 아래와 같은 코드 작성하기를 추천합니다.
(누가? 제가요…^^)
1 2 3 |
String maxCountParams = chunkContext.getStepContext().getStepExecution() .getJobParameters().getString("maxCount"); int maxCount = NumberUtils.toInt(maxCountParams, DEFAULT_MAX_COUNT); |