You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@griffin.apache.org by gu...@apache.org on 2018/01/16 09:00:26 UTC

[1/3] incubator-griffin git commit: fix job management sysnc bug and delete job triggerkey not exist bug

Repository: incubator-griffin
Updated Branches:
  refs/heads/master 06f969fea -> 44eea866d


http://git-wip-us.apache.org/repos/asf/incubator-griffin/blob/44eea866/service/src/main/java/org/apache/griffin/core/job/JobController.java
----------------------------------------------------------------------
diff --git a/service/src/main/java/org/apache/griffin/core/job/JobController.java b/service/src/main/java/org/apache/griffin/core/job/JobController.java
index 50f6614..3731d9f 100644
--- a/service/src/main/java/org/apache/griffin/core/job/JobController.java
+++ b/service/src/main/java/org/apache/griffin/core/job/JobController.java
@@ -42,7 +42,7 @@ public class JobController {
     }
 
     @RequestMapping(value = "/jobs", method = RequestMethod.POST)
-    public GriffinOperationMessage addJob(@RequestBody JobSchedule jobSchedule) {
+    public GriffinOperationMessage addJob(@RequestBody JobSchedule jobSchedule) throws Exception {
         return jobService.addJob(jobSchedule);
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-griffin/blob/44eea866/service/src/main/java/org/apache/griffin/core/job/JobInstance.java
----------------------------------------------------------------------
diff --git a/service/src/main/java/org/apache/griffin/core/job/JobInstance.java b/service/src/main/java/org/apache/griffin/core/job/JobInstance.java
index a785fbf..0c8b554 100644
--- a/service/src/main/java/org/apache/griffin/core/job/JobInstance.java
+++ b/service/src/main/java/org/apache/griffin/core/job/JobInstance.java
@@ -150,7 +150,8 @@ public class JobInstance implements Job {
     private Long[] genSampleTs(SegmentRange segRange, DataConnector dc) throws IOException {
         Long offset = TimeUtil.str2Long(segRange.getBegin());
         Long range = TimeUtil.str2Long(segRange.getLength());
-        Long dataUnit = TimeUtil.str2Long(dc.getDataUnit());
+        String unit = dc.getDataUnit();
+        Long dataUnit = TimeUtil.str2Long(unit != null ? unit : dc.getDefaultDataUnit());
         //offset usually is negative
         Long dataStartTime = jobStartTime + offset;
         if (range < 0) {

http://git-wip-us.apache.org/repos/asf/incubator-griffin/blob/44eea866/service/src/main/java/org/apache/griffin/core/job/JobService.java
----------------------------------------------------------------------
diff --git a/service/src/main/java/org/apache/griffin/core/job/JobService.java b/service/src/main/java/org/apache/griffin/core/job/JobService.java
index a210105..33dce25 100644
--- a/service/src/main/java/org/apache/griffin/core/job/JobService.java
+++ b/service/src/main/java/org/apache/griffin/core/job/JobService.java
@@ -32,7 +32,7 @@ public interface JobService {
 
     List<JobDataBean> getAliveJobs();
 
-    GriffinOperationMessage addJob(JobSchedule jobSchedule);
+    GriffinOperationMessage addJob(JobSchedule jobSchedule) throws Exception;
 
     boolean pauseJob(String group, String name) throws SchedulerException;
 

http://git-wip-us.apache.org/repos/asf/incubator-griffin/blob/44eea866/service/src/main/java/org/apache/griffin/core/job/JobServiceImpl.java
----------------------------------------------------------------------
diff --git a/service/src/main/java/org/apache/griffin/core/job/JobServiceImpl.java b/service/src/main/java/org/apache/griffin/core/job/JobServiceImpl.java
index 90c18ec..92188b4 100644
--- a/service/src/main/java/org/apache/griffin/core/job/JobServiceImpl.java
+++ b/service/src/main/java/org/apache/griffin/core/job/JobServiceImpl.java
@@ -44,7 +44,7 @@ import org.springframework.data.domain.Sort;
 import org.springframework.scheduling.annotation.Scheduled;
 import org.springframework.scheduling.quartz.SchedulerFactoryBean;
 import org.springframework.stereotype.Service;
-import org.springframework.transaction.interceptor.TransactionAspectSupport;
+import org.springframework.transaction.annotation.Transactional;
 import org.springframework.util.CollectionUtils;
 import org.springframework.web.client.RestClientException;
 import org.springframework.web.client.RestTemplate;
@@ -53,8 +53,7 @@ import java.io.IOException;
 import java.text.ParseException;
 import java.util.*;
 
-import static org.apache.griffin.core.util.GriffinOperationMessage.CREATE_JOB_FAIL;
-import static org.apache.griffin.core.util.GriffinOperationMessage.CREATE_JOB_SUCCESS;
+import static org.apache.griffin.core.util.GriffinOperationMessage.*;
 import static org.quartz.JobBuilder.newJob;
 import static org.quartz.JobKey.jobKey;
 import static org.quartz.TriggerBuilder.newTrigger;
@@ -140,40 +139,38 @@ public class JobServiceImpl implements JobService {
     }
 
     @Override
-    public GriffinOperationMessage addJob(JobSchedule js) {
+    @Transactional(rollbackFor = Exception.class)
+    public GriffinOperationMessage addJob(JobSchedule js) throws Exception {
         Long measureId = js.getMeasureId();
         GriffinMeasure measure = getMeasureIfValid(measureId);
-        if (measure != null) {
-            return addJob(js, measure);
+        if (measure != null && addJob(js, measure)) {
+            return CREATE_JOB_SUCCESS;
         }
         return CREATE_JOB_FAIL;
     }
 
-    private GriffinOperationMessage addJob(JobSchedule js, GriffinMeasure measure) {
-        String qName = js.getJobName() + "_" + System.currentTimeMillis();
+    private boolean addJob(JobSchedule js, GriffinMeasure measure) throws Exception {
+        String qName = getQuartzName(js);
         String qGroup = getQuartzGroupName();
-        try {
-            if (addJob(js, measure, qName, qGroup)) {
-                return CREATE_JOB_SUCCESS;
-            }
-        } catch (Exception e) {
-            LOGGER.error("Add job exception happens.", e);
-            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
+        TriggerKey triggerKey = triggerKey(qName, qGroup);
+        if (!isJobScheduleParamValid(js, measure) || factory.getObject().checkExists(triggerKey)) {
+            return false;
         }
-        return CREATE_JOB_FAIL;
+        GriffinJob job = new GriffinJob(measure.getId(), js.getJobName(), qName, qGroup, false);
+        jobRepo.save(job);
+        js = jobScheduleRepo.save(js);
+        addJob(triggerKey, js, job);
+        return true;
     }
 
-    private boolean addJob(JobSchedule js, GriffinMeasure measure, String qName, String qGroup) throws SchedulerException, ParseException {
+    private void addJob(TriggerKey triggerKey, JobSchedule js, GriffinJob job) throws Exception {
         Scheduler scheduler = factory.getObject();
-        TriggerKey triggerKey = triggerKey(qName, qGroup);
-        if (!isJobScheduleParamValid(js, measure)) {
-            return false;
-        }
-        if (scheduler.checkExists(triggerKey)) {
-            return false;
-        }
-        GriffinJob job = saveGriffinJob(measure.getId(), js.getJobName(), qName, qGroup);
-        return job != null && saveAndAddQuartzJob(scheduler, triggerKey, js, job);
+        JobDetail jobDetail = addJobDetail(scheduler, triggerKey, js, job);
+        scheduler.scheduleJob(genTriggerInstance(triggerKey, jobDetail, js));
+    }
+
+    private String getQuartzName(JobSchedule js) {
+        return js.getJobName() + "_" + System.currentTimeMillis();
     }
 
     private String getQuartzGroupName() {
@@ -253,24 +250,12 @@ public class JobServiceImpl implements JobService {
     private GriffinMeasure getMeasureIfValid(Long measureId) {
         Measure measure = measureRepo.findByIdAndDeleted(measureId, false);
         if (measure == null) {
-            LOGGER.warn("The measure id {} isn't valid. Maybe it doesn't exist or is deleted.", measureId);
+            LOGGER.warn("The measure id {} isn't valid. Maybe it doesn't exist or is external measure type.", measureId);
             return null;
         }
         return (GriffinMeasure) measure;
     }
 
-    private GriffinJob saveGriffinJob(Long measureId, String jobName, String qName, String qGroup) {
-        GriffinJob job = new GriffinJob(measureId, jobName, qName, qGroup, false);
-        return jobRepo.save(job);
-    }
-
-    private boolean saveAndAddQuartzJob(Scheduler scheduler, TriggerKey triggerKey, JobSchedule js, GriffinJob job) throws SchedulerException, ParseException {
-        js = jobScheduleRepo.save(js);
-        JobDetail jobDetail = addJobDetail(scheduler, triggerKey, js, job);
-        scheduler.scheduleJob(genTriggerInstance(triggerKey, jobDetail, js));
-        return true;
-    }
-
 
     private Trigger genTriggerInstance(TriggerKey triggerKey, JobDetail jd, JobSchedule js) throws ParseException {
         return newTrigger()
@@ -298,8 +283,9 @@ public class JobServiceImpl implements JobService {
 
 
     private void setJobDataMap(JobDetail jd, JobSchedule js, GriffinJob job) {
-        jd.getJobDataMap().put(JOB_SCHEDULE_ID, js.getId().toString());
-        jd.getJobDataMap().put(GRIFFIN_JOB_ID, job.getId().toString());
+        JobDataMap jobDataMap = jd.getJobDataMap();
+        jobDataMap.put(JOB_SCHEDULE_ID, js.getId().toString());
+        jobDataMap.put(GRIFFIN_JOB_ID, job.getId().toString());
     }
 
     private boolean pauseJob(List<JobInstanceBean> instances) {
@@ -337,7 +323,7 @@ public class JobServiceImpl implements JobService {
         JobKey jobKey = new JobKey(name, group);
         if (!scheduler.checkExists(jobKey)) {
             LOGGER.warn("Job({},{}) does not exist.", jobKey.getGroup(), jobKey.getName());
-            return false;
+            return true;
         }
         scheduler.pauseJob(jobKey);
         return true;
@@ -375,7 +361,7 @@ public class JobServiceImpl implements JobService {
     @Override
     public GriffinOperationMessage deleteJob(Long jobId) {
         GriffinJob job = jobRepo.findByIdAndDeleted(jobId, false);
-        return deleteJob(job) ? GriffinOperationMessage.DELETE_JOB_SUCCESS : GriffinOperationMessage.DELETE_JOB_FAIL;
+        return deleteJob(job) ? DELETE_JOB_SUCCESS : DELETE_JOB_FAIL;
     }
 
     /**
@@ -389,14 +375,14 @@ public class JobServiceImpl implements JobService {
         List<GriffinJob> jobs = jobRepo.findByJobNameAndDeleted(name, false);
         if (CollectionUtils.isEmpty(jobs)) {
             LOGGER.warn("There is no job with '{}' name.", name);
-            return GriffinOperationMessage.DELETE_JOB_FAIL;
+            return DELETE_JOB_FAIL;
         }
         for (GriffinJob job : jobs) {
             if (!deleteJob(job)) {
-                return GriffinOperationMessage.DELETE_JOB_FAIL;
+                return DELETE_JOB_FAIL;
             }
         }
-        return GriffinOperationMessage.DELETE_JOB_SUCCESS;
+        return DELETE_JOB_SUCCESS;
     }
 
     private boolean deleteJob(GriffinJob job) {
@@ -419,7 +405,7 @@ public class JobServiceImpl implements JobService {
         JobKey jobKey = new JobKey(name, group);
         if (scheduler.checkExists(jobKey)) {
             LOGGER.warn("Job({},{}) does not exist.", jobKey.getGroup(), jobKey.getName());
-            return false;
+            return true;
         }
         scheduler.deleteJob(jobKey);
         return true;
@@ -435,8 +421,8 @@ public class JobServiceImpl implements JobService {
     public boolean deleteJobsRelateToMeasure(Long measureId) {
         List<GriffinJob> jobs = jobRepo.findByMeasureIdAndDeleted(measureId, false);
         if (CollectionUtils.isEmpty(jobs)) {
-            LOGGER.warn("Measure id {} has no related jobs.", measureId);
-            return false;
+            LOGGER.info("Measure id {} has no related jobs.", measureId);
+            return true;
         }
         for (GriffinJob job : jobs) {
             deleteJob(job);
@@ -563,7 +549,7 @@ public class JobServiceImpl implements JobService {
 
     private Boolean isJobHealthy(Long jobId) {
         Pageable pageable = new PageRequest(0, 1, Sort.Direction.DESC, "tms");
-        List<JobInstanceBean> instances = jobInstanceRepo.findByJobId(jobId,pageable);
+        List<JobInstanceBean> instances = jobInstanceRepo.findByJobId(jobId, pageable);
         return !CollectionUtils.isEmpty(instances) && LivySessionStates.isHealthy(instances.get(0).getState());
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-griffin/blob/44eea866/service/src/main/java/org/apache/griffin/core/job/entity/JobDataSegment.java
----------------------------------------------------------------------
diff --git a/service/src/main/java/org/apache/griffin/core/job/entity/JobDataSegment.java b/service/src/main/java/org/apache/griffin/core/job/entity/JobDataSegment.java
index 7009b5d..b0f81cb 100644
--- a/service/src/main/java/org/apache/griffin/core/job/entity/JobDataSegment.java
+++ b/service/src/main/java/org/apache/griffin/core/job/entity/JobDataSegment.java
@@ -78,4 +78,9 @@ public class JobDataSegment extends AbstractAuditableEntity {
 
     public JobDataSegment() {
     }
+
+    public JobDataSegment(String dataConnectorName, boolean baseline) {
+        this.dataConnectorName =dataConnectorName;
+        this.baseline = baseline;
+    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-griffin/blob/44eea866/service/src/main/java/org/apache/griffin/core/job/entity/JobSchedule.java
----------------------------------------------------------------------
diff --git a/service/src/main/java/org/apache/griffin/core/job/entity/JobSchedule.java b/service/src/main/java/org/apache/griffin/core/job/entity/JobSchedule.java
index 131fe03..1406b5e 100644
--- a/service/src/main/java/org/apache/griffin/core/job/entity/JobSchedule.java
+++ b/service/src/main/java/org/apache/griffin/core/job/entity/JobSchedule.java
@@ -41,8 +41,6 @@ import javax.validation.constraints.NotNull;
 import java.io.IOException;
 import java.util.*;
 
-@Configurable(preConstruction = true)
-@Component
 @Entity
 public class JobSchedule extends AbstractAuditableEntity {
 
@@ -178,11 +176,11 @@ public class JobSchedule extends AbstractAuditableEntity {
     public JobSchedule() throws JsonProcessingException {
     }
 
-    public JobSchedule(Long measureId, String jobName, String cronExpression, Map configMap, List<JobDataSegment> segments) throws JsonProcessingException {
+    public JobSchedule(Long measureId, String jobName, String cronExpression,String timeZone, List<JobDataSegment> segments) throws JsonProcessingException {
         this.measureId = measureId;
         this.jobName = jobName;
         this.cronExpression = cronExpression;
-        setConfigMap(configMap);
+        this.timeZone = timeZone;
         this.segments = segments;
     }
 }

http://git-wip-us.apache.org/repos/asf/incubator-griffin/blob/44eea866/service/src/main/java/org/apache/griffin/core/login/LoginController.java
----------------------------------------------------------------------
diff --git a/service/src/main/java/org/apache/griffin/core/login/LoginController.java b/service/src/main/java/org/apache/griffin/core/login/LoginController.java
index a4e997d..47b0ed3 100644
--- a/service/src/main/java/org/apache/griffin/core/login/LoginController.java
+++ b/service/src/main/java/org/apache/griffin/core/login/LoginController.java
@@ -36,8 +36,7 @@ public class LoginController {
     private LoginService loginService;
 
     @RequestMapping(value = "/authenticate", method = RequestMethod.POST)
-    public ResponseEntity<Map<String, Object>> login(
-            @RequestBody Map<String, String> map) {
+    public ResponseEntity<Map<String, Object>> login(@RequestBody Map<String, String> map) {
         return loginService.login(map);
     }
 }

http://git-wip-us.apache.org/repos/asf/incubator-griffin/blob/44eea866/service/src/main/java/org/apache/griffin/core/measure/ExternalMeasureOperationImpl.java
----------------------------------------------------------------------
diff --git a/service/src/main/java/org/apache/griffin/core/measure/ExternalMeasureOperationImpl.java b/service/src/main/java/org/apache/griffin/core/measure/ExternalMeasureOperationImpl.java
index f38982a..ca9aae1 100644
--- a/service/src/main/java/org/apache/griffin/core/measure/ExternalMeasureOperationImpl.java
+++ b/service/src/main/java/org/apache/griffin/core/measure/ExternalMeasureOperationImpl.java
@@ -31,6 +31,8 @@ import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 
+import static org.apache.griffin.core.util.GriffinOperationMessage.*;
+
 @Component("externalOperation")
 public class ExternalMeasureOperationImpl implements MeasureOperation {
     private static final Logger LOGGER = LoggerFactory.getLogger(ExternalMeasureOperationImpl.class);
@@ -45,18 +47,18 @@ public class ExternalMeasureOperationImpl implements MeasureOperation {
         ExternalMeasure em = (ExternalMeasure) measure;
         if (StringUtils.isBlank(em.getMetricName())) {
             LOGGER.error("Failed to create external measure {}. Its metric name is blank.", measure.getName());
-            return GriffinOperationMessage.CREATE_MEASURE_FAIL;
+            return CREATE_MEASURE_FAIL;
         }
         try {
             em.setVirtualJob(new VirtualJob());
             em = measureRepo.save(em);
             VirtualJob vj = genVirtualJob(em, em.getVirtualJob());
             jobRepo.save(vj);
-            return GriffinOperationMessage.CREATE_MEASURE_SUCCESS;
+            return CREATE_MEASURE_SUCCESS;
         } catch (Exception e) {
             LOGGER.error("Failed to create new measure {}.{}", em.getName(), e.getMessage());
         }
-        return GriffinOperationMessage.CREATE_MEASURE_FAIL;
+        return CREATE_MEASURE_FAIL;
     }
 
     @Override
@@ -64,18 +66,18 @@ public class ExternalMeasureOperationImpl implements MeasureOperation {
         ExternalMeasure latestMeasure = (ExternalMeasure) measure;
         if (StringUtils.isBlank(latestMeasure.getMetricName())) {
             LOGGER.error("Failed to create external measure {}. Its metric name is blank.", measure.getName());
-            return GriffinOperationMessage.UPDATE_MEASURE_FAIL;
+            return UPDATE_MEASURE_FAIL;
         }
         try {
             ExternalMeasure originMeasure = measureRepo.findOne(latestMeasure.getId());
             VirtualJob vj = genVirtualJob(latestMeasure, originMeasure.getVirtualJob());
             latestMeasure.setVirtualJob(vj);
             measureRepo.save(latestMeasure);
-            return GriffinOperationMessage.UPDATE_MEASURE_SUCCESS;
+            return UPDATE_MEASURE_SUCCESS;
         } catch (Exception e) {
             LOGGER.error("Failed to update measure. {}", e.getMessage());
         }
-        return GriffinOperationMessage.UPDATE_MEASURE_FAIL;
+        return UPDATE_MEASURE_FAIL;
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/incubator-griffin/blob/44eea866/service/src/main/java/org/apache/griffin/core/measure/GriffinMeasureOperationImpl.java
----------------------------------------------------------------------
diff --git a/service/src/main/java/org/apache/griffin/core/measure/GriffinMeasureOperationImpl.java b/service/src/main/java/org/apache/griffin/core/measure/GriffinMeasureOperationImpl.java
index 88c5409..f21b60d 100644
--- a/service/src/main/java/org/apache/griffin/core/measure/GriffinMeasureOperationImpl.java
+++ b/service/src/main/java/org/apache/griffin/core/measure/GriffinMeasureOperationImpl.java
@@ -37,6 +37,8 @@ import org.springframework.util.CollectionUtils;
 import java.util.ArrayList;
 import java.util.List;
 
+import static org.apache.griffin.core.util.GriffinOperationMessage.*;
+
 @Component("griffinOperation")
 public class GriffinMeasureOperationImpl implements MeasureOperation {
     private static final Logger LOGGER = LoggerFactory.getLogger(GriffinMeasureOperationImpl.class);
@@ -52,26 +54,26 @@ public class GriffinMeasureOperationImpl implements MeasureOperation {
     @Override
     public GriffinOperationMessage create(Measure measure) {
         if (!isConnectorNamesValid((GriffinMeasure) measure)) {
-            return GriffinOperationMessage.CREATE_MEASURE_FAIL;
+            return CREATE_MEASURE_FAIL;
         }
         try {
             measureRepo.save(measure);
-            return GriffinOperationMessage.CREATE_MEASURE_SUCCESS;
+            return CREATE_MEASURE_SUCCESS;
         } catch (Exception e) {
             LOGGER.error("Failed to create new measure {}.", measure.getName(), e);
         }
-        return GriffinOperationMessage.CREATE_MEASURE_FAIL;
+        return CREATE_MEASURE_FAIL;
     }
 
     @Override
     public GriffinOperationMessage update(Measure measure) {
         try {
             measureRepo.save(measure);
-            return GriffinOperationMessage.UPDATE_MEASURE_SUCCESS;
+            return UPDATE_MEASURE_SUCCESS;
         } catch (Exception e) {
             LOGGER.error("Failed to update measure. {}", e.getMessage());
         }
-        return GriffinOperationMessage.UPDATE_MEASURE_FAIL;
+        return UPDATE_MEASURE_FAIL;
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/incubator-griffin/blob/44eea866/service/src/main/java/org/apache/griffin/core/measure/MeasureServiceImpl.java
----------------------------------------------------------------------
diff --git a/service/src/main/java/org/apache/griffin/core/measure/MeasureServiceImpl.java b/service/src/main/java/org/apache/griffin/core/measure/MeasureServiceImpl.java
index ecb9fdd..34a780d 100644
--- a/service/src/main/java/org/apache/griffin/core/measure/MeasureServiceImpl.java
+++ b/service/src/main/java/org/apache/griffin/core/measure/MeasureServiceImpl.java
@@ -33,6 +33,8 @@ import org.springframework.util.CollectionUtils;
 
 import java.util.List;
 
+import static org.apache.griffin.core.util.GriffinOperationMessage.*;
+
 @Service
 public class MeasureServiceImpl implements MeasureService {
     private static final Logger LOGGER = LoggerFactory.getLogger(MeasureServiceImpl.class);
@@ -66,7 +68,7 @@ public class MeasureServiceImpl implements MeasureService {
         List<Measure> aliveMeasureList = measureRepo.findByNameAndDeleted(measure.getName(), false);
         if (!CollectionUtils.isEmpty(aliveMeasureList)) {
             LOGGER.warn("Failed to create new measure {}, it already exists.", measure.getName());
-            return GriffinOperationMessage.CREATE_MEASURE_FAIL_DUPLICATE;
+            return CREATE_MEASURE_FAIL_DUPLICATE;
         }
         MeasureOperation op = getOperation(measure);
         return op.create(measure);
@@ -76,11 +78,11 @@ public class MeasureServiceImpl implements MeasureService {
     public GriffinOperationMessage updateMeasure(Measure measure) {
         Measure m = measureRepo.findByIdAndDeleted(measure.getId(), false);
         if (m == null) {
-            return GriffinOperationMessage.RESOURCE_NOT_FOUND;
+            return RESOURCE_NOT_FOUND;
         }
         if (!m.getType().equals(measure.getType())) {
             LOGGER.error("Can't update measure to different type.");
-            return GriffinOperationMessage.UPDATE_MEASURE_FAIL;
+            return UPDATE_MEASURE_FAIL;
         }
         MeasureOperation op = getOperation(measure);
         return op.update(measure);
@@ -90,17 +92,17 @@ public class MeasureServiceImpl implements MeasureService {
     public GriffinOperationMessage deleteMeasureById(Long measureId) {
         Measure measure = measureRepo.findByIdAndDeleted(measureId, false);
         if (measure == null) {
-            return GriffinOperationMessage.RESOURCE_NOT_FOUND;
+            return RESOURCE_NOT_FOUND;
         }
         try {
             MeasureOperation op = getOperation(measure);
             if (op.delete(measure)) {
-                return GriffinOperationMessage.DELETE_MEASURE_BY_ID_SUCCESS;
+                return DELETE_MEASURE_BY_ID_SUCCESS;
             }
         } catch (Exception e) {
             LOGGER.error("Delete measure id: {} name: {} failure. {}", measure.getId(), measure.getName(), e.getMessage());
         }
-        return GriffinOperationMessage.DELETE_MEASURE_BY_ID_FAIL;
+        return DELETE_MEASURE_BY_ID_FAIL;
     }
 
     private MeasureOperation getOperation(Measure measure) {

http://git-wip-us.apache.org/repos/asf/incubator-griffin/blob/44eea866/service/src/main/java/org/apache/griffin/core/measure/entity/DataConnector.java
----------------------------------------------------------------------
diff --git a/service/src/main/java/org/apache/griffin/core/measure/entity/DataConnector.java b/service/src/main/java/org/apache/griffin/core/measure/entity/DataConnector.java
index 3c4abf5..8a87ea5 100644
--- a/service/src/main/java/org/apache/griffin/core/measure/entity/DataConnector.java
+++ b/service/src/main/java/org/apache/griffin/core/measure/entity/DataConnector.java
@@ -97,13 +97,9 @@ public class DataConnector extends AbstractAuditableEntity {
         return config;
     }
 
-
     @JsonProperty("data.unit")
     public String getDataUnit() {
-        if (dataUnit != null) {
-            return dataUnit;
-        }
-        return defaultDataUnit;
+        return dataUnit;
     }
 
     @JsonProperty("data.unit")
@@ -111,6 +107,14 @@ public class DataConnector extends AbstractAuditableEntity {
         this.dataUnit = dataUnit;
     }
 
+    public String getDefaultDataUnit() {
+        return defaultDataUnit;
+    }
+
+    public void setDefaultDataUnit(String defaultDataUnit) {
+        this.defaultDataUnit = defaultDataUnit;
+    }
+
     public String getName() {
         return name;
     }
@@ -152,6 +156,13 @@ public class DataConnector extends AbstractAuditableEntity {
         });
     }
 
+    public DataConnector(String name, String dataUnit, Map configMap,List<SegmentPredicate> predicates) throws IOException {
+        this.name = name;
+        this.dataUnit = dataUnit;
+        this.configMap = configMap;
+        this.predicates = predicates;
+    }
+
     @Override
     public String toString() {
         return "DataConnector{" +

http://git-wip-us.apache.org/repos/asf/incubator-griffin/blob/44eea866/service/src/main/java/org/apache/griffin/core/measure/entity/GriffinMeasure.java
----------------------------------------------------------------------
diff --git a/service/src/main/java/org/apache/griffin/core/measure/entity/GriffinMeasure.java b/service/src/main/java/org/apache/griffin/core/measure/entity/GriffinMeasure.java
index 3c5c602..c448c0b 100644
--- a/service/src/main/java/org/apache/griffin/core/measure/entity/GriffinMeasure.java
+++ b/service/src/main/java/org/apache/griffin/core/measure/entity/GriffinMeasure.java
@@ -112,4 +112,12 @@ public class GriffinMeasure extends Measure {
         this.evaluateRule = evaluateRule;
     }
 
+    public GriffinMeasure(Long measureId,String name, String owner, List<DataSource> dataSources, EvaluateRule evaluateRule) {
+        this.setId(measureId);
+        this.name = name;
+        this.owner = owner;
+        this.dataSources = dataSources;
+        this.evaluateRule = evaluateRule;
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/incubator-griffin/blob/44eea866/service/src/main/java/org/apache/griffin/core/metric/MetricController.java
----------------------------------------------------------------------
diff --git a/service/src/main/java/org/apache/griffin/core/metric/MetricController.java b/service/src/main/java/org/apache/griffin/core/metric/MetricController.java
index fcaa51d..359858b 100644
--- a/service/src/main/java/org/apache/griffin/core/metric/MetricController.java
+++ b/service/src/main/java/org/apache/griffin/core/metric/MetricController.java
@@ -21,6 +21,7 @@ package org.apache.griffin.core.metric;
 
 import org.apache.griffin.core.metric.model.Metric;
 import org.apache.griffin.core.metric.model.MetricValue;
+import org.apache.griffin.core.util.GriffinOperationMessage;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.http.ResponseEntity;
 import org.springframework.web.bind.annotation.*;
@@ -48,12 +49,12 @@ public class MetricController {
     }
 
     @RequestMapping(value = "/metrics/values", method = RequestMethod.POST)
-    public ResponseEntity addMetricValues(@RequestBody List<MetricValue> values) {
+    public ResponseEntity<GriffinOperationMessage> addMetricValues(@RequestBody List<MetricValue> values) {
         return metricService.addMetricValues(values);
     }
 
     @RequestMapping(value = "/metrics/values", method = RequestMethod.DELETE)
-    public ResponseEntity deleteMetricValues(@RequestParam("metricName") String metricName) {
+    public ResponseEntity<GriffinOperationMessage> deleteMetricValues(@RequestParam("metricName") String metricName) {
         return metricService.deleteMetricValues(metricName);
     }
 }

http://git-wip-us.apache.org/repos/asf/incubator-griffin/blob/44eea866/service/src/main/java/org/apache/griffin/core/metric/MetricService.java
----------------------------------------------------------------------
diff --git a/service/src/main/java/org/apache/griffin/core/metric/MetricService.java b/service/src/main/java/org/apache/griffin/core/metric/MetricService.java
index f68d83c..502f254 100644
--- a/service/src/main/java/org/apache/griffin/core/metric/MetricService.java
+++ b/service/src/main/java/org/apache/griffin/core/metric/MetricService.java
@@ -22,6 +22,7 @@ package org.apache.griffin.core.metric;
 
 import org.apache.griffin.core.metric.model.Metric;
 import org.apache.griffin.core.metric.model.MetricValue;
+import org.apache.griffin.core.util.GriffinOperationMessage;
 import org.springframework.http.ResponseEntity;
 
 import java.util.List;
@@ -33,7 +34,7 @@ public interface MetricService {
 
     List<MetricValue> getMetricValues(String metricName, int offset, int size);
 
-    ResponseEntity addMetricValues(List<MetricValue> values);
+    ResponseEntity<GriffinOperationMessage> addMetricValues(List<MetricValue> values);
 
-    ResponseEntity deleteMetricValues(String metricName);
+    ResponseEntity<GriffinOperationMessage> deleteMetricValues(String metricName);
 }

http://git-wip-us.apache.org/repos/asf/incubator-griffin/blob/44eea866/service/src/main/java/org/apache/griffin/core/metric/MetricServiceImpl.java
----------------------------------------------------------------------
diff --git a/service/src/main/java/org/apache/griffin/core/metric/MetricServiceImpl.java b/service/src/main/java/org/apache/griffin/core/metric/MetricServiceImpl.java
index 68b26eb..4d992e2 100644
--- a/service/src/main/java/org/apache/griffin/core/metric/MetricServiceImpl.java
+++ b/service/src/main/java/org/apache/griffin/core/metric/MetricServiceImpl.java
@@ -41,6 +41,8 @@ import java.util.*;
 import java.util.function.Function;
 import java.util.stream.Collectors;
 
+import static org.apache.griffin.core.util.GriffinOperationMessage.*;
+
 @Service
 public class MetricServiceImpl implements MetricService {
     private static final Logger LOGGER = LoggerFactory.getLogger(MetricServiceImpl.class);
@@ -88,22 +90,22 @@ public class MetricServiceImpl implements MetricService {
     public ResponseEntity addMetricValues(List<MetricValue> values) {
         for (MetricValue value : values) {
             if (!isMetricValueValid(value)) {
-                LOGGER.error("Invalid metric value.");
-                return new ResponseEntity<>(GriffinOperationMessage.ADD_METRIC_VALUES_FAIL, HttpStatus.BAD_REQUEST);
+                LOGGER.warn("Invalid metric value.");
+                return new ResponseEntity<>(ADD_METRIC_VALUES_FAIL, HttpStatus.BAD_REQUEST);
             }
         }
         try {
             for (MetricValue value : values) {
                 metricStore.addMetricValue(value);
             }
-            return new ResponseEntity<>(GriffinOperationMessage.ADD_METRIC_VALUES_SUCCESS, HttpStatus.CREATED);
+            return new ResponseEntity<>(ADD_METRIC_VALUES_SUCCESS, HttpStatus.CREATED);
         } catch (ResponseException e) {
             LOGGER.error("Failed to add metric values. {}", e.getMessage());
             HttpStatus status = HttpStatus.valueOf(e.getResponse().getStatusLine().getStatusCode());
-            return new ResponseEntity<>(GriffinOperationMessage.ADD_METRIC_VALUES_FAIL, status);
+            return new ResponseEntity<>(ADD_METRIC_VALUES_FAIL, status);
         } catch (Exception e) {
             LOGGER.error("Failed to add metric values. {}", e.getMessage());
-            return new ResponseEntity<>(GriffinOperationMessage.ADD_METRIC_VALUES_FAIL, HttpStatus.INTERNAL_SERVER_ERROR);
+            return new ResponseEntity<>(ADD_METRIC_VALUES_FAIL, HttpStatus.INTERNAL_SERVER_ERROR);
         }
     }
 
@@ -112,17 +114,17 @@ public class MetricServiceImpl implements MetricService {
     }
 
     @Override
-    public ResponseEntity deleteMetricValues(String metricName) {
+    public ResponseEntity<GriffinOperationMessage> deleteMetricValues(String metricName) {
         try {
             metricStore.deleteMetricValues(metricName);
-            return ResponseEntity.ok(GriffinOperationMessage.DELETE_METRIC_VALUES_SUCCESS);
+            return ResponseEntity.ok(DELETE_METRIC_VALUES_SUCCESS);
         } catch (ResponseException e) {
             LOGGER.error("Failed to delete metric values named {}. {}", metricName, e.getMessage());
             HttpStatus status = HttpStatus.valueOf(e.getResponse().getStatusLine().getStatusCode());
-            return new ResponseEntity<>(GriffinOperationMessage.DELETE_METRIC_VALUES_FAIL, status);
+            return new ResponseEntity<>(DELETE_METRIC_VALUES_FAIL, status);
         } catch (Exception e) {
             LOGGER.error("Failed to delete metric values named {}. {}", metricName, e.getMessage());
-            return new ResponseEntity<>(GriffinOperationMessage.DELETE_METRIC_VALUES_FAIL, HttpStatus.INTERNAL_SERVER_ERROR);
+            return new ResponseEntity<>(DELETE_METRIC_VALUES_FAIL, HttpStatus.INTERNAL_SERVER_ERROR);
         }
     }
 }

http://git-wip-us.apache.org/repos/asf/incubator-griffin/blob/44eea866/service/src/main/java/org/apache/griffin/core/metric/MetricStoreImpl.java
----------------------------------------------------------------------
diff --git a/service/src/main/java/org/apache/griffin/core/metric/MetricStoreImpl.java b/service/src/main/java/org/apache/griffin/core/metric/MetricStoreImpl.java
index 30b60f9..d055b37 100644
--- a/service/src/main/java/org/apache/griffin/core/metric/MetricStoreImpl.java
+++ b/service/src/main/java/org/apache/griffin/core/metric/MetricStoreImpl.java
@@ -46,7 +46,7 @@ public class MetricStoreImpl implements MetricStore {
 
     private ObjectMapper mapper = new ObjectMapper();
 
-    public MetricStoreImpl(@Value("${elasticsearch.host}") String host, @Value("${elasticsearch.port}") int port) {
+    public MetricStoreImpl(@Value("${elasticsearch.host}") String host, @Value("${elasticsearch.port}") int port) throws IOException {
         client = RestClient.builder(new HttpHost(host, port, "http")).build();
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-griffin/blob/44eea866/service/src/main/resources/application.properties
----------------------------------------------------------------------
diff --git a/service/src/main/resources/application.properties b/service/src/main/resources/application.properties
index f2d83f4..b3f5e94 100644
--- a/service/src/main/resources/application.properties
+++ b/service/src/main/resources/application.properties
@@ -29,24 +29,24 @@ spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5Dialect
 # Naming strategy
 spring.jpa.hibernate.naming-strategy = org.hibernate.cfg.ImprovedNamingStrategy
 
-# hive metastore
+# Hive metastore
 hive.metastore.uris = thrift://localhost:9083
 hive.metastore.dbname = default
 hive.hmshandler.retry.attempts = 15
 hive.hmshandler.retry.interval = 2000ms
+# Hive cache time
+cache.evict.hive.fixedRate.in.milliseconds = 900000
 
-# kafka schema registry
+# Kafka schema registry
 kafka.schema.registry.url = http://localhost:8081
 
-# jobInstance
+# Update job instance state at regular intervals
 jobInstance.fixedDelay.in.milliseconds = 60000
-# default job instance expired time is 7 days that is 604800000 milliseconds
+# Expired time of job instance which is 7 days that is 604800000 milliseconds
 jobInstance.expired.milliseconds = 604800000
 
-# spring cache
-cache.evict.hive.fixedRate.in.milliseconds = 900000
-
-# predicate job
+# schedule predicate job every 5 minutes and repeat 12 times at most
+#interval unit m:minute h:hour d:day,only support these three units
 predicate.job.interval = 5m
 predicate.job.repeat.count = 12
 

http://git-wip-us.apache.org/repos/asf/incubator-griffin/blob/44eea866/service/src/test/java/org/apache/griffin/core/job/JobControllerTest.java
----------------------------------------------------------------------
diff --git a/service/src/test/java/org/apache/griffin/core/job/JobControllerTest.java b/service/src/test/java/org/apache/griffin/core/job/JobControllerTest.java
index d3fdd97..51edad8 100644
--- a/service/src/test/java/org/apache/griffin/core/job/JobControllerTest.java
+++ b/service/src/test/java/org/apache/griffin/core/job/JobControllerTest.java
@@ -1,148 +1,160 @@
-///*
-//Licensed to the Apache Software Foundation (ASF) under one
-//or more contributor license agreements.  See the NOTICE file
-//distributed with this work for additional information
-//regarding copyright ownership.  The ASF licenses this file
-//to you under the Apache License, Version 2.0 (the
-//"License"); you may not use this file except in compliance
-//with the License.  You may obtain a copy of the License at
-//
-//  http://www.apache.org/licenses/LICENSE-2.0
-//
-//Unless required by applicable law or agreed to in writing,
-//software distributed under the License is distributed on an
-//"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-//KIND, either express or implied.  See the License for the
-//specific language governing permissions and limitations
-//under the License.
-//*/
-//
-//package org.apache.griffin.core.job;
-//
-//import org.apache.griffin.core.job.entity.*;
-//import org.apache.griffin.core.util.GriffinOperationMessage;
-//import org.apache.griffin.core.util.JsonUtil;
-//import org.apache.griffin.core.util.URLHelper;
-//import org.junit.Before;
-//import org.junit.Test;
-//import org.junit.runner.RunWith;
-//import org.springframework.beans.factory.annotation.Autowired;
-//import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
-//import org.springframework.boot.test.mock.mockito.MockBean;
-//import org.springframework.http.MediaType;
-//import org.springframework.test.context.junit4.SpringRunner;
-//import org.springframework.test.web.servlet.MockMvc;
-//
-//import java.io.Serializable;
-//import java.util.Arrays;
-//import java.util.HashMap;
-//import java.util.Map;
-//
-//import static org.hamcrest.CoreMatchers.is;
-//import static org.mockito.BDDMockito.given;
-//import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
-//import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
-//import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
-//import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
-//
-//@RunWith(SpringRunner.class)
-//@WebMvcTest(value = JobController.class, secure = false)
-//public class JobControllerTest {
-//    @Autowired
-//    private MockMvc mvc;
-//
-//    @MockBean
-//    private JobService service;
-//
-//    @Before
-//    public void setup() {
-//    }
-//
-//
-//    @Test
-//    public void testGetJobs() throws Exception {
-//        JobDataBean jobBean = new JobDataBean();
-//        jobBean.setJobName("job1");
-//        given(service.getAliveJobs()).willReturn(Arrays.asList(jobBean));
-//
-//        mvc.perform(get(URLHelper.API_VERSION_PATH + "/jobs/").contentType(MediaType.APPLICATION_JSON))
-//                .andExpect(status().isOk())
-//                .andExpect(jsonPath("$.[0].jobName", is("job1")));
-//    }
-//
-//    @Test
-//    public void testAddJobForSuccess() throws Exception {
-//        JobSchedule jobSchedule = new JobSchedule(1L, "jobName","0 0/4 * * * ?", null,null);
-//        given(service.addJob(jobSchedule)).willReturn(GriffinOperationMessage.CREATE_JOB_SUCCESS);
-//
-//        mvc.perform(post(URLHelper.API_VERSION_PATH + "/job")
-//                .contentType(MediaType.APPLICATION_JSON)
-//                .content("{\"measure.id\": 1,\"cron.expression\": \"0 0/4 * * * ?\"}"))
-//                .andExpect(status().isOk())
-//                .andExpect(jsonPath("$.code", is(205)))
-//                .andExpect(jsonPath("$.description", is("Create Job Succeed")))
-//                .andDo(print());
-//    }
-//
-//    @Test
-//    public void testAddJobForFail() throws Exception {
-//        Map configMap = new HashMap();
-//        configMap.put("interval", "1m");
-//        configMap.put("repeat", "2");
-//        JobSchedule jobSchedule = new JobSchedule(1L, "jobName","0 0/4 * * * ?", configMap,null);
-//        given(service.addJob(jobSchedule)).willReturn(GriffinOperationMessage.CREATE_JOB_FAIL);
-//
-//        mvc.perform(post(URLHelper.API_VERSION_PATH + "/job")
-//                .contentType(MediaType.APPLICATION_JSON)
-//                .content(JsonUtil.toJson(jobSchedule)))
-//                .andExpect(status().isOk())
-//                .andExpect(jsonPath("$.code", is(405)))
-//                .andExpect(jsonPath("$.description", is("Create Job Failed")))
-//                .andDo(print());
-//    }
-//
-//    @Test
-//    public void testDeleteJobForSuccess() throws Exception {
-//        String jobName = "job1";
-//        given(service.deleteJob(jobName)).willReturn(GriffinOperationMessage.DELETE_JOB_SUCCESS);
-//
-//        mvc.perform(delete(URLHelper.API_VERSION_PATH + "/job").param("jobName", jobName))
-//                .andExpect(status().isOk())
-//                .andExpect(jsonPath("$.code", is(206)))
-//                .andExpect(jsonPath("$.description", is("Delete Job Succeed")));
-//    }
-//
-//    @Test
-//    public void testDeleteJobForFail() throws Exception {
-//        String jobName = "job1";
-//        given(service.deleteJob(jobName)).willReturn(GriffinOperationMessage.DELETE_JOB_FAIL);
-//
-//        mvc.perform(delete(URLHelper.API_VERSION_PATH + "/job").param("jobName", jobName))
-//                .andExpect(status().isOk())
-//                .andExpect(jsonPath("$.code", is(406)))
-//                .andExpect(jsonPath("$.description", is("Delete Job Failed")));
-//    }
-//
-//    @Test
-//    public void testFindInstancesOfJob() throws Exception {
-//        int page = 0;
-//        int size = 2;
-//        JobInstanceBean jobInstance = new JobInstanceBean(1L,  LivySessionStates.State.running, "", "", System.currentTimeMillis(),System.currentTimeMillis());
-//        given(service.findInstancesOfJob(1L, page, size)).willReturn(Arrays.asList(jobInstance));
-//
-//        mvc.perform(get(URLHelper.API_VERSION_PATH + "/jobs/instances").param("jobId",String.valueOf(1L))
-//                .param("page", String.valueOf(page)).param("size", String.valueOf(size)))
-//                .andExpect(status().isOk())
-//                .andExpect(jsonPath("$.[0].jobId", is(1)));
-//    }
-//
-//    @Test
-//    public void testGetHealthInfo() throws Exception {
-////        JobHealth jobHealth = new JobHealth(1, 3);
-////        given(service.getHealthInfo()).willReturn(jobHealth);
-////
-////        mvc.perform(get(URLHelper.API_VERSION_PATH + "/jobs/health"))
-////                .andExpect(status().isOk())
-////                .andExpect(jsonPath("$.healthyJobCount", is(1)));
-//    }
-//}
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+package org.apache.griffin.core.job;
+
+import org.apache.griffin.core.job.entity.*;
+import org.apache.griffin.core.util.GriffinOperationMessage;
+import org.apache.griffin.core.util.JsonUtil;
+import org.apache.griffin.core.util.URLHelper;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
+import org.springframework.boot.test.mock.mockito.MockBean;
+import org.springframework.http.MediaType;
+import org.springframework.test.context.junit4.SpringRunner;
+import org.springframework.test.web.servlet.MockMvc;
+
+import java.io.Serializable;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.apache.griffin.core.util.GriffinOperationMessage.*;
+import static org.hamcrest.CoreMatchers.is;
+import static org.mockito.BDDMockito.given;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
+import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
+
+@RunWith(SpringRunner.class)
+@WebMvcTest(value = JobController.class, secure = false)
+public class JobControllerTest {
+    @Autowired
+    private MockMvc mvc;
+
+    @MockBean
+    private JobService service;
+
+    @Before
+    public void setup() {
+    }
+
+
+    @Test
+    public void testGetJobs() throws Exception {
+        JobDataBean jobBean = new JobDataBean();
+        jobBean.setJobName("job_name");
+        given(service.getAliveJobs()).willReturn(Arrays.asList(jobBean));
+
+        mvc.perform(get(URLHelper.API_VERSION_PATH + "/jobs").contentType(MediaType.APPLICATION_JSON))
+                .andExpect(status().isOk())
+                .andExpect(jsonPath("$.[0].jobName", is("job_name")));
+    }
+
+    @Test
+    public void testAddJobForSuccess() throws Exception {
+        JobSchedule jobSchedule = new JobSchedule(1L, "jobName","0 0/4 * * * ?","GMT+8:00", null);
+        given(service.addJob(jobSchedule)).willReturn(CREATE_JOB_SUCCESS);
+
+        mvc.perform(post(URLHelper.API_VERSION_PATH + "/jobs")
+                .contentType(MediaType.APPLICATION_JSON)
+                .content(JsonUtil.toJson(jobSchedule)))
+                .andExpect(status().isOk())
+                .andExpect(jsonPath("$.code", is(205)))
+                .andDo(print());
+    }
+
+    @Test
+    public void testAddJobForFailure() throws Exception {
+        JobSchedule jobSchedule = new JobSchedule(1L, "jobName","0 0/4 * * * ?","GMT+8:00", null);
+        given(service.addJob(jobSchedule)).willReturn(CREATE_JOB_FAIL);
+
+        mvc.perform(post(URLHelper.API_VERSION_PATH + "/jobs")
+                .contentType(MediaType.APPLICATION_JSON)
+                .content(JsonUtil.toJson(jobSchedule)))
+                .andExpect(status().isOk())
+                .andExpect(jsonPath("$.code", is(405)))
+                .andDo(print());
+    }
+
+    @Test
+    public void testDeleteJobByIdForSuccess() throws Exception {
+        given(service.deleteJob(1L)).willReturn(DELETE_JOB_SUCCESS);
+
+        mvc.perform(delete(URLHelper.API_VERSION_PATH + "/jobs/1"))
+                .andExpect(status().isOk())
+                .andExpect(jsonPath("$.code", is(206)));
+    }
+
+    @Test
+    public void testDeleteJobByIdForFailure() throws Exception {
+        given(service.deleteJob(1L)).willReturn(DELETE_JOB_FAIL);
+
+        mvc.perform(delete(URLHelper.API_VERSION_PATH + "/jobs/1"))
+                .andExpect(status().isOk())
+                .andExpect(jsonPath("$.code", is(406)));
+    }
+
+    @Test
+    public void testDeleteJobByNameForSuccess() throws Exception {
+        String jobName = "jobName";
+        given(service.deleteJob(jobName)).willReturn(DELETE_JOB_SUCCESS);
+
+        mvc.perform(delete(URLHelper.API_VERSION_PATH + "/jobs").param("jobName",jobName))
+                .andExpect(status().isOk())
+                .andExpect(jsonPath("$.code", is(206)));
+    }
+
+    @Test
+    public void testDeleteJobByNameForFailure() throws Exception {
+        String jobName = "jobName";
+        given(service.deleteJob(jobName)).willReturn(DELETE_JOB_FAIL);
+
+        mvc.perform(delete(URLHelper.API_VERSION_PATH + "/jobs").param("jobName",jobName))
+                .andExpect(status().isOk())
+                .andExpect(jsonPath("$.code", is(406)));
+    }
+
+    @Test
+    public void testFindInstancesOfJob() throws Exception {
+        int page = 0;
+        int size = 2;
+        JobInstanceBean jobInstance = new JobInstanceBean(1L,  LivySessionStates.State.running, "", "", null,null);
+        given(service.findInstancesOfJob(1L, page, size)).willReturn(Arrays.asList(jobInstance));
+
+        mvc.perform(get(URLHelper.API_VERSION_PATH + "/jobs/instances").param("jobId",String.valueOf(1L))
+                .param("page", String.valueOf(page)).param("size", String.valueOf(size)))
+                .andExpect(status().isOk())
+                .andExpect(jsonPath("$.[0].state", is("running")));
+    }
+
+    @Test
+    public void testGetHealthInfo() throws Exception {
+        JobHealth jobHealth = new JobHealth(1, 3);
+        given(service.getHealthInfo()).willReturn(jobHealth);
+
+        mvc.perform(get(URLHelper.API_VERSION_PATH + "/jobs/health"))
+                .andExpect(status().isOk())
+                .andExpect(jsonPath("$.healthyJobCount", is(1)));
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-griffin/blob/44eea866/service/src/test/java/org/apache/griffin/core/job/repo/JobInstanceRepoTest.java
----------------------------------------------------------------------
diff --git a/service/src/test/java/org/apache/griffin/core/job/repo/JobInstanceRepoTest.java b/service/src/test/java/org/apache/griffin/core/job/repo/JobInstanceRepoTest.java
new file mode 100644
index 0000000..72dbc8c
--- /dev/null
+++ b/service/src/test/java/org/apache/griffin/core/job/repo/JobInstanceRepoTest.java
@@ -0,0 +1,87 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+package org.apache.griffin.core.job.repo;
+
+import org.apache.griffin.core.job.entity.JobInstanceBean;
+import org.apache.griffin.core.job.entity.LivySessionStates;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
+import org.springframework.boot.test.autoconfigure.orm.jpa.TestEntityManager;
+import org.springframework.test.context.junit4.SpringRunner;
+
+import java.util.List;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+@RunWith(SpringRunner.class)
+@DataJpaTest
+public class JobInstanceRepoTest {
+
+    @Autowired
+    private TestEntityManager entityManager;
+
+    @Autowired
+    private JobInstanceRepo jobInstanceRepo;
+
+    @Before
+    public void setup() {
+        entityManager.clear();
+        entityManager.flush();
+        setEntityManager();
+    }
+
+    @Test
+    public void testFindByActiveState() {
+        List<JobInstanceBean> beans = jobInstanceRepo.findByActiveState();
+        assertThat(beans.size()).isEqualTo(1);
+    }
+
+    @Test
+    public void testFindByPredicateName() {
+        JobInstanceBean bean = jobInstanceRepo.findByPredicateName("pName1");
+        assertThat(bean).isNotNull();
+    }
+
+    @Test
+    public void testFindByExpireTmsLessThanEqual() {
+        List<JobInstanceBean> beans = jobInstanceRepo.findByExpireTmsLessThanEqual(1516004640092L);
+        assertThat(beans.size()).isEqualTo(2);
+    }
+
+    @Test
+    public void testDeleteByExpireTimestamp() {
+        int count = jobInstanceRepo.deleteByExpireTimestamp(1516004640092L);
+        assertThat(count).isEqualTo(2);
+    }
+
+    private void setEntityManager() {
+        JobInstanceBean bean1 = new JobInstanceBean( LivySessionStates.State.finding, "pName1", "pGroup1", null, 1516004640092L);
+        JobInstanceBean bean2 = new JobInstanceBean( LivySessionStates.State.not_found, "pName2", "pGroup2", null, 1516004640093L);
+        JobInstanceBean bean3 = new JobInstanceBean( LivySessionStates.State.running, "pName3", "pGroup3", null, 1516004640082L);
+        JobInstanceBean bean4 = new JobInstanceBean( LivySessionStates.State.success, "pName4", "pGroup4", null, 1516004640094L);
+        entityManager.persistAndFlush(bean1);
+        entityManager.persistAndFlush(bean2);
+        entityManager.persistAndFlush(bean3);
+        entityManager.persistAndFlush(bean4);
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-griffin/blob/44eea866/service/src/test/java/org/apache/griffin/core/measure/MeasureControllerTest.java
----------------------------------------------------------------------
diff --git a/service/src/test/java/org/apache/griffin/core/measure/MeasureControllerTest.java b/service/src/test/java/org/apache/griffin/core/measure/MeasureControllerTest.java
index 2abd4b5..82a9ff9 100644
--- a/service/src/test/java/org/apache/griffin/core/measure/MeasureControllerTest.java
+++ b/service/src/test/java/org/apache/griffin/core/measure/MeasureControllerTest.java
@@ -1,200 +1,198 @@
-///*
-//Licensed to the Apache Software Foundation (ASF) under one
-//or more contributor license agreements.  See the NOTICE file
-//distributed with this work for additional information
-//regarding copyright ownership.  The ASF licenses this file
-//to you under the Apache License, Version 2.0 (the
-//"License"); you may not use this file except in compliance
-//with the License.  You may obtain a copy of the License at
-//
-//  http://www.apache.org/licenses/LICENSE-2.0
-//
-//Unless required by applicable law or agreed to in writing,
-//software distributed under the License is distributed on an
-//"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-//KIND, either express or implied.  See the License for the
-//specific language governing permissions and limitations
-//under the License.
-//*/
-//
-//package org.apache.griffin.core.measure;
-//
-//import org.apache.griffin.core.measure.entity.Measure;
-//import org.apache.griffin.core.util.GriffinOperationMessage;
-//import org.apache.griffin.core.util.JsonUtil;
-//import org.apache.griffin.core.util.URLHelper;
-//import org.junit.Before;
-//import org.junit.Test;
-//import org.junit.runner.RunWith;
-//import org.springframework.beans.factory.annotation.Autowired;
-//import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
-//import org.springframework.boot.test.mock.mockito.MockBean;
-//import org.springframework.http.MediaType;
-//import org.springframework.test.context.junit4.SpringRunner;
-//import org.springframework.test.web.servlet.MockMvc;
-//
-//import java.util.*;
-//
-//import static org.apache.griffin.core.measure.MeasureTestHelper.createATestGriffinMeasure;
-//import static org.hamcrest.CoreMatchers.is;
-//import static org.mockito.BDDMockito.given;
-//import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
-//import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
-//import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
-//
-//@RunWith(SpringRunner.class)
-//@WebMvcTest(value = MeasureController.class, secure = false)
-//public class MeasureControllerTest {
-//    @Autowired
-//    private MockMvc mvc;
-//
-//    @MockBean
-//    private MeasureService service;
-//
-//
-//    @Before
-//    public void setup() {
-//
-//    }
-//
-//    @Test
-//    public void testGetAllMeasures() throws Exception {
-//        Measure measure = createATestGriffinMeasure("view_item_hourly", "test");
-//        given(service.getAllAliveMeasures()).willReturn(Arrays.asList(measure));
-//
-//        mvc.perform(get(URLHelper.API_VERSION_PATH + "/measures").contentType(MediaType.APPLICATION_JSON))
-//                .andExpect(status().isOk())
-//                .andExpect(jsonPath("$.[0].name", is("view_item_hourly")));
-//    }
-//
-//
-//    @Test
-//    public void testGetMeasuresById() throws Exception {
-//        Measure measure = createATestGriffinMeasure("view_item_hourly", "test");
-//        given(service.getMeasureById(1L)).willReturn(measure);
-//
-//        mvc.perform(get(URLHelper.API_VERSION_PATH + "/measure/1").contentType(MediaType.APPLICATION_JSON))
-//                .andExpect(status().isOk())
-//                .andExpect(jsonPath("$.name", is("view_item_hourly")))
-//        ;
-//    }
-//
-//    @Test
-//    public void testDeleteMeasuresByIdForSuccess() throws Exception {
-//        given(service.deleteMeasureById(1L)).willReturn(GriffinOperationMessage.DELETE_MEASURE_BY_ID_SUCCESS);
-//
-//        mvc.perform(delete(URLHelper.API_VERSION_PATH + "/measure/1").contentType(MediaType.APPLICATION_JSON))
-//                .andExpect(status().isOk())
-//                .andExpect(jsonPath("$.description", is("Delete Measures By Id Succeed")))
-//                .andExpect(jsonPath("$.code", is(202)));
-//    }
-//
-//    @Test
-//    public void testDeleteMeasuresByIdForNotFound() throws Exception {
-//        given(service.deleteMeasureById(1L)).willReturn(GriffinOperationMessage.RESOURCE_NOT_FOUND);
-//
-//        mvc.perform(delete(URLHelper.API_VERSION_PATH + "/measure/1").contentType(MediaType.APPLICATION_JSON))
-//                .andExpect(status().isOk())
-//                .andExpect(jsonPath("$.description", is("Resource Not Found")))
-//                .andExpect(jsonPath("$.code", is(400)));
-//    }
-//
-//    @Test
-//    public void testDeleteMeasuresByIdForFail() throws Exception {
-//        given(service.deleteMeasureById(1L)).willReturn(GriffinOperationMessage.DELETE_MEASURE_BY_ID_FAIL);
-//
-//        mvc.perform(delete(URLHelper.API_VERSION_PATH + "/measure/1").contentType(MediaType.APPLICATION_JSON))
-//                .andExpect(status().isOk())
-//                .andExpect(jsonPath("$.description", is("Delete Measures By Id Failed")))
-//                .andExpect(jsonPath("$.code", is(402)));
-//    }
-//
-//    @Test
-//    public void testUpdateMeasureForSuccess() throws Exception {
-//        Measure measure = createATestGriffinMeasure("view_item_hourly", "test");
-//        String measureJson = JsonUtil.toJson(measure);
-//        given(service.updateMeasure(measure)).willReturn(GriffinOperationMessage.UPDATE_MEASURE_SUCCESS);
-//
-//        mvc.perform(put(URLHelper.API_VERSION_PATH + "/measure").contentType(MediaType.APPLICATION_JSON).content(measureJson))
-//                .andExpect(status().isOk())
-//                .andExpect(jsonPath("$.description", is("Update Measure Succeed")))
-//                .andExpect(jsonPath("$.code", is(204)));
-//    }
-//
-//    @Test
-//    public void testUpdateMeasureForNotFound() throws Exception {
-//        Measure measure = createATestGriffinMeasure("view_item_hourly", "test");
-//        String measureJson = JsonUtil.toJson(measure);
-//        given(service.updateMeasure(measure)).willReturn(GriffinOperationMessage.RESOURCE_NOT_FOUND);
-//
-//        mvc.perform(put(URLHelper.API_VERSION_PATH + "/measure").contentType(MediaType.APPLICATION_JSON).content(measureJson))
-//                .andExpect(status().isOk())
-//                .andExpect(jsonPath("$.description", is("Resource Not Found")))
-//                .andExpect(jsonPath("$.code", is(400)));
-//
-//    }
-//
-//    @Test
-//    public void testUpdateMeasureForFail() throws Exception {
-//        Measure measure = createATestGriffinMeasure("view_item_hourly", "test");
-//        String measureJson = JsonUtil.toJson(measure);
-//        given(service.updateMeasure(measure)).willReturn(GriffinOperationMessage.UPDATE_MEASURE_FAIL);
-//
-//        mvc.perform(put(URLHelper.API_VERSION_PATH + "/measure").contentType(MediaType.APPLICATION_JSON).content(measureJson))
-//                .andExpect(status().isOk())
-//                .andExpect(jsonPath("$.description", is("Update Measure Failed")))
-//                .andExpect(jsonPath("$.code", is(404)));
-//    }
-//
-//    @Test
-//    public void testGetAllMeasuresByOwner() throws Exception {
-//        String owner = "test";
-//        List<Measure> measureList = new LinkedList<>();
-//        Measure measure = createATestGriffinMeasure("view_item_hourly", owner);
-//        measureList.add(measure);
-//        given(service.getAliveMeasuresByOwner(owner)).willReturn(measureList);
-//
-//        mvc.perform(get(URLHelper.API_VERSION_PATH + "/measures/owner/" + owner).contentType(MediaType.APPLICATION_JSON))
-//                .andExpect(status().isOk())
-//                .andExpect(jsonPath("$.[0].name", is("view_item_hourly")))
-//        ;
-//    }
-//
-//    @Test
-//    public void testCreateNewMeasureForSuccess() throws Exception {
-//        Measure measure = createATestGriffinMeasure("view_item_hourly", "test");
-//        String measureJson = JsonUtil.toJson(measure);
-//        given(service.createMeasure(measure)).willReturn(GriffinOperationMessage.CREATE_MEASURE_SUCCESS);
-//
-//        mvc.perform(post(URLHelper.API_VERSION_PATH + "/measure").contentType(MediaType.APPLICATION_JSON).content(measureJson))
-//                .andExpect(status().isOk())
-//                .andExpect(jsonPath("$.description", is("Create Measure Succeed")))
-//                .andExpect(jsonPath("$.code", is(201)));
-//    }
-//
-//    @Test
-//    public void testCreateNewMeasureForFailWithDuplicate() throws Exception {
-//        Measure measure = createATestGriffinMeasure("view_item_hourly", "test");
-//        String measureJson = JsonUtil.toJson(measure);
-//        given(service.createMeasure(measure)).willReturn(GriffinOperationMessage.CREATE_MEASURE_FAIL_DUPLICATE);
-//
-//        mvc.perform(post(URLHelper.API_VERSION_PATH + "/measure").contentType(MediaType.APPLICATION_JSON).content(measureJson))
-//                .andExpect(status().isOk())
-//                .andExpect(jsonPath("$.description", is("Create Measure Failed, duplicate records")))
-//                .andExpect(jsonPath("$.code", is(410)));
-//    }
-//
-//    @Test
-//    public void testCreateNewMeasureForFailWithSaveException() throws Exception {
-//        Measure measure = createATestGriffinMeasure("view_item_hourly", "test");
-//        String measureJson = JsonUtil.toJson(measure);
-//        given(service.createMeasure(measure)).willReturn(GriffinOperationMessage.CREATE_MEASURE_FAIL);
-//
-//        mvc.perform(post(URLHelper.API_VERSION_PATH + "/measure").contentType(MediaType.APPLICATION_JSON).content(measureJson))
-//                .andExpect(status().isOk())
-//                .andExpect(jsonPath("$.description", is("Create Measure Failed")))
-//                .andExpect(jsonPath("$.code", is(401)));
-//    }
-//
-//
-//}
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+package org.apache.griffin.core.measure;
+
+import org.apache.griffin.core.measure.entity.Measure;
+import org.apache.griffin.core.util.GriffinOperationMessage;
+import org.apache.griffin.core.util.JsonUtil;
+import org.apache.griffin.core.util.URLHelper;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
+import org.springframework.boot.test.mock.mockito.MockBean;
+import org.springframework.http.MediaType;
+import org.springframework.test.context.junit4.SpringRunner;
+import org.springframework.test.web.servlet.MockMvc;
+
+import java.util.*;
+
+import static org.apache.griffin.core.util.EntityHelper.createATestGriffinMeasure;
+import static org.apache.griffin.core.util.GriffinOperationMessage.*;
+import static org.hamcrest.CoreMatchers.is;
+import static org.mockito.BDDMockito.given;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
+
+@RunWith(SpringRunner.class)
+@WebMvcTest(value = MeasureController.class, secure = false)
+public class MeasureControllerTest {
+    @Autowired
+    private MockMvc mvc;
+
+    @MockBean
+    private MeasureService service;
+
+
+    @Before
+    public void setup() {
+
+    }
+
+    @Test
+    public void testGetAllMeasures() throws Exception {
+        Measure measure = createATestGriffinMeasure("view_item_hourly", "test");
+        given(service.getAllAliveMeasures()).willReturn(Arrays.asList(measure));
+
+        mvc.perform(get(URLHelper.API_VERSION_PATH + "/measures"))
+                .andExpect(status().isOk())
+                .andExpect(jsonPath("$.[0].name", is("view_item_hourly")));
+    }
+
+
+    @Test
+    public void testGetMeasuresById() throws Exception {
+        Measure measure = createATestGriffinMeasure("view_item_hourly", "test");
+        given(service.getMeasureById(1L)).willReturn(measure);
+
+        mvc.perform(get(URLHelper.API_VERSION_PATH + "/measures/1"))
+                .andExpect(status().isOk())
+                .andExpect(jsonPath("$.name", is("view_item_hourly")))
+        ;
+    }
+
+    @Test
+    public void testDeleteMeasuresByIdForSuccess() throws Exception {
+        given(service.deleteMeasureById(1L)).willReturn(DELETE_MEASURE_BY_ID_SUCCESS);
+
+        mvc.perform(delete(URLHelper.API_VERSION_PATH + "/measures/1"))
+                .andExpect(status().isOk())
+                .andExpect(jsonPath("$.code", is(202)));
+    }
+
+    @Test
+    public void testDeleteMeasuresByIdForNotFound() throws Exception {
+        given(service.deleteMeasureById(1L)).willReturn(RESOURCE_NOT_FOUND);
+
+        mvc.perform(delete(URLHelper.API_VERSION_PATH + "/measures/1"))
+                .andExpect(status().isOk())
+                .andExpect(jsonPath("$.code", is(400)));
+    }
+
+    @Test
+    public void testDeleteMeasuresByIdForFail() throws Exception {
+        given(service.deleteMeasureById(1L)).willReturn(DELETE_MEASURE_BY_ID_FAIL);
+
+        mvc.perform(delete(URLHelper.API_VERSION_PATH + "/measures/1"))
+                .andExpect(status().isOk())
+                .andExpect(jsonPath("$.code", is(402)));
+    }
+
+    @Test
+    public void testUpdateMeasureForSuccess() throws Exception {
+        Measure measure = createATestGriffinMeasure("view_item_hourly", "test");
+        String measureJson = JsonUtil.toJson(measure);
+        given(service.updateMeasure(measure)).willReturn(UPDATE_MEASURE_SUCCESS);
+
+        mvc.perform(put(URLHelper.API_VERSION_PATH + "/measures")
+                .contentType(MediaType.APPLICATION_JSON).content(measureJson))
+                .andExpect(status().isOk())
+                .andExpect(jsonPath("$.code", is(204)));
+    }
+
+    @Test
+    public void testUpdateMeasureForNotFound() throws Exception {
+        Measure measure = createATestGriffinMeasure("view_item_hourly", "test");
+        String measureJson = JsonUtil.toJson(measure);
+        given(service.updateMeasure(measure)).willReturn(RESOURCE_NOT_FOUND);
+
+        mvc.perform(put(URLHelper.API_VERSION_PATH + "/measures")
+                .contentType(MediaType.APPLICATION_JSON).content(measureJson))
+                .andExpect(status().isOk())
+                .andExpect(jsonPath("$.code", is(400)));
+
+    }
+
+    @Test
+    public void testUpdateMeasureForFail() throws Exception {
+        Measure measure = createATestGriffinMeasure("view_item_hourly", "test");
+        String measureJson = JsonUtil.toJson(measure);
+        given(service.updateMeasure(measure)).willReturn(UPDATE_MEASURE_FAIL);
+
+        mvc.perform(put(URLHelper.API_VERSION_PATH + "/measures")
+                .contentType(MediaType.APPLICATION_JSON).content(measureJson))
+                .andExpect(status().isOk())
+                .andExpect(jsonPath("$.code", is(404)));
+    }
+
+    @Test
+    public void testGetAllMeasuresByOwner() throws Exception {
+        String owner = "test";
+        List<Measure> measureList = new LinkedList<>();
+        Measure measure = createATestGriffinMeasure("view_item_hourly", owner);
+        measureList.add(measure);
+        given(service.getAliveMeasuresByOwner(owner)).willReturn(measureList);
+
+        mvc.perform(get(URLHelper.API_VERSION_PATH + "/measures/owner/" + owner)
+                .contentType(MediaType.APPLICATION_JSON))
+                .andExpect(status().isOk())
+                .andExpect(jsonPath("$.[0].name", is("view_item_hourly")))
+        ;
+    }
+
+    @Test
+    public void testCreateNewMeasureForSuccess() throws Exception {
+        Measure measure = createATestGriffinMeasure("view_item_hourly", "test");
+        String measureJson = JsonUtil.toJson(measure);
+        given(service.createMeasure(measure)).willReturn(CREATE_MEASURE_SUCCESS);
+
+        mvc.perform(post(URLHelper.API_VERSION_PATH + "/measures")
+                .contentType(MediaType.APPLICATION_JSON).content(measureJson))
+                .andExpect(status().isOk())
+                .andExpect(jsonPath("$.code", is(201)));
+    }
+
+    @Test
+    public void testCreateNewMeasureForFailWithDuplicate() throws Exception {
+        Measure measure = createATestGriffinMeasure("view_item_hourly", "test");
+        String measureJson = JsonUtil.toJson(measure);
+        given(service.createMeasure(measure)).willReturn(CREATE_MEASURE_FAIL_DUPLICATE);
+
+        mvc.perform(post(URLHelper.API_VERSION_PATH + "/measures")
+                .contentType(MediaType.APPLICATION_JSON).content(measureJson))
+                .andExpect(status().isOk())
+                .andExpect(jsonPath("$.code", is(410)));
+    }
+
+    @Test
+    public void testCreateNewMeasureForFailWithSaveException() throws Exception {
+        Measure measure = createATestGriffinMeasure("view_item_hourly", "test");
+        String measureJson = JsonUtil.toJson(measure);
+        given(service.createMeasure(measure)).willReturn(GriffinOperationMessage.CREATE_MEASURE_FAIL);
+
+        mvc.perform(post(URLHelper.API_VERSION_PATH + "/measures").contentType(MediaType.APPLICATION_JSON).content(measureJson))
+                .andExpect(status().isOk())
+                .andExpect(jsonPath("$.code", is(401)));
+    }
+
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-griffin/blob/44eea866/service/src/test/java/org/apache/griffin/core/measure/MeasureOrgControllerTest.java
----------------------------------------------------------------------
diff --git a/service/src/test/java/org/apache/griffin/core/measure/MeasureOrgControllerTest.java b/service/src/test/java/org/apache/griffin/core/measure/MeasureOrgControllerTest.java
index bd3e2dc..df7fdca 100644
--- a/service/src/test/java/org/apache/griffin/core/measure/MeasureOrgControllerTest.java
+++ b/service/src/test/java/org/apache/griffin/core/measure/MeasureOrgControllerTest.java
@@ -34,7 +34,6 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
-import static org.apache.griffin.core.measure.MeasureTestHelper.createJobDetailMap;
 import static org.hamcrest.CoreMatchers.is;
 import static org.hamcrest.CoreMatchers.notNullValue;
 import static org.hamcrest.Matchers.hasKey;

http://git-wip-us.apache.org/repos/asf/incubator-griffin/blob/44eea866/service/src/test/java/org/apache/griffin/core/measure/MeasureOrgServiceImplTest.java
----------------------------------------------------------------------
diff --git a/service/src/test/java/org/apache/griffin/core/measure/MeasureOrgServiceImplTest.java b/service/src/test/java/org/apache/griffin/core/measure/MeasureOrgServiceImplTest.java
index e69bec3..7eda50e 100644
--- a/service/src/test/java/org/apache/griffin/core/measure/MeasureOrgServiceImplTest.java
+++ b/service/src/test/java/org/apache/griffin/core/measure/MeasureOrgServiceImplTest.java
@@ -31,8 +31,8 @@
 //import java.io.Serializable;
 //import java.util.*;
 //
-//import static org.apache.griffin.core.measure.MeasureTestHelper.createATestGriffinMeasure;
-//import static org.apache.griffin.core.measure.MeasureTestHelper.createJobDetailMap;
+//import static org.apache.griffin.core.util.EntityHelper.createATestGriffinMeasure;
+//import static org.apache.griffin.core.util.EntityHelper.createJobDetailMap;
 //import static org.assertj.core.api.Assertions.assertThat;
 //import static org.mockito.BDDMockito.given;
 //import static org.mockito.Mockito.when;

http://git-wip-us.apache.org/repos/asf/incubator-griffin/blob/44eea866/service/src/test/java/org/apache/griffin/core/measure/MeasureServiceImplTest.java
----------------------------------------------------------------------
diff --git a/service/src/test/java/org/apache/griffin/core/measure/MeasureServiceImplTest.java b/service/src/test/java/org/apache/griffin/core/measure/MeasureServiceImplTest.java
index 659626a..c49ee82 100644
--- a/service/src/test/java/org/apache/griffin/core/measure/MeasureServiceImplTest.java
+++ b/service/src/test/java/org/apache/griffin/core/measure/MeasureServiceImplTest.java
@@ -21,8 +21,6 @@ package org.apache.griffin.core.measure;
 
 
 import org.apache.griffin.core.job.JobServiceImpl;
-import org.apache.griffin.core.measure.entity.DataConnector;
-import org.apache.griffin.core.measure.entity.GriffinMeasure;
 import org.apache.griffin.core.measure.entity.Measure;
 import org.apache.griffin.core.measure.repo.DataConnectorRepo;
 import org.apache.griffin.core.measure.repo.MeasureRepo;
@@ -31,7 +29,6 @@ import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.InjectMocks;
-import org.mockito.Matchers;
 import org.mockito.Mock;
 import org.springframework.test.context.junit4.SpringRunner;
 
@@ -39,11 +36,10 @@ import java.util.Arrays;
 import java.util.LinkedList;
 import java.util.List;
 
-import static org.apache.griffin.core.measure.MeasureTestHelper.createATestGriffinMeasure;
+import static org.apache.griffin.core.util.EntityHelper.createATestGriffinMeasure;
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.junit.Assert.assertEquals;
 import static org.mockito.BDDMockito.given;
-import static org.mockito.Mockito.doNothing;
 
 @RunWith(SpringRunner.class)
 public class MeasureServiceImplTest {

http://git-wip-us.apache.org/repos/asf/incubator-griffin/blob/44eea866/service/src/test/java/org/apache/griffin/core/measure/MeasureTestHelper.java
----------------------------------------------------------------------
diff --git a/service/src/test/java/org/apache/griffin/core/measure/MeasureTestHelper.java b/service/src/test/java/org/apache/griffin/core/measure/MeasureTestHelper.java
deleted file mode 100644
index dc9a659..0000000
--- a/service/src/test/java/org/apache/griffin/core/measure/MeasureTestHelper.java
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
-Licensed to the Apache Software Foundation (ASF) under one
-or more contributor license agreements.  See the NOTICE file
-distributed with this work for additional information
-regarding copyright ownership.  The ASF licenses this file
-to you under the Apache License, Version 2.0 (the
-"License"); you may not use this file except in compliance
-with the License.  You may obtain a copy of the License at
-
-  http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing,
-software distributed under the License is distributed on an
-"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-KIND, either express or implied.  See the License for the
-specific language governing permissions and limitations
-under the License.
-*/
-
-package org.apache.griffin.core.measure;
-
-
-import org.apache.griffin.core.measure.entity.*;
-import org.codehaus.jackson.map.ObjectMapper;
-import org.quartz.JobDataMap;
-import org.quartz.Trigger;
-import org.quartz.impl.JobDetailImpl;
-
-import java.io.Serializable;
-import java.util.*;
-
-public class MeasureTestHelper {
-    public static GriffinMeasure createATestGriffinMeasure(String name, String org) throws Exception {
-        HashMap<String, String> configMap1 = new HashMap<>();
-        configMap1.put("database", "default");
-        configMap1.put("table.name", "test_data_src");
-        HashMap<String, String> configMap2 = new HashMap<>();
-        configMap2.put("database", "default");
-        configMap2.put("table.name", "test_data_tgt");
-        String configJson1 = new ObjectMapper().writeValueAsString(configMap1);
-        String configJson2 = new ObjectMapper().writeValueAsString(configMap2);
-
-        DataSource dataSource = new DataSource("source", Arrays.asList(new DataConnector("source_name", "HIVE", "1.2", configJson1)));
-        DataSource targetSource = new DataSource("target", Arrays.asList(new DataConnector("target-name", "HIVE", "1.2", configJson2)));
-
-        List<DataSource> dataSources = new ArrayList<>();
-        dataSources.add(dataSource);
-        dataSources.add(targetSource);
-        String rules = "source.id=target.id AND source.name=target.name AND source.age=target.age";
-        Map<String, Object> map = new HashMap<>();
-        map.put("detail", "detail info");
-        Rule rule = new Rule("griffin-dsl", "accuracy", rules, map);
-        EvaluateRule evaluateRule = new EvaluateRule(Arrays.asList(rule));
-        return new GriffinMeasure(1L,name, "description", org, "batch", "test", dataSources, evaluateRule);
-    }
-
-    public static JobDetailImpl createJobDetail() {
-        JobDetailImpl jobDetail = new JobDetailImpl();
-        JobDataMap jobInfoMap = new JobDataMap();
-        jobInfoMap.put("triggerState", Trigger.TriggerState.NORMAL);
-        jobInfoMap.put("measureId", "1");
-        jobInfoMap.put("sourcePattern", "YYYYMMdd-HH");
-        jobInfoMap.put("targetPattern", "YYYYMMdd-HH");
-        jobInfoMap.put("jobStartTime", "1506356105876");
-        jobInfoMap.put("interval", "3000");
-        jobInfoMap.put("deleted", "false");
-        jobInfoMap.put("blockStartTimestamp", "1506634804254");
-        jobInfoMap.put("lastBlockStartTimestamp", "1506634804254");
-        jobInfoMap.put("groupName", "BA");
-        jobInfoMap.put("jobName", "jobName");
-        jobDetail.setJobDataMap(jobInfoMap);
-        return jobDetail;
-    }
-
-    public static Map<String, Object> createJobDetailMap() {
-        Map<String, Object> jobDetailMap = new HashMap<>();
-        jobDetailMap.put("jobName", "jobName");
-        jobDetailMap.put("measureId", "1");
-        jobDetailMap.put("groupName", "BA");
-        jobDetailMap.put("targetPattern", "YYYYMMdd-HH");
-        jobDetailMap.put("triggerState", Trigger.TriggerState.NORMAL);
-        jobDetailMap.put("nextFireTime", "1509613440000");
-        jobDetailMap.put("previousFireTime", "1509613410000");
-        jobDetailMap.put("interval", "3000");
-        jobDetailMap.put("sourcePattern", "YYYYMMdd-HH");
-        jobDetailMap.put("jobStartTime", "1506356105876");
-        return jobDetailMap;
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-griffin/blob/44eea866/service/src/test/java/org/apache/griffin/core/measure/repo/MeasureRepoTest.java
----------------------------------------------------------------------
diff --git a/service/src/test/java/org/apache/griffin/core/measure/repo/MeasureRepoTest.java b/service/src/test/java/org/apache/griffin/core/measure/repo/MeasureRepoTest.java
index 4052630..c7132e6 100644
--- a/service/src/test/java/org/apache/griffin/core/measure/repo/MeasureRepoTest.java
+++ b/service/src/test/java/org/apache/griffin/core/measure/repo/MeasureRepoTest.java
@@ -30,7 +30,7 @@
 //
 //import java.util.List;
 //
-//import static org.apache.griffin.core.measure.MeasureTestHelper.createATestGriffinMeasure;
+//import static org.apache.griffin.core.util.EntityHelper.createATestGriffinMeasure;
 //import static org.assertj.core.api.Assertions.assertThat;
 //
 //@RunWith(SpringRunner.class)

http://git-wip-us.apache.org/repos/asf/incubator-griffin/blob/44eea866/service/src/test/java/org/apache/griffin/core/util/EntityHelper.java
----------------------------------------------------------------------
diff --git a/service/src/test/java/org/apache/griffin/core/util/EntityHelper.java b/service/src/test/java/org/apache/griffin/core/util/EntityHelper.java
new file mode 100644
index 0000000..627325c
--- /dev/null
+++ b/service/src/test/java/org/apache/griffin/core/util/EntityHelper.java
@@ -0,0 +1,89 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+package org.apache.griffin.core.util;
+
+
+import org.apache.griffin.core.measure.entity.*;
+import org.codehaus.jackson.map.ObjectMapper;
+import org.quartz.JobDataMap;
+import org.quartz.Trigger;
+import org.quartz.impl.JobDetailImpl;
+
+import java.io.Serializable;
+import java.util.*;
+
+public class EntityHelper {
+    public static GriffinMeasure createATestGriffinMeasure(String name, String org) throws Exception {
+        HashMap<String, String> configMap1 = new HashMap<>();
+        configMap1.put("database", "default");
+        configMap1.put("table.name", "test_data_src");
+        HashMap<String, String> configMap2 = new HashMap<>();
+        configMap2.put("database", "default");
+        configMap2.put("table.name", "test_data_tgt");
+        String configJson1 = new ObjectMapper().writeValueAsString(configMap1);
+        String configJson2 = new ObjectMapper().writeValueAsString(configMap2);
+
+        DataSource dataSource = new DataSource("source", Arrays.asList(new DataConnector("source_name", "HIVE", "1.2", configJson1)));
+        DataSource targetSource = new DataSource("target", Arrays.asList(new DataConnector("target-name", "HIVE", "1.2", configJson2)));
+
+        List<DataSource> dataSources = new ArrayList<>();
+        dataSources.add(dataSource);
+        dataSources.add(targetSource);
+        String rules = "source.id=target.id AND source.name=target.name AND source.age=target.age";
+        Map<String, Object> map = new HashMap<>();
+        map.put("detail", "detail info");
+        Rule rule = new Rule("griffin-dsl", "accuracy", rules, map);
+        EvaluateRule evaluateRule = new EvaluateRule(Arrays.asList(rule));
+        return new GriffinMeasure(1L,name, "description", org, "batch", "test", dataSources, evaluateRule);
+    }
+
+    public static JobDetailImpl createJobDetail() {
+        JobDetailImpl jobDetail = new JobDetailImpl();
+        JobDataMap jobInfoMap = new JobDataMap();
+        jobInfoMap.put("triggerState", Trigger.TriggerState.NORMAL);
+        jobInfoMap.put("measureId", "1");
+        jobInfoMap.put("sourcePattern", "YYYYMMdd-HH");
+        jobInfoMap.put("targetPattern", "YYYYMMdd-HH");
+        jobInfoMap.put("jobStartTime", "1506356105876");
+        jobInfoMap.put("interval", "3000");
+        jobInfoMap.put("deleted", "false");
+        jobInfoMap.put("blockStartTimestamp", "1506634804254");
+        jobInfoMap.put("lastBlockStartTimestamp", "1506634804254");
+        jobInfoMap.put("groupName", "BA");
+        jobInfoMap.put("jobName", "jobName");
+        jobDetail.setJobDataMap(jobInfoMap);
+        return jobDetail;
+    }
+
+    public static Map<String, Object> createJobDetailMap() {
+        Map<String, Object> jobDetailMap = new HashMap<>();
+        jobDetailMap.put("jobName", "jobName");
+        jobDetailMap.put("measureId", "1");
+        jobDetailMap.put("groupName", "BA");
+        jobDetailMap.put("targetPattern", "YYYYMMdd-HH");
+        jobDetailMap.put("triggerState", Trigger.TriggerState.NORMAL);
+        jobDetailMap.put("nextFireTime", "1509613440000");
+        jobDetailMap.put("previousFireTime", "1509613410000");
+        jobDetailMap.put("interval", "3000");
+        jobDetailMap.put("sourcePattern", "YYYYMMdd-HH");
+        jobDetailMap.put("jobStartTime", "1506356105876");
+        return jobDetailMap;
+    }
+}


[2/3] incubator-griffin git commit: fix job management sysnc bug and delete job triggerkey not exist bug

Posted by gu...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-griffin/blob/44eea866/griffin-doc/service/postman/griffin.json
----------------------------------------------------------------------
diff --git a/griffin-doc/service/postman/griffin.json b/griffin-doc/service/postman/griffin.json
index 7b64552..88a220a 100644
--- a/griffin-doc/service/postman/griffin.json
+++ b/griffin-doc/service/postman/griffin.json
@@ -1,155 +1,142 @@
 {
-	"id": "871762c3-97f9-1ac0-f17c-d17bd3446b87",
-	"name": "Griffin",
+	"id": "a743e1b9-583f-6bd7-e2ae-f03a1f807c63",
+	"name": "Griffin_2018_01_09",
 	"description": "",
 	"order": [],
 	"folders": [
 		{
 			"name": "Auth",
 			"description": "user authentication",
-			"collectionId": "871762c3-97f9-1ac0-f17c-d17bd3446b87",
+			"collectionId": "a743e1b9-583f-6bd7-e2ae-f03a1f807c63",
 			"order": [
-				"37578eb8-93b0-4903-0e51-42361aec3a90"
+				"c7b8e9b6-edde-e01b-1b4f-09d9396aada6"
 			],
-			"owner": "2830994",
+			"owner": "503523",
 			"folders_order": [],
-			"id": "c42b54fc-895c-d10c-72b0-01642ce776e8"
+			"id": "208120a7-5805-89eb-4472-775e0f73a819"
 		},
 		{
 			"name": "Basic",
 			"description": "",
-			"collectionId": "871762c3-97f9-1ac0-f17c-d17bd3446b87",
+			"collectionId": "a743e1b9-583f-6bd7-e2ae-f03a1f807c63",
 			"order": [
-				"4495d595-55a8-88af-4afb-85b2d722d00f"
+				"e7dd72bc-b1a2-7e84-525e-4f176bb2f635"
 			],
-			"owner": "2830994",
+			"owner": "503523",
 			"folders_order": [],
-			"id": "20092b46-e67b-f886-5433-32d7105b6379"
+			"id": "ee22ca52-aa2b-18a3-1070-bc9fdc018a7d"
 		},
 		{
 			"name": "Hive MetaStore",
 			"description": "",
-			"collectionId": "871762c3-97f9-1ac0-f17c-d17bd3446b87",
+			"collectionId": "a743e1b9-583f-6bd7-e2ae-f03a1f807c63",
 			"order": [
-				"bb002dbb-fc6e-b885-21c6-9896a8ae0521",
-				"d0eb17bc-7eea-8cc6-1a21-fccabd3e5d8b",
-				"b84b34c1-8861-7ed7-f4e3-396ea5908d0c",
-				"79d22e4f-89e4-5e61-7c24-92f4e2f6450e",
-				"eb6eb4a9-89f6-b0c1-34e7-1d5a24659554"
+				"9f536c3d-d3e0-bcf9-102a-d2d25ac3ef14",
+				"2d90ae20-5f65-df06-b533-e7f3e9ea3b50",
+				"7daeb86c-dc01-fa99-9898-73ec4a6e7e57",
+				"91e19d73-87b1-f388-93a9-22c7a0ec2b43",
+				"f0666097-2cbf-7875-a9a3-c505ba7820b3"
 			],
-			"owner": "2830994",
+			"owner": "503523",
 			"folders_order": [],
-			"id": "022408d6-3e26-da08-eb52-ca3c83d8f226"
+			"id": "7ae8e04f-c5cb-aeab-9af3-65cb3bf87b1f"
 		},
 		{
 			"name": "Jobs",
 			"description": "",
-			"collectionId": "871762c3-97f9-1ac0-f17c-d17bd3446b87",
+			"collectionId": "a743e1b9-583f-6bd7-e2ae-f03a1f807c63",
 			"order": [
-				"742889e2-52e1-58eb-9c50-9a225bba87bb",
-				"78aae644-ccbe-9381-0a64-4d463b1d76c0",
-				"02e56b82-6e21-4c68-f6a9-61e9f8a1b8bf",
-				"63066f6e-27ad-546d-27bc-e424dc0bd636",
-				"82c3a170-5bf6-2dc9-5295-3cca6e628d18"
+				"01e1bf7a-0a88-2039-ec03-777222c33bf5",
+				"8a94fa54-5df7-0e9e-06b5-158239e0570a",
+				"cde4e7ad-6b6a-96d6-ee3b-aeeeeb8f6805",
+				"aad1b117-7c8e-4185-ff59-28e0b3e8f4b1",
+				"5767e1b2-a078-caec-34ae-b4366d66ba3d",
+				"2bfc82ab-ec97-ee89-d6b4-db5ffefce28b"
 			],
-			"owner": "2830994",
+			"owner": "503523",
 			"folders_order": [],
-			"id": "a6877336-53f6-b720-ee4f-313d6c9d9c94"
+			"id": "40702c96-d08c-fd56-add4-5d26598e539e"
 		},
 		{
 			"name": "Measures",
 			"description": "",
-			"collectionId": "871762c3-97f9-1ac0-f17c-d17bd3446b87",
+			"collectionId": "a743e1b9-583f-6bd7-e2ae-f03a1f807c63",
 			"order": [
-				"da6be1fb-a790-b275-f2a5-0f584e8f4fcb",
-				"f5b9e3cb-f691-12b5-f675-48ac51da6b14",
-				"a85f7d39-c0bc-dd29-4739-18d3651c9796",
-				"9d390c13-a375-54c6-dcc2-4753edd4e9e4",
-				"cca39e41-3c38-eef6-f9d1-e797936eb7e9",
-				"9a0a2201-2a06-daeb-5abb-c9e08f4ee00c"
+				"f268747b-b506-7c8f-4463-8a860e09fc09",
+				"e0cfd3ea-0fea-4920-0dc1-c42a0212b401",
+				"57cf1684-d812-5867-3c76-e285527a7c58",
+				"2ebbf1cd-c78a-861e-6382-4a4d9dfba4be",
+				"12232e4c-2720-f5ac-0c6c-71b877a14d94",
+				"f989dff6-0847-cc8a-0989-ccae76f33562"
 			],
-			"owner": "2830994",
+			"owner": "503523",
 			"folders_order": [
-				"a59711e8-e3ea-db95-56cf-6c6c70e150a8"
+				"04a4a902-f33b-bce5-06dc-4da56cae7c4f"
 			],
-			"id": "7511d4fa-72ce-8671-54d0-2f3432d86445"
+			"id": "523a7f9f-1970-018e-9241-57caa3d6ea60"
+		},
+		{
+			"name": "Metrics",
+			"description": "",
+			"collectionId": "a743e1b9-583f-6bd7-e2ae-f03a1f807c63",
+			"order": [
+				"0b69e4c7-b0fd-c313-76f7-694296789293",
+				"ea9d5dd7-6b22-e10a-777d-c9f3b8233858",
+				"f203eccc-73e3-6e0c-f526-ef635c43fd82",
+				"d6bd3339-7186-1eb8-8659-a2f1330d830c"
+			],
+			"owner": "503523",
+			"folders_order": [],
+			"auth": null,
+			"id": "a220d584-8aba-5112-5f30-dc287d4742de"
 		},
 		{
 			"name": "OrgnizationDimension",
 			"description": "",
-			"collectionId": "871762c3-97f9-1ac0-f17c-d17bd3446b87",
+			"collectionId": "a743e1b9-583f-6bd7-e2ae-f03a1f807c63",
 			"order": [
-				"d9fa6f9b-14eb-7b02-9d8e-6017d6d442a7",
-				"2cc34a2b-d4e0-ff5d-3e73-4be4b1bcbfb8",
-				"7f475e07-d86e-8ff8-b087-57d926389f10",
-				"d49b0e8b-53f9-3089-895e-ad013220f306"
+				"d480edbd-2188-d55e-f106-b1a7809a3fcb",
+				"619972f0-9f96-d4b5-3287-d2958f3a60c7",
+				"45aef93d-2bcf-4a1f-245a-29611d3d740e"
 			],
-			"owner": "2830994",
-			"folder": "7511d4fa-72ce-8671-54d0-2f3432d86445",
+			"owner": "503523",
+			"folder": "523a7f9f-1970-018e-9241-57caa3d6ea60",
 			"folders_order": [],
-			"id": "a59711e8-e3ea-db95-56cf-6c6c70e150a8"
+			"id": "04a4a902-f33b-bce5-06dc-4da56cae7c4f"
 		}
 	],
 	"folders_order": [
-		"20092b46-e67b-f886-5433-32d7105b6379",
-		"7511d4fa-72ce-8671-54d0-2f3432d86445",
-		"a6877336-53f6-b720-ee4f-313d6c9d9c94",
-		"022408d6-3e26-da08-eb52-ca3c83d8f226",
-		"c42b54fc-895c-d10c-72b0-01642ce776e8"
+		"ee22ca52-aa2b-18a3-1070-bc9fdc018a7d",
+		"523a7f9f-1970-018e-9241-57caa3d6ea60",
+		"40702c96-d08c-fd56-add4-5d26598e539e",
+		"a220d584-8aba-5112-5f30-dc287d4742de",
+		"7ae8e04f-c5cb-aeab-9af3-65cb3bf87b1f",
+		"208120a7-5805-89eb-4472-775e0f73a819"
 	],
-	"timestamp": 0,
-	"owner": "2830994",
+	"timestamp": 1509932685084,
+	"owner": "503523",
 	"public": false,
 	"requests": [
 		{
-			"id": "02e56b82-6e21-4c68-f6a9-61e9f8a1b8bf",
+			"id": "01e1bf7a-0a88-2039-ec03-777222c33bf5",
 			"headers": "",
 			"headerData": [],
-			"url": "{{BASE_PATH}}/api/v1/jobs/instances?group=BA&jobName=measure-BA-0-1508478921000&page=0&size=10",
-			"folder": "a6877336-53f6-b720-ee4f-313d6c9d9c94",
-			"queryParams": [
-				{
-					"key": "group",
-					"value": "BA",
-					"equals": true,
-					"description": "",
-					"enabled": true
-				},
-				{
-					"key": "jobName",
-					"value": "measure-BA-0-1508478921000",
-					"equals": true,
-					"description": "",
-					"enabled": true
-				},
-				{
-					"key": "page",
-					"value": "0",
-					"equals": true,
-					"description": "",
-					"enabled": true
-				},
-				{
-					"key": "size",
-					"value": "10",
-					"equals": true,
-					"description": "",
-					"enabled": true
-				}
-			],
+			"url": "{{BASE_PATH}}/api/v1/jobs",
+			"queryParams": [],
 			"preRequestScript": null,
 			"pathVariables": {},
 			"pathVariableData": [],
 			"method": "GET",
 			"data": null,
 			"dataMode": "params",
+			"version": 2,
 			"tests": null,
 			"currentHelper": "normal",
-			"helperAttributes": {},
-			"time": 1508997518626,
-			"name": "Get job instances",
-			"description": "`GET /api/v1/instances`\n\nGet all job instances scheduled at different time using the same prototype job.The prototype job is determined by SCHED_NAME, group name and job name in table QRTZ_JOB_DETAILS.\n\n<center>name<center/> | <center>description<center/> | <center>type<center/> | <center>example value<center/>\n--- | --- | --- | ---\ngroup | job group name | String | BA\njobName | job name | String | measure-BA-job-1\npage | page you want starting from index 0 | int | 0\nsize | instance number per page | int | 10",
-			"collectionId": "871762c3-97f9-1ac0-f17c-d17bd3446b87",
+			"helperAttributes": "{}",
+			"time": 1509005652378,
+			"name": "Get jobs",
+			"description": "`GET /api/v1/jobs`",
+			"collectionId": "a743e1b9-583f-6bd7-e2ae-f03a1f807c63",
 			"responses": [
 				{
 					"status": "",
@@ -157,7 +144,7 @@
 						"code": 200,
 						"name": "OK"
 					},
-					"time": 3755,
+					"time": 129,
 					"headers": [
 						{
 							"name": "access-control-allow-headers",
@@ -192,7 +179,7 @@
 						{
 							"name": "date",
 							"key": "date",
-							"value": "Wed, 25 Oct 2017 01:43:23 GMT",
+							"value": "Tue, 24 Oct 2017 12:01:29 GMT",
 							"description": "The date and time that the message was sent"
 						},
 						{
@@ -204,7 +191,7 @@
 					],
 					"cookies": [],
 					"mime": "",
-					"text": "[{\"id\":6248,\"groupName\":\"BA\",\"jobName\":\"measure-BA-0-1508478921000\",\"sessionId\":17887,\"state\":\"unknown\",\"appId\":null,\"appUri\":null,\"timestamp\":1508895600513},{\"id\":6245,\"groupName\":\"BA\",\"jobName\":\"measure-BA-0-1508478921000\",\"sessionId\":17884,\"state\":\"dead\",\"appId\":null,\"appUri\":null,\"timestamp\":1508895300471},{\"id\":6243,\"groupName\":\"BA\",\"jobName\":\"measure-BA-0-1508478921000\",\"sessionId\":17882,\"state\":\"dead\",\"appId\":null,\"appUri\":null,\"timestamp\":1508895000461},{\"id\":6241,\"groupName\":\"BA\",\"jobName\":\"measure-BA-0-1508478921000\",\"sessionId\":17880,\"state\":\"dead\",\"appId\":null,\"appUri\":null,\"timestamp\":1508894700451},{\"id\":6239,\"groupName\":\"BA\",\"jobName\":\"measure-BA-0-1508478921000\",\"sessionId\":17878,\"state\":\"dead\",\"appId\":null,\"appUri\":null,\"timestamp\":1508894400457},{\"id\":6237,\"groupName\":\"BA\",\"jobName\":\"measure-BA-0-1508478921000\",\"sessionId\":17876,\"
 state\":\"dead\",\"appId\":null,\"appUri\":null,\"timestamp\":1508894100455},{\"id\":6235,\"groupName\":\"BA\",\"jobName\":\"measure-BA-0-1508478921000\",\"sessionId\":17874,\"state\":\"dead\",\"appId\":null,\"appUri\":null,\"timestamp\":1508893800444},{\"id\":6233,\"groupName\":\"BA\",\"jobName\":\"measure-BA-0-1508478921000\",\"sessionId\":17872,\"state\":\"dead\",\"appId\":null,\"appUri\":null,\"timestamp\":1508893500452},{\"id\":6231,\"groupName\":\"BA\",\"jobName\":\"measure-BA-0-1508478921000\",\"sessionId\":17870,\"state\":\"dead\",\"appId\":null,\"appUri\":null,\"timestamp\":1508893200452},{\"id\":6229,\"groupName\":\"BA\",\"jobName\":\"measure-BA-0-1508478921000\",\"sessionId\":17868,\"state\":\"dead\",\"appId\":null,\"appUri\":null,\"timestamp\":1508892900452}]",
+					"text": "[\n    {\n        \"jobId\": 1,\n        \"jobName\": \"job_name\",\n        \"measureId\": 2,\n        \"triggerState\": \"NORMAL\",\n        \"nextFireTime\": 1515400080000,\n        \"previousFireTime\": 1515399840000,\n        \"cronExpression\": \"0 0/4 * * * ?\"\n    }\n]",
 					"language": "json",
 					"rawDataType": "text",
 					"previewType": "text",
@@ -213,174 +200,161 @@
 					"write": true,
 					"empty": false,
 					"failed": false,
-					"id": "bfa36b71-8fc0-c26b-34d0-41d77aecafc3",
-					"name": "Get job instances example",
+					"id": "b7b16ee4-b9a2-132a-9d02-47665332b270",
+					"name": "Get jobs example",
 					"isSample": true,
 					"scrollToResult": false,
 					"runTests": false,
 					"request": {
-						"url": "{{BASE_PATH}}/api/v1/jobs/instances?group=BA&jobName=measure-BA-0-1508478921000&page=0&size=10",
+						"url": "{{BASE_PATH}}/api/v1/jobs",
 						"pathVariables": {},
 						"pathVariableData": [],
-						"queryParams": [
-							{
-								"key": "group",
-								"value": "BA",
-								"equals": true,
-								"description": "",
-								"enabled": true
-							},
-							{
-								"key": "jobName",
-								"value": "measure-BA-0-1508478921000",
-								"equals": true,
-								"description": "",
-								"enabled": true
-							},
-							{
-								"key": "page",
-								"value": "0",
-								"equals": true,
-								"description": "",
-								"enabled": true
-							},
-							{
-								"key": "size",
-								"value": "10",
-								"equals": true,
-								"description": "",
-								"enabled": true
-							}
-						],
+						"queryParams": [],
 						"headerData": [],
 						"headers": "",
-						"data": null,
+						"data": "",
 						"method": "GET",
-						"dataMode": "params"
+						"dataMode": "raw"
 					},
-					"owner": "2830994"
+					"owner": "503523"
 				}
 			],
-			"collection_id": "871762c3-97f9-1ac0-f17c-d17bd3446b87"
+			"collection_id": "a743e1b9-583f-6bd7-e2ae-f03a1f807c63",
+			"isFromCollection": true,
+			"folder": "40702c96-d08c-fd56-add4-5d26598e539e"
 		},
 		{
-			"id": "2cc34a2b-d4e0-ff5d-3e73-4be4b1bcbfb8",
+			"id": "0b69e4c7-b0fd-c313-76f7-694296789293",
 			"headers": "",
 			"headerData": [],
-			"url": "{{BASE_PATH}}/api/v1/org/:org",
-			"folder": "a59711e8-e3ea-db95-56cf-6c6c70e150a8",
+			"url": "{{BASE_PATH}}/api/v1/metrics",
 			"queryParams": [],
-			"preRequestScript": null,
-			"pathVariables": {
-				"org": "test"
-			},
-			"pathVariableData": [
-				{
-					"key": "org",
-					"value": "test"
-				}
-			],
+			"pathVariables": {},
+			"pathVariableData": [],
+			"events": [],
+			"auth": null,
 			"method": "GET",
+			"collectionId": "a743e1b9-583f-6bd7-e2ae-f03a1f807c63",
 			"data": null,
 			"dataMode": "params",
-			"tests": null,
-			"currentHelper": "normal",
-			"helperAttributes": {},
-			"time": 1508998400445,
-			"name": "Get measure names by org",
-			"description": "`GET /api/v1/org/{org}`\n#### Path Variable\n- org - `required` `String` organization name.\n\n#### Request Sample\n`/api/v1/org/test`",
-			"collectionId": "871762c3-97f9-1ac0-f17c-d17bd3446b87",
+			"name": "Get metrics",
+			"description": "`GET /api/v1/metrics`\n\nGet all metrics that are computed by griffin jobs or subscribed by external measure.",
+			"descriptionFormat": "html",
+			"time": 1515485493066,
+			"version": 2,
 			"responses": [
 				{
 					"status": "",
 					"responseCode": {
 						"code": 200,
-						"name": "OK",
-						"detail": "Standard response for successful HTTP requests. The actual response will depend on the request method used. In a GET request, the response will contain an entity corresponding to the requested resource. In a POST request the response will contain an entity describing or containing the result of the action."
+						"name": "OK"
 					},
-					"time": 26,
+					"time": 800,
 					"headers": [
 						{
-							"name": "access-control-allow-headers",
-							"key": "access-control-allow-headers",
+							"key": "Access-Control-Allow-Headers",
 							"value": "X-PINGOTHER, Origin, X-Requested-With, Content-Type, Accept",
+							"name": "Access-Control-Allow-Headers",
 							"description": "Used in response to a preflight request to indicate which HTTP headers can be used when making the actual request."
 						},
 						{
-							"name": "access-control-allow-methods",
-							"key": "access-control-allow-methods",
+							"key": "Access-Control-Allow-Methods",
 							"value": "POST, GET, OPTIONS, DELETE,PUT",
+							"name": "Access-Control-Allow-Methods",
 							"description": "Specifies the method or methods allowed when accessing the resource. This is used in response to a preflight request."
 						},
 						{
-							"name": "access-control-allow-origin",
-							"key": "access-control-allow-origin",
+							"key": "Access-Control-Allow-Origin",
 							"value": "*",
+							"name": "Access-Control-Allow-Origin",
 							"description": "Specifies a URI that may access the resource. For requests without credentials, the server may specify '*' as a wildcard, thereby allowing any origin to access the resource."
 						},
 						{
-							"name": "access-control-max-age",
-							"key": "access-control-max-age",
+							"key": "Access-Control-Max-Age",
 							"value": "3600",
+							"name": "Access-Control-Max-Age",
 							"description": "Indicates how long the results of a preflight request can be cached in seconds."
 						},
 						{
-							"name": "content-type",
-							"key": "content-type",
+							"key": "Content-Type",
 							"value": "application/json;charset=UTF-8",
+							"name": "Content-Type",
 							"description": "The mime type of this content"
 						},
 						{
-							"name": "date",
-							"key": "date",
-							"value": "Thu, 26 Oct 2017 06:10:23 GMT",
+							"key": "Date",
+							"value": "Tue, 09 Jan 2018 08:39:20 GMT",
+							"name": "Date",
 							"description": "The date and time that the message was sent"
 						},
 						{
-							"name": "transfer-encoding",
-							"key": "transfer-encoding",
+							"key": "Transfer-Encoding",
 							"value": "chunked",
+							"name": "Transfer-Encoding",
 							"description": "The form of encoding used to safely transfer the entity to the user. Currently defined methods are: chunked, compress, deflate, gzip, identity."
 						}
 					],
-					"cookies": [],
+					"cookies": [
+						{
+							"domain": "localhost",
+							"expirationDate": 2147483647,
+							"httpOnly": true,
+							"name": "JSESSIONID",
+							"path": "/",
+							"secure": false,
+							"url": "http://localhost:8080",
+							"value": "DC35BDC91FC450DE5D89D477E27FD19E"
+						}
+					],
 					"mime": "",
-					"text": "[\"measure1\"]",
+					"text": "[{\"name\":\"external_name\",\"description\":\" test measure\",\"organization\":\"orgName\",\"owner\":\"test\",\"metricValues\":[{\"name\":\"metricName\",\"tmst\":1509599811123,\"value\":{\"__tmst\":1509599811123,\"miss\":11,\"total\":125000,\"matched\":124989}}]}]",
 					"language": "json",
-					"rawDataType": "text",
 					"previewType": "text",
 					"searchResultScrolledTo": -1,
 					"forceNoPretty": false,
 					"write": true,
 					"empty": false,
 					"failed": false,
-					"name": "Get measure names by org example",
-					"id": "a665b053-90d1-668b-880b-5fb87c093669",
-					"request": {
-						"url": "{{BASE_PATH}}/api/v1/org/:org",
-						"pathVariables": {
-							"org": "test"
-						},
-						"pathVariableData": [
-							{
-								"key": "org",
-								"value": "test"
-							}
-						],
+					"code": 200,
+					"responseSize": {
+						"body": 231,
+						"header": 345,
+						"total": 576
+					},
+					"mimeType": "text",
+					"fileName": "response.json",
+					"dataURI": "data:application/json;base64, W3sibmFtZSI6ImV4dGVybmFsX25hbWUiLCJkZXNjcmlwdGlvbiI6IiB0ZXN0IG1lYXN1cmUiLCJvcmdhbml6YXRpb24iOiJvcmdOYW1lIiwib3duZXIiOiJ0ZXN0IiwibWV0cmljVmFsdWVzIjpbeyJuYW1lIjoibWV0cmljTmFtZSIsInRtc3QiOjE1MDk1OTk4MTExMjMsInZhbHVlIjp7Il9fdG1zdCI6MTUwOTU5OTgxMTEyMywibWlzcyI6MTEsInRvdGFsIjoxMjUwMDAsIm1hdGNoZWQiOjEyNDk4OX19XX1d",
+					"id": "508596a6-43a1-7c8b-a430-32834dbac515",
+					"name": "Get metcis example",
+					"isSample": true,
+					"scrollToResult": false,
+					"runTests": false,
+					"request": "0b69e4c7-b0fd-c313-76f7-694296789293",
+					"owner": "503523",
+					"requestObject": {
+						"url": "{{BASE_PATH}}/api/v1/metrics",
+						"pathVariables": {},
+						"pathVariableData": [],
 						"queryParams": [],
 						"headerData": [],
 						"headers": "",
 						"data": null,
 						"method": "GET",
 						"dataMode": "params"
-					},
-					"owner": "2830994"
+					}
 				}
 			],
-			"collection_id": "871762c3-97f9-1ac0-f17c-d17bd3446b87"
+			"folder": "a220d584-8aba-5112-5f30-dc287d4742de",
+			"collection_id": "0afa8193-bfa7-7735-dd77-d5014d360e4c",
+			"currentHelper": null,
+			"helperAttributes": "null",
+			"preRequestScript": "",
+			"tests": "",
+			"isFromCollection": true,
+			"collectionRequestId": "70038dbb-8fd2-3bd2-1333-5ee86e8a8cff"
 		},
 		{
-			"id": "37578eb8-93b0-4903-0e51-42361aec3a90",
+			"id": "12232e4c-2720-f5ac-0c6c-71b877a14d94",
 			"headers": "Content-Type: application/json\n",
 			"headerData": [
 				{
@@ -390,22 +364,22 @@
 					"enabled": true
 				}
 			],
-			"url": "{{BASE_PATH}}/api/v1/login/authenticate",
-			"folder": "c42b54fc-895c-d10c-72b0-01642ce776e8",
+			"url": "{{BASE_PATH}}/api/v1/measures",
+			"folder": "523a7f9f-1970-018e-9241-57caa3d6ea60",
 			"queryParams": [],
 			"preRequestScript": null,
 			"pathVariables": {},
 			"pathVariableData": [],
-			"method": "POST",
-			"data": null,
-			"dataMode": "params",
+			"method": "PUT",
+			"data": [],
+			"dataMode": "raw",
 			"tests": null,
 			"currentHelper": "normal",
 			"helperAttributes": {},
-			"time": 1508997889462,
-			"name": "User authentication",
-			"description": "`POST /api/v1/login/authenticate`\n\n#### Request Parameter\nname | description | type |example value\n--- | --- | --- | ---\nmap | a map contains user name and password | Map |  `{\"username\":\"user\",\"password\":\"test\"}`",
-			"collectionId": "871762c3-97f9-1ac0-f17c-d17bd3446b87",
+			"time": 1515399022575,
+			"name": "Update measure",
+			"description": "`PUT /api/v1/measures`\n\n#### Request Header\nkey | value\n--- | ---\nContent-Type | application/json\n\n#### Request Body\n\nname | description | type\n--- | --- | --- \nmeasure | measure entity | Measure\n\nThere are two different measures that are griffin measure and external measure.\nIf you want to update an external measure,you can use following example json in request body.\n```\n{\n\t\"id\":1,\n    \"type\": \"external\",\n    \"name\": \"external_name\",\n    \"description\": \" update test measure\",\n    \"organization\": \"orgName\",\n    \"owner\": \"test\",\n    \"metricName\": \"metricName\"\n}\n```\nPostman gives a griffin measure example in request body and response body. \n#### Response Body Sample\n```\n{\n  \"code\": 204,\n  \"description\": \"Update Measure Succeed\"\n}\n```\n\nIt may return failed messages.Such as,\n\n```\n {\n  \"code\": 400,\n  \"description\": \"Resource Not Found\"\n}\n\n```\n\nThe reason for failure may be that measure 
 id doesn't exist.",
+			"collectionId": "a743e1b9-583f-6bd7-e2ae-f03a1f807c63",
 			"responses": [
 				{
 					"status": "",
@@ -413,7 +387,7 @@
 						"code": 200,
 						"name": "OK"
 					},
-					"time": 70,
+					"time": 157,
 					"headers": [
 						{
 							"name": "access-control-allow-headers",
@@ -448,7 +422,7 @@
 						{
 							"name": "date",
 							"key": "date",
-							"value": "Wed, 25 Oct 2017 08:18:38 GMT",
+							"value": "Tue, 24 Oct 2017 11:05:46 GMT",
 							"description": "The date and time that the message was sent"
 						},
 						{
@@ -460,7 +434,7 @@
 					],
 					"cookies": [],
 					"mime": "",
-					"text": "{\"fullName\":\"Default\",\"ntAccount\":\"user\",\"status\":0}",
+					"text": "{\"code\":204,\"description\":\"Update Measure Succeed\"}",
 					"language": "json",
 					"rawDataType": "text",
 					"previewType": "text",
@@ -469,13 +443,13 @@
 					"write": true,
 					"empty": false,
 					"failed": false,
-					"id": "c115cb54-3bf9-e7c8-827a-a7d93bf21946",
-					"name": "User authentication example",
+					"id": "d32fe979-cba5-bb88-09fd-e71c3a7135ac",
+					"name": "Update measure example",
 					"isSample": true,
 					"scrollToResult": false,
 					"runTests": false,
 					"request": {
-						"url": "{{BASE_PATH}}/api/v1/login/authenticate",
+						"url": "{{BASE_PATH}}/api/v1/measures",
 						"pathVariables": {},
 						"pathVariableData": [],
 						"queryParams": [],
@@ -488,44 +462,50 @@
 							}
 						],
 						"headers": "Content-Type: application/json\n",
-						"data": "{\"username\":\"user\",\"password\":\"test\"}",
-						"method": "POST",
+						"data": "{\n        \"id\": 1,\n        \"name\": \"measure_official_update\",\n        \"description\": \"create a measure\",\n        \"organization\": \"test\",\n        \"owner\": \"test\",\n        \"deleted\": false,\n        \"type\": \"griffin\",\n        \"process.type\": \"batch\",\n        \"data.sources\": [\n            {\n                \"id\": 1,\n                \"name\": \"source\",\n                \"connectors\": [\n                    {\n                        \"id\": 1,\n                        \"name\": \"connector_name_source\",\n                        \"type\": \"HIVE\",\n                        \"version\": \"1.2\",\n                        \"predicates\": [],\n                        \"data.unit\": \"1h\",\n                        \"config\": {\n                            \"database\": \"default\",\n                            \"table.name\": \"demo_src\",\n                            \"where\": \"dt=#YYYYMMdd# AND hour=#HH#\"\n                   
      }\n                    }\n                ]\n            },\n            {\n                \"id\": 2,\n                \"name\": \"target\",\n                \"connectors\": [\n                    {\n                        \"id\": 2,\n                        \"name\": \"connector_name_target\",\n                        \"type\": \"HIVE\",\n                        \"version\": \"1.2\",\n                        \"predicates\": [],\n                        \"data.unit\": \"1h\",\n                        \"config\": {\n                            \"database\": \"default\",\n                            \"table.name\": \"demo_src\",\n                            \"where\": \"dt=#YYYYMMdd# AND hour=#HH#\"\n                        }\n                    }\n                ]\n            }\n        ],\n        \"evaluate.rule\": {\n            \"id\": 1,\n            \"rules\": [\n                {\n                    \"id\": 1,\n                    \"rule\": \"source.desc=target.desc
 \",\n                    \"dsl.type\": \"griffin-dsl\",\n                    \"dq.type\": \"accuracy\",\n                    \"details\": {}\n                }\n            ]\n        }\n    }",
+						"method": "PUT",
 						"dataMode": "raw"
-					},
-					"owner": "2830994"
+					}
 				}
 			],
-			"collection_id": "871762c3-97f9-1ac0-f17c-d17bd3446b87"
+			"rawModeData": "{\n        \"id\": 1,\n        \"name\": \"measureName_test_edit\",\n        \"description\": \"This is a test measure\",\n        \"organization\": \"orgName\",\n        \"evaluateRule\": {\n            \"rules\": [\n                {\n                    \"rule\": \"source.id = target.id and source.age = target.age and source.desc = target.desc\",\n                    \"dsl.type\": \"griffin-dsl\",\n                    \"dq.type\": \"accuracy\"\n                }\n            ]\n        },\n        \"owner\": \"test\",\n        \"deleted\": false,\n        \"process.type\": \"batch\",\n        \"data.sources\": [\n            {\n                \"name\": \"source\",\n                \"connectors\": [\n                    {\n                        \"type\": \"HIVE\",\n                        \"version\": \"1.2\",\n                        \"config\": {\n                            \"database\": \"default\",\n                            \"table.name\": \"demo_src\
 "\n                        }\n                    }\n                ]\n            },\n            {\n                \"name\": \"target\",\n                \"connectors\": [\n                    {\n                        \"type\": \"HIVE\",\n                        \"version\": \"1.2\",\n                        \"config\": {\n                            \"database\": \"default\",\n                            \"table.name\": \"demo_tgt\"\n                        }\n                    }\n                ]\n            }\n        ]\n}",
+			"collection_id": "a743e1b9-583f-6bd7-e2ae-f03a1f807c63"
 		},
 		{
-			"id": "4495d595-55a8-88af-4afb-85b2d722d00f",
+			"id": "2bfc82ab-ec97-ee89-d6b4-db5ffefce28b",
 			"headers": "",
 			"headerData": [],
-			"url": "{{BASE_PATH}}/api/v1/version",
-			"folder": "20092b46-e67b-f886-5433-32d7105b6379",
+			"url": "{{BASE_PATH}}/api/v1/jobs/:id",
 			"queryParams": [],
 			"preRequestScript": null,
-			"pathVariables": {},
-			"pathVariableData": [],
-			"method": "GET",
+			"pathVariables": {
+				"id": "3"
+			},
+			"pathVariableData": [
+				{
+					"key": "id",
+					"value": "3"
+				}
+			],
+			"method": "DELETE",
 			"data": null,
 			"dataMode": "params",
-			"version": 2,
 			"tests": null,
 			"currentHelper": "normal",
 			"helperAttributes": {},
-			"time": 1508997903989,
-			"name": "Get griffin version",
-			"description": "`GET /api/v1/version`",
-			"collectionId": "871762c3-97f9-1ac0-f17c-d17bd3446b87",
+			"time": 1515389245150,
+			"name": "Delete  job by id",
+			"description": "`DELETE /api/v1/jobs/{id}`\n#### Path Variable\n- id -`required` `Long` job id\n\n#### Response Body Sample\n```\n{\n  \"code\": 206,\n  \"description\": \"Delete Job Succeed\"\n}\n\n```\nIt may return failed messages.Such as,\n```\n{\n    \"code\": 406,\n    \"description\": \"Delete Job Failed\"\n}\n```\nThe reason for failure may be that job id does not exist.",
+			"collectionId": "a743e1b9-583f-6bd7-e2ae-f03a1f807c63",
 			"responses": [
 				{
 					"status": "",
 					"responseCode": {
 						"code": 200,
-						"name": "OK"
+						"name": "OK",
+						"detail": "Standard response for successful HTTP requests. The actual response will depend on the request method used. In a GET request, the response will contain an entity corresponding to the requested resource. In a POST request the response will contain an entity describing or containing the result of the action."
 					},
-					"time": 63,
+					"time": 42,
 					"headers": [
 						{
 							"name": "access-control-allow-headers",
@@ -552,28 +532,28 @@
 							"description": "Indicates how long the results of a preflight request can be cached in seconds."
 						},
 						{
-							"name": "content-length",
-							"key": "content-length",
-							"value": "5",
-							"description": "The length of the response body in octets (8-bit bytes)"
-						},
-						{
 							"name": "content-type",
 							"key": "content-type",
-							"value": "text/plain;charset=UTF-8",
+							"value": "application/json;charset=UTF-8",
 							"description": "The mime type of this content"
 						},
 						{
 							"name": "date",
 							"key": "date",
-							"value": "Thu, 26 Oct 2017 05:45:09 GMT",
+							"value": "Wed, 10 Jan 2018 06:17:35 GMT",
 							"description": "The date and time that the message was sent"
+						},
+						{
+							"name": "transfer-encoding",
+							"key": "transfer-encoding",
+							"value": "chunked",
+							"description": "The form of encoding used to safely transfer the entity to the user. Currently defined methods are: chunked, compress, deflate, gzip, identity."
 						}
 					],
 					"cookies": [],
 					"mime": "",
-					"text": "0.1.0",
-					"language": "plainText",
+					"text": "{\n    \"code\": 405,\n    \"description\": \"Delete Job Succeed\"\n}",
+					"language": "json",
 					"rawDataType": "text",
 					"previewType": "text",
 					"searchResultScrolledTo": -1,
@@ -581,59 +561,50 @@
 					"write": true,
 					"empty": false,
 					"failed": false,
-					"name": "Get griffin version example",
-					"id": "f4d01121-2424-8457-eb37-75b3d2638732",
+					"name": "Delete  job by id example",
+					"id": "24c5f527-5e24-0272-3e0b-02789b9b25c0",
 					"request": {
-						"url": "{{BASE_PATH}}/api/v1/version",
-						"pathVariables": {},
-						"pathVariableData": [],
+						"url": "{{BASE_PATH}}/api/v1/jobs/:id",
+						"pathVariables": {
+							"id": "1"
+						},
+						"pathVariableData": [
+							{
+								"key": "id",
+								"value": "1"
+							}
+						],
 						"queryParams": [],
 						"headerData": [],
 						"headers": "",
 						"data": null,
-						"method": "GET",
+						"method": "DELETE",
 						"dataMode": "params"
-					},
-					"owner": "2830994"
+					}
 				}
 			],
-			"collection_id": "871762c3-97f9-1ac0-f17c-d17bd3446b87"
+			"collection_id": "a743e1b9-583f-6bd7-e2ae-f03a1f807c63",
+			"folder": "40702c96-d08c-fd56-add4-5d26598e539e"
 		},
 		{
-			"id": "63066f6e-27ad-546d-27bc-e424dc0bd636",
+			"id": "2d90ae20-5f65-df06-b533-e7f3e9ea3b50",
 			"headers": "",
 			"headerData": [],
-			"url": "{{BASE_PATH}}/api/v1/jobs?group=BA&jobName=measure_name-BA-0-1508847304000",
-			"folder": "a6877336-53f6-b720-ee4f-313d6c9d9c94",
-			"queryParams": [
-				{
-					"key": "group",
-					"value": "BA",
-					"equals": true,
-					"description": "",
-					"enabled": true
-				},
-				{
-					"key": "jobName",
-					"value": "measure_name-BA-0-1508847304000",
-					"equals": true,
-					"description": "",
-					"enabled": true
-				}
-			],
+			"url": "{{BASE_PATH}}/api/v1/metadata/hive/dbs",
+			"queryParams": [],
 			"preRequestScript": null,
 			"pathVariables": {},
 			"pathVariableData": [],
-			"method": "DELETE",
+			"method": "GET",
 			"data": null,
 			"dataMode": "params",
 			"tests": null,
 			"currentHelper": "normal",
-			"helperAttributes": {},
-			"time": 1508997593266,
-			"name": "Delete  job",
-			"description": "`DELETE /api/v1/jobs`\n#### Request Parameters \n\n<center>name<center/> | <center>description<center/> | <center>type<center/> | <center>example value<center/>\n--- | --- | --- | ---\ngroup | job group name | String | BA\njobName | job name | String | measure_name-BA-0-1508846730000\n\n#### Response Body Sample\n```\n{\n  \"code\": 206,\n  \"description\": \"Delete Job Succeed\"\n}\n\n```\nIt may return failed messages.Such as,\n```\n{\n    \"code\": 406,\n    \"description\": \"Delete Job Failed\"\n}\n```\nThe reason for failure may be that there is no corresponding job of provided group and jobName.You should check group and jobName to make sure they exist .",
-			"collectionId": "871762c3-97f9-1ac0-f17c-d17bd3446b87",
+			"helperAttributes": "{}",
+			"time": 1508997670920,
+			"name": "Get database names",
+			"description": "`GET /api/v1/metadata/hive/dbs`\n \n #### Get all database names",
+			"collectionId": "a743e1b9-583f-6bd7-e2ae-f03a1f807c63",
 			"responses": [
 				{
 					"status": "",
@@ -641,7 +612,7 @@
 						"code": 200,
 						"name": "OK"
 					},
-					"time": 67,
+					"time": 225,
 					"headers": [
 						{
 							"name": "access-control-allow-headers",
@@ -676,7 +647,7 @@
 						{
 							"name": "date",
 							"key": "date",
-							"value": "Tue, 24 Oct 2017 12:07:39 GMT",
+							"value": "Wed, 25 Oct 2017 05:12:36 GMT",
 							"description": "The date and time that the message was sent"
 						},
 						{
@@ -688,7 +659,7 @@
 					],
 					"cookies": [],
 					"mime": "",
-					"text": "{\"code\":206,\"description\":\"Delete Job Succeed\"}",
+					"text": "[\"default\"]",
 					"language": "json",
 					"rawDataType": "text",
 					"previewType": "text",
@@ -697,63 +668,46 @@
 					"write": true,
 					"empty": false,
 					"failed": false,
-					"id": "5c1651fb-044e-de26-c5df-f72d03d51e13",
-					"name": "Delete  job example",
+					"id": "52f80f82-5894-37bb-1d2e-84d0c5975991",
+					"name": "Get db names example",
 					"isSample": true,
 					"scrollToResult": false,
 					"runTests": false,
-					"request": {
-						"url": "{{BASE_PATH}}/api/v1/jobs?group=BA&jobName=measure_name-BA-0-1508846730000",
-						"pathVariables": {},
-						"pathVariableData": [],
-						"queryParams": [
-							{
-								"key": "group",
-								"value": "BA",
-								"equals": true,
-								"description": "",
-								"enabled": true
-							},
-							{
-								"key": "jobName",
-								"value": "measure_name-BA-0-1508846730000",
-								"equals": true,
-								"description": "",
-								"enabled": true
-							}
-						],
-						"headerData": [],
-						"headers": "",
-						"data": null,
-						"method": "DELETE",
-						"dataMode": "params"
-					},
-					"owner": "2830994"
+					"request": "5985157f-88de-dd0c-70c2-add0f6b7d9f8",
+					"owner": "503523",
+					"requestObject": "{\"url\":\"{{BASE_PATH}}/api/v1/metadata/hive/dbs\",\"pathVariables\":{},\"pathVariableData\":[],\"queryParams\":[],\"headerData\":[],\"headers\":\"\",\"data\":null,\"method\":\"GET\",\"dataMode\":\"params\"}"
 				}
 			],
-			"collection_id": "871762c3-97f9-1ac0-f17c-d17bd3446b87"
+			"collection_id": "a743e1b9-583f-6bd7-e2ae-f03a1f807c63",
+			"folder": "7ae8e04f-c5cb-aeab-9af3-65cb3bf87b1f"
 		},
 		{
-			"id": "742889e2-52e1-58eb-9c50-9a225bba87bb",
-			"headers": "",
-			"headerData": [],
-			"url": "{{BASE_PATH}}/api/v1/jobs",
-			"folder": "a6877336-53f6-b720-ee4f-313d6c9d9c94",
+			"id": "2ebbf1cd-c78a-861e-6382-4a4d9dfba4be",
+			"headers": "Content-Type: application/json\n",
+			"headerData": [
+				{
+					"key": "Content-Type",
+					"value": "application/json",
+					"description": "",
+					"enabled": true
+				}
+			],
+			"url": "{{BASE_PATH}}/api/v1/measures",
+			"folder": "523a7f9f-1970-018e-9241-57caa3d6ea60",
 			"queryParams": [],
 			"preRequestScript": null,
 			"pathVariables": {},
 			"pathVariableData": [],
-			"method": "GET",
-			"data": null,
-			"dataMode": "params",
-			"version": 2,
+			"method": "POST",
+			"data": [],
+			"dataMode": "raw",
 			"tests": null,
 			"currentHelper": "normal",
 			"helperAttributes": {},
-			"time": 1509005652378,
-			"name": "Get jobs",
-			"description": "`GET /api/v1/jobs/`",
-			"collectionId": "871762c3-97f9-1ac0-f17c-d17bd3446b87",
+			"time": 1515398727266,
+			"name": "Add measure",
+			"description": "`POST /api/v1/measures`\n\n#### Request Header\nkey | value\n--- | ---\nContent-Type | application/json\n\n#### Request Body\n\nname | description | type\n--- | --- | --- \nmeasure | measure entity | Measure\n\nThere are two different measures that are griffin measure and external measure.\nIf you want to create an external measure,you can use following example json in request body.\n```\n{\n    \"type\": \"external\",\n    \"name\": \"external_name\",\n    \"description\": \" test measure\",\n    \"organization\": \"orgName\",\n    \"owner\": \"test\",\n    \"metricName\": \"metricName\"\n}\n```\nPostman gives a griffin measure example in request body and response body. \n#### Response Body Sample\n```\n{\n  \"code\": 201,\n  \"description\": \"Create Measure Succeed\"\n}\n```\n\nIt may return failed messages.Such as,\n\n```\n {\n  \"code\": 410,\n  \"description\": \"Create Measure Failed, duplicate records\"\n}\n\n```\n\nThe reason for failure may be that measu
 re name already exists.You can change measure name to make it unique.\n\n```\n {\n  \"code\": 401,\n  \"description\": \"Create Measure Failed\"\n}\n```\nThe reason for failure may be that connector names already exist or connector names are empty.",
+			"collectionId": "a743e1b9-583f-6bd7-e2ae-f03a1f807c63",
 			"responses": [
 				{
 					"status": "",
@@ -761,7 +715,7 @@
 						"code": 200,
 						"name": "OK"
 					},
-					"time": 129,
+					"time": 629,
 					"headers": [
 						{
 							"name": "access-control-allow-headers",
@@ -796,7 +750,7 @@
 						{
 							"name": "date",
 							"key": "date",
-							"value": "Tue, 24 Oct 2017 12:01:29 GMT",
+							"value": "Tue, 24 Oct 2017 10:59:21 GMT",
 							"description": "The date and time that the message was sent"
 						},
 						{
@@ -808,7 +762,7 @@
 					],
 					"cookies": [],
 					"mime": "",
-					"text": "[{\"jobName\":\"measure_name-BA-0-1508846486000\",\"measureId\":\"2\",\"groupName\":\"BA\",\"targetPattern\":\"YYYYMMdd-HH\",\"triggerState\":\"NORMAL\",\"nextFireTime\":1508846700000,\"previousFireTime\":-1,\"interval\":\"300\",\"sourcePattern\":\"YYYYMMdd-HH\",\"jobStartTime\":\"1508774400000\"}]",
+					"text": "{\"code\":201,\"description\":\"Create Measure Succeed\"}",
 					"language": "json",
 					"rawDataType": "text",
 					"previewType": "text",
@@ -817,33 +771,39 @@
 					"write": true,
 					"empty": false,
 					"failed": false,
-					"id": "53709f60-4690-0ab3-7b7f-d183a20d3c1d",
-					"name": "Get jobs example",
+					"id": "230f49b2-4c6c-2e0b-d2c5-8f4d127fff80",
+					"name": "Add measure  example",
 					"isSample": true,
 					"scrollToResult": false,
 					"runTests": false,
 					"request": {
-						"url": "{{BASE_PATH}}/api/v1/jobs",
+						"url": "{{BASE_PATH}}/api/v1/measures",
 						"pathVariables": {},
 						"pathVariableData": [],
 						"queryParams": [],
-						"headerData": [],
-						"headers": "",
-						"data": null,
-						"method": "GET",
-						"dataMode": "params"
-					},
-					"owner": "2830994"
+						"headerData": [
+							{
+								"key": "Content-Type",
+								"value": "application/json",
+								"enabled": true,
+								"description": ""
+							}
+						],
+						"headers": "Content-Type: application/json\n",
+						"data": "{\r\n    \"name\":\"measure_name\",\r\n\t\"type\":\"griffin\",\r\n    \"description\":\"create a measure\",\r\n    \"organization\":\"test\",\r\n    \"evaluate.rule\":{\r\n        \"rules\":[\r\n            {\r\n                \"rule\":\"source.desc=target.desc\",\r\n                \"dsl.type\":\"griffin-dsl\",\r\n                \"dq.type\":\"accuracy\",\r\n                \"details\":{}\r\n            }\r\n        ]\r\n    },\r\n    \"owner\":\"test\",\r\n    \"process.type\":\"batch\",\r\n    \"data.sources\":[\r\n        {\r\n            \"name\":\"source\",\r\n            \"connectors\":[\r\n                {\r\n\t\t\t\t\t\"name\":\"connector_name_source\",\r\n                    \"type\":\"HIVE\",\r\n                    \"version\":\"1.2\",\r\n\t\t\t\t\t\"data.unit\":\"1h\",\r\n                    \"config\":{\r\n                        \"database\":\"default\",\r\n                        \"table.name\":\"demo_src\",\r\n                        \"where\":\"dt=#
 YYYYMMdd# AND hour=#HH#\"\r\n                    },\r\n                    \"predicates\":[\r\n                        {\r\n                            \"type\":\"file.exist\",\r\n                            \"config\":{\r\n                                \"root.path\":\"hdfs:///griffin/demo_src\",\r\n                                \"path\":\"/dt=#YYYYMMdd#/hour=#HH#/_DONE\"\r\n                            }\r\n                        }\r\n                    ]\r\n                }\r\n            ]\r\n        },\r\n        {\r\n            \"name\":\"target\",\r\n            \"connectors\":[\r\n                {\r\n\t\t\t\t\t\"name\":\"connector_name_target\",\r\n                    \"type\":\"HIVE\",\r\n                    \"version\":\"1.2\",\r\n\t\t\t\t\t\"data.unit\":\"1h\",\r\n                    \"config\":{\r\n                        \"database\":\"default\",\r\n                        \"table.name\":\"demo_src\",\r\n                        \"where\":\"dt=#YYYYMMdd# AND hour=
 #HH#\"\r\n                    },\r\n                    \"predicates\":[\r\n                        {\r\n                            \"type\":\"file.exist\",\r\n                            \"config\":{\r\n                                \"root.path\":\"hdfs:///griffin/demo_src\",\r\n                                \"path\":\"/dt=#YYYYMMdd#/hour=#HH#/_DONE\"\r\n                            }\r\n                        }\r\n                    ]\r\n                }\r\n            ]\r\n        }\r\n    ]\r\n}",
+						"method": "POST",
+						"dataMode": "raw"
+					}
 				}
 			],
-			"collection_id": "871762c3-97f9-1ac0-f17c-d17bd3446b87"
+			"rawModeData": "{\r\n    \"name\":\"measure_official\",\r\n\t\"type\":\"griffin\",\r\n    \"description\":\"create a measure\",\r\n    \"organization\":\"test\",\r\n    \"evaluate.rule\":{\r\n        \"rules\":[\r\n            {\r\n                \"rule\":\"source.desc=target.desc\",\r\n                \"dsl.type\":\"griffin-dsl\",\r\n                \"dq.type\":\"accuracy\",\r\n                \"details\":{}\r\n            }\r\n        ]\r\n    },\r\n    \"owner\":\"test\",\r\n    \"process.type\":\"batch\",\r\n    \"data.sources\":[\r\n        {\r\n            \"name\":\"source\",\r\n            \"connectors\":[\r\n                {\r\n\t\t\t\t\t\"name\":\"connector_name_source\",\r\n                    \"type\":\"HIVE\",\r\n                    \"version\":\"1.2\",\r\n\t\t\t\t\t\"data.unit\":\"1h\",\r\n                    \"config\":{\r\n                        \"database\":\"default\",\r\n                        \"table.name\":\"demo_src\",\r\n                        \"where\
 ":\"dt=#YYYYMMdd# AND hour=#HH#\"\r\n                    },\r\n                    \"predicates\":[\r\n                        {\r\n                            \"type\":\"file.exist\",\r\n                            \"config\":{\r\n                                \"root.path\":\"hdfs:///griffin/demo_src\",\r\n                                \"path\":\"/dt=#YYYYMMdd#/hour=#HH#/_DONE\"\r\n                            }\r\n                        }\r\n                    ]\r\n                }\r\n            ]\r\n        },\r\n        {\r\n            \"name\":\"target\",\r\n            \"connectors\":[\r\n                {\r\n\t\t\t\t\t\"name\":\"connector_name_target\",\r\n                    \"type\":\"HIVE\",\r\n                    \"version\":\"1.2\",\r\n\t\t\t\t\t\"data.unit\":\"1h\",\r\n                    \"config\":{\r\n                        \"database\":\"default\",\r\n                        \"table.name\":\"demo_src\",\r\n                        \"where\":\"dt=#YYYYMMdd# A
 ND hour=#HH#\"\r\n                    },\r\n                    \"predicates\":[\r\n                        {\r\n                            \"type\":\"file.exist\",\r\n                            \"config\":{\r\n                                \"root.path\":\"hdfs:///griffin/demo_src\",\r\n                                \"path\":\"/dt=#YYYYMMdd#/hour=#HH#/_DONE\"\r\n                            }\r\n                        }\r\n                    ]\r\n                }\r\n            ]\r\n        }\r\n    ]\r\n}",
+			"collection_id": "a743e1b9-583f-6bd7-e2ae-f03a1f807c63"
 		},
 		{
-			"id": "78aae644-ccbe-9381-0a64-4d463b1d76c0",
+			"id": "45aef93d-2bcf-4a1f-245a-29611d3d740e",
 			"headers": "",
 			"headerData": [],
-			"url": "{{BASE_PATH}}/api/v1/jobs/health",
-			"folder": "a6877336-53f6-b720-ee4f-313d6c9d9c94",
+			"url": "{{BASE_PATH}}/api/v1/org/measure/names",
 			"queryParams": [],
 			"preRequestScript": null,
 			"pathVariables": {},
@@ -851,13 +811,14 @@
 			"method": "GET",
 			"data": null,
 			"dataMode": "params",
+			"version": 2,
 			"tests": null,
 			"currentHelper": "normal",
-			"helperAttributes": {},
-			"time": 1508997449658,
-			"name": "Get job healthy statistics",
-			"description": "`GET /api/v1/jobs/health`\n\n#### Response Body Sample\n```\n{\n  \"healthyJobCount\": 17,\n  \"jobCount\": 23\n}\n```",
-			"collectionId": "871762c3-97f9-1ac0-f17c-d17bd3446b87",
+			"helperAttributes": "{}",
+			"time": 1509332871323,
+			"name": "Get  measure names group by org",
+			"description": "`GET /api/v1/orgWithMetricsName`",
+			"collectionId": "a743e1b9-583f-6bd7-e2ae-f03a1f807c63",
 			"responses": [
 				{
 					"status": "",
@@ -865,7 +826,7 @@
 						"code": 200,
 						"name": "OK"
 					},
-					"time": 391,
+					"time": 5216,
 					"headers": [
 						{
 							"name": "access-control-allow-headers",
@@ -900,7 +861,7 @@
 						{
 							"name": "date",
 							"key": "date",
-							"value": "Wed, 25 Oct 2017 08:10:53 GMT",
+							"value": "Mon, 30 Oct 2017 03:07:48 GMT",
 							"description": "The date and time that the message was sent"
 						},
 						{
@@ -912,7 +873,7 @@
 					],
 					"cookies": [],
 					"mime": "",
-					"text": "{\"healthyJobCount\":15,\"jobCount\":23}",
+					"text": "{\"orgName\":[\"measureName_test_edit\",\"measureName_test_edit\",\"measureName1\"],\"test\":[\"measure1\"],\"ebay\":[\"new_measure_test_again\",\"third_measure\",\"fourth_measure\",\"fifth_measure\",\"third_measure\",\"measure\"]}",
 					"language": "json",
 					"rawDataType": "text",
 					"previewType": "text",
@@ -921,62 +882,44 @@
 					"write": true,
 					"empty": false,
 					"failed": false,
-					"id": "a77d6763-143e-a77a-1fbd-0ff26897b84e",
-					"name": "Get job healthy statistics example",
-					"isSample": true,
-					"scrollToResult": false,
-					"runTests": false,
-					"request": {
-						"url": "{{BASE_PATH}}/api/v1/jobs/health",
-						"pathVariables": {},
-						"pathVariableData": [],
-						"queryParams": [],
-						"headerData": [],
-						"headers": "",
-						"data": null,
-						"method": "GET",
-						"dataMode": "params"
-					},
-					"owner": "2830994"
+					"name": "Get  measure names group by org example",
+					"id": "35731fab-7671-5f16-6554-c9a34b6389c1",
+					"request": "8d77e0e0-62fd-242b-ea83-a7fc4829c778",
+					"owner": "503523",
+					"requestObject": "{\"url\":\"{{BASE_PATH}}/api/v1/org/measure/names\",\"pathVariables\":{},\"pathVariableData\":[],\"queryParams\":[],\"headerData\":[],\"headers\":\"\",\"data\":null,\"method\":\"GET\",\"dataMode\":\"params\"}"
 				}
 			],
-			"collection_id": "871762c3-97f9-1ac0-f17c-d17bd3446b87"
+			"isFromCollection": true,
+			"collection_id": "a743e1b9-583f-6bd7-e2ae-f03a1f807c63",
+			"folder": "04a4a902-f33b-bce5-06dc-4da56cae7c4f"
 		},
 		{
-			"id": "79d22e4f-89e4-5e61-7c24-92f4e2f6450e",
-			"headers": "",
-			"headerData": [],
-			"url": "{{BASE_PATH}}/api/v1/metadata/hive/table?db=default&table=demo_src",
-			"folder": "022408d6-3e26-da08-eb52-ca3c83d8f226",
-			"queryParams": [
-				{
-					"key": "db",
-					"value": "default",
-					"equals": true,
-					"description": "",
-					"enabled": true
-				},
+			"id": "5767e1b2-a078-caec-34ae-b4366d66ba3d",
+			"headers": "Content-Type: application/json\n",
+			"headerData": [
 				{
-					"key": "table",
-					"value": "demo_src",
-					"equals": true,
+					"key": "Content-Type",
+					"value": "application/json",
 					"description": "",
 					"enabled": true
 				}
 			],
+			"url": "{{BASE_PATH}}/api/v1/jobs",
+			"folder": "40702c96-d08c-fd56-add4-5d26598e539e",
+			"queryParams": [],
 			"preRequestScript": null,
 			"pathVariables": {},
 			"pathVariableData": [],
-			"method": "GET",
-			"data": null,
-			"dataMode": "params",
+			"method": "POST",
+			"data": [],
+			"dataMode": "raw",
 			"tests": null,
 			"currentHelper": "normal",
 			"helperAttributes": {},
-			"time": 1508997723742,
-			"name": "Get table metadata",
-			"description": "`GET /api/v1/metadata/hive/table`\n#### Request Parameters\n name  |  description |  type  |  example value \n---- | ---------- | ----- |-----\ndb | hive database name | String | default\ntable | hive table name | String | demo_src",
-			"collectionId": "871762c3-97f9-1ac0-f17c-d17bd3446b87",
+			"time": 1515396086639,
+			"name": "Add job",
+			"description": "`POST /api/v1/jobs`\n\n#### Request Header\nkey | value\n--- | ---\nContent-Type | application/json\n\n\n#### Request Body\nname | description | type \n--- | --- | ---\njobSchedule | custom class composed of job key parameters | JobSchedule \n\n\n#### Response Body Sample\n```\n{\n  \"code\": 205,\n  \"description\": \"Create Job Succeed\"\n}\n```\nIt may return failed messages.Such as,\n\n```\n{\n  \"code\": 405,\n  \"description\": \"Create Job Failed\"\n}\n```\n\nThere are several reasons to create job failure. \n- Measure id does not exist.\n- Job name already exits.\n- Param as.baselines aren't set or are all false.\n- Connector name doesn't exist in your measure.\n- The trigger key already exists.",
+			"collectionId": "a743e1b9-583f-6bd7-e2ae-f03a1f807c63",
 			"responses": [
 				{
 					"status": "",
@@ -984,7 +927,7 @@
 						"code": 200,
 						"name": "OK"
 					},
-					"time": 289,
+					"time": 1772,
 					"headers": [
 						{
 							"name": "access-control-allow-headers",
@@ -1019,7 +962,7 @@
 						{
 							"name": "date",
 							"key": "date",
-							"value": "Wed, 25 Oct 2017 05:06:48 GMT",
+							"value": "Mon, 30 Oct 2017 03:11:43 GMT",
 							"description": "The date and time that the message was sent"
 						},
 						{
@@ -1031,7 +974,7 @@
 					],
 					"cookies": [],
 					"mime": "",
-					"text": "{\"tableName\":\"demo_src\",\"dbName\":\"default\",\"owner\":\"root\",\"createTime\":1507861756,\"lastAccessTime\":0,\"retention\":0,\"sd\":{\"cols\":[{\"name\":\"id\",\"type\":\"bigint\",\"comment\":null,\"setName\":true,\"setType\":true,\"setComment\":false},{\"name\":\"age\",\"type\":\"int\",\"comment\":null,\"setName\":true,\"setType\":true,\"setComment\":false},{\"name\":\"desc\",\"type\":\"string\",\"comment\":null,\"setName\":true,\"setType\":true,\"setComment\":false}],\"location\":\"hdfs://griffin:9000/griffin/data/batch/demo_src\",\"inputFormat\":\"org.apache.hadoop.mapred.TextInputFormat\",\"outputFormat\":\"org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat\",\"compressed\":false,\"numBuckets\":-1,\"serdeInfo\":{\"name\":null,\"serializationLib\":\"org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe\",\"parameters\":{\"field.delim\":\"|\",\"serialization.format\":\"|\"},\"setName\":false,\"setParameters\":true,\"parametersSize\":2,\"setSerializationL
 ib\":true},\"bucketCols\":[],\"sortCols\":[],\"parameters\":{},\"skewedInfo\":{\"skewedColNames\":[],\"skewedColValues\":[],\"skewedColValueLocationMaps\":{},\"skewedColValueLocationMapsSize\":0,\"skewedColNamesSize\":0,\"skewedColValuesSize\":0,\"setSkewedColNames\":true,\"setSkewedColValues\":true,\"skewedColNamesIterator\":[],\"setSkewedColValueLocationMaps\":true,\"skewedColValuesIterator\":[]},\"storedAsSubDirectories\":false,\"setParameters\":true,\"parametersSize\":0,\"bucketColsIterator\":[],\"setOutputFormat\":true,\"bucketColsSize\":0,\"sortColsIterator\":[],\"setCols\":true,\"colsIterator\":[{\"name\":\"id\",\"type\":\"bigint\",\"comment\":null,\"setName\":true,\"setType\":true,\"setComment\":false},{\"name\":\"age\",\"type\":\"int\",\"comment\":null,\"setName\":true,\"setType\":true,\"setComment\":false},{\"name\":\"desc\",\"type\":\"string\",\"comment\":null,\"setName\":true,\"setType\":true,\"setComment\":false}],\"colsSize\":3,\"setLocation\":true,\"setInputFormat\":t
 rue,\"setCompressed\":true,\"setNumBuckets\":true,\"setSerdeInfo\":true,\"sortColsSize\":0,\"setSortCols\":true,\"setSkewedInfo\":true,\"setBucketCols\":true,\"setStoredAsSubDirectories\":true},\"partitionKeys\":[],\"parameters\":{\"totalSize\":\"0\",\"EXTERNAL\":\"TRUE\",\"COLUMN_STATS_ACCURATE\":\"true\",\"numFiles\":\"0\",\"transient_lastDdlTime\":\"1508897403\"},\"viewOriginalText\":null,\"viewExpandedText\":null,\"tableType\":\"EXTERNAL_TABLE\",\"privileges\":null,\"temporary\":false,\"setSd\":true,\"setCreateTime\":true,\"setTableName\":true,\"setRetention\":true,\"setOwner\":true,\"setDbName\":true,\"setParameters\":true,\"setPrivileges\":false,\"setTemporary\":false,\"setTableType\":true,\"partitionKeysIterator\":[],\"setViewExpandedText\":false,\"setViewOriginalText\":false,\"partitionKeysSize\":0,\"setLastAccessTime\":true,\"setPartitionKeys\":true,\"parametersSize\":5}",
+					"text": "{\"code\":205,\"description\":\"Create Job Succeed\"}",
 					"language": "json",
 					"rawDataType": "text",
 					"previewType": "text",
@@ -1040,63 +983,61 @@
 					"write": true,
 					"empty": false,
 					"failed": false,
-					"id": "0d2eb90a-90db-83ae-ffb6-a14acd9cfece",
-					"name": "Get table metadata example",
+					"id": "f0be7fe1-93b8-1342-e597-6512c60a54ea",
+					"name": "Add job example",
 					"isSample": true,
 					"scrollToResult": false,
 					"runTests": false,
 					"request": {
-						"url": "{{BASE_PATH}}/api/v1/metadata/hive/table?db=default&table=demo_src",
+						"url": "{{BASE_PATH}}/api/v1/jobs",
 						"pathVariables": {},
 						"pathVariableData": [],
-						"queryParams": [
-							{
-								"key": "db",
-								"value": "default",
-								"equals": true,
-								"description": "",
-								"enabled": true
-							},
+						"queryParams": [],
+						"headerData": [
 							{
-								"key": "table",
-								"value": "demo_src",
-								"equals": true,
-								"description": "",
-								"enabled": true
+								"key": "Content-Type",
+								"value": "application/json",
+								"enabled": true,
+								"description": ""
 							}
 						],
-						"headerData": [],
-						"headers": "",
-						"data": null,
-						"method": "GET",
-						"dataMode": "params"
-					},
-					"owner": "2830994"
+						"headers": "Content-Type: application/json\n",
+						"data": "{\r\n    \"measure.id\": 1,\r\n\t\"job.name\":\"job_name\",\r\n    \"cron.expression\": \"0 0/4 * * * ?\",\r\n    \"cron.time.zone\": \"GMT+8:00\",\r\n    \"predicate.config\": {\r\n\t\t\"checkdonefile.schedule\":{\r\n\t\t\t\"interval\": \"5m\",\r\n\t\t\t\"repeat\": 12\r\n\t\t}\r\n    },\r\n    \"data.segments\": [\r\n        {\r\n            \"data.connector.name\": \"connector_name_source_test\",\r\n\t\t\t\"as.baseline\":true, \r\n            \"segment.range\": {\r\n                \"begin\": \"-1h\",\r\n                \"length\": \"1h\"\r\n            }\r\n        },\r\n        {\r\n            \"data.connector.name\": \"connector_name_target_test\",\r\n            \"segment.range\": {\r\n                \"begin\": \"-1h\",\r\n                \"length\": \"1h\"\r\n            }\r\n        }\r\n    ]\r\n}",
+						"method": "POST",
+						"dataMode": "raw"
+					}
 				}
 			],
-			"collection_id": "871762c3-97f9-1ac0-f17c-d17bd3446b87"
+			"rawModeData": "{\r\n    \"measure.id\": 2,\r\n\t\"job.name\":\"job_name\",\r\n    \"cron.expression\": \"0 0/4 * * * ?\",\r\n    \"cron.time.zone\": \"GMT+8:00\",\r\n    \"predicate.config\": {\r\n\t\t\"checkdonefile.schedule\":{\r\n\t\t\t\"interval\": \"1m\",\r\n\t\t\t\"repeat\": 2\r\n\t\t}\r\n    },\r\n    \"data.segments\": [\r\n        {\r\n            \"data.connector.name\": \"connector_name_source_test\",\r\n\t\t\t\"as.baseline\":true, \r\n            \"segment.range\": {\r\n                \"begin\": \"-1h\",\r\n                \"length\": \"1h\"\r\n            }\r\n        },\r\n        {\r\n            \"data.connector.name\": \"connector_name_target_test\",\r\n            \"segment.range\": {\r\n                \"begin\": \"-1h\",\r\n                \"length\": \"1h\"\r\n            }\r\n        }\r\n    ]\r\n}",
+			"collection_id": "a743e1b9-583f-6bd7-e2ae-f03a1f807c63"
 		},
 		{
-			"id": "7f475e07-d86e-8ff8-b087-57d926389f10",
+			"id": "57cf1684-d812-5867-3c76-e285527a7c58",
 			"headers": "",
 			"headerData": [],
-			"url": "{{BASE_PATH}}/api/v1/org/measure/names",
-			"folder": "a59711e8-e3ea-db95-56cf-6c6c70e150a8",
+			"url": "{{BASE_PATH}}/api/v1/measures/owner/:owner",
 			"queryParams": [],
 			"preRequestScript": null,
-			"pathVariables": {},
-			"pathVariableData": [],
+			"pathVariables": {
+				"owner": "test"
+			},
+			"pathVariableData": [
+				{
+					"key": "owner",
+					"value": "test"
+				}
+			],
 			"method": "GET",
 			"data": null,
 			"dataMode": "params",
 			"version": 2,
 			"tests": null,
 			"currentHelper": "normal",
-			"helperAttributes": {},
-			"time": 1509332871323,
-			"name": "Get  measure names group by org",
-			"description": "`GET /api/v1/org/measure/names`",
-			"collectionId": "871762c3-97f9-1ac0-f17c-d17bd3446b87",
+			"helperAttributes": "{}",
+			"time": 1508998395708,
+			"name": "Get measures by owner",
+			"description": "`GET /api/v1/measures/owner/{owner}`\n\n#### Path Variable\n- owner -`required` `String` owner name\n\n#### Request Sample\n\n`/api/v1/measures/owner/test`\n\n#### Response Body Sample\n```\n[\n  {\n    \"name\": \"demo-accu\",\n    \"id\": \"2\"\n  }\n]\n```",
+			"collectionId": "a743e1b9-583f-6bd7-e2ae-f03a1f807c63",
 			"responses": [
 				{
 					"status": "",
@@ -1104,7 +1045,7 @@
 						"code": 200,
 						"name": "OK"
 					},
-					"time": 5216,
+					"time": 67,
 					"headers": [
 						{
 							"name": "access-control-allow-headers",
@@ -1139,7 +1080,7 @@
 						{
 							"name": "date",
 							"key": "date",
-							"value": "Mon, 30 Oct 2017 03:07:48 GMT",
+							"value": "Thu, 26 Oct 2017 06:12:10 GMT",
 							"description": "The date and time that the message was sent"
 						},
 						{
@@ -1151,7 +1092,7 @@
 					],
 					"cookies": [],
 					"mime": "",
-					"text": "{\"orgName\":[\"measureName_test_edit\",\"measureName_test_edit\",\"measureName1\"],\"test\":[\"measure1\"],\"ebay\":[\"new_measure_test_again\",\"third_measure\",\"fourth_measure\",\"fifth_measure\",\"third_measure\",\"measure\"]}",
+					"text": "[{\"id\":2,\"name\":\"measureName_test_edit\",\"description\":\"This is a test measure\",\"organization\":\"orgName\",\"evaluateRule\":{\"id\":18,\"rules\":[{\"id\":10,\"rule\":\"source.id==target.id\",\"dsl.type\":\"griffin-dsl\",\"dq.type\":\"accuracy\"}]},\"owner\":\"test\",\"deleted\":false,\"process.type\":\"batch\",\"data.sources\":[{\"id\":35,\"name\":\"source\",\"connectors\":[{\"id\":19,\"type\":\"HIVE\",\"version\":\"1.2\",\"config\":{\"database\":\"default\",\"table.name\":\"demo_src\"}}]},{\"id\":36,\"name\":\"target\",\"connectors\":[{\"id\":20,\"type\":\"HIVE\",\"version\":\"1.2\",\"config\":{\"database\":\"default\",\"table.name\":\"demo_tgt\"}}]}]},{\"id\":6,\"name\":\"third_measure\",\"description\":null,\"organization\":\"ebay\",\"evaluateRule\":{\"id\":6,\"rules\":[{\"id\":6,\"rule\":\"source.id=target.id AND source.age=target.age\",\"dsl.type\":\"griffin-dsl\",\"dq.type\":\"accuracy\"}]},\"owner\":\"test\",\"deleted\":false,\"process.type\":\"batch\
 ",\"data.sources\":[{\"id\":11,\"name\":\"source\",\"connectors\":[{\"id\":11,\"type\":\"HIVE\",\"version\":\"1.2\",\"config\":{\"database\":\"default\",\"table.name\":\"demo_src\"}}]},{\"id\":12,\"name\":\"target\",\"connectors\":[{\"id\":12,\"type\":\"HIVE\",\"version\":\"1.2\",\"config\":{\"database\":\"default\",\"table.name\":\"demo_tgt\"}}]}]},{\"id\":8,\"name\":\"measure1\",\"description\":null,\"organization\":\"test\",\"evaluateRule\":{\"id\":8,\"rules\":[{\"id\":8,\"rule\":\"source.age=target.age\",\"dsl.type\":\"griffin-dsl\",\"dq.type\":\"accuracy\"}]},\"owner\":\"test\",\"deleted\":false,\"process.type\":\"batch\",\"data.sources\":[{\"id\":15,\"name\":\"source\",\"connectors\":[{\"id\":15,\"type\":\"HIVE\",\"version\":\"1.2\",\"config\":{\"database\":\"default\",\"table.name\":\"demo_src\"}}]},{\"id\":16,\"name\":\"target\",\"connectors\":[{\"id\":16,\"type\":\"HIVE\",\"version\":\"1.2\",\"config\":{\"database\":\"default\",\"table.name\":\"demo_tgt\"}}]}]},{\"id\":9,\"
 name\":\"measureName_test_edit\",\"description\":\"This is a test measure\",\"organization\":\"orgName\",\"evaluateRule\":{\"id\":14,\"rules\":[]},\"owner\":\"test\",\"deleted\":false,\"process.type\":\"batch\",\"data.sources\":[{\"id\":27,\"name\":null,\"connectors\":[]},{\"id\":28,\"name\":null,\"connectors\":[]}]},{\"id\":10,\"name\":\"measureName1\",\"description\":\"This is a test measure\",\"organization\":\"orgName\",\"evaluateRule\":{\"id\":19,\"rules\":[{\"id\":11,\"rule\":\"source.id==target.id\",\"dsl.type\":\"griffin-dsl\",\"dq.type\":\"accuracy\"}]},\"owner\":\"test\",\"deleted\":false,\"process.type\":\"batch\",\"data.sources\":[{\"id\":37,\"name\":\"source\",\"connectors\":[{\"id\":21,\"type\":\"HIVE\",\"version\":\"1.2\",\"config\":{\"database\":\"default\",\"table.name\":\"demo_src\"}}]},{\"id\":38,\"name\":\"target\",\"connectors\":[{\"id\":22,\"type\":\"HIVE\",\"version\":\"1.2\",\"config\":{\"database\":\"default\",\"table.name\":\"demo_tgt\"}}]}]}]",
 					"language": "json",
 					"rawDataType": "text",
 					"previewType": "text",
@@ -1160,73 +1101,46 @@
 					"write": true,
 					"empty": false,
 					"failed": false,
-					"name": "Get  measure names group by org example",
-					"id": "2acc9f74-c6e2-badd-2c40-c8a45e4fb88f",
-					"request": {
-						"url": "{{BASE_PATH}}/api/v1/org/measure/names",
-						"pathVariables": {},
-						"pathVariableData": [],
-						"queryParams": [],
-						"headerData": [],
-						"headers": "",
-						"data": null,
-						"method": "GET",
-						"dataMode": "params"
-					},
-					"owner": "2830994"
+					"id": "146e3154-6a76-fb26-0de7-1572b363e1c8",
+					"name": "Get measures by  owner example",
+					"isSample": true,
+					"scrollToResult": false,
+					"runTests": false,
+					"request": "738b5d6d-4fea-85af-89a8-949468d3cde2",
+					"owner": "503523",
+					"requestObject": "{\"url\":\"{{BASE_PATH}}/api/v1/measures/owner/:owner\",\"pathVariables\":{\"owner\":\"test\"},\"pathVariableData\":[{\"key\":\"owner\",\"value\":\"test\"}],\"queryParams\":[],\"headerData\":[],\"headers\":\"\",\"data\":null,\"method\":\"GET\",\"dataMode\":\"params\"}"
 				}
 			],
-			"collection_id": "871762c3-97f9-1ac0-f17c-d17bd3446b87"
+			"isFromCollection": true,
+			"collection_id": "a743e1b9-583f-6bd7-e2ae-f03a1f807c63",
+			"folder": "523a7f9f-1970-018e-9241-57caa3d6ea60"
 		},
 		{
-			"id": "82c3a170-5bf6-2dc9-5295-3cca6e628d18",
-			"headers": "Content-Type: application/json\n",
-			"headerData": [
-				{
-					"key": "Content-Type",
-					"value": "application/json",
-					"description": "",
-					"enabled": true
-				}
-			],
-			"url": "{{BASE_PATH}}/api/v1/jobs?group=BA&jobName=measure-BA-0-1508478934000&measureId=1",
-			"folder": "a6877336-53f6-b720-ee4f-313d6c9d9c94",
-			"queryParams": [
-				{
-					"key": "group",
-					"value": "BA",
-					"equals": true,
-					"description": "",
-					"enabled": true
-				},
-				{
-					"key": "jobName",
-					"value": "measure-BA-0-1508478934000",
-					"equals": true,
-					"description": "",
-					"enabled": true
-				},
+			"id": "619972f0-9f96-d4b5-3287-d2958f3a60c7",
+			"headers": "",
+			"headerData": [],
+			"url": "{{BASE_PATH}}/api/v1/org/:org",
+			"queryParams": [],
+			"preRequestScript": null,
+			"pathVariables": {
+				"org": "test"
+			},
+			"pathVariableData": [
 				{
-					"key": "measureId",
-					"value": "1",
-					"equals": true,
-					"description": "",
-					"enabled": true
+					"key": "org",
+					"value": "test"
 				}
 			],
-			"preRequestScript": null,
-			"pathVariables": {},
-			"pathVariableData": [],
-			"method": "POST",
+			"method": "GET",
 			"data": null,
 			"dataMode": "params",
 			"tests": null,
 			"currentHelper": "normal",
-			"helperAttributes": {},
-			"time": 1509333184841,
-			"name": "Add job",
-			"description": "`POST /api/v1/jobs`\n\n#### Request Header\nkey | value\n--- | ---\nContent-Type | application/json\n\n#### Request Parameters\nname | description | type | example value\n--- | --- | --- | ---\ngroup | job group name | String | BA\njobName | job name | String | measure-BA-0-1508466621000 \nmeasureId | measure id | Long | 4\n\n#### Request Body\nname | description | type | example value\n--- | --- | --- | ---\njobRequestBody | custom class composed of job key parameters | JobRequestBody | `{\"sourcePattern\":\"YYYYMMdd-HH\",\"targetPattern\":\"YYYYMMdd-HH\",\"jobStartTime\":1508428800000,\"interval\":36000,\"groupName\":\"BA\"}`\n\n\n#### Response Body Sample\n```\n{\n  \"code\": 205,\n  \"description\": \"Create Job Succeed\"\n}\n```\nIt may return failed messages.Such as,\n\n```\n{\n  \"code\": 405,\n  \"description\": \"Create Job Failed\"\n}\n```\n\nThe reason for failure may be that trigger key already exists or the measure id associated with job may not exist
 . Firstly,You should check group and job name to make trigger key unique. Secondly,you should check whether your measure id exists.",
-			"collectionId": "871762c3-97f9-1ac0-f17c-d17bd3446b87",
+			"helperAttributes": "{}",
+			"time": 1508998400445,
+			"name": "Get measure names by org",
+			"description": "`GET /api/v1/org/{org}`\n#### Path Variable\n- org - `required` `String` organization name.\n\n#### Request Sample\n`/api/v1/org/test`",
+			"collectionId": "a743e1b9-583f-6bd7-e2ae-f03a1f807c63",
 			"responses": [
 				{
 					"status": "",
@@ -1235,7 +1149,7 @@
 						"name": "OK",
 						"detail": "Standard response for successful HTTP requests. The actual response will depend on the request method used. In a GET request, the response will contain an entity corresponding to the requested resource. In a POST request the response will contain an entity describing or containing the result of the action."
 					},
-					"time": 1772,
+					"time": 26,
 					"headers": [
 						{
 							"name": "access-control-allow-headers",
@@ -1270,7 +1184,7 @@
 						{
 							"name": "date",
 							"key": "date",
-							"value": "Mon, 30 Oct 2017 03:11:43 GMT",
+							"value": "Thu, 26 Oct 2017 06:10:23 GMT",
 							"description": "The date and time that the message was sent"
 						},
 						{
@@ -1282,7 +1196,7 @@
 					],
 					"cookies": [],
 					"mime": "",
-					"text": "{\"code\":205,\"description\":\"Create Job Succeed\"}",
+					"text": "[\"measure1\"]",
 					"language": "json",
 					"rawDataType": "text",
 					"previewType": "text",
@@ -1291,73 +1205,44 @@
 					"write": true,
 					"empty": false,
 					"failed": false,
-					"name": "Add job example",
-					"id": "4a978d95-809e-b126-ef14-95aaf7ee33b3",
-					"request": {
-						"url": "{{BASE_PATH}}/api/v1/jobs?group=BA&jobName=measure-BA-0-1508478934000&measureId=1",
-						"pathVariables": {},
-						"pathVariableData": [],
-						"queryParams": [
-							{
-								"key": "group",
-								"value": "BA",
-								"equals": true,
-								"description": "",
-								"enabled": true
-							},
-							{
-								"key": "jobName",
-								"value": "measure-BA-0-1508478934000",
-								"equals": true,
-								"description": "",
-								"enabled": true
-							},
-							{
-								"key": "measureId",
-								"value": "1",
-								"equals": true,
-								"description": "",
-								"enabled": true
-							}
-						],
-						"headerData": [
-							{
-								"key": "Content-Type",
-								"value": "application/json",
-								"enabled": true,
-								"description": ""
-							}
-						],
-						"headers": "Content-Type: application/json\n",
-						"data": "{\r\n\t\"sourcePattern\":\"YYYYMMdd-HH\",\r\n\t\"targetPattern\":\"YYYYMMdd-HH\",\r\n\t\"jobStartTime\":1508256000000,\r\n\t\"interval\":300,\r\n\t\"groupName\":\"BA\"\r\n}",
-						"method": "POST",
-						"dataMode": "raw"
-					},
-					"owner": "2830994"
+					"name": "Get measure names by org example",
+					"id": "aa21397f-6fe9-6f87-3ed6-00e5e7052932",
+					"request": "9f6e5105-1aaf-22a0-f88a-dbc25277751d",
+					"owner": "503523",
+					"requestObject": "{\"url\":\"{{BASE_PATH}}/api/v1/org/:org\",\"pathVariables\":{\"org\":\"test\"},\"pathVariableData\":[{\"key\":\"org\",\"value\":\"test\"}],\"queryParams\":[],\"headerData\":[],\"headers\":\"\",\"data\":null,\"method\":\"GET\",\"dataMode\":\"params\"}"
 				}
 			],
-			"collection_id": "871762c3-97f9-1ac0-f17c-d17bd3446b87"
+			"isFromCollection": true,
+			"collection_id": "a743e1b9-583f-6bd7-e2ae-f03a1f807c63",
+			"folder": "04a4a902-f33b-bce5-06dc-4da56cae7c4f"
 		},
 		{
-			"id": "9a0a2201-2a06-daeb-5abb-c9e08f4ee00c",
+			"id": "7daeb86c-dc01-fa99-9898-73ec4a6e7e57",
 			"headers": "",
 			"headerData": [],
-			"url": "{{BASE_PATH}}/api/v1/measure/1",
-			"folder": "7511d4fa-72ce-8671-54d0-2f3432d86445",
-			"queryParams": [],
+			"url": "{{BASE_PATH}}/api/v1/metadata/hive/tables/names?db=default",
+			"queryParams": [
+				{
+					"key": "db",
+					"value": "default",
+					"equals": true,
+					"description": "",
+					"enabled": true
+				}
+			],
 			"preRequestScript": null,
 			"pathVariables": {},
 			"pathVariableData": [],
-			"method": "DELETE",
+			"method": "GET",
 			"data": null,
 			"dataMode": "params",
 			"tests": null,
 			"currentHelper": "normal",
-			"helperAttributes": {},
-			"time": 1508997393184,
-			"name": "Delete measure",
-			"description": "`DELETE /api/v1/measure/{id}`\n\n#### Path Variable\n- id -`required` `Long` measure id\n\n#### Request Sample\n\n`/api/v1/measure/1`\n\n#### Response Body Sample\n```\n{\n  \"code\": 202,\n  \"description\": \"Delete Measures By Id Succeed\"\n}\n```\n\nIt may return failed messages.Such as,\n\n```\n {\n  \"code\": 400,\n  \"description\": \"Resource Not Found\"\n}\n\n```\n\nThe reason for failure may be that measure id doesn't exist.You should check your measure.",
-			"collectionId": "871762c3-97f9-1ac0-f17c-d17bd3446b87",
+			"helperAttributes": "{}",
+			"time": 1508997683445,
+			"name": "Get table names",
+			"description": "`GET /api/v1/metadata/hive/tables/names`\n#### Request Parameter\nname | description | typ | example value\n--- | --- | --- | ---\ndb | hive database name | String | default",
+			"collectionId": "a743e1b9-583f-6bd7-e2ae-f03a1f807c63",
 			"responses": [
 				{
 					"status": "",
@@ -1365,7 +1250,7 @@
 						"code": 200,
 						"name": "OK"
 					},
-					"time": 673,
+					"time": 226,
 					"headers": [
 						{
 							"name": "access-control-allow-headers",
@@ -1400,7 +1285,7 @@
 						{
 							"name": "date",
 							"key": "date",
-							"value": "Tue, 24 Oct 2017 11:39:45 GMT",
+							"value": "Wed, 25 Oct 2017 05:11:54 GMT",
 							"description": "The date and time that the message was sent"
 						},
 						{
@@ -1412,7 +1297,7 @@
 					],
 					"cookies": [],
 					"mime": "",
-					"text": "{\"code\":202,\"description\":\"Delete Measures By Id Succeed\"}",
+					"text": "[\"demo_src\",\"demo_tgt\"]",
 					"language": "json",
 					"rawDataType": "text",
 					"previewType": "text",
@@ -1421,54 +1306,39 @@
 					"write": true,
 					"empty": false,
 					"failed": false,
-					"id": "84eb0730-82fb-9d5a-7093-9428787c2131",
-					"name": "Delete measure example",
+					"id": "9e116cfc-4880-c6e6-e289-04036011d5c1",
+					"name": "Get table names example",
 					"isSample": true,
 					"scrollToResult": false,
 					"runTests": false,
-					"request": {
-						"url": "{{BASE_PATH}}/api/v1/measure/1",
-						"pathVariables": {},
-						"pathVariableData": [],
-						"queryParams": [],
-						"headerData": [],
-						"headers": "",
-						"data": null,
-						"method": "DELETE",
-						"dataMode": "params"
-					},
-					"owner": "2830994"
+					"request": "2d875b81-1a6e-6b3d-93a2-1cc225879369",
+					"owner": "503523",
+					"requestObject": "{\"url\":\"{{BASE_PATH}}/api/v1/metadata/hive/tables/names?db=default\",\"pathVariables\":{},\"pathVariableData\":[],\"queryParams\":[{\"key\":\"db\",\"value\":\"default\",\"equals\":true,\"description\":\"\",\"enabled\":true}],\"headerData\":[],\"headers\":\"\",\"data\":null,\"method\":\"GET\",\"dataMode\":\"params\"}"
 				}
 			],
-			"collection_id": "871762c3-97f9-1ac0-f17c-d17bd3446b87"
+			"collection_id": "a743e1b9-583f-6bd7-e2ae-f03a1f807c63",
+			"folder": "7ae8e04f-c5cb-aeab-9af3-65cb3bf87b1f"
 		},
 		{
-			"id": "9d390c13-a375-54c6-dcc2-4753edd4e9e4",
-			"headers": "Content-Type: application/json\n",
-			"headerData": [
-				{
-					"key": "Content-Type",
-					"value": "application/json",
-					"description": "",
-					"enabled": true
-				}
-			],
-			"url": "{{BASE_PATH}}/api/v1/measure",
-			"folder": "7511d4fa-72ce-8671-54d0-2f3432d86445",
+			"id": "8a94fa54-5df7-0e9e-06b5-158239e0570a",
+			"headers": "",
+			"headerData": [],
+			"url": "{{BASE_PATH}}/api/v1/jobs/health",
+			"folder": "40702c96-d08c-fd56-add4-5d26598e539e",
 			"queryParams": [],
 			"preRequestScript": null,
 			"pathVariables": {},
 			"pathVariableData": [],
-			"method": "POST",
-			"data": [],
-			"dataMode": "raw",
+			"method": "GET",
+			"data": null,
+			"dataMode": "params",
 			"tests": null,
 			"currentHelper": "normal",
 			"helperAttributes": {},
-			"time": 1509330288995,
-			"name": "Add measure",
-			"description": "`POST /api/v1/measure`\n\n#### Request Header\nkey | value\n--- | ---\nContent-Type | application/json\n\n#### Request Body\n\nname | description | type\n--- | --- | --- \nmeasure | measure entity | Measure\n\n#### Response Body Sample\n```\n{\n  \"code\": 201,\n  \"description\": \"Create Measure Succeed\"\n}\n```\n\nIt may return failed messages.Such as,\n\n```\n {\n  \"code\": 410,\n  \"description\": \"Create Measure Failed, duplicate records\"\n}\n\n```\n\nThe reason for failure may be that measure name already exists.You can change measure name to make it unique.",
-			"collectionId": "871762c3-97f9-1ac0-f17c-d17bd3446b87",
+			"time": 1515396046330,
+			"name": "Get job healthy statistics",
+			"description": "`GET /api/v1/jobs/health`\n\n#### Response Body Sample\n```\n{\n  \"healthyJobCount\": 1,\n  \"jobCount\": 2\n}\n```",
+			"collectionId": "a743e1b9-583f-6bd7-e2ae-f03a1f807c63",
 			"responses": [
 				{
 					"status": "",
@@ -1476,7 +1346,7 @@
 						"code": 200,
 						"name": "OK"
 					},
-					"time": 629,
+					"time": 391,
 					"headers": [
 						{
 							"name": "access-control-allow-headers",
@@ -1511,7 +1381,7 @@
 						{
 							"name": "date",
 							"key": "date",
-							"value": "Tue, 24 Oct 2017 10:59:21 GMT",
+							"value": "Wed, 25 Oct 2017 08:10:53 GMT",
 							"description": "The date and time that the message was sent"
 						},
 						{
@@ -1523,7 +1393,7 @@
 					],
 					"cookies": [],
 					"mime": "",
-					"text": "{\"code\":201,\"description\":\"Create Measure Succeed\"}",
+					"text": "{\n    \"healthyJobCount\": 1,\n    \"jobCount\": 2\n}",
 					"language": "json",
 					"rawDataType": "text",
 					"previewType": "text",
@@ -1532,72 +1402,69 @@
 					"write": true,
 					"empty": false,
 					"failed": false,
-					"id": "da49437f-ea4f-fcac-47e9-93cc622da278",
-					"name": "Add measure  example",
+					"id": "6c28b0c5-b724-4683-1f0d-35b770920b64",
+					"name": "Get job healthy statistics example",
 					"isSample": true,
 					"scrollToResult": false,
 					"runTests": false,
 					"request": {
-						"url": "{{BASE_PATH}}/api/v1/measure",
+						"url": "{{BASE_PATH}}/api/v1/jobs/health",
 						"pathVariables": {},
 						"pathVariableData": [],
 						"queryParams": [],
-						"headerData": [
-							{
-								"key": "Content-Type",
-								"value": "application/json",
-								"enabled": true,
-								"description": ""
-							}
-						],
-						"headers": "Content-Type: application/json\n",
-						"data": "{\r\n    \"name\": \"measureName\",\r\n    \"process.type\": \"batch\",\r\n    \"owner\": \"test\",\r\n    \"description\": \"This is a test measure\",\r\n    \"organization\": \"orgName\",\r\n    \"data.sources\": [\r\n        {\r\n            \"name\": \"source\",\r\n            \"connectors\": [\r\n                {\r\n                    \"type\": \"HIVE\",\r\n                    \"version\": \"1.2\",\r\n                    \"config\": {\r\n                        \"database\": \"default\",\r\n                        \"table.name\": \"demo_src\"\r\n                    }\r\n                }\r\n            ]\r\n        },\r\n        {\r\n            \"name\": \"target\",\r\n            \"connectors\": [\r\n                {\r\n                    \"type\": \"HIVE\",\r\n                    \"version\": \"1.2\",\r\n                    \"config\": {\r\n                        \"database\": \"default\",\r\n                        \"table.name\": \"demo_tgt\"\r\n       
              }\r\n                }\r\n            ]\r\n        }\r\n    ],\r\n    \"evaluateRule\": {\r\n        \"rules\": [\r\n            {\r\n                \"dsl.type\": \"griffin-dsl\",\r\n                \"dq.type\": \"accuracy\",\r\n                \"rule\": \"source.id=target.id\"\r\n            }\r\n        ]\r\n    }\r\n}",
-						"method": "POST",
-						"dataMode": "raw"
+						"headerData": [],
+						"headers": "",
+						"data": null,
+						"method": "GET",
+						"dataMode": "params"
 					},
-					"owner": "2830994"
+					"owner": "503523"
 				}
 			],
-			"rawModeData": "{\r\n    \"name\": \"measureName1\",\r\n    \"process.type\": \"batch\",\r\n    \"owner\": \"test\",\r\n    \"description\": \"This is a test measure\",\r\n    \"organization\": \"orgName\",\r\n    \"data.sources\": [\r\n        {\r\n            \"name\": \"source\",\r\n            \"connectors\": [\r\n                {\r\n                    \"type\": \"HIVE\",\r\n                    \"version\": \"1.2\",\r\n                    \"config\": {\r\n                        \"database\": \"default\",\r\n                        \"table.name\": \"demo_src\"\r\n                    }\r\n                }\r\n            ]\r\n        },\r\n        {\r\n            \"name\": \"target\",\r\n            \"connectors\": [\r\n                {\r\n                    \"type\": \"HIVE\",\r\n                    \"version\": \"1.2\",\r\n                    \"config\": {\r\n                        \"database\": \"default\",\r\n                        \"table.name\": \"demo_tgt\"\r\n  
                   }\r\n                }\r\n            ]\r\n        }\r\n    ],\r\n    \"evaluateRule\": {\r\n        \"rules\": [\r\n            {\r\n                \"dsl.type\": \"griffin-dsl\",\r\n                \"dq.type\": \"accuracy\",\r\n                \"rule\": \"source.id = target.id and source.age = target.age and source.desc = target.desc\"\r\n            }\r\n        ]\r\n    }\r\n}",
-			"collection_id": "871762c3-97f9-1ac0-f17c-d17bd3446b87"
+			"collection_id": "a743e1b9-583f-6bd7-e2ae-f03a1f807c63"
 		},
 		{
-			"id": "a85f7d39-c0bc-dd29-4739-18d3651c9796",
+			"id": "91e19d73-87b1-f388-93a9-22c7a0ec2b43",
 			"headers": "",
 			"headerData": [],
-			"url": "{{BASE_PATH}}/api/v1/measures/owner/:owner",
-			"folder": "7511d4fa-72ce-8671-54d0-2f3432d86445",
-			"queryParams": [],
-			"preRequestScript": null,
-			"pathVariables": {
-				"owner": "test"
-			},
-			"pathVariableData": [
+			"url": "{{BASE_PATH}}/api/v1/metadata/hive/table?db=default&table=demo_src",
+			"queryParams": [
 				{
-					"key": "owner",
-					"value": "test"
+					"key": "db",
+					"value": "default",
+					"equals": true,
+					"description": "",
+					"enabled": true
+				},
+				{
+					"key": "table",
+					"value": "demo_src",
+					"equals": true,
+					"description": "",
+					"enabled": true
 				}
 			],
+			"preRequestScript": null,
+			"pathVariables": {},
+			"pathVariableData": [],
 			"method": "GET",
 			"data": null,
 			"dataMode": "params",
-			"version": 2,
 			"tests": null,
 			"currentHelper": "normal",
-			"helperAttributes": {},
-			"time": 1508998395708,
-			"name": "Get measures by owner",
-			"description": "`GET /api/v1/measures/owner/{owner}`\n\n#### Path Variable\n- owner -`required` `String` owner name\n\n#### Request Sample\n\n`/api/v1/measures/owner/test`\n\n#### Response Body Sample\n```\n[\n  {\n    \"name\": \"demo-accu\",\n    \"id\": \"2\"\n  }\n]\n```",
-			"collectionId": "871762c3-97f9-1ac0-f17c-d17bd3446b87",
+			"helperAttributes": "{}",
+			"time": 1508997723742,
+			"name": "Get table metadata",
+			"description": "`GET /api/v1/metadata/hive/table`\n#### Request Parameters\n name  |  description |  type  |  example value \n---- | ---------- | ----- |-----\ndb | hive database name | String | default\ntable | hive table name | String | demo_src",
+			"collectionId": "a743e1b9-583f-6bd7-e2ae-f03a1f807c63",
 			"responses": [
 				{
 					"status": "",
 					"responseCode": {
 						"code": 200,
-						"name": "OK",
-						"detail": "Standard response for successful HTTP requests. The actual response will depend on the request method used. In a GET request, the response will contain an entity corresponding to the requested resource. In a POST request the response will contain an entity describing or containing the result of the action."
+						"name": "OK"
 					},
-					"time": 67,
+					"time": 289,
 					"headers": [
 						{
 							"name": "access-control-allow-headers",
@@ -1632,7 +1499,7 @@
 						{
 							"name": "date",
 							"key": "date",
-							"value": "Thu, 26 Oct 2017 06:12:10 GMT",
+							"value": "Wed, 25 Oct 2017 05:06:48 GMT",
 							"description": "The date and time that the message was sent"
 						},
 						{
@@ -1644,7 +1511,7 @@
 					],
 					"cookies": [],
 					"mime": "",
-					"text": "[{\"id\":2,\"name\":\"measureName_test_edit\",\"description\":\"This is a test measure\",\"organization\":\"orgName\",\"evaluateRule\":{\"id\":18,\"rules\":[{\"id\":10,\"rule\":\"source.id==target.id\",\"dsl.type\":\"griffin-dsl\",\"dq.type\":\"accuracy\"}]},\"owner\":\"test\",\"deleted\":false,\"process.type\":\"batch\",\"data.sources\":[{\"id\":35,\"name\":\"source\",\"connectors\":[{\"id\":19,\"type\":\"HIVE\",\"version\":\"1.2\",\"config\":{\"database\":\"default\",\"table.name\":\"demo_src\"}}]},{\"id\":36,\"name\":\"target\",\"connectors\":[{\"id\":20,\"type\":\"HIVE\",\"version\":\"1.2\",\"config\":{\"database\":\"default\",\"table.name\":\"demo_tgt\"}}]}]},{\"id\":6,\"name\":\"third_measure\",\"description\":null,\"organization\":\"ebay\",\"evaluateRule\":{\"id\":6,\"rules\":[{\"id\":6,\"rule\":\"source.id=target.id AND source.age=target.age\",\"dsl.type\":\"griffin-dsl\",\"dq.type\":\"accuracy\"}]},\"owner\":\"test\",\"deleted\":false,\"process.type\":\"batch\
 ",\"data.sources\":[{\"id\":11,\"name\":\"source\",\"connectors\":[{\"id\":11,\"type\":\"HIVE\",\"version\":\"1.2\",\"config\":{\"database\":\"default\",\"table.name\":\"demo_src\"}}]},{\"id\":12,\"name\":\"target\",\"connectors\":[{\"id\":12,\"type\":\"HIVE\",\"version\":\"1.2\",\"config\":{\"database\":\"default\",\"table.name\":\"demo_tgt\"}}]}]},{\"id\":8,\"name\":\"measure1\",\"description\":null,\"organization\":\"test\",\"evaluateRule\":{\"id\":8,\"rules\":[{\"id\":8,\"rule\":\"source.age=target.age\",\"dsl.type\":\"griffin-dsl\",\"dq.type\":\"accuracy\"}]},\"owner\":\"test\",\"deleted\":false,\"process.type\":\"batch\",\"data.sources\":[{\"id\":15,\"name\":\"source\",\"connectors\":[{\"id\":15,\"type\":\"HIVE\",\"version\":\"1.2\",\"config\":{\"database\":\"default\",\"table.name\":\"demo_src\"}}]},{\"id\":16,\"name\":\"target\",\"connectors\":[{\"id\":16,\"type\":\"HIVE\",\"version\":\"1.2\",\"config\":{\"database\":\"default\",\"table.name\":\"demo_tgt\"}}]}]},{\"id\":9,\"
 name\":\"measureName_test_edit\",\"description\":\"This is a test measure\",\"organization\":\"orgName\",\"evaluateRule\":{\"id\":14,\"rules\":[]},\"owner\":\"test\",\"deleted\":false,\"process.type\":\"batch\",\"data.sources\":[{\"id\":27,\"name\":null,\"connectors\":[]},{\"id\":28,\"name\":null,\"connectors\":[]}]},{\"id\":10,\"name\":\"measureName1\",\"description\":\"This is a test measure\",\"organization\":\"orgName\",\"evaluateRule\":{\"id\":19,\"rules\":[{\"id\":11,\"rule\":\"source.id==target.id\",\"dsl.type\":\"griffin-dsl\",\"dq.type\":\"accuracy\"}]},\"owner\":\"test\",\"deleted\":false,\"process.type\":\"batch\",\"data.sources\":[{\"id\":37,\"name\":\"source\",\"connectors\":[{\"id\":21,\"type\":\"HIVE\",\"version\":\"1.2\",\"config\":{\"database\":\"default\",\"table.name\":\"demo_src\"}}]},{\"id\":38,\"name\":\"target\",\"connectors\":[{\"id\":22,\"type\":\"HIVE\",\"version\":\"1.2\",\"config\":{\"database\":\"default\",\"table.name\":\"demo_tgt\"}}]}]}]",
+					"text": "{\"tableName\":\"demo_src\",\"dbName\":\"default\",\"owner\":\"root\",\"createTime\":1507861756,\"lastAccessTime\":0,\"retention\":0,\"sd\":{\"cols\":[{\"name\":\"id\",\"type\":\"bigint\",\"comment\":null,\"setName\":true,\"setType\":true,\"setComment\":false},{\"name\":\"age\",\"type\":\"int\",\"comment\":null,\"setName\":true,\"setType\":true,\"setComment\":false},{\"name\":\"desc\",\"type\":\"string\",\"comment\":null,\"setName\":true,\"setType\":true,\"setComment\":false}],\"location\":\"hdfs://griffin:9000/griffin/data/batch/demo_src\",\"inputFormat\":\"org.apache.hadoop.mapred.TextInputFormat\",\"outputFormat\":\"org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat\",\"compressed\":false,\"numBuckets\":-1,\"serdeInfo\":{\"name\":null,\"serializationLib\":\"org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe\",\"parameters\":{\"field.delim\":\"|\",\"serialization.format\":\"|\"},\"setName\":false,\"setParameters\":true,\"parametersSize\":2,\"setSerializationL
 ib\":true},\"bucketCols\":[],\"sortCols\":[],\"parameters\":{},\"skewedInfo\":{\"skewedColNames\":[],\"skewedColValues\":[],\"skewedColValueLocationMaps\":{},\"skewedColValueLocationMapsSize\":0,\"skewedColNamesSize\":0,\"skewedColValuesSize\":0,\"setSkewedColNames\":true,\"setSkewedColValues\":true,\"skewedColNamesIterator\":[],\"setSkewedColValueLocationMaps\":true,\"skewedColValuesIterator\":[]},\"storedAsSubDirectories\":false,\"setParameters\":true,\"parametersSize\":0,\"bucketColsIterator\":[],\"setOutputFormat\":true,\"bucketColsSize\":0,\"sortColsIterator\":[],\"setCols\":true,\"colsIterator\":[{\"name\":\"id\",\"type\":\"bigint\",\"comment\":null,\"setName\":true,\"setType\":true,\"setComment\":false},{\"name\":\"age\",\"type\":\"int\",\"comment\":null,\"setName\":true,\"setType\":true,\"setComment\":false},{\"name\":\"desc\",\"type\":\"string\",\"comment\":null,\"setName\":true,\"setType\":true,\"setComment\":false}],\"colsSize\":3,\"setLocation\":true,\"setInputFormat\":t
 rue,\"setCompressed\":true,\"setNumBuckets\":true,\"setSerdeInfo\":true,\"sortColsSize\":0,\"setSortCols\":true,\"setSkewedInfo\":true,\"setBucketCols\":true,\"setStoredAsSubDirectories\":true},\"partitionKeys\":[],\"parameters\":{\"totalSize\":\"0\",\"EXTERNAL\":\"TRUE\",\"COLUMN_STATS_ACCURATE\":\"true\",\"numFiles\":\"0\",\"transient_lastDdlTime\":\"1508897403\"},\"viewOriginalText\":null,\"viewExpandedText\":null,\"tableType\":\"EXTERNAL_TABLE\",\"privileges\":null,\"temporary\":false,\"setSd\":true,\"setCreateTime\":true,\"setTableName\":true,\"setRetention\":true,\"setOwner\":true,\"setDbName\":true,\"setParameters\":true,\"setPrivileges\":false,\"setTemporary\":false,\"setTableType\":true,\"partitionKeysIterator\":[],\"setViewExpandedText\":false,\"setViewOriginalText\":false,\"partitionKeysSize\":0,\"setLastAccessTime\":true,\"setPartitionKeys\":true,\"parametersSize\":5}",
 					"language": "json",
 					"rawDataType": "text",
 					"previewType": "text",
@@ -1653,59 +1520,39 @@
 					"write":

<TRUNCATED>


[3/3] incubator-griffin git commit: fix job management sysnc bug and delete job triggerkey not exist bug

Posted by gu...@apache.org.
fix job management sysnc bug and delete job triggerkey not exist bug

Author: ahutsunshine <ah...@gmail.com>
Author: He Wang <wa...@qq.com>

Closes #190 from ahutsunshine/master.


Project: http://git-wip-us.apache.org/repos/asf/incubator-griffin/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-griffin/commit/44eea866
Tree: http://git-wip-us.apache.org/repos/asf/incubator-griffin/tree/44eea866
Diff: http://git-wip-us.apache.org/repos/asf/incubator-griffin/diff/44eea866

Branch: refs/heads/master
Commit: 44eea866d34fdd6729b67bf9dfaa87d655d22d58
Parents: 06f969f
Author: ahutsunshine <ah...@gmail.com>
Authored: Tue Jan 16 17:00:18 2018 +0800
Committer: Lionel Liu <bh...@163.com>
Committed: Tue Jan 16 17:00:18 2018 +0800

----------------------------------------------------------------------
 griffin-doc/service/api-guide.md                | 1084 +++++++++
 griffin-doc/service/postman/griffin.json        | 2259 ++++++++++--------
 .../apache/griffin/core/job/JobController.java  |    2 +-
 .../apache/griffin/core/job/JobInstance.java    |    3 +-
 .../org/apache/griffin/core/job/JobService.java |    2 +-
 .../apache/griffin/core/job/JobServiceImpl.java |   86 +-
 .../griffin/core/job/entity/JobDataSegment.java |    5 +
 .../griffin/core/job/entity/JobSchedule.java    |    6 +-
 .../griffin/core/login/LoginController.java     |    3 +-
 .../measure/ExternalMeasureOperationImpl.java   |   14 +-
 .../measure/GriffinMeasureOperationImpl.java    |   12 +-
 .../core/measure/MeasureServiceImpl.java        |   14 +-
 .../core/measure/entity/DataConnector.java      |   21 +-
 .../core/measure/entity/GriffinMeasure.java     |    8 +
 .../griffin/core/metric/MetricController.java   |    5 +-
 .../griffin/core/metric/MetricService.java      |    5 +-
 .../griffin/core/metric/MetricServiceImpl.java  |   20 +-
 .../griffin/core/metric/MetricStoreImpl.java    |    2 +-
 .../src/main/resources/application.properties   |   16 +-
 .../griffin/core/job/JobControllerTest.java     |  308 +--
 .../core/job/repo/JobInstanceRepoTest.java      |   87 +
 .../core/measure/MeasureControllerTest.java     |  398 ++-
 .../core/measure/MeasureOrgControllerTest.java  |    1 -
 .../core/measure/MeasureOrgServiceImplTest.java |    4 +-
 .../core/measure/MeasureServiceImplTest.java    |    6 +-
 .../griffin/core/measure/MeasureTestHelper.java |   89 -
 .../core/measure/repo/MeasureRepoTest.java      |    2 +-
 .../apache/griffin/core/util/EntityHelper.java  |   89 +
 28 files changed, 3057 insertions(+), 1494 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-griffin/blob/44eea866/griffin-doc/service/api-guide.md
----------------------------------------------------------------------
diff --git a/griffin-doc/service/api-guide.md b/griffin-doc/service/api-guide.md
new file mode 100644
index 0000000..9668145
--- /dev/null
+++ b/griffin-doc/service/api-guide.md
@@ -0,0 +1,1084 @@
+<!--
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+-->
+
+# Apache Griffin API Guide
+
+This page lists the major RESTful APIs provided by Griffin.
+
+Apache Griffin default `BASE_PATH` is `http://<your ip>:8080`. 
+
+- [Griffin Basic](#1)
+
+- [Measures](#2)
+
+- [Jobs](#3)
+
+- [Metrics](#4)
+
+- [Hive MetaStore](#5)
+
+- [Auth](#6)
+
+
+<h2 id = "1"></h2>
+## Griffin Basic
+
+### Get griffin version
+`GET /api/v1/version`
+
+#### Response Body Sample
+`0.1.0`
+
+<h2 id = "2"></h2>
+## Measures
+### Add measure
+`POST /api/v1/measures`
+
+#### Request Header
+| key          | value            |
+| ------------ | ---------------- |
+| Content-Type | application/json |
+
+#### Request Body
+
+| name    | description    | type    |
+| ------- | -------------- | ------- |
+| measure | measure entity | Measure |
+
+There are two different measures that are griffin measure and external measure.
+If you want to create an external measure,you can use following example json in request body.
+```
+{
+    "type": "external",
+    "name": "external_name",
+    "description": " test measure",
+    "organization": "orgName",
+    "owner": "test",
+    "metricName": "metricName"
+}
+```
+Here gives a griffin measure example in request body and response body. 
+#### Request Body example 
+```
+{
+    "name":"measure_name",
+	"type":"griffin",
+    "description":"create a measure",
+    "evaluate.rule":{
+        "rules":[
+            {
+                "rule":"source.desc=target.desc",
+                "dsl.type":"griffin-dsl",
+                "dq.type":"accuracy",
+                "details":{}
+            }
+        ]
+    },
+    "data.sources":[
+        {
+            "name":"source",
+            "connectors":[
+                {
+					"name":"connector_name_source",
+                    "type":"HIVE",
+                    "version":"1.2",
+					"data.unit":"1h",
+                    "config":{
+                        "database":"default",
+                        "table.name":"demo_src",
+                        "where":"dt=#YYYYMMdd# AND hour=#HH#"
+                    },
+                    "predicates":[
+                        {
+                            "type":"file.exist",
+                            "config":{
+                                "root.path":"hdfs:///griffin/demo_src",
+                                "path":"/dt=#YYYYMMdd#/hour=#HH#/_DONE"
+                            }
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            "name":"target",
+            "connectors":[
+                {
+					"name":"connector_name_target",
+                    "type":"HIVE",
+                    "version":"1.2",
+					"data.unit":"1h",
+                    "config":{
+                        "database":"default",
+                        "table.name":"demo_src",
+                        "where":"dt=#YYYYMMdd# AND hour=#HH#"
+                    },
+                    "predicates":[
+                        {
+                            "type":"file.exist",
+                            "config":{
+                                "root.path":"hdfs:///griffin/demo_src",
+                                "path":"/dt=#YYYYMMdd#/hour=#HH#/_DONE"
+                            }
+                        }
+                    ]
+                }
+            ]
+        }
+    ]
+}
+```
+#### Response Body Sample
+```
+{
+  "code": 201,
+  "description": "Create Measure Succeed"
+}
+```
+It may return failed messages.Such as,
+```
+{
+  "code": 410,
+  "description": "Create Measure Failed, duplicate records"
+}
+
+```
+The reason for failure may be that connector names already exist or connector names are empty.
+
+
+### Get measures
+`GET /api/v1/measures`
+#### Response Body Sample
+```
+[
+    {
+        "id": 1,
+        "name": "measurename",
+        "description": "This is measure test.",
+        "owner": "test",
+        "deleted": false,
+        "process.type": "batch",
+        "evaluateRule": {
+            "id": 1,
+            "rules": [
+                {
+                    "id": 1,
+                    "rule": "source.id=target.id AND source.age=target.age",
+                    "dsl.type": "griffin-dsl",
+                    "dq.type": "accuracy"
+                }
+            ]
+        },
+        "data.sources": [
+            {
+                "id": 1,
+                "name": "source",
+                "connectors": [
+                    {
+                        "id": 1,
+                        "type": "HIVE",
+                        "version": "1.2",
+                        "config": {
+                            "database": "default",
+                            "table.name": "demo_src"
+                        }
+                    }
+                ]
+            },
+            {
+                "id": 2,
+                "name": "target",
+                "connectors": [
+                    {
+                        "id": 2,
+                        "type": "HIVE",
+                        "version": "1.2",
+                        "config": {
+                            "database": "default",
+                            "table.name": "demo_tgt"
+                        }
+                    }
+                ]
+            }
+        ]
+    }
+]
+```
+
+
+### Update measure
+`PUT /api/v1/measures`
+#### Request Header
+| key          | value            |
+| ------------ | ---------------- |
+| Content-Type | application/json |
+
+#### Request Body
+| name    | description    | type    |
+| ------- | -------------- | ------- |
+| measure | measure entity | Measure |
+There are two different measures that are griffin measure and external measure.
+If you want to update an external measure,you can use following example json in request body.
+```
+{
+	"id":1,
+    "type": "external",
+    "name": "external_name",
+    "description": " update test measure",
+    "organization": "orgName",
+    "owner": "test",
+    "metricName": "metricName"
+}
+```
+Here gives a griffin measure example in request body and response body. 
+#### Request Body example 
+```
+{
+        "id": 1,
+        "name": "measure_official_update",
+        "description": "create a measure",
+        "owner": "test",
+        "deleted": false,
+        "type": "griffin",
+        "process.type": "batch",
+        "data.sources": [
+            {
+                "id": 1,
+                "name": "source",
+                "connectors": [
+                    {
+                        "id": 1,
+                        "name": "connector_name_source",
+                        "type": "HIVE",
+                        "version": "1.2",
+                        "predicates": [],
+                        "data.unit": "1h",
+                        "config": {
+                            "database": "default",
+                            "table.name": "demo_src",
+                            "where": "dt=#YYYYMMdd# AND hour=#HH#"
+                        }
+                    }
+                ]
+            },
+            {
+                "id": 2,
+                "name": "target",
+                "connectors": [
+                    {
+                        "id": 2,
+                        "name": "connector_name_target",
+                        "type": "HIVE",
+                        "version": "1.2",
+                        "predicates": [],
+                        "data.unit": "1h",
+                        "config": {
+                            "database": "default",
+                            "table.name": "demo_src",
+                            "where": "dt=#YYYYMMdd# AND hour=#HH#"
+                        }
+                    }
+                ]
+            }
+        ],
+        "evaluate.rule": {
+            "id": 1,
+            "rules": [
+                {
+                    "id": 1,
+                    "rule": "source.desc=target.desc",
+                    "dsl.type": "griffin-dsl",
+                    "dq.type": "accuracy",
+                    "details": {}
+                }
+            ]
+        }
+    }
+```
+#### Response Body Sample
+```
+{
+  "code": 204,
+  "description": "Update Measure Succeed"
+}
+```
+It may return failed messages.Such as,
+```
+{
+  "code": 400,
+  "description": "Resource Not Found"
+}
+
+```
+
+The reason for failure may be that measure id doesn't exist.
+
+### Delete measure
+`DELETE /api/v1/measures/{id}`
+When deleting a measure,api will also delete related jobs.
+#### Path Variable
+- id -`required` `Long` measure id
+
+#### Request Sample
+
+`/api/v1/measures/1`
+
+#### Response Body Sample
+```
+{
+  "code": 202,
+  "description": "Delete Measures By Id Succeed"
+}
+```
+
+It may return failed messages.Such as,
+
+```
+{
+  "code": 400,
+  "description": "Resource Not Found"
+}
+
+```
+
+The reason for failure may be that measure id doesn't exist.
+
+
+### Get measure by id
+`GET /api/v1/measures/{id}`
+#### Path Variable
+- id -`required` `Long` measure id
+
+#### Request Sample
+
+`/api/v1/measures/1`
+
+#### Response Body Sample
+```
+{
+    "id": 1,
+    "name": "measureName",
+    "description": "This is a test measure",
+    "organization": "orgName",
+    "evaluateRule": {
+        "id": 1,
+        "rules": [
+            {
+                "id": 1,
+                "rule": "source.id = target.id and source.age = target.age and source.desc = target.desc",
+                "dsl.type": "griffin-dsl",
+                "dq.type": "accuracy"
+            }
+        ]
+    },
+    "owner": "test",
+    "deleted": false,
+    "process.type": "batch",
+    "data.sources": [
+        {
+            "id": 39,
+            "name": "source",
+            "connectors": [
+                {
+                    "id": 1,
+                    "type": "HIVE",
+                    "version": "1.2",
+                    "config": {
+                        "database": "default",
+                        "table.name": "demo_src"
+                    }
+                }
+            ]
+        },
+        {
+            "id": 2,
+            "name": "target",
+            "connectors": [
+                {
+                    "id": 2,
+                    "type": "HIVE",
+                    "version": "1.2",
+                    "config": {
+                        "database": "default",
+                        "table.name": "demo_tgt"
+                    }
+                }
+            ]
+        }
+    ]
+}
+```
+It may return no content.That's because your measure id doesn't exist.
+
+<h2 id = "3"></h2>
+## Jobs
+### Add job
+`POST /api/v1/jobs`
+#### Request Header
+| key          | value            |
+| ------------ | ---------------- |
+| Content-Type | application/json |
+
+#### Request Body
+| name        | description                              | type        |
+| ----------- | ---------------------------------------- | ----------- |
+| jobSchedule | custom class composed of job key parameters | JobSchedule |
+
+#### Request Body Sample
+```
+{
+    "measure.id": 1,
+	"job.name":"job_name",
+    "cron.expression": "0 0/4 * * * ?",
+    "cron.time.zone": "GMT+8:00",
+    "predicate.config": {
+		"checkdonefile.schedule":{
+			"interval": "5m",
+			"repeat": 12
+		}
+    },
+    "data.segments": [
+        {
+            "data.connector.name": "connector_name_source_test",
+			"as.baseline":true, 
+            "segment.range": {
+                "begin": "-1h",
+                "length": "1h"
+            }
+        },
+        {
+            "data.connector.name": "connector_name_target_test",
+            "segment.range": {
+                "begin": "-1h",
+                "length": "1h"
+            }
+        }
+    ]
+}
+```
+#### Response Body Sample
+```
+{
+  "code": 205,
+  "description": "Create Job Succeed"
+}
+```
+It may return failed messages.Such as,
+
+```
+{
+  "code": 405,
+  "description": "Create Job Failed"
+}
+```
+
+There are several reasons to create job failure.
+
+- Measure id does not exist.
+- Job name already exits.
+- Param as.baselines aren't set or are all false.
+- Connector name doesn't exist in your measure.
+- The trigger key already exists.
+
+### Get jobs
+`GET /api/v1/jobs`
+
+#### Response Body Sample
+```
+[
+    {
+        "jobId": 1,
+        "jobName": "job_name",
+        "measureId": 1,
+        "triggerState": "NORMAL",
+        "nextFireTime": 1515400080000,
+        "previousFireTime": 1515399840000,
+        "cronExpression": "0 0/4 * * * ?"
+    }
+]
+
+```
+
+### Delete job by id
+#### `DELETE /api/v1/jobs/{id}`
+#### Path Variable
+- id -`required` `Long` job id
+
+#### Response Body Sample
+```
+{
+  "code": 206,
+  "description": "Delete Job Succeed"
+}
+
+```
+It may return failed messages.Such as,
+```
+{
+    "code": 406,
+    "description": "Delete Job Failed"
+}
+```
+The reason for failure may be that job id does not exist.
+
+### Delete job by name
+#### `DELETE /api/v1/jobs`
+| name    | description | type   | example value |
+| ------- | ----------- | ------ | ------------- |
+| jobName | job name    | String | job_name      |
+
+#### Response Body Sample
+```
+{
+  "code": 206,
+  "description": "Delete Job Succeed"
+}
+
+```
+It may return failed messages.Such as,
+```
+{
+    "code": 406,
+    "description": "Delete Job Failed"
+}
+```
+The reason for failure may that job name does not exist.
+
+
+### Get job instances
+`GET /api/v1/jobs/instances`
+
+| name  | description                         | type | example value |
+| ----- | ----------------------------------- | ---- | ------------- |
+| jobId | job id                              | Long | 1             |
+| page  | page you want starting from index 0 | int  | 0             |
+| size  | instance number per page            | int  | 10            |
+
+#### Response Body Sample
+```
+[
+    {
+        "id": 1,
+        "sessionId": null,
+        "state": "success",
+        "appId": null,
+        "appUri": null,
+        "predicateGroup": "PG",
+        "predicateName": "job_name_predicate_1515399840077",
+        "deleted": true,
+        "timestamp": 1515399840092,
+        "expireTimestamp": 1516004640092
+    },
+    {
+        "id": 2,
+        "sessionId": null,
+        "state": "not_found",
+        "appId": null,
+        "appUri": null,
+        "predicateGroup": "PG",
+        "predicateName": "job_name_predicate_1515399840066",
+        "deleted": true,
+        "timestamp": 1515399840067,
+        "expireTimestamp": 1516004640067
+    }
+]
+```
+
+### Get job healthy statistics
+`GET /api/v1/jobs/health`
+
+#### Response Body Sample
+```
+{
+  "healthyJobCount": 1,
+  "jobCount": 2
+}
+```
+
+<h2 id = "4"></h2>
+## Metrics
+### Get metrics
+`GET /api/v1/metrics`
+#### Response Example
+```
+[
+    {
+        "name": "external_name",
+        "description": " test measure",
+        "organization": "orgName",
+        "owner": "test",
+        "metricValues": [
+            {
+                "name": "metricName",
+                "tmst": 1509599811123,
+                "value": {
+                    "__tmst": 1509599811123,
+                    "miss": 11,
+                    "total": 125000,
+                    "matched": 124989
+                }
+            }
+        ]
+    }
+]
+```
+
+### Add metric values
+`POST /api/v1/metrics/values`
+#### Request Header
+| key          | value            |
+| ------------ | ---------------- |
+| Content-Type | application/json |
+#### Request Body
+| name          | description             | type        |
+| ------------- | ----------------------- | ----------- |
+| Metric Values | A list of metric values | MetricValue |
+#### Request Body Sample
+```
+[
+	{
+		"name" : "metricName",
+		"tmst" : 1509599811123,
+		"value" : {
+			"__tmst" : 1509599811123,
+			"miss" : 11,
+			"total" : 125000,
+			"matched" : 124989
+		}
+   }
+]
+```
+#### Response Body Sample
+```
+{
+    "code": 210,
+    "description": "Add Metric Values Success"
+}
+```
+
+It may return failed message
+
+```
+{
+	"code": 412,
+    "description": "Add Metric Values Failed"
+}
+```
+The returned HTTP status code identifies the reason for failure.
+### Get metric values by name 
+`GET /api/v1/metrics/values`
+
+#### Request Parameter
+| name       | description                              | type   | example value |
+| ---------- | ---------------------------------------- | ------ | ------------- |
+| metricName | name of the metric values                | String | metricName    |
+| size       | max amount of return values              | int    | 5             |
+| offset     | the amount of records to skip by timestamp in descending order | int    | 0             |
+
+Parameter offset is optional, it has default value as 0.
+#### Response Body Sample
+```
+[
+    {
+        "name": "metricName",
+        "tmst": 1509599811123,
+        "value": {
+            "__tmst": 1509599811123,
+            "miss": 11,
+            "total": 125000,
+            "matched": 124989
+        }
+    }
+]
+```
+
+### Delete metric values by name
+`DELETE /api/v1/metrics/values`
+#### Request Parameters 
+| name       | description               | type   | example value |
+| ---------- | ------------------------- | ------ | ------------- |
+| metricName | name of the metric values | String | metricName    |
+#### Response Body Sample
+```
+{
+    "code": 211,
+    "description": "Delete Metric Values Success"
+}
+```
+It may return failed messages
+```
+{
+    "code": 413,
+    "description": "Delete Metric Values Failed"
+}
+```
+The returned HTTP status code identifies the reason for failure.
+
+<h2 id = "5"></h2>
+### Hive MetaStore
+### Get table metadata
+`GET /api/v1/metadata/hive/table`
+#### Request Parameters
+| name  | description        | type   | example value |
+| ----- | ------------------ | ------ | ------------- |
+| db    | hive database name | String | default       |
+| table | hive table name    | String | demo_src      |
+
+#### Response Example Sample
+```
+{
+    "tableName": "demo_src",
+    "dbName": "default",
+    "owner": "root",
+    "createTime": 1505986176,
+    "lastAccessTime": 0,
+    "retention": 0,
+    "sd": {
+        "cols": [
+            {
+                "name": "id",
+                "type": "bigint",
+                "comment": null,
+                "setName": true,
+                "setType": true,
+                "setComment": false
+            },
+            {
+                "name": "age",
+                "type": "int",
+                "comment": null,
+                "setName": true,
+                "setType": true,
+                "setComment": false
+            },
+            {
+                "name": "desc",
+                "type": "string",
+                "comment": null,
+                "setName": true,
+                "setType": true,
+                "setComment": false
+            }
+        ],
+        "location": "hdfs://sandbox:9000/griffin/data/batch/demo_src"
+    },
+    "partitionKeys": [
+        {
+            "name": "dt",
+            "type": "string",
+            "comment": null,
+            "setName": true,
+            "setType": true,
+            "setComment": false
+        },
+        {
+            "name": "hour",
+            "type": "string",
+            "comment": null,
+            "setName": true,
+            "setType": true,
+            "setComment": false
+        }
+    ]
+}
+```
+### Get table names
+`GET /api/v1/metadata/hive/tables/names`
+#### Request Parameter
+| name | description        | typ    | example value |
+| ---- | ------------------ | ------ | ------------- |
+| db   | hive database name | String | default       |
+
+#### Response Example Sample
+```
+[
+  "demo_src",
+  "demo_tgt"
+]
+```
+
+### Get all database tables metadata
+`GET /api/v1/metadata/hive/dbs/tables`
+#### Response Example Sample
+```
+{
+   "default": [
+    {
+      "tableName": "demo_src",
+      "dbName": "default",
+      "owner": "root",
+      "createTime": 1505986176,
+      "lastAccessTime": 0,
+      "sd": {
+        "cols": [
+          {
+            "name": "id",
+            "type": "bigint",
+            "comment": null,
+            "setComment": false,
+            "setType": true,
+            "setName": true
+          },
+          {
+            "name": "age",
+            "type": "int",
+            "comment": null,
+            "setComment": false,
+            "setType": true,
+            "setName": true
+          },
+          {
+            "name": "desc",
+            "type": "string",
+            "comment": null,
+            "setComment": false,
+            "setType": true,
+            "setName": true
+          }
+        ],
+        "location": "hdfs://sandbox:9000/griffin/data/batch/demo_src"
+      },
+      "partitionKeys": [
+        {
+          "name": "dt",
+          "type": "string",
+          "comment": null,
+          "setComment": false,
+          "setType": true,
+          "setName": true
+        },
+        {
+          "name": "hour",
+          "type": "string",
+          "comment": null,
+          "setComment": false,
+          "setType": true,
+          "setName": true
+        }
+      ]
+    },
+    {
+      "tableName": "demo_tgt",
+      "dbName": "default",
+      "owner": "root",
+      "createTime": 1505986176,
+      "lastAccessTime": 0,
+      "sd": {
+        "cols": [
+          {
+            "name": "id",
+            "type": "bigint",
+            "comment": null,
+            "setComment": false,
+            "setType": true,
+            "setName": true
+          },
+          {
+            "name": "age",
+            "type": "int",
+            "comment": null,
+            "setComment": false,
+            "setType": true,
+            "setName": true
+          },
+          {
+            "name": "desc",
+            "type": "string",
+            "comment": null,
+            "setComment": false,
+            "setType": true,
+            "setName": true
+          }
+        ],
+        "location": "hdfs://sandbox:9000/griffin/data/batch/demo_tgt"
+      },
+      "partitionKeys": [
+        {
+          "name": "dt",
+          "type": "string",
+          "comment": null,
+          "setComment": false,
+          "setType": true,
+          "setName": true
+        },
+        {
+          "name": "hour",
+          "type": "string",
+          "comment": null,
+          "setComment": false,
+          "setType": true,
+          "setName": true
+        }
+      ]
+    }
+  ]
+}
+
+```
+
+### Get database names
+`GET /api/v1/metadata/hive/dbs`
+#### Response Example Sample
+```
+[
+	"default"
+]
+```
+
+### Get tables metadata
+`GET /api/v1/metadata/hive/tables`
+#### Request Parameter
+| name | description        | typ    | example value |
+| ---- | ------------------ | ------ | ------------- |
+| db   | hive database name | String | default       |
+#### Response Body Sample
+```
+[
+  {
+    "tableName": "demo_src",
+    "dbName": "default",
+    "owner": "root",
+    "createTime": 1508216660,
+    "lastAccessTime": 0,
+    "retention": 0,
+    "sd": {
+      "cols": [
+        {
+          "name": "id",
+          "type": "bigint",
+          "comment": null,
+          "setName": true,
+          "setType": true,
+          "setComment": false
+        },
+        {
+          "name": "age",
+          "type": "int",
+          "comment": null,
+          "setName": true,
+          "setType": true,
+          "setComment": false
+        },
+        {
+          "name": "desc",
+          "type": "string",
+          "comment": null,
+          "setName": true,
+          "setType": true,
+          "setComment": false
+        }
+      ],
+      "location": "hdfs://sandbox:9000/griffin/data/batch/demo_src"
+    },
+    "partitionKeys": [
+      {
+        "name": "dt",
+        "type": "string",
+        "comment": null,
+        "setName": true,
+        "setType": true,
+        "setComment": false
+      },
+      {
+        "name": "hour",
+        "type": "string",
+        "comment": null,
+        "setName": true,
+        "setType": true,
+        "setComment": false
+      }
+    ]
+  },
+  {
+    "tableName": "demo_tgt",
+    "dbName": "default",
+    "owner": "root",
+    "createTime": 1508216660,
+    "lastAccessTime": 0,
+    "retention": 0,
+    "sd": {
+      "cols": [
+        {
+          "name": "id",
+          "type": "bigint",
+          "comment": null,
+          "setName": true,
+          "setType": true,
+          "setComment": false
+        },
+        {
+          "name": "age",
+          "type": "int",
+          "comment": null,
+          "setName": true,
+          "setType": true,
+          "setComment": false
+        },
+        {
+          "name": "desc",
+          "type": "string",
+          "comment": null,
+          "setName": true,
+          "setType": true,
+          "setComment": false
+        }
+      ],
+      "location": "hdfs://sandbox:9000/griffin/data/batch/demo_tgt"
+ },
+    "partitionKeys": [
+      {
+        "name": "dt",
+        "type": "string",
+        "comment": null,
+        "setName": true,
+        "setType": true,
+        "setComment": false
+      },
+      {
+        "name": "hour",
+        "type": "string",
+        "comment": null,
+        "setName": true,
+        "setType": true,
+        "setComment": false
+      }
+    ]
+  }
+]
+```
+
+
+<h2 id = "6"></h2>
+## Auth
+### User authentication
+`POST /api/v1/login/authenticate`
+
+#### Request Parameter
+| name | description                           | type | example value                           |
+| ---- | ------------------------------------- | ---- | --------------------------------------- |
+| map  | a map contains user name and password | Map  | `{"username":"user","password":"test"}` |
+
+#### Response Body Sample
+```
+{
+  "fullName": "Default",
+  "ntAccount": "user",
+  "status": 0
+}
+```