J-Jobs

Guides -J-Jobs Ent. v2.1 REST API 가이드

페이지 개요

  1. J-Jobs Enterprise v2.1 Rest API Guide
  2. 1. 사용법
    1. 1.1 API 버전
    2. 1.2 접속 허용 IP 설정
    3. 1.3 토큰
    4. 1.4 API 기본 요청 주소
    5. 1.5 REST API 호출 예제
    6. 1.6 API 호출 응답 코드
  3. 2. 상세 API
    1. 2.1 Job API
      1. Job 목록 조회
      2. Job 조회
      3. Job 삭제
      4. Job 수정
      5. Job 파라미터 조회
      6. Job 권한 조회
      7. Job 실행
      8. Job 자동 생성
      9. Job Step Overview 조회
    2. 2.2 Job Request API
      1. Job Request 목록 조회
      2. Job Request 조회
      3. Job 요청 결과 상태 별 개수 조회
    3. 2.3 Job Instance API
      1. Job Instance 조회
    4. 2.4 Job Execution API
      1. Job Execution 목록 조회
      2. Job Execution 조회
      3. Job Execution 제어
      4. Job Execution 로그 조회
      5. Step Execution 결과를 포함한 Job Execution 결과 조회
    5. 2.5 Step Execution API
      1. Step Execution 목록 조회
      2. Step Execution 조회
      3. Step Execution 로그 조회
    6. 2.6 스케줄 API
      1. 스케줄 목록 조회
      2. 스케줄 조회
    7. 2.7 Agent API
      1. 프로세스 reload
      2. Agent 재시작
      3. Agent 중지
      4. Agent 프로세스 중지(KILL)
  4. 3.예제
    1. Job 실행부터 로그확인까지 따라해보기
      1. 사전준비
      2. Job을 실행하기
      3. 실행된 Job의 요청내역 조회
      4. Job실행ID 로그조회 (Job 로그조회)
      5. Job 실행ID 목록 조회 (Job Execution 목록조회)
      6. Step 실행ID 목록 조회 (Step Execution 목록조회)
      7. Step실행ID 로그조회 (Step 로그조회)
    2. Rest API를 이용하여 Step Skip 기능 테스트해보기
      1. 사전 준비
      2. Job 생성
      3. Job 실행
      4. 요청ID 조회
      5. Job 실행ID 조회 (Job Execution 목록조회)
      6. Step 실행ID 목록 조회 (Step Execution 목록조회)
    3. Rest API를 이용하여 재실행 테스트하기
      1. 사전 준비
      2. Job 생성
      3. Job 실행
      4. 요청ID 조회
      5. Job 재실행
      6. 재실행된 Job 실행ID 확인
      7. Step 실행ID 목록 조회

J-Jobs Enterprise v2.1 Rest API Guide

최종 작성일 : 2018년 6월 7일

기준 버전 : J-Jobs v1.2.6 이상

1. 사용법

1.1 API 버전

v1

1.2 접속 허용 IP 설정

허용된 IP로부터의 REST API 호출만 허용할 경우 운영관리의 ip_access_allow.properties 설정파일에서 허용할 IP 목록을 설정한다.

  • servlet-context.xml
<mvc:interceptors>
    <mvc:interceptor>
        <mvc:mapping path="/**" /> &lt;!&ndash; 모든 URL 에 대해 Interceptor 를 적용하고자 한다면 /** &ndash;&gt;
        <bean class="jjob.manager.common.interceptor.IPCheckInterceptor"/> &lt;!&ndash; HandlerInterceptor 인터페이스를 구현한 클래스 &ndash;&gt;
    </mvc:interceptor>
    <mvc:interceptor>
        <mvc:mapping path="/**" /> <!-- 모든 URL 에 대해 Interceptor 를 적용하고자 한다면 /** -->
        <bean class="jjob.manager.common.interceptor.LoginCheckInterceptor"/> <!-- HandlerInterceptor 인터페이스를 구현한 클래스 -->
    </mvc:interceptor>
</mvc:interceptors>
  • ip_access_allow.properties
127.0.0.1         // localhost
0:0:0:0:0:0:0:1   // localhost(IPv6)

10.64.74.219

1.3 토큰

각 사용자는 사용자 정보 > 토큰 발급을 이용하여 토큰을 발급하고, REST API 호출 시 아래와 같이 HEADER의 필수값으로 전달해야 한다.

private-token : {사용자 토큰값}

1.4 API 기본 요청 주소

http://{JJOBS_MANAGER_ADDRESS}/jjob-manager/api/{API_VERSION}

1.5 REST API 호출 예제

오픈 소스인 Apache HttpComponentsjson-simple을 이용하여 J-jobs의 REST API를 호출한다.

  • GET 방식으로 Job 목록을 조회하여 출력하는 예제
try{
    String token = "ed01e0d5a7d0c6b8896e";

    HttpClient httpClient = HttpClientBuilder.create().build();
    HttpGet request = new HttpGet("http://127.0.0.1:8080/jjob-manager/api/v1/job/");
    request.addHeader("private-token", token);

    HttpResponse response = httpClient.execute(request);
    if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
        throw new RuntimeException("Failed : HTTP error code : " + response.getStatusLine().getStatusCode());
    }
    String jsonResult = EntityUtils.toString(response.getEntity(), Consts.UTF_8);

    JSONObject jsonObject = (JSONObject) JSONValue.parse(jsonResult);
    if(jsonObject != null) {
        if(jsonObject.get("list") instanceof JSONArray) {
            JSONArray list = (JSONArray) jsonObject.get("list");
            for(int i = 0 ; i < list.size() ; i++) {
                if(list.get(i) instanceof JSONObject) {
                    JSONObject job = (JSONObject) list.get(i);
                    System.out.println(job.get("name"));
                }
            }
        }
    }
} catch(ClientProtocolException e) {
    e.printStackTrace();
} catch(IOException e) {
    e.printStackTrace();
}
  • POST 방식으로 Sleep_Wait_Job을 실행하고, Request ID를 출력하는 예제
try {
    String token = "ed01e0d5a7d0c6b8896e";
    String jobId = "Sleep_Wait_Job";

    HttpClient httpClient = HttpClientBuilder.create().build();
    HttpPost request = new HttpPost("http://127.0.0.1:8080/jjob-manager/api/v1/job/" + jobId +"/run");
    request.setHeader("private-token", token);
    request.setHeader(HTTP.CONTENT_TYPE, "application/json");

    JSONArray array = new JSONArray();
    JSONObject param = new JSONObject();
    param.put("name", "sleep");
    param.put("value", "1000");
    array.add(param);

    request.setEntity(new StringEntity(array.toJSONString(), Consts.UTF_8));

    HttpResponse response = httpClient.execute(request);
    if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
        throw new RuntimeException("Failed : HTTP error code : " + response.getStatusLine().getStatusCode());
    }
    String jsonResult = EntityUtils.toString(response.getEntity(), Consts.UTF_8);

    JSONObject jsonObject = (JSONObject) JSONValue.parse(jsonResult);
    if (jsonObject != null) {
        if (jsonObject.get("status") instanceof JSONObject) {
            JSONObject result = (JSONObject) jsonObject.get("status");
            for (Object msg : result.values()) {
                if (msg instanceof JSONObject) {
                    if("success".equals(((JSONObject) msg).get("dev_message"))) {
                        System.out.println("REQUEST ID : " + ((JSONObject) msg).get("reqId"));
                    } else if("fail".equals(((JSONObject) msg).get("dev_message"))) {
                        System.out.println("FAIL MESSAGE : " + ((JSONObject) msg).get("detail_raw_message"));
                    }
                }
            }
        }
    }
} catch (ClientProtocolException e) {
    e.printStackTrace();
} catch (IOException e) {
    e.printStackTrace();
}

1.6 API 호출 응답 코드

J-jobs의 REST API를 호출할 경우, 다음의 응답 코드 중 하나가 반환된다.

응답 코드상태설명
200OKGET, PUT 또는 DELETE에 대한 요청 성공
400Bad Request해당 API의 필수값을 넘기지 않았거나, 결과값이 너무 많을 경우
401Unauthorized해당 API가 제공되지 않거나 API에 대한 호출 권한이 없을 경우
405Not SupportedAPI 호출에 대한 메소드가 제공되지 않을 경우
500Server Error현재 REST API 서버에서 오류가 발생한 경우

2. 상세 API

2.1 Job API

Job 목록 조회

사용자가 소유하고 있는 Job 목록을 조회한다.

  • 사용 가능 권한

ADMINISTRATOR, MANAGER, DEVELOPER, GUEST

  • 요청 주소
GET /job/list
  • 요청 파라미터 (URL)
파라미터타입필수여부설명
filter:ownerGroupOthersstringNoJob Permission 필터링
- OWNER
- GROUP
- OTHERS
filter:jobIdstringNoJob ID 필터링
filter:validYnstringNo유효상태 필터링
  • 응답 예제
{
    "param": {},
    "list": [
        {
            "seq": 0,
            "modDt": "2017-03-03 10:48:22.881",
            "regDt": "2017-03-03 10:48:22.881",
            "modUserId": "root",
            "regUserId": "root",
            "msg": null,
            "jobId": "Infinite_Wait_Job",
            "name": "Infinite Wait Job",
            "restartable": "true",
            "bpmnXml": null,
            "jslXml": null,
            "version": "1.01",
            "stepIdList": null,
            "stepIds": "Infinite_Wait_Step",
            "validYn": "Y",
            "jobLoadBalanceId": null,
            "jobLoadBalanceName": null,
            "jobLoadBalanceDesc": null,
            "lastJobExecution": null,
            "ownerId": "jimin",
            "groupId": "DEFAULT_GROUP",
            "permissionOctalValue": null,
            "launchable": false
        },
        {
            "seq": 0,
            "modDt": "2017-03-03 10:48:23.241",
            "regDt": "2017-03-03 10:48:23.241",
            "modUserId": "root",
            "regUserId": "root",
            "msg": null,
            "jobId": "Partitioned_Sleep_Wait_For_Setjob_Job",
            "name": "Partitioned Sleep Wait For Setjob Job",
            "restartable": "true",
            "bpmnXml": null,
            "jslXml": null,
            "version": "1.0",
            "stepIdList": null,
            "stepIds": "Partitioned_Sleep_Wait_For_Setjob_Step",
            "validYn": "Y",
            "jobLoadBalanceId": null,
            "jobLoadBalanceName": null,
            "jobLoadBalanceDesc": null,
            "lastJobExecution": null,
            "ownerId": "jimin",
            "groupId": "DEFAULT_GROUP",
            "permissionOctalValue": null,
            "launchable": false
        }
    ]
}

Job 조회

Job ID로 Job의 내용을 조회한다.

  • 사용 가능 권한

ADMINISTRATOR, MANAGER, DEVELOPER, GUEST

  • 요청 주소
GET /job/:id
  • 요청 파라미터 (URL)
파라미터타입필수여부설명
idstringYesJob ID
  • 응답 예제
{
    "vo": {
        "seq": 0,
        "modDt": "2017-02-28 16:44:26.912",
        "regDt": "2017-02-22 14:33:00.393",
        "modUserId": "root",
        "regUserId": "root",
        "msg": null,
        "jobId": "Sleep_Wait_Job",
        "name": "Sleep Wait Job",
        "restartable": "true",
        "bpmnXml": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>...</step>\n</job>\n",
        "version": "1.07",
        "stepIdList": null,
        "stepIds": "Sleep_Wait_Step",
        "validYn": "Y",
        "jobLoadBalanceId": "3",
        "jobLoadBalanceName": "1-*",
        "jobLoadBalanceDesc": "1번 에이전트 그룹 내에서 로드 밸런스",
        "lastJobExecution": null,
        "ownerId": null,
        "groupId": null,
        "permissionOctalValue": null,
        "launchable": false
    }
}

Job 삭제

등록된 Job을 삭제한다.

  • 사용 가능 권한

ADMINISTRATOR, MANAGER, DEVELOPER

  • 요청 주소
DELETE /job/delete
  • 요청 파라미터 (URL)
파라미터타입필수여부설명
jobIdstringYesJob ID

Job 수정

등록된 Job을 수정한다.

  • 사용 가능 권한

ADMINISTRATOR, MANAGER, DEVELOPER

  • 요청 주소
PUT /job/modify
  • 요청 파라미터 (Body)
파라미터타입필수여부설명
jobIdstringYes수정 Job ID
restartablebooleanYes재시작 여부
modUserIdstringNo수정 사용자 ID
namestringYes변경 Job 명
emailNotificationbooleanNo알림 기능 사용 여부
  • 알림 기능 사용시 추가 파라미터
파라미터타입필수여부설명
notiServerTypestringYes알림 서버 종류
additionalRecipientsstringNo추가 수신자, ';'로 구분
notificationConditionsstringNo알림 조건 목록, 하단 참고
  • 알림 조건 목록

아래의 4 가지 종류만 지원하며 ';'로 구분하여 사용한다.

파라미터타입설명
onSuccessRule-Job 실행 성공 시 알림
onFailureRule-Job 실행 실패 시 알림
atStartRule-Job 실행 시작 시 알림
inProgressMoreThanRuleintJob 실행 후 지연 시 알림(분 단위)
  • 요청 예제
// Job의 일반 정보만 수정 시
{
	"jobId" : "testJob1",
	"restartable" : "true",
	"name" : "테스트 Job"
}

// Job의 알림 정보를 수정 시
{
	"jobId" : "testJob1",
	"restartable" : "true",
	"name" : "테스트 Job",
	"notiServerType" : "SMTP",
	"emailNotification" : "true",
	"additionalRecipients" : "user1@test.com;user2@test.com;user3@test.com",
	"notificationConditions" : "onSuccessRule;onFailureRule;atStartRule;inProgressMoreThanRule=1"
}

Job 파라미터 조회

Job에 대한 파라미터 목록과 default 값을 조회한다.

  • 사용 가능 권한

ADMINISTRATOR, MANAGER, DEVELOPER, GUEST

  • 요청 주소
GET /job/:id/params
  • 요청 파라미터 (URL)
파라미터타입필수여부설명
idstringYesJob Id
  • 응답 예제
{
    "hasParameters": true,
    "jobId": "Sleep_Wait_Job",
    "list": [
        {
            "name": "sleep",
            "value": "1000"
        }
    ]
}

Job 권한 조회

Job에 대한 권한 관련 정보를 조회한다.

  • 사용 가능 권한

ADMINISTRATOR, MANAGER, DEVELOPER, GUEST

  • 요청 주소
GET /job/:id/permission
  • 요청 파라미터 (URL)
파라미터타입필수여부설명
idstringYesJob ID
  • 응답 예제
{
    "vo": {
        "seq": 0,
        "modDt": "2017-02-22 14:33:00.402",
        "regDt": "2017-02-22 14:33:00.402",
        "modUserId": "root",
        "regUserId": "root",
        "jobId": "Sleep_Wait_Job",
        "ownerId": "root",
        "groupId": "DEFAULT_GROUP",
        "othersIds": "OTHERS",
        "ownerPermission": "7",
        "groupPermission": "4",
        "othersPermission": "0",
        "permissionOctalValue": "740"
    }
}

Job 실행

Job을 실행시킨다.

  • 사용 가능 권한

ADMINISTRATOR, MANAGER, DEVELOPER

  • 요청 주소
POST /job/:id/run
  • 요청 파라미터 (URL)
파라미터타입필수여부설명
idstringYesJob ID
  • 요청 파라미터 (Body)
파라미터타입필수여부설명
name*stringYesJob 전달 파라미터명
value*stringYesJob 전달 파라미터 값
  • 요청 예제
[
    {
        "name" : "param1",
        "value" : "1000"
    },
    {
        "name" : "param2",
        "value" : "200"
    }
]
  • 응답 예제
{
    "status": {
        "http://10.77.148.47:8081/jjob-controller-rd-web": {
            "dev_message": "success",
            "reqId": 127
        }
    }
}

요청 파라미터 상세

v1.2.5 이후 부터는 Job 의 실행에 관련된 설정이 Job 실행때마다 동적으로 설정되도록 변경할 수 있다. 이때에 사용하는 파라미터들은 다음과 같다.

  • 추가 요청 파라미터 (Body)
파라미터타입필수여부예제설명
jobLogLvlstringNOT동적으로 Job로그를 조정한다. 각각의 문자의 설명은 다음과 같다.
E : Error, I : Info, T : Trace, D : Debug
stepLogLvlstringNOT동적으로 step로그를 조정한다. 각각의 문자의 설명은 다음과 같다.
E : Error, I : Info, T : Trace, D : Debug
logLvlstringNOTT위에 jobLogLvl과 stepLogLvl을 하나의 파라미터로 보낼때 사용한다. 이키워드를 사용할 경우는 위에 설정한 jobLogLvl, stepLogLvl이 무시된다.
priorityintNO9동적으로 Job의 우선순위를 부여한다. 단 해당 Job이 특정 로드밸런스에 할당되어 있을 경우 이 값은 무시된다.
0~9 : 숫자가 높을 수록 우선순위가 높다.
mergeLogstringNOYstep의 로그를 job로그에 같이 기록하기를 원할 때 설정값을 Y로 입력한다. 이때의 로그레벨은 Step의 로그레벨을 따라간다.
groupIdintNO1동적으로 Job이 실행될 서버그룹 ID을 설정한다. 단 해당 Job이 특정 로드밸런스에 할당되어 있을 경우 이 값은 무시된다.
agentGroupIdintNO1동적으로 Job이 실행될 에이전트그룹 ID을 설정한다. 단 해당 Job이 특정 로드밸런스에 할당되어 있을 경우 이 값은 무시된다. 설정한 에이전트 그룹ID가 서버그룹에 소속되지 않은 값을 입력한 경우 Job이 정상적으로 실행되지 않는다.
agentNamestringNOhostname동적으로 Job이 실행될 에이전트명을 설정한다. 단 해당 Job이 특정 로드밸런스에 할당되어 있을 경우 이 값은 무시된다. 설정한 에이전트명이 에이전트그룹에 소속되지 않은 값을 입력한 경우 Job이 정상적으로 실행되지 않는다.
expGpuUsageintNO30GPU 예상 사용량으로 사후에 실행될때 예상값과 실제 사용량값의 통계로 활용될 값이다.
expCpuUsageintNO20CPU 예상 사용량으로 사후에 실행될때 예상값과 실제 사용량값의 통계로 활용될 값이다.
expMemUsageintNO10Memory 예상 사용량으로 사후에 실행될때 예상값과 실제 사용량값의 통계로 활용될 값이다.
expWorkingTimeintNO2[sec] Job의 예상걸린시간으로 사후에 실행될때 예상값과 실제 사용량값의 통계로 활용될 값이다.
  • 요청 예제
[
    {
        "name" : "param1",
        "value" : "1000"
    },
    {
        "name" : "param2",
        "value" : "200"
    },
    {
    	"jobLogLvl": "I"
    },
    {
    	"stepLogLvl": "T"
    },
    {
        "priority": "9"
    },
    {
        "mergeLog": "Y"
    }
]
  • 응답 예제
{
    "status": {
        "http://10.77.148.47:8081/jjob-controller-rd-web": {
            "dev_message": "success",
            "reqId": 127
        }
    }
}
  • 주의 사항

위의 요청 예제에서 보듯 필요한 요청파라미터만 body부에 json 형태로 추가하도록 한다. 만약 비어있는 항목을 json의 key로 요청하고 그에해당 하는 값이 없는 경우에는 입력값 검증에 처리되어 Job 이 실행 되지 않을 수 있다.

Job 자동 생성

Command/Shell Step을 순차 처리하는 Job을 생성한다.
Command/Shell 템플릿 형식만 지원한다.
분기나 병렬처리 등은 지원하지 않는다.
Step 별로 로그 레벨을 설정할 수 있다. (error, warn, debug, trace 4가지 이며 미입력 시 trace가 기본값)
Step의 templateId는 대소문자를 구분한다.("command", "setjob"만 입력)
setjob의 subJobId는 반드시 해당 Job이 등록되어 있어야 하며 실행 권한이 있어야 한다.

생성될 Job이 속할 작업 그룹을 지정할 수 있으며 생략 시 기본 값은 Job을 등록한 사용자가 속한 작업 그룹들로 매핑된다.

  • 사용 가능 권한

ADMINISTRATOR, MANAGER, DEVELOPER

  • 요청 주소
POST /job/create/sequence
  • 요청 파라미터 (Body)
파라미터타입필수여부설명
jobIdstringYesJob ID
namestringNoJob 이름
stepstep_obj[]YesStep 목록
loadBalanceIdstringNoJob이 실행될 로드 밸런스 ID
    1. step_obj 공통 (Body)
파라미터타입필수여부설명
templateIdstringYesTemplate ID, "command", "setjob" 두 가지 지원
namestringNoStep 이름
skipAllExceptionsbooleanNo오류 발생 시 Skip 처리 여부
skipExceptionListstringNo특정 오류 발생 시 Skip 처리
skipRestartWhenFailedOrStoppedbooleanNo재시작 시 Skip 처리 여부
logLevelStringNoStep의 로그 레벨
targetGroupIdStringNoStep 원격 실행구역의 서버그룹ID, "0" 을 입력할 경우 * 처리
targetAgentGroupIdStringNoStep 원격 실행구역의 에이전트그룹ID, "0" 을 입력할 경우 * 처리
targetAgentNameStringNoStep 원격 에이전트명
    1. step_obj 중 templateId가 command일 경우 (Body)
파라미터타입필수여부설명
commandPathstringYesStep이 실행할 command의 경로 정보
commandstringYesStep이 실행할 command
argumentsstringNocommand 실행시 사용할 argument 정보
    1. step_obj 중 templateId가 setjob일 경우 (Body)
파라미터타입필수여부설명
subJobIdstringYesStep이 호출할 하위 Job ID
callTypestringYes호출 유형, "REQUEST", "INSTANCE" 두 가지 지원
timeOutstringYes등록된 Job을 호출하는 타임아웃
groupIdintegerNo실행될 서버그룹을 지정합니다.
agentGroupIdintegerNo실행될 에이전트 그룹을 지정합니다.
agentNamestringNo실행될 에이전트를 지정합니다.
jobLogLvlstringNo실행될 Job 로그레벨을 동적으로 설정합니다. T(trace), I(info), D(debug), E(error)
stepLogLvlstringNo실행될 Step 로그레벨을 동적으로 설정합니다. T(trace), I(info), D(debug), E(error)
mergeLogstringNoJob 로그에 하위에 있는 Step 의 로그를 모아보기합니다. Y(사용), N(사용안함)
  • 요청 예제
{
	"jobId" : "testJob1",
	"name" : "테스트 Job",
	"loadBalanceId" : "111",
  "groups" : ["FIRST_GROUP", "SECOND_GROUP"],
	"step" : [
    {
			"templateId" : "command",
			"name" : "step1",
			"commandPath": "/bin",
			"command" : "ls",
			"arguments" : "-al",
            "skipAllExceptions" : "true",
			"skipExceptionList" : "",
            "skipRestartWhenFailedOrStopped" : "true"
    },
		{
			"templateId" : "setjob",
			"subJobId": "Dummy_Job",
			"callType" : "REQUEST",
			"timeOut" : "0",
			"skipAllExceptions" : "true",
			"skipExceptionList" : "",
            "skipRestartWhenFailedOrStopped" : "true",
            "groupId" : "0",
            "agentGroupId" : "0",
            "agentName" : "",
            "jobLogLvl" : "T",
            "stepLogLvl" : "T",
            "mergeLog" : "Y"
    }
	]
}
  • 응답 예제
{
    "jobId": "testJob1"
}

Job Step Overview 조회

Job에 속한 Step들의 구조를 json 으로 보여준다. Step의 순차적인 흐름을 배열로 나타내며 분기와 병렬처리는 각각의 하위 Step 흐름을 보여준다. setjob의 경우는 하위 Job의 정보를 포함하여 조회한다.

  • 사용 가능 권한

ADMINISTRATOR, MANAGER, DEVELOPER

  • 요청 주소
GET /job/:id/step
  • 요청 파라미터 (URL)
파라미터타입필수여부설명
idstringYesJob ID
filter:detailbooleanNo조회 결과에 Step의 Property 포함 여부
  • 요청 예제
http://127.0.0.1/jjob-manager/api/v1/job/testJob1/step?filter:detail=false

  • 응답 예제
{
  "jobId": "testJob1",
  "step":[
    {
      "split_0":[
        {
          "name": "Dummy",
          "templateId": "dummy",
          "id": "Batchlet_0lpwwov"
        }
      ],
      "split_1":[
        {
          "name": "Dummy",
          "templateId": "dummy",
          "id": "Batchlet_0zrwv1z"
        }
      ]
    },
    {
      "name": "Command/Shell",
      "templateId": "command",
      "id": "Batchlet_1eh4cfa"
    },
    {
      "decision_*":[
        {
        "name": "Dummy",
        "templateId": "dummy",
        "id": "Batchlet_0mfzx7d"
        }
      ],
      "decision_COMPLETED":[
        {
          "name": "Job",
          "templateId": "setjob",
          "id": "Batchlet_03wgvn3",
          "subJobId": "Dummy_Job",
          "subJobStep":[
            {
            "name": "Dummy",
            "templateId": "dummy",
            "id": "Batchlet_1olmzc1"
            }
          ]
        }
      ]
    }
  ]
}

2.2 Job Request API

Job Request 목록 조회

Job 요청 목록을 조회한다.

  • 사용 가능 권한

ADMINISTRATOR, MANAGER, DEVELOPER, GUEST

  • 요청 주소
GET /job/request/list
  • 요청 파라미터 (URL)
파라미터타입필수여부설명
filter:searchStartDatestingYes시작시간 (yyyyMMddHHmmss) 필터링
filter:searchEndDatestingYes종료시간 (yyyyMMddHHmmss) 필터링
filter:reqIdintNoRequest ID 필터링
filter:idListint[]No다건 Request ID 필터링
filter:jobIdstringNoJob ID 필터링
filter:searchJobIdstringNoJob ID LIKE 검색 필터링
filter:namestringNoJob 명 LIKE 검색 필터링
filter:workerGroupIdintNoAgent Group ID 필터링
filter:execIdintNoExecution ID 필터링
filter:instanceIdintNoInstance ID 필터링
filter:statusstringNo상태 필터링
- pending : PENDING
- done : COMPLETED
- error : FAILED
- running : RUNNING
filter:statusMajorstring[]NoMAJOR 상태 필터링
- C : COMPLETE
- F : FETCHED
- P : PENDING
filter:statusMinorstring[]NoMINOR 상태 필터링
- N : NORMAL
- W : WAITING
- E : ERROR
- S : STOP
filter:scheduleNamestringNo스케줄 이름 필터링
  • 응답 예제
{
    "param": {},
    "list": [
        {
            "seq": 0,
            "modDt": null,
            "regDt": null,
            "modUserId": null,
            "regUserId": null,
            "msg": null,
            "jobId": "Sleep_Wait_Job",
            "name": "Sleep Wait Job",
            "searchJobId": null,
            "groupId": null,
            "agentId": null,
            "instanceId": "193",
            "execId": "193",
            "scheduleId": null,
            "scheduleName": null,
            "exceptionId": null,
            "message": null,
            "status": "COMPLETED",
            "exitStatus": null,
            "createDate": null,
            "endDate": null,
            "durationTime": 7163,
            "timeOffset": null,
            "reqId": 225,
            "reqRcvDate": "2017-03-02 13:49:12",
            "jobParam": "1&sleep&4&1000",
            "jobParamText": "sleep=1000",
            "statusMajor": "C",
            "statusMinor": "E",
            "workerGroupId": 1,
            "workerAgentId": 1,
            "workerId": 2,
            "jobStartDate": null,
            "fetchDate": null,
            "completeDate": null
        },
        {
            "seq": 0,
            "modDt": null,
            "regDt": null,
            "modUserId": null,
            "regUserId": null,
            "msg": null,
            "jobId": "Sleep_Wait_Job",
            "name": "Sleep Wait Job",
            "searchJobId": null,
            "groupId": null,
            "agentId": null,
            "instanceId": "172",
            "execId": "172",
            "scheduleId": null,
            "scheduleName": null,
            "exceptionId": null,
            "message": null,
            "status": "COMPLETED",
            "exitStatus": null,
            "createDate": null,
            "endDate": null,
            "durationTime": 1,
            "timeOffset": null,
            "reqId": 209,
            "reqRcvDate": "2017-02-28 17:03:48",
            "jobParam": "1&sleep&4&1000",
            "jobParamText": "sleep=1000",
            "statusMajor": "C",
            "statusMinor": "N",
            "workerGroupId": 1,
            "workerAgentId": 1,
            "workerId": 2,
            "jobStartDate": null,
            "fetchDate": null,
            "completeDate": null
        }
    ]
}

Job Request 조회

Job 요청에 대한 정보를 조회한다.

  • 사용 가능 권한

ADMINISTRATOR, MANAGER, DEVELOPER, GUEST

  • 요청 주소
GET /job/request/:id
  • 요청 파라미터 (URL)
파라미터타입필수여부설명
idintYesJob Request ID
  • 응답 예제
{
    "vo": {
        "seq": 0,
        "modDt": null,
        "regDt": null,
        "modUserId": null,
        "regUserId": null,
        "msg": null,
        "jobId": "Sleep_Wait_Job",
        "name": null,
        "searchJobId": null,
        "groupId": null,
        "agentId": null,
        "instanceId": null,
        "execId": null,
        "scheduleId": null,
        "scheduleName": null,
        "exceptionId": null,
        "message": null,
        "status": null,
        "exitStatus": null,
        "createDate": null,
        "endDate": null,
        "durationTime": 1,
        "timeOffset": null,
        "reqId": 209,
        "reqRcvDate": "2017-02-28 17:03:48",
        "jobParam": "1&sleep&4&1000",
        "jobParamText": "sleep=1000",
        "statusMajor": "C",
        "statusMinor": "N",
        "workerGroupId": 1,
        "workerAgentId": 1,
        "workerId": 2,
        "jobStartDate": null,
        "fetchDate": "2017-02-28 17:03:49",
        "completeDate": "2017-02-28 17:03:50"
    }
}

Job 요청 결과 상태 별 개수 조회

Job 요청 결과 상태 별 개수를 조회한다.

  • 사용 가능 권한

ADMINISTRATOR, MANAGER, DEVELOPER, GUEST

  • 요청 주소
GET /job/request/status/count
  • 요청 파라미터 (URL)
파라미터타입필수여부설명
filter:reqIdintNoRequest ID 필터링
filter:idListint[]No다건 Request ID 필터링
filter:jobIdstringNoJob ID 필터링
filter:searchJobIdstringNoJob ID LIKE 검색 필터링
filter:workerGroupIdintNoAgent Group ID 필터링
filter:execIdintNoExecution ID 필터링
filter:instanceIdintNoInstance ID 필터링
filter:statusMajorstring[]NoMAJOR 상태 필터링
- C : COMPLETE
- F : FETCHED
- P : PENDING
filter:statusMinorstring[]NoMINOR 상태 필터링
- N : NORMAL
- W : WAITING
- E : ERROR
filter:scheduleNamestringNo스케줄 이름 필터링
filter:searchStartDatestingNo시작시간 필터링
filter:searchEndDatestingNo종료시간 필터링
  • 응답 예제
[
    {
        "count": 1,
        "statusMinor": "E",
        "statusMajor": "C"
    },
    {
        "count": 58,
        "statusMinor": "N",
        "statusMajor": "C"
    }
]

2.3 Job Instance API

Job Instance 조회

단건의 Job Instance를 조회한다.

  • 사용 가능 권한

ADMINISTRATOR, MANAGER, DEVELOPER, GUEST

  • 요청 주소
GET /job/instance/:id
  • 요청 파라미터 (URL)
파라미터타입필수여부설명
idstringNoJob Instance ID
  • 응답 예제
{
    "vo": {
        "seq": 0,
        "modDt": null,
        "regDt": null,
        "modUserId": null,
        "regUserId": null,
        "msg": null,
        "jobId": "Sleep_Wait_Job",
        "name": null,
        "searchJobId": null,
        "groupId": "1",
        "agentId": "1",
        "instanceId": "3",
        "execId": null,
        "scheduleId": null,
        "scheduleName": null,
        "exceptionId": "",
        "message": null,
        "status": "COMPLETED",
        "exitStatus": "done",
        "createDate": "2017-03-03 13:37:19",
        "endDate": "2017-03-03 13:37:20",
        "durationTime": 1,
        "timeOffset": null,
        "description": "Sleep Wait Job",
        "execCount": 1
    }
}

2.4 Job Execution API

Job Execution 목록 조회

Job Execution 목록을 조회한다.

  • 사용 가능 권한

ADMINISTRATOR, MANAGER, DEVELOPER, GUEST

  • 요청 주소
GET /job/execution/list
  • 요청 파라미터 (URL)
파라미터타입필수여부설명
filter:instanceIdstringYesJob Instance ID 필터링
filter:idListstringNo다건 Job Execution ID 필터링
filter:execIdstringNoJob Execution ID 필터링
filter:parentExecIdstringNo부모 Job Execution ID 필터링
filter:jobIdstringNoJob ID 필터링
filter:searchJobIdstringNoJob ID LIKE 검색 필터링
filter:descriptionstringNoDescription LIKE 검색 필터링
filter:groupIdintNoAgent Group ID 필터링
filter:agentIdintNoAgent ID 필터링
filter:statusstringNo상태 필터링
- STARTING
- STARTED
- STOPPING
- STOPPED
- FAILED
- COMPLETED
- ABANDONED
filter:exitStatusstringNo종료 상태 필터링
- done
- fail
filter:exceptionIdstringNo실패 Exception ID 필터링
filter:scheduleNamestringNo스케줄 명 필터링
filter:searchStartDatestringNo시작시간 필터링
filter:searchEndDatestringNo종료시간 필터링

Job Execution 조회

단건의 Job Execution 결과를 조회한다.

  • 사용 가능 권한

ADMINISTRATOR, MANAGER, DEVELOPER, GUEST

  • 요청 주소
GET /job/execution/:id
  • 요청 파라미터 (URL)
파라미터타입필수여부설명
idintYesJob Execution ID
  • 응답 예제
{
    "vo": {
        "seq": 0,
        "modDt": null,
        "regDt": null,
        "modUserId": null,
        "regUserId": null,
        "msg": null,
        "jobId": "Sleep_Wait_Job",
        "name": null,
        "searchJobId": null,
        "groupId": "1",
        "agentId": "1",
        "instanceId": "3",
        "execId": "3",
        "scheduleId": null,
        "scheduleName": null,
        "exceptionId": "",
        "message": null,
        "status": "COMPLETED",
        "exitStatus": "done",
        "createDate": "2017-03-03 13:37:19",
        "endDate": "2017-03-03 13:37:20",
        "durationTime": 1,
        "timeOffset": null,
        "parentExecId": "3",
        "description": "Sleep Wait Job",
        "execCount": 0,
        "params": "sleep=1000\n",
        "restartable": "true",
        "ip": "10.77.148.47:8081",
        "logFile": "20170303\\Sleep_Wait_Job_3_20170303",
        "callerInstanceId": null
    }
}

Job Execution 제어

Job에 대해 신호를 보내 Job을 제어한다.

  • 사용 가능 권한

ADMINISTRATOR, MANAGER, DEVELOPER

  • 요청 주소
POST /job/execution/:id/signal
  • 요청 파라미터 (URL) | 파라미터 | 타입 | 필수여부 | 설명 | | --------------- | ------------ | ----------- | -------------------------- | | id | int | Yes | Job Execution ID |

  • 요청 파라미터 (Body) | 파라미터 | 타입 | 필수여부 | 설명 | | --------------- | ------------ | ----------- | -------------------------- | | jobId | string | yes | Job ID | | instanceId | string | yes | Job Instance ID | | executionId | string | yes | Job 실행 ID | | agentName | string | yes | 실행 Agent 명 | | controlType | string | yes | 신호 타입
    - STOP
    - RESTART
    - ABANDON|

  • 요청 예제

요청 URL : http://localhost:18080/jjob-manager/api/v1/job/execution/44/signal

Body :

{  
  "jobId":"dummy_job",
  "instanceId":"45",
  "executionId":"44",
  "agentName":"LCNC16V0282_1",
  "controlType":"RESTART"
}
  • 응답 예제
{
    "status": {
        "http://10.77.148.47:8081/jjob-controller-rd-web/SendSignal.do": {
            "dev_message": "success"
        }
    }
}

Job Execution 로그 조회

Stream 방식

실행한 Job에 대한 결과 로그를 stream(Plain Text)으로 받을 수 있다.

  • 사용 가능 권한

ADMINISTRATOR, MANAGER, DEVELOPER, GUEST

  • 요청 주소
GET /job/execution/:id/log/stream
  • 요청 파라미터 (URL)
파라미터타입필수여부설명
idstringYesJob 실행 ID
  • 응답 예제
[2017-10-16 16:52:31]  INFO (impl.JobInstanceImpl - execute:126) - job execute
[2017-10-16 16:52:31]  INFO (impl.JobInstanceImpl - mainExecute:254) - Job Instance :: executionId::26426847 jobParam:: {}
[2017-10-16 16:52:31] DEBUG (runtime.AbstractJobExecution - beforeRunExecute:301) -

[2017-10-16 16:52:31] DEBUG (runtime.AbstractJobExecution - beforeRunExecute:302) - ===========================Job Execute=================================
[2017-10-16 16:52:31] DEBUG (runtime.AbstractJobExecution - beforeRunExecute:303) -  * Job Start::CommandTest_Partition(26426847)
[2017-10-16 16:52:31] DEBUG (runtime.AbstractJobExecution - beforeRunExecute:304) - =======================================================================
[2017-10-16 16:52:31] DEBUG (runtime.AbstractJobExecution - runExecution:269) -   - Start Job

RandomAccess 방식

일반적으로 조회하려는 로그파일이 작을 때에는 Stream 방식을 사용하여 진행해도 상관없지만 대용량 파일이거나 실행중에 있어 지속적으로 파일을 읽는 API를 호출할 때에는 파일의 처음부터 읽게 되어 불필요한 성능상의 손실이 있게 된다. 이를 방지하기 위해 파일을 읽는 위치를 파라미터로 받아 끝의 위치를 리턴하는 방식을 제공하는 API이다.

  • 사용 가능 권한

ADMINISTRATOR, MANAGER, DEVELOPER, GUEST

  • 요청 주소
GET /job/execution/:id/log/random
  • 요청 파라미터 (URL)
파라미터타입필수여부설명
idstringYesJob 실행 ID
start_poslongNo파일의 시작 Byte 위치
max_bytelongNo응답받을 파일의 최대 byte 수
buffer_sizeintNo파일을 읽는 단위
  • 응답 헤더
파라미터타입필수여부설명
end_posstringYes파일을 읽은 끝의 Byte 위치
start_poslongNo파일의 시작 Byte 위치
max_bytelongNo응답받을 파일의 최대 byte 수
buffer_sizeintNo파일을 읽는 단위
  • 예제

  • 파일의 시작부터 최대 1M를 읽어온다. http://localhost:18080/jjob-manager/api/v1/job/execution/26/log/random?start_pos=0&max_byte=1000000&buffer_size=1000

  • 응답 예제

  • 응답 헤더

JSESSIONID=944E0970843C60A556B11F193F771937; Path=/jjob-manager; HttpOnly
start_pos: 0
buffer_size: 512
max_byte: 2048
end_pos: 00002048
content-type: text/plain;charset=UTF-8
content-length: 2048
date:Wed, 01 Nov 2017 00:57:32 GMT
  • 본문
[2017-10-16 16:52:31]  INFO (impl.JobInstanceImpl - execute:126) - job execute
[2017-10-16 16:52:31]  INFO (impl.JobInstanceImpl - mainExecute:254) - Job Instance :: executionId::26426847 jobParam:: {}
[2017-10-16 16:52:31] DEBUG (runtime.AbstractJobExecution - beforeRunExecute:301) -

[2017-10-16 16:52:31] DEBUG (runtime.AbstractJobExecution - beforeRunExecute:302) - ===========================Job Execute=================================
[2017-10-16 16:52:31] DEBUG (runtime.AbstractJobExecution - beforeRunExecute:303) -  * Job Start::CommandTest_Partition(26426847)
[2017-10-16 16:52:31] DEBUG (runtime.AbstractJobExecution - beforeRunExecute:304) - =======================================================================
[2017-10-16 16:52:31] DEBUG (runtime.AbstractJobExecution - runExecution:269) -   - Start Job
  • 제약사항 및 주의사항
  • max_byte 를 과도하고 높게 설정할 경우 서버 과부하를 발생시킬수 있음
  • buffer_size 너무 작게 설정하면 성능상 이슈가 있을 수 있음 (1024 이상)
  • buffer_size 를 max_size보다 크게 설정할 경우 buffer_size 가 자동으로 max_size로 변경됨
  • start_pos, end_pos 는 파일의 절대위치(byte)임
  • stream을 리턴하게 되므로 String으로 변환할 때 인코딩에 주의해야함
  • 사용자 편의성을 위해 시작 line, 마지막 line으로 받을 수 있으나 Byte 한글처리 및 기타 성능상 제약사항 (line 으로 접근할 경우 skip 메서드를 사용하게 되어 위의 요구사항에 반하게 된다. RandomAccessFile 의 seek 를 최대한 이용했음)
  • buffer_size 의 단위로 ByteArrayOutputStream에 write하기 때문에 내가 정한 max_byte수와 정확히 일치하지 않을 수 있다. cf) if (max_byte > (buffer_size * times) ) return;

Step Execution 결과를 포함한 Job Execution 결과 조회

하위 Step Execution 결과를 포함하여 Job Execution 결과를 조회한다.
하위 Step은 실제로 해당 Job Execution에서 실행된 결과만을 포함한다.
Job이 재실행된 경우 앞선 실행에서 수행된 Step의 결과는 조회되지 않는다.
Step이 setjob일 경우 호출된 Job Execution 결과도 포함한다.

  • 사용 가능 권한

ADMINISTRATOR, MANAGER, DEVELOPER, GUEST

  • 요청 주소
GET /job/execution/:id/step
  • 요청 파라미터 (URL)
파라미터타입필수여부설명
idintYesJob Execution ID
  • 응답 예제
{
 "jobId": "test",
 "status": "FAILED",
 "jobExecId": "742",
 "instanceId": "699",
 "agent": "2",
 "steps":[
   {
     "name": "Dummy",
     "status": "COMPLETED",
     "id": "Batchlet_1wtmz8c",
     "stepExecId": "815",
     "agent": "2",
     "setJobYn": "N",
     "partitionNo": 1,
     "calleeJobExecId": null,
     "child": null
   },
   {
     "name": "Job",
     "status": "COMPLETED",
     "id": "Batchlet_0587da4",
     "stepExecId": "816",
     "agent": "2",
     "setJobYn": "Y",
     "partitionNo": 1,
     "calleeJobExecId": "743",
     "child":{
       "jobId": "Dummy_Job",
       "status": "COMPLETED",
       "jobExecId": "743",
       "instanceId": "700",
       "agent": "1",
       "steps":[
         {
           "name": "Dummy",
           "status": "COMPLETED",
           "id": "Batchlet_1olmzc1",
           "stepExecId": "818",
           "agent": "1",
           "setJobYn": "N",
           "partitionNo": 1,
           "calleeJobExecId": null,
           "child": null
         }
       ]
     }
   },
   {
     "name": "Dummy",
     "status": "FAILED",
     "id": "Batchlet_14axazq",
     "stepExecId": "817",
     "agent": "2",
     "setJobYn": "N",
     "partitionNo": 1,
     "calleeJobExecId": null,
     "child": null
   }
 ]
}

2.5 Step Execution API

Step Execution 목록 조회

Step Execution 목록을 조회한다.

  • 사용 가능 권한

ADMINISTRATOR, MANAGER, DEVELOPER, GUEST

  • 요청 주소
GET /step/execution/list
  • 요청 파라미터 (URL)
파라미터타입필수여부설명
filter:jobExecIdintyesJob Execution ID 필터링
filter:reqIdintNoJob Request ID 필터링
filter:instanceIdintNoJob Instance ID 필터링
filter:execIdintNoStep Execution ID 필터링
filter:stepIdstringNoStep ID 필터링
filter:groupIdintNoAgent Group ID 필터링
filter:agentIdintNoAgent ID 필터링
filter:statusstringNo상태 필터링
- STARTING
- STARTED
- STOPPING
- STOPPED
- FAILED
- COMPLETED
- ABANDONED
filter:exitStatusstringNo종료 상태 필터링
- done
- fail
filter:exceptionIdstringNoException ID 필터링
  • 응답 예제
{
    "param": {},
    "list": [
        {
            "seq": 0,
            "modDt": null,
            "regDt": null,
            "modUserId": null,
            "regUserId": null,
            "msg": null,
            "jobId": null,
            "name": null,
            "searchJobId": null,
            "groupId": "1",
            "agentId": "1",
            "instanceId": "6",
            "execId": "6",
            "scheduleId": null,
            "scheduleName": null,
            "exceptionId": "",
            "message": null,
            "status": "COMPLETED",
            "exitStatus": "done",
            "createDate": "2017-03-03 13:54:43",
            "endDate": "2017-03-03 13:54:44",
            "durationTime": 1,
            "timeOffset": null,
            "jobExecId": 6,
            "stepId": "Sleep_Wait_Step",
            "partitionNo": 0,
            "commitCount": 0,
            "rollbackCount": 0,
            "filterCount": 0,
            "processSkipCount": 0,
            "readCount": 0,
            "readSkipCount": 0,
            "writeCount": 0,
            "writeSkipCount": 0,
            "ip": "10.77.148.47:8081",
            "logFile": "20170303\\Sleep_Wait_Step_6_20170303",
            "reqId": "6",
            "reqExecId": null,
            "workerGroupId": null,
            "metricList": [
                {
                    "seq": 0,
                    "modDt": null,
                    "regDt": null,
                    "modUserId": null,
                    "regUserId": null,
                    "msg": null,
                    "jobId": null,
                    "name": null,
                    "searchJobId": null,
                    "groupId": "1",
                    "agentId": "1",
                    "instanceId": "6",
                    "execId": "6",
                    "scheduleId": null,
                    "scheduleName": null,
                    "exceptionId": "",
                    "message": null,
                    "status": "COMPLETED",
                    "exitStatus": "done",
                    "createDate": "2017-03-03 13:54:43",
                    "endDate": "2017-03-03 13:54:44",
                    "durationTime": 1,
                    "timeOffset": null,
                    "jobExecId": 6,
                    "stepId": "Sleep_Wait_Step",
                    "partitionNo": 1,
                    "commitCount": 0,
                    "rollbackCount": 0,
                    "filterCount": 0,
                    "processSkipCount": 0,
                    "readCount": 0,
                    "readSkipCount": 0,
                    "writeCount": 0,
                    "writeSkipCount": 0,
                    "ip": "10.77.148.47:8081",
                    "logFile": "20170303\\Sleep_Wait_Step_6_20170303",
                    "reqId": "0",
                    "reqExecId": null,
                    "workerGroupId": null,
                    "metricList": null
                }
            ]
        },
        {
            "seq": 0,
            "modDt": null,
            "regDt": null,
            "modUserId": null,
            "regUserId": null,
            "msg": null,
            "jobId": null,
            "name": null,
            "searchJobId": null,
            "groupId": "1",
            "agentId": "1",
            "instanceId": "4",
            "execId": "4",
            "scheduleId": null,
            "scheduleName": null,
            "exceptionId": "",
            "message": null,
            "status": "COMPLETED",
            "exitStatus": "done",
            "createDate": "2017-03-03 13:48:46",
            "endDate": "2017-03-03 13:48:47",
            "durationTime": 1,
            "timeOffset": null,
            "jobExecId": 4,
            "stepId": "Sleep_Wait_Step",
            "partitionNo": 0,
            "commitCount": 0,
            "rollbackCount": 0,
            "filterCount": 0,
            "processSkipCount": 0,
            "readCount": 0,
            "readSkipCount": 0,
            "writeCount": 0,
            "writeSkipCount": 0,
            "ip": "10.77.148.47:8081",
            "logFile": "20170303\\Sleep_Wait_Step_4_20170303",
            "reqId": "4",
            "reqExecId": null,
            "workerGroupId": null,
            "metricList": [
                {
                    "seq": 0,
                    "modDt": null,
                    "regDt": null,
                    "modUserId": null,
                    "regUserId": null,
                    "msg": null,
                    "jobId": null,
                    "name": null,
                    "searchJobId": null,
                    "groupId": "1",
                    "agentId": "1",
                    "instanceId": "4",
                    "execId": "4",
                    "scheduleId": null,
                    "scheduleName": null,
                    "exceptionId": "",
                    "message": null,
                    "status": "COMPLETED",
                    "exitStatus": "done",
                    "createDate": "2017-03-03 13:48:46",
                    "endDate": "2017-03-03 13:48:47",
                    "durationTime": 1,
                    "timeOffset": null,
                    "jobExecId": 4,
                    "stepId": "Sleep_Wait_Step",
                    "partitionNo": 1,
                    "commitCount": 0,
                    "rollbackCount": 0,
                    "filterCount": 0,
                    "processSkipCount": 0,
                    "readCount": 0,
                    "readSkipCount": 0,
                    "writeCount": 0,
                    "writeSkipCount": 0,
                    "ip": "10.77.148.47:8081",
                    "logFile": "20170303\\Sleep_Wait_Step_4_20170303",
                    "reqId": "0",
                    "reqExecId": null,
                    "workerGroupId": null,
                    "metricList": null
                }
            ]
        }
    ]
}

Step Execution 조회

단건의 Step Execution 결과를 조회한다.

  • 사용 가능 권한

ADMINISTRATOR, MANAGER, DEVELOPER, GUEST

  • 요청 주소
GET /step/execution/:id
  • 요청 파라미터 (URL)
파라미터타입필수여부설명
idstringYesStep 실행 ID
  • 응답 예제
{
    "vo": {
        "seq": 0,
        "modDt": null,
        "regDt": null,
        "modUserId": null,
        "regUserId": null,
        "msg": null,
        "jobId": null,
        "name": null,
        "searchJobId": null,
        "groupId": "1",
        "agentId": "1",
        "instanceId": "1",
        "execId": "1",
        "scheduleId": null,
        "scheduleName": null,
        "exceptionId": "",
        "message": null,
        "status": "COMPLETED",
        "exitStatus": "done",
        "createDate": "2017-03-03 11:48:02",
        "endDate": "2017-03-03 11:48:04",
        "durationTime": 2,
        "timeOffset": null,
        "jobExecId": 1,
        "stepId": "Sleep_Wait_Step",
        "partitionNo": 0,
        "commitCount": 0,
        "rollbackCount": 0,
        "filterCount": 0,
        "processSkipCount": 0,
        "readCount": 0,
        "readSkipCount": 0,
        "writeCount": 0,
        "writeSkipCount": 0,
        "ip": "10.77.148.47:8081",
        "logFile": "20170303\\Sleep_Wait_Step_1_20170303",
        "reqId": null,
        "reqExecId": null,
        "workerGroupId": null,
        "metricList": null
    }
}

Step Execution 로그 조회

Stream 방식

실행한 Step에 대한 결과 로그의 내용을 stream(Plain Text)으로 받을 수 있다.

  • 사용 가능 권한

ADMINISTRATOR, MANAGER, DEVELOPER, GUEST

  • 요청 주소
GET /step/execution/:id/log/stream
  • 요청 파라미터 (URL)
파라미터타입필수여부설명
idstringYesStep 실행 ID
  • 응답 예제
[2017-10-16 16:52:32]  INFO (impl.BatchletWorkerImpl - execute:87) - start batchlet
[2017-10-16 16:52:32]  INFO (impl.BatchletWorkerImpl - execute:87) - start batchlet
[2017-10-16 16:52:32]  INFO (impl.BatchletWorkerImpl - execute:87) - start batchlet
[2017-10-16 16:52:32]  INFO (batchlet.CommandLineBatchlet - makeProcessBuilder:73) - in newCommand=/bin/ls
[2017-10-16 16:52:32]  INFO (batchlet.CommandLineBatchlet - makeProcessBuilder:73) - in newCommand=/bin/ls
[2017-10-16 16:52:32]  INFO (batchlet.CommandLineBatchlet - makeProcessBuilder:73) - in newCommand=/bin/ls
[2017-10-16 16:52:32]  INFO (batchlet.CommandLineBatchlet - makeProcessBuilder:90) - out newCommand=/bin/ls
[2017-10-16 16:52:32]  INFO (batchlet.CommandLineBatchlet - makeProcessBuilder:90) - out newCommand=/bin/ls
[2017-10-16 16:52:32]  INFO (batchlet.CommandLineBatchlet - makeProcessBuilder:90) - out newCommand=/bin/ls
[2017-10-16 16:52:32] TRACE (batchlet.CommandLineBatchlet - readLine:111) - META-INF
agent.err
classes
err
err2
lib
repo

[2017-10-16 16:52:32] TRACE (batchlet.CommandLineBatchlet - process:149) - exit value[0]
[2017-10-16 16:52:32] TRACE (batchlet.CommandLineBatchlet - readLine:111) - 합계 24
drwxrwxr-x 3 lena lena 4096 2017-05-11 15:52 classes
drwxrwxr-x 2 lena lena 4096 2017-06-29 15:03 repo
drwxrwxr-x 6 lena lena 4096 2017-08-01 15:11 META-INF
-rw-rw-r-- 1 lena lena  110 2017-09-15 11:44 agent.err
-rw-rw-r-- 1 lena lena    0 2017-09-28 16:43 err
drwxrwxr-x 2 lena lena 4096 2017-09-28 16:43 lib
-rw-rw-r-- 1 lena lena  160 2017-10-16 15:57 err2

[2017-10-16 16:52:32] TRACE (batchlet.CommandLineBatchlet - readLine:111) - 합계 36
drwxrwxr-x  6 lena lena 4096 2017-09-15 11:44 .
drwxrwxr-x 16 lena lena 4096 2017-09-13 02:00 ..
-rw-rw-r--  1 lena lena    0 2017-07-31 15:05 .attach_pid32132
-rw-rw-r--  1 lena lena  302 2017-07-05 15:40 .zip
drwxrwxr-x  6 lena lena 4096 2017-08-01 15:11 META-INF
-rw-rw-r--  1 lena lena  110 2017-09-15 11:44 agent.err
drwxrwxr-x  3 lena lena 4096 2017-05-11 15:52 classes
-rw-rw-r--  1 lena lena    0 2017-09-28 16:43 err
-rw-rw-r--  1 lena lena  160 2017-10-16 15:57 err2
drwxrwxr-x  2 lena lena 4096 2017-09-28 16:43 lib
drwxrwxr-x  2 lena lena 4096 2017-06-29 15:03 repo

[2017-10-16 16:52:32]  INFO (impl.BatchletWorkerImpl - execute:111) - end batchlet
[2017-10-16 16:52:32] TRACE (batchlet.CommandLineBatchlet - process:149) - exit value[0]
[2017-10-16 16:52:32] TRACE (batchlet.CommandLineBatchlet - process:149) - exit value[0]
[2017-10-16 16:52:32]  INFO (impl.BatchletWorkerImpl - execute:111) - end batchlet
[2017-10-16 16:52:32]  INFO (impl.BatchletWorkerImpl - execute:111) - end batchlet

RandomAccess 방식

일반적으로 조회하려는 로그파일이 작을 때에는 Stream 방식을 사용하여 진행해도 상관없지만 대용량 파일이거나 실행중에 있어 지속적으로 파일을 읽는 API를 호출할 때에는 파일의 처음부터 읽게 되어 불필요한 성능상의 손실이 있게 된다. 이를 방지하기 위해 파일을 읽는 위치를 파라미터로 받아 끝의 위치를 리턴하는 방식을 제공하는 API이다.

  • 사용 가능 권한

ADMINISTRATOR, MANAGER, DEVELOPER, GUEST

  • 요청 주소
GET /step/execution/:id/log/random
  • 요청 파라미터 (URL)
파라미터타입필수여부설명
idstringYesStep 실행 ID
start_poslongNo파일의 시작 Byte 위치
max_bytelongNo응답받을 파일의 최대 byte 수
buffer_sizeintNo파일을 읽는 단위
  • 응답 헤더
파라미터타입필수여부설명
end_posstringYes파일을 읽은 끝의 Byte 위치
start_poslongNo파일의 시작 Byte 위치
max_bytelongNo응답받을 파일의 최대 byte 수
buffer_sizeintNo파일을 읽는 단위
  • 예제

  • 파일의 시작부터 최대 1M를 읽어온다. http://localhost:18080/jjob-manager/api/v1/step/execution/26/log/random?start_pos=0&max_byte=1000000&buffer_size=1000

  • 응답 예제

  • 응답 헤더

JSESSIONID=944E0970843C60A556B11F193F771937; Path=/jjob-manager; HttpOnly
start_pos: 0
buffer_size: 512
max_byte: 2048
end_pos: 00002048
content-type: text/plain;charset=UTF-8
content-length: 2048
date:Wed, 01 Nov 2017 00:57:32 GMT
  • 본문
[2017-10-16 16:52:32]  INFO (impl.BatchletWorkerImpl - execute:87) - start batchlet
[2017-10-16 16:52:32]  INFO (impl.BatchletWorkerImpl - execute:87) - start batchlet
[2017-10-16 16:52:32]  INFO (impl.BatchletWorkerImpl - execute:87) - start batchlet
[2017-10-16 16:52:32]  INFO (batchlet.CommandLineBatchlet - makeProcessBuilder:73) - in newCommand=/bin/ls
[2017-10-16 16:52:32]  INFO (batchlet.CommandLineBatchlet - makeProcessBuilder:73) - in newCommand=/bin/ls
[2017-10-16 16:52:32]  INFO (batchlet.CommandLineBatchlet - makeProcessBuilder:73) - in newCommand=/bin/ls
[2017-10-16 16:52:32]  INFO (batchlet.CommandLineBatchlet - makeProcessBuilder:90) - out newCommand=/bin/ls
[2017-10-16 16:52:32]  INFO (batchlet.CommandLineBatchlet - makeProcessBuilder:90) - out newCommand=/bin/ls
[2017-10-16 16:52:32]  INFO (batchlet.CommandLineBatchlet - makeProcessBuilder:90) - out newCommand=/bin/ls
[2017-10-16 16:52:32] TRACE (batchlet.CommandLineBatchlet - readLine:111) - META-INF
agent.err
classes
err
err2
lib
repo

[2017-10-16 16:52:32] TRACE (batchlet.CommandLineBatchlet - process:149) - exit value[0]
[2017-10-16 16:52:32] TRACE (batchlet.CommandLineBatchlet - readLine:111) - 합계 24
drwxrwxr-x 3 lena lena 4096 2017-05-11 15:52 classes
drwxrwxr-x 2 lena lena 4096 2017-06-29 15:03 repo
drwxrwxr-x 6 lena lena 4096 2017-08-01 15:11 META-INF
-rw-rw-r-- 1 lena lena  110 2017-09-15 11:44 agent.err
-rw-rw-r-- 1 lena lena    0 2017-09-28 16:43 err
drwxrwxr-x 2 lena lena 4096 2017-09-28 16:43 lib
-rw-rw-r-- 1 lena lena  160 2017-10-16 15:57 err2

[2017-10-16 16:52:32] TRACE (batchlet.CommandLineBatchlet - readLine:111) - 합계 36
drwxrwxr-x  6 lena lena 4096 2017-09-15 11:44 .
drwxrwxr-x 16 lena lena 4096 2017-09-13 02:00 ..
-rw-rw-r--  1 lena lena    0 2017-07-31 15:05 .attach_pid32132
-rw-rw-r--  1 lena lena  302 2017-07-05 15:40 .zip
drwxrwxr-x  6 lena lena 4096 2017-08-01 15:11 META-INF
-rw-rw-r--  1 lena lena  110 2017-09-15 11:44 agent.err
drwxrwxr-x  3 lena lena 4096 2017-05-11 15:52 classes
-rw-rw-r--  1 lena lena    0 2017-09-28 16:43 err
-rw-rw-r--  1 lena lena  160 2017-10-16 15:57 err2
drwxrwxr-x  2 lena lena 4096 2017-09-28 16:43 lib
drwxrwxr-x  2 lena lena 4096 2017-06-29 15:03 repo

[2017-10-16 16:52:32]  INFO (impl.BatchletWorkerImpl - execute:111) - end batchlet
[2017-10-16 16:52:32] TRACE (batchlet.CommandLineBatchlet - process:149) - exit value[0]
[2017-10-16 16:52:32] TRACE (batchlet.CommandLineBatchlet - process:149) - exit value[0]
[2017-10-16 16:52:32]  INFO (impl.BatchletWorkerImpl - execute:111) - end batchlet
[2017-10-16 16:52:32]  INFO (impl.BatchletWorkerImpl - execute:111) - end batchlet
  • 제약사항 및 주의사항
  • max_byte 를 과도하고 높게 설정할 경우 서버 과부하를 발생시킬수 있음
  • buffer_size 너무 작게 설정하면 성능상 이슈가 있을 수 있음 (1024 이상)
  • buffer_size 를 max_size보다 크게 설정할 경우 buffer_size 가 자동으로 max_size로 변경됨
  • start_pos, end_pos 는 파일의 절대위치(byte)임
  • stream을 리턴하게 되므로 String으로 변환할 때 인코딩에 주의해야함
  • 사용자 편의성을 위해 시작 line, 마지막 line으로 받을 수 있으나 Byte 한글처리 및 기타 성능상 제약사항 (line 으로 접근할 경우 skip 메서드를 사용하게 되어 위의 요구사항에 반하게 된다. RandomAccessFile 의 seek 를 최대한 이용했음)
  • buffer_size 의 단위로 ByteArrayOutputStream에 write하기 때문에 내가 정한 max_byte수와 정확히 일치하지 않을 수 있다. cf) if (max_byte > (buffer_size * times) ) return;

2.6 스케줄 API

스케줄 목록 조회

사용자가 등록한 스케줄 목록을 조회한다.

  • 사용 가능 권한

ADMINISTRATOR, MANAGER, DEVELOPER, GUEST

  • 요청 주소
GET /scheduledjob/list
  • 요청 파라미터 (URL)
파라미터타입필수여부설명
filter:useYnstringNo사용여부 필터링
filter:jobIdstringNoJob ID LIKE 검색 필터링
  • 응답 예제
{
    "param": {},
    "list": [
        {
            "seq": 0,
            "modDt": null,
            "regDt": null,
            "modUserId": null,
            "regUserId": "root",
            "msg": null,
            "jobScheduleId": 1,
            "scheduleType": "date-ui",
            "expression": "0 0 15 ? * THU",
            "jobId": "Sleep_Wait_Job",
            "jobParam": "1&sleep&4&1000",
            "jobParamText": null,
            "description": "test schedule",
            "name": "test_schdule",
            "useYn": "Y",
            "useStartDate": null,
            "useStartDate2": null,
            "useEndDate": null,
            "useEndDate2": null,
            "useStartTime": null,
            "useEndTime": null,
            "timezone": "Asia/Seoul",
            "createDate": "2017-02-23 10:01:32",
            "modifyDate": "2017-02-28 16:44:26",
            "nowDate": null,
            "scheduleSubType": "weekly",
            "exprDay": "1",
            "exprWeekday": "THU",
            "exprHour": "15",
            "exprMinute": "0",
            "exprSecond": "0",
            "prevUseYn": null,
            "modType": 0
        }
    ]
}

스케줄 조회

스케줄에 대한 정보를 조회한다.

  • 사용 가능 권한

ADMINISTRATOR, MANAGER, DEVELOPER, GUEST

  • 요청 주소
GET /scheduledjob/:id
  • 요청 파라미터 (URL)
파라미터타입필수여부설명
idintYes스케줄 ID
  • 응답 예제
{
    "vo": {
        "seq": 0,
        "modDt": null,
        "regDt": null,
        "modUserId": null,
        "regUserId": null,
        "msg": null,
        "jobScheduleId": 1,
        "scheduleType": "date-ui",
        "expression": "0 0 15 ? * THU",
        "jobId": "Sleep_Wait_Job",
        "jobParam": "1&sleep&4&1000",
        "jobParamText": null,
        "description": "test schedule",
        "name": "test_schdule",
        "useYn": "Y",
        "useStartDate": null,
        "useStartDate2": null,
        "useEndDate": null,
        "useEndDate2": null,
        "useStartTime": null,
        "useEndTime": null,
        "timezone": "Asia/Seoul",
        "createDate": "20170223100132",
        "modifyDate": "20170228164426",
        "nowDate": null,
        "scheduleSubType": "weekly",
        "exprDay": "1",
        "exprWeekday": "THU",
        "exprHour": "15",
        "exprMinute": "0",
        "exprSecond": "0",
        "prevUseYn": null,
        "modType": 0
    }
}

2.7 Agent API

프로세스 reload

프로세스에 대한 reload를 요청한다.

  • 사용 가능 권한

ADMINISTRATOR, MANAGER

  • 요청 주소
POST /serversetting/agent/reloadProcess
  • 요청 파라미터 (Body)
파라미터타입필수여부설명
agentNamestringYes에이전트명
selectedAgentIdsstringYes다수의 에이전트 ID(콤마로 구분)

Agent 재시작

Agent의 재시작을 요청한다.

  • 사용 가능 권한

ADMINISTRATOR, MANAGER

  • 요청 주소
POST /serversetting/agent/restartAgent
  • 요청 파라미터 (Body)
파라미터타입필수여부설명
agentNamestringYes에이전트명
selectedAgentIdsstringYes다수의 에이전트 ID(콤마로 구분)

Agent 중지

Agent를 중지한다.

  • 사용 가능 권한

ADMINISTRATOR, MANAGER

  • 요청 주소
POST /serversetting/agent/stopAgent
  • 요청 파라미터 (Body)
파라미터타입필수여부설명
agentNamestringYes에이전트명
selectedAgentIdsstringYes다수의 에이전트 ID(콤마로 구분)

Agent 프로세스 중지(KILL)

Agent의 특정 프로세스를 PID로 kill(중지)한다.

  • 사용 가능 권한

ADMINISTRATOR, MANAGER

  • 요청 주소
POST /serversetting/agent/killPid
  • 요청 파라미터 (Body)
파라미터타입필수여부설명
agentNamestringYes에이전트명
pidstringYes중지할 프로세스 ID(PID)

3.예제

예제에서는 위의 API를 연결하여 확인할 때 자주 사용것에 대한 예제이다. 아래의 예제를 수행하기전에 위의 Rest API를 먼저 사용해서 private-token 의 사용법, POST의 Body부에 json 형태로 파라미터 보내기 등을 실습을 해보도록 한다. 일반적인 Http 호출에 관한 부분의 가이드는 이 문서에서 하지 않는다.

Job 실행부터 로그확인까지 따라해보기

사용자 가이드에도 나와있지만 Job이 실행되면 생기는 여러가지 ID들에서 간략하게 설명하자면

  • Job을 실행하면 하나의 요청ID(reqId)와 하나의 Job 인스턴스ID(instanceId)가 나온다.
  • 하나의 Job 인스턴스ID(instanceId)는 Job의 재실행, 병렬처리등의 이유로 여러개의 Job 실행ID(jobExecId) 가 나올수 있다.
  • 하나의 Job 실행ID(jobExecID)는 (당연히) 여러개의 Step 실행ID(stepExecID)를 가질 수 있다.

아래의 예는 JobID가 Dummy_Job 을 실행하고 로그확인까지 하는 것을 일련의 과정으로 설명하겠다. 요청시 필요한 파라미터들과 상세내용은 이미 이 문서에 개별적으로 설명이 되어있으므로 참고한다. J-Job Manager는 localhost:18080 에 기동되고 있음을 가정한다.

사전준비

아래의 요청하는 모든 헤더에는 인증된 토큰값이 있어야 한다. 아래의 값은 예제를 위한 것이며 토큰발급에 대한 설명은 이 문서에 이미 소개되어있다.

private-token: 8f2efab460af0433ec23

Job을 실행하기

Dummy_Job 이라는 Job이 이미 등록되어있음을 가정하고 아래의 API를 실행한다. (Dummy_Job은 기본예제에 포함되어 있다. Job목록에서 확인가능)

  • Method : POST
  • URL : http://localhost:18080/jjob-manager/api/v1/job/Dummy_Job/run
  • Body content type : application/json
  • Body :
[]
  • 응답 :
{
  "status": {
      "result": {
          "dev_message": "success",
          "reqId": "45"
      }
  }
}
  • 응답 설명
keyvalue설명
status.result.dev_messagesuccess상태를 응답받는 곳이다. 성공한 것을 확인 할 수 있다.
status.result.reqId45요청ID(reqID)값이 45로 리턴된 것을 확인 할 수 있다.

실행된 Job의 요청내역 조회

위에서 응답받은 요청ID(reqID=4)를 자세히 조회하면 해당건에 자세한 정보를 확인 할 수 있다.
자세한 사항은 Job Request 조회를 참고한다.

  • Method : GET
  • URL : http://localhost:18080/jjob-manager/api/v1/job/request/45
  • Body content type : application/json
  • 응답 :
{
    "vo": {
        "seq": 0,
        "modDt": null,
        "regDt": null,
        "modUserId": null,
        "regUserId": null,
        "msg": null,
        "jobId": "dummy_job",
        "name": null,
        "searchJobId": null,
        "groupId": "1",
        "serverId": "1",
        "agentId": null,
        "agentName": null,
        "instanceId": "43",
        "execId": "41",
        "scheduleId": null,
        "scheduleName": null,
        "exceptionId": null,
        "message": null,
        "status": "COMPLETED",
        "exitStatus": null,
        "createDate": null,
        "endDate": null,
        "durationTime": 1970,
        "timeOffset": null,
        "params": null,
        "reqId": 45,
        "parentReqId": null,
        "reqRcvDate": "2017-11-28 13:11:36",
        "jobParam": "",
        "jobParamText": "",
        "statusMajor": "C",
        "statusMinor": "N",
        "workerId": 1,
        "jobStartDate": null,
        "fetchDate": "2017-11-28 13:44:18",
        "completeDate": "2017-11-28 13:44:26",
        "reqUserId": "root",
        "jobExecutionVo": {
            "seq": 0,
            "modDt": null,
            "regDt": null,
            "modUserId": null,
            "regUserId": null,
            "msg": null,
            "jobId": "Dummy_Job",
            "name": null,
            "searchJobId": null,
            "groupId": "1",
            "serverId": "1",
            "agentId": "1",
            "agentName": "LCNC16V0282_1",
            "instanceId": "43",
            "execId": "41",
            "scheduleId": null,
            "scheduleName": null,
            "exceptionId": "",
            "message": null,
            "status": "COMPLETED",
            "exitStatus": "COMPLETED",
            "createDate": "2017-11-28 13:44:21",
            "endDate": "2017-11-28 13:44:26",
            "durationTime": 5,
            "timeOffset": null,
            "params": null,
            "parentExecId": "41",
            "description": null,
            "execCount": 0,
            "restartable": null,
            "ip": null,
            "logFile": null,
            "callerInstanceId": null
        }
    }
}
  • 응답 설명 위의 값들 중에서 꼭 필요한 것들만 발췌해서 설명하겠다. 나머지 정보들의 설명은 위의 개별 API내용을 참고하라.
keyvalue설명
vo.reqId45조회된 요청정보의 ID 이다.
vo.statusCOMPLETED요청상태값
vo.instanceId43Job이 실행이 되면 생기는 인스턴스ID이다. 만약 실행이 되지 않았다면 null을 응답할 것이다.
vo.execId41Job이 실행시 생기는 Job실행ID이다. 하나의 인스턴스ID는 여러개의 실행내역을 가지고 있지만 이중에서 가장 최근에 실행된 경우이다. 재시작이나 Job의 구조가 복잡하지 않다면 하나의 Job실행ID를 가질 것이다.

Job실행ID 로그조회 (Job 로그조회)

Job실행ID(jobExecID)별로 하나의 Job로그가 쌓인다. Job 로그를 조회하는 API를 호출하면 아래와 같이 Stream 으로 응답이 온다. 자세한 사항은 로그조회 API를 참고하라

  • Method : GET
  • URL : http://localhost:18080/jjob-manager/api/v1/job/execution/41/log/stream
  • Body content type : application/json
  • 응답 :
[2017-11-28 13:44:21] DEBUG (runtime.AbstractStepExecution - beforeRunExecute:292) -

[2017-11-28 13:44:21] DEBUG (runtime.AbstractStepExecution - beforeRunExecute:293) - -------------------------- Step Execute -------------------------------
[2017-11-28 13:44:21] DEBUG (runtime.AbstractStepExecution - beforeRunExecute:294) -  * Step Start::Batchlet_1olmzc1(78)
[2017-11-28 13:44:21] DEBUG (runtime.AbstractStepExecution - beforeRunExecute:295) - -----------------------------------------------------------------------
[2017-11-28 13:44:26] DEBUG (runtime.AbstractStepExecution - afterRunExecute:266) - -----------------------------------------------------------------------
[2017-11-28 13:44:26] DEBUG (runtime.AbstractStepExecution - afterRunExecute:267) - - Step End:: Batchlet_1olmzc1(78)
[2017-11-28 13:44:26] DEBUG (runtime.AbstractStepExecution - afterRunExecute:268) -          - Batch Status is COMPLETED
[2017-11-28 13:44:26] DEBUG (runtime.AbstractStepExecution - afterRunExecute:269) -          - Exit Status is COMPLETED
[2017-11-28 13:44:26] DEBUG (runtime.AbstractStepExecution - afterRunExecute:270) -          - Next Job Id is COMPLETED
[2017-11-28 13:44:26] DEBUG (runtime.AbstractStepExecution - afterRunExecute:271) - -----------------------------------------------------------------------
[2017-11-28 13:44:26] DEBUG (runtime.AbstractStepExecution - afterRunExecute:272) -

[2017-11-28 13:44:26] DEBUG (runtime.AbstractJobExecution - runExecution:280) -   - End Job [Job Result is ] COMPLETED

Job 실행ID 목록 조회 (Job Execution 목록조회)

요청ID에 최근 실행한 Job실행ID의 값이 있으므로 이 단계는 건너뛰어도 상관없다.

Step 실행ID 목록 조회 (Step Execution 목록조회)

하나의 Job실행ID(jobExecID)에 따라 여러개의 Step실행(stepExecID)가 나올수 있다. 위의 job실행ID의 값이 41 이었으므로 그 값을 파라미터로 요청하면 아래와 같이 응답이 온다.

  • Method : GET
  • URL : http://localhost:18080/jjob-manager/api/v1/step/execution/list?filter:jobExecId=41
  • Body content type : application/json
  • 응답 :
{
    "param": {
      "filter:jobExecId": "41"
    },
    "list": [
        {
            "seq": 0,
            "modDt": null,
            "regDt": null,
            "modUserId": null,
            "regUserId": null,
            "msg": null,
            "jobId": null,
            "name": null,
            "searchJobId": null,
            "groupId": "1",
            "serverId": "1",
            "agentId": "1",
            "agentName": null,
            "instanceId": "44",
            "execId": "80",
            "scheduleId": null,
            "scheduleName": null,
            "exceptionId": "",
            "message": null,
            "status": "COMPLETED",
            "exitStatus": "COMPLETED",
            "createDate": "2017-11-28 13:45:25",
            "endDate": "2017-11-28 13:45:30",
            "durationTime": 5,
            "timeOffset": null,
            "params": null,
            "jobExecId": 41,
            "stepId": "Batchlet_1olmzc1",
            "partitionNo": 0,
            "commitCount": 0,
            "rollbackCount": 0,
            "filterCount": 0,
            "processSkipCount": 0,
            "readCount": 0,
            "readSkipCount": 0,
            "writeCount": 0,
            "writeSkipCount": 0,
            "ip": "127.0.0.1:8080",
            "logFile": "20171128\Batchlet_1olmzc1_80_20171128",
            "reqId": null,
            "reqExecId": null,
            "metricList": [
                  {
                    "seq": 0,
                    "modDt": null,
                    "regDt": null,
                    "modUserId": null,
                    "regUserId": null,
                    "msg": null,
                    "jobId": null,
                    "name": null,
                    "searchJobId": null,
                    "groupId": "1",
                    "serverId": "1",
                    "agentId": "1",
                    "agentName": null,
                    "instanceId": "44",
                    "execId": "80",
                    "scheduleId": null,
                    "scheduleName": null,
                    "exceptionId": "",
                    "message": null,
                    "status": "COMPLETED",
                    "exitStatus": "COMPLETED",
                    "createDate": "2017-11-28 13:45:25",
                    "endDate": "2017-11-28 13:45:30",
                    "durationTime": 5,
                    "timeOffset": null,
                    "params": null,
                    "jobExecId": 41,
                    "stepId": "Batchlet_1olmzc1",
                    "partitionNo": 1,
                    "commitCount": 0,
                    "rollbackCount": 0,
                    "filterCount": 0,
                    "processSkipCount": 0,
                    "readCount": 0,
                    "readSkipCount": 0,
                    "writeCount": 0,
                    "writeSkipCount": 0,
                    "ip": "127.0.0.1:8080",
                    "logFile": "20171128\Batchlet_1olmzc1_80_20171128",
                    "reqId": "0",
                    "reqExecId": null,
                    "metricList": null
                  }
            ]
        }
    ]
}
  • 응답 설명

위의 값들 중에서 꼭 필요한 것들만 발췌해서 설명하겠다. 나머지 정보들의 설명은 위의 개별 API내용을 참고하라.

keyvalue설명
list[0].execId80Step실행ID(stepExecID)이다.
list[0].jobExecId41Job실행ID(jobExecID)이다.
list[0].statusCOMPLETEDStep실행의 상태코드이다.
list[0].exitStatusCOMPLETEDStep실행에 관한 종료코드이다.

종료코드와 상태코드는 Step이 실행완료되면 별도의 커스터마이징을 하지 않는 이상 같은 값이 된다. 즉 종료코드는 Step실행이 종료될 때만 값을 가지지만 상태코드는 처음 시작부터 값을 가진다. 위의 list의 index는 여러개의 Step실행ID를 리턴하므로 생기는 것이다. 예제의 경우에는 Job 안에 하나의 Step만 있기 때문에 index를 0을 넣어 각각의 속성을 조회했다고 보면 된다.

Step실행ID 로그조회 (Step 로그조회)

Step실행ID(stepExecID)별로 하나의 Step로그가 쌓인다. Step 로그를 조회하는 API를 호출하면 아래와 같이 Stream 으로 응답이 온다. 위의 목록조회에서 받은 Step실행ID(stepExecID=80)을 파라미터로 넘긴다. 자세한 사항은 Step로그조회 API를 참고하라

  • Method : GET
  • URL : http://localhost:18080/jjob-manager/api/v1/step/execution/80/log/stream
  • Body content type : application/json
  • 응답 :
[2017-11-28 13:45:25]  INFO (impl.BatchletWorkerImpl - execute:87) - start batchlet
[2017-11-28 13:45:25] DEBUG (batchlet.DelayTestBatch - delay:20) - Sleep Time is 5000 [sec]
[2017-11-28 13:45:25] DEBUG (batchlet.DelayTestBatch - delay:21) - Date :
[2017-11-28 13:45:25] DEBUG (batchlet.DelayTestBatch - delay:25) - Start to wait  5000 [sec]
[2017-11-28 13:45:30] DEBUG (batchlet.DelayTestBatch - delay:27) - End 5000 [sec]
[2017-11-28 13:45:30]  INFO (impl.BatchletWorkerImpl - execute:111) - end batchlet

이렇게 Job을 실행하는 것부터 Step의 로그를 확인하기 까지의 절차를 예제를 중심으로 진행했다.

Rest API를 이용하여 Step Skip 기능 테스트해보기

이번에는 Step Skip 기능을 테스트 해보자. Step Skip 기능이란 해당 Step이 실패하더라도 다음 Step을 진행하도록 하는 기능이다. jjob-manager 화면에서는 각각의 Step 의 실행에서 값을 수정을 할 수 있으며 Rest API를 활용해서 해보도록 하자. 아래의 예제는 윈도우버전을 예를 들어서 진행했지만 Linux 계열도 대동소이하다.

사전 준비

사전에 성공과 실패코드를 리턴해주는 bat 파일을 하나 만들도록 하자.

  • 파일 위치 : C:\
  • 파일명 : error_code_return.bat
  • 파일 내용 :
echo input error code %1
@exit /b %1

해당 bat 파일은 간단하다. argument를 입력받으면 입력받은 값을 종료코드로 리턴한다. 즉 C:\error_code_return.bat 0 을 실행시키면 종료코드인 0을 리턴하고 성공이다. C:\error_code_return.bat 1 을 실행시키면 종료코드인 1을 리턴하고 0이 아닌 모든 값을 실패처리 된다.

Job 생성

  • Method : POST
  • URL : http://localhost:18080/jjob-manager/api/v1/job/create/sequence
  • Body content Type : application/json
  • body :
{
  "jobId": "StepSkipTest01",
  "name": "StepSkip기능테스트 Job",
  "loadBalanceId": "1",
  "step": [
    {
      "templateId": "command",
      "name": "success_step_0",
      "commandPath": "C:\\",
      "command": "error_code_return.bat",
      "arguments": "0",
      "skipAllExceptions": "true",
      "skipExceptionList": "",
      "skipRestartWhenFailedOrStopped": "true"
    },
    {
      "templateId": "command",
      "name": "error_step_1",
      "commandPath": "C:\\",
      "command": "error_code_return.bat",
      "arguments": "1",
      "skipAllExceptions": "true",
      "skipExceptionList": "",
      "skipRestartWhenFailedOrStopped": "true"
    },
    {
      "templateId": "command",
      "name": "success_step_2",
      "commandPath": "C:\\",
      "command": "error_code_return.bat",
      "arguments": "0",
      "skipAllExceptions": "true",
      "skipExceptionList": "",
      "skipRestartWhenFailedOrStopped": "true"
    }
  ]
}

Step의 설정값중에 skipAllExceptions 이 부분이 true가 되면 Step이 실패하더라도 다음 Step을 실행한다.

  • 응답
{
"jobId": "StepSkipTest01"
}

성공적으로 StepSkipTest01 이라는 Job 이 생성되었다. http://localhost:18080/jjob-manager/jjob/#/editor/job/plan/StepSkipTest01 여기로 들어가면 Job이 정상적으로 등록되었는지 확인 할 수 있다. 각각의 Step 을 들어가면 오른쪽 실행 Tab에서 오류발생시 Skip 처리 란에 사용으로 체크되어있는 것도 같이 확인하자.

Job 실행

위에 생성된 Job을 한번 실행해보자.

  • Method : POST
  • URL : http://localhost:18080/jjob-manager/api/v1/job/StepSkipTest01/run
  • Body content type : application/json
  • Body :
[]
  • 응답 :
{
  "status": {
    "result": {
        "dev_message": "success",
        "reqId": "84"
    }
   }
}

성공적으로 Job이 실행되었고 요청 ID는 84번으로 생성되었다.

요청ID 조회

위에서 응답으로 받은 요청ID 84 를 조회해보자. 요청ID는 매번 변경되기 때문에 응답을 받은 값을 아래의 URL에 넣어주어야 한다.

  • Method : GET
  • URL : http://localhost:18080/jjob-manager/api/v1/job/request/84
  • Body content type : application/json
  • 응답 :
{
    "vo": {
        "seq": 0,
        "modDt": null,
        "regDt": null,
        "modUserId": null,
        "regUserId": null,
        "msg": null,
        "jobId": "StepSkipTest01",
        "name": null,
        "searchJobId": null,
        "groupId": "1",
        "serverId": "1",
        "agentId": null,
        "agentName": null,
        "instanceId": "82",
        "execId": "94",
        "scheduleId": null,
        "scheduleName": null,
        "exceptionId": null,
        "message": null,
        "status": "COMPLETED",
        "exitStatus": null,
        "createDate": null,
        "endDate": null,
        "durationTime": 2,
        "timeOffset": null,
        "params": null,
        "reqId": 84,
        "parentReqId": null,
        "reqRcvDate": "2017-12-14 16:48:22",
        "jobParam": "",
        "jobParamText": "",
        "statusMajor": "C",
        "statusMinor": "N",
        "workerId": 1,
        "jobStartDate": null,
        "fetchDate": "2017-12-14 16:48:23",
        "completeDate": "2017-12-14 16:48:24",
        "reqUserId": "root",
        "jobExecutionVo": {
            "seq": 0,
            "modDt": null,
            "regDt": null,
            "modUserId": null,
            "regUserId": null,
            "msg": null,
            "jobId": "StepSkipTest01",
            "name": null,
            "searchJobId": null,
            "groupId": "1",
            "serverId": "1",
            "agentId": "1",
            "agentName": "LCNC16V0282_1",
            "instanceId": "82",
            "execId": "94",
            "scheduleId": null,
            "scheduleName": null,
            "exceptionId": "",
            "message": null,
            "status": "COMPLETED",
            "exitStatus": "COMPLETED",
            "createDate": "2017-12-14 16:48:23",
            "endDate": "2017-12-14 16:48:24",
            "durationTime": 1,
            "timeOffset": null,
            "params": null,
            "parentExecId": "94",
            "description": null,
            "execCount": 0,
            "restartable": null,
            "ip": null,
            "logFile": null,
            "callerInstanceId": null
        }
    }
}

여기서 다음 Job 실행 ID를 가져오기 위해서는 vo.execId 값이 중요하다. 위에 값을 보면 94 번의 실행ID가 생긴것을 알수 있다.

Job 실행ID 조회 (Job Execution 목록조회)

우리가 보고 싶은거는 Step의 목록이기 때문에 이 단계를 건너뛰어도 상관없다.

Step 실행ID 목록 조회 (Step Execution 목록조회)

하나의 Job실행ID(jobExecID)에 따라 여러개의 Step실행(stepExecID)가 나올수 있다. 위의 job실행ID의 값이 94 이었으므로 그 값을 파라미터로 요청하면 아래와 같이 응답이 온다.

  • Method : GET
  • URL : http://localhost:18080/jjob-manager/api/v1/step/execution/list?filter:jobExecId=94
  • Body content type : application/json
  • 응답 :
{
  "param": {
    "filter:jobExecId": "94"
  },
  "list": [
      {
        "execId": "168",
        "status": "COMPLETED",
        "exitStatus": "COMPLETED",
        "createDate": "2017-12-14 16:48:24",
        "endDate": "2017-12-14 16:48:24",
        "jobExecId": 94,
        "stepId": "Batchlet_272c647",
        "commitCount": 1,
        "rollbackCount": 0
      },
      {
        "execId": "167",
        "status": "FAILED",
        "exitStatus": "FAILED",
        "createDate": "2017-12-14 16:48:24",
        "endDate": "2017-12-14 16:48:24",
        "jobExecId": 94,
        "stepId": "Batchlet_c168b18",
        "commitCount": 0,
        "rollbackCount": 1
      },
      {
        "execId": "166",
        "status": "COMPLETED",
        "exitStatus": "COMPLETED",
        "createDate": "2017-12-14 16:48:23",
        "endDate": "2017-12-14 16:48:24",
        "jobExecId": 94,
        "stepId": "Batchlet_d5d0ac6",
        "commitCount": 1,
        "rollbackCount": 0
      }
  ]
}

위 json 응답값은 모든 응답을 보여준 것이 아니라 필요한 것만 발췌했다. 자세히 봐야 할 것은 Step 목록중에 step 실행ID가 167 인 Step이 실패했다는 것이다. 원래 실패한 Step 이 있으면 그 이후의 Step이 진행되지 않는다. 처음에 등록했던데로 3개의 Step이 모두 실행된 것을 확인 할 수 있다. jjob-manager 에서 http://localhost:18080/jjob-manager/jjob/#/execution/execution/detail/94 조회해서 자세히 보면 Job의 실행상태는 COMPLETE 이고 Step 실행페이지에 가보면 중간에 Step이 FAILED 로 된 것을 확인 할 수 있다.

Rest API를 이용하여 재실행 테스트하기

우선 기존의 재실행 방법을 알아보자. 1-2-3 의 Step이 있다고 쳤을 때 2번에서 Step이 실패해서 Job이 멈췄다고 가정하자. 그래서 Job을 재실행 하게 되면 1번은 성공했기 때문에 Skip 하고 2번부터 다시 실행 될 것이다. 그런데 어떤 경우는 실패한 2번을 넘어가고 3번이 실행되기를 바랄때도 있을 것이다. 이런 경우에 사용하는 옵션이 재시작시 Skip처리 기능이다. Job 편집화면에서 Step을 선택한뒤 실행Tab에 가면 설정할 수 있는데 여기에서는 Rest API를 이용해서 재실행 테스트를 해보도록 하자. 여기에서도 위에 Skip Test와 했던 처리가 비슷한데 중지하고 재실행하는 프로세스가 추가된다.

사전 준비

사전에 성공과 실패코드를 리턴해주는 bat 파일을 하나 만들도록 하자.

  • 파일 위치 : C:\
  • 파일명 : error_code_return.bat
  • 파일 내용 :
echo input error code %1
@exit /b %1

해당 bat 파일은 간단하다. argument를 입력받으면 입력받은 값을 종료코드로 리턴한다. 즉 C:\error_code_return.bat 0 을 실행시키면 종료코드인 0을 리턴하고 성공이다. C:\error_code_return.bat 1 을 실행시키면 종료코드인 1을 리턴하고 0이 아닌 모든 값을 실패처리 된다.

Job 생성

  • Method : POST
  • URL : http://localhost:18080/jjob-manager/api/v1/job/create/sequence
  • Body content Type : application/json
  • body :
{
  "jobId": "StepSkipTest02",
  "name": "재시작시 StepSkip기능테스트 Job",
  "loadBalanceId": "1",
  "step": [
    {
      "templateId": "command",
      "name": "success_step_0",
      "commandPath": "C:\\",
      "command": "error_code_return.bat",
      "arguments": "0",
      "skipAllExceptions": "false",
      "skipExceptionList": "",
      "skipRestartWhenFailedOrStopped": "true"
    },
    {
      "templateId": "command",
      "name": "error_step_1",
      "commandPath": "C:\\",
      "command": "error_code_return.bat",
      "arguments": "1",
      "skipAllExceptions": "false",
      "skipExceptionList": "",
      "skipRestartWhenFailedOrStopped": "true"
    },
    {
      "templateId": "command",
      "name": "success_step_2",
      "commandPath": "C:\\",
      "command": "error_code_return.bat",
      "arguments": "0",
      "skipAllExceptions": "false",
      "skipExceptionList": "",
      "skipRestartWhenFailedOrStopped": "true"
    }
  ]
}

Step의 설정값중에 skipRestartWhenFailedOrStopped 이 부분이 true가 되면 Job을 재실행 했을 때에 오류가 발생했던 Step은 넘어가고 3번째 Step이 실행된다. (성공한 Step은 재실행시 다시 실행되지 않는다.)

  • 응답
{
"jobId": "StepSkipTest02"
}

성공적으로 StepSkipTest01 이라는 Job 이 생성되었다. http://localhost:18080/jjob-manager/jjob/#/editor/job/plan/StepSkipTest02 여기로 들어가면 Job이 정상적으로 등록되었는지 확인 할 수 있다. 각각의 Step 을 들어가면 오른쪽 실행 Tab에서 재시작시 Skip 란에 사용으로 체크되어있는 것도 같이 확인하자.

Job 실행

위에 생성된 Job을 한번 실행해보자.

  • Method : POST
  • URL : http://localhost:18080/jjob-manager/api/v1/job/StepSkipTest02/run
  • Body content type : application/json
  • Body :
[]
  • 응답 :
{
  "status": {
    "result": {
        "dev_message": "success",
        "reqId": "87"
    }
   }
}

성공적으로 Job이 실행되었고 요청 ID는 87번으로 생성되었다.

요청ID 조회

위에서 응답으로 받은 요청ID 87 를 조회해보자. 요청ID는 매번 변경되기 때문에 응답을 받은 값을 아래의 URL에 넣어주어야 한다.

  • Method : GET
  • URL : http://localhost:18080/jjob-manager/api/v1/job/request/87
  • Body content type : application/json
  • 응답 :
{
    "vo": {
    "seq": 0,
    "modDt": null,
    "regDt": null,
    "modUserId": null,
    "regUserId": null,
    "msg": null,
    "jobId": "StepSkipTest02",
    "name": null,
    "searchJobId": null,
    "groupId": "1",
    "serverId": "1",
    "agentId": null,
    "agentName": null,
    "instanceId": "85",
    "execId": "98",
    "scheduleId": null,
    "scheduleName": null,
    "exceptionId": null,
    "message": null,
    "status": "FAILED",
    "exitStatus": null,
    "createDate": null,
    "endDate": null,
    "durationTime": 1,
    "timeOffset": null,
    "params": null,
    "reqId": 87,
    "parentReqId": null,
    "reqRcvDate": "2017-12-14 17:27:59",
    "jobParam": "",
    "jobParamText": "",
    "statusMajor": "C",
    "statusMinor": "E",
    "workerId": 1,
    "jobStartDate": null,
    "fetchDate": "2017-12-14 17:27:59",
    "completeDate": "2017-12-14 17:28:00",
    "reqUserId": "root",
    "jobExecutionVo": {
        "seq": 0,
        "modDt": null,
        "regDt": null,
        "modUserId": null,
        "regUserId": null,
        "msg": null,
        "jobId": "StepSkipTest02",
        "name": null,
        "searchJobId": null,
        "groupId": "1",
        "serverId": "1",
        "agentId": "1",
        "agentName": "LCNC16V0282_1",
        "instanceId": "85",
        "execId": "98",
        "scheduleId": null,
        "scheduleName": null,
        "exceptionId": "957f341d-fc00-3052-83a2-cec0eba34aa5",
        "message": null,
        "status": "FAILED",
        "exitStatus": "COMPLETED",
        "createDate": "2017-12-14 17:27:59",
        "endDate": "2017-12-14 17:28:00",
        "durationTime": 1,
        "timeOffset": null,
        "params": null,
        "parentExecId": "98",
        "description": null,
        "execCount": 0,
        "restartable": null,
        "ip": null,
        "logFile": null,
        "callerInstanceId": null
        }
    }
}

상태를 보면 vo.status 가 FAILED로 실패한 것을 알 수 있다. 자세히 확인해 보면 1번 Step은 실행되고 2번 Step에서 실패 된 것을 확인할 수 있을 것이다. Job을 재실행 하기 위해서는 Job의 실행ID, 인스턴스ID, 에이전트명이 필요한데 위에서 응답값을 보면 다 알수 있다.

  • 인스턴스 ID (vo.instanceID) : 85
  • Job 실행ID (vo.instanceID) : 98
  • 에이전트 명 (vo.jobExecutionVo.agentName) = LCNC16V0282_1

Job 재실행

  • Method : POST
  • URL : http://localhost:18080/jjob-manager/api/v1/job/execution/98/signal
  • Body content type : application/json
  • Body :
{  
  "jobId":"StepSkipTest02",
  "instanceId":"85",
  "executionId":"98",
  "agentName":"LCNC16V0282_1",
  "controlType":"RESTART"
}
  • 응답 :
{
  "status": {
    "jobId(StepSkipTest02),instanceId(85),executionId(98),agentName(LCNC16V0282_1),controlType(RESTART),": {
      "dev_message": "success"
    }
  }
}

재실행된 Job 실행ID 확인

Job이 재실행 되면 Job Instance ID는 변화없이 Job실행 ID가 새롭게 생성된다. 정리해보면 한번 실행된 Job을 재실행하면 하나의 Instance ID에 여러개의 Job 실행ID가 생긴다.

  • Method : GET
  • URL : http://localhost:18080/jjob-manager/api/v1/job/execution/list?filter:instanceId=85
  • Body content type : application/json
  • 응답 :
{
  "param": {
  "filter:instanceId": "85"
  },
  "list": [
      {
        "seq": 0,
        "modDt": null,
        "regDt": null,
        "modUserId": null,
        "regUserId": null,
        "msg": null,
        "jobId": "StepSkipTest02",
        "name": null,
        "searchJobId": null,
        "groupId": "1",
        "serverId": "1",
        "agentId": "1",
        "agentName": null,
        "instanceId": "85",
        "execId": "99",
        "scheduleId": null,
        "scheduleName": null,
        "exceptionId": "",
        "message": null,
        "status": "COMPLETED",
        "exitStatus": "COMPLETED",
        "createDate": "2017-12-14 17:35:49",
        "endDate": "2017-12-14 17:35:50",
        "durationTime": 1,
        "timeOffset": null,
        "params": null,
        "parentExecId": "99",
        "description": "재시작시 StepSkip기능테스트 Job",
        "execCount": 0,
        "restartable": null,
        "ip": "127.0.0.1:8080",
        "logFile": "20171214\StepSkipTest02_85_20171214",
        "callerInstanceId": null
      },
      {
        "seq": 0,
        "modDt": null,
        "regDt": null,
        "modUserId": null,
        "regUserId": null,
        "msg": null,
        "jobId": "StepSkipTest02",
        "name": null,
        "searchJobId": null,
        "groupId": "1",
        "serverId": "1",
        "agentId": "1",
        "agentName": null,
        "instanceId": "85",
        "execId": "98",
        "scheduleId": null,
        "scheduleName": null,
        "exceptionId": "957f341d-fc00-3052-83a2-cec0eba34aa5",
        "message": null,
        "status": "FAILED",
        "exitStatus": "COMPLETED",
        "createDate": "2017-12-14 17:27:59",
        "endDate": "2017-12-14 17:28:00",
        "durationTime": 1,
        "timeOffset": null,
        "params": null,
        "parentExecId": "98",
        "description": "재시작시 StepSkip기능테스트 Job",
        "execCount": 0,
        "restartable": null,
        "ip": "127.0.0.1:8080",
        "logFile": "20171214\StepSkipTest02_85_20171214",
        "callerInstanceId": null
      }
  ]
}

위의 조회 결과를 보면 instanceID 85 에 해당하는 두개의 Job 실행ID를 볼수 있다. 98, 99 번 인데 98번이 처음에 실행했던 번호이고 재실행했을 때 받은 Job 실행ID는 99 이다.

Step 실행ID 목록 조회

마찬가지로 이번에는 Job실행ID 가 99 인 Step 들을 확인해 보자.

  • Method : GET
  • URL : http://localhost:18080/jjob-manager/api/v1/step/execution/list?filter:jobExecId=99
  • Body content type : application/json
  • 응답 :
{
  "param": {
    "filter:jobExecId": "99"
  },
  "list": [
    {
      "instanceId": "85",
      "execId": "183",
      "status": "COMPLETED",
      "exitStatus": "COMPLETED",
      "createDate": "2017-12-14 17:35:49",
      "endDate": "2017-12-14 17:35:50",
      "jobExecId": 99,
      "stepId": "Batchlet_b9e2174",
      "commitCount": 1,
      "rollbackCount": 0
    },
    {
      "instanceId": "85",
      "execId": "182",
      "status": "FAILED",
      "exitStatus": "",
      "createDate": "2017-12-14 17:35:49",
      "endDate": "2017-12-14 17:35:49",
      "jobExecId": 99,
      "stepId": "Batchlet_138a916",
      "commitCount": 0,
      "rollbackCount": 0
    },
    {
      "instanceId": "85",
      "execId": "181",
      "status": "COMPLETED",
      "exitStatus": "COMPLETED",
      "createDate": "2017-12-14 17:35:49",
      "endDate": "2017-12-14 17:35:49",
      "jobExecId": 99,
      "stepId": "Batchlet_2ecb373",
      "commitCount": 0,
      "rollbackCount": 0
    }
  ]
}

위에서 확인 할 수 있듯이 두번째 Step (execID = 182) 은 재실행 해도 계속 실패했어야 함에도 불구하고 두번째 Step을 건너뛴뒤에 세번째 Step(execId = 183) 을 실행했다. 이 값이 Job을 생성할때 Step에 파라미터로 넣어줬던 skipRestartWhenFailedOrStopped 의 설정의 역할 이다.