You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@oozie.apache.org by ja...@apache.org on 2016/08/23 18:41:54 UTC

oozie git commit: OOZIE-2517 Add support for startCreatedTime and endCreatedTime filters for coord and bundles (abhishekbafna via jaydeepvishwakarma)

Repository: oozie
Updated Branches:
  refs/heads/master 1b46fd92f -> 0754451da


OOZIE-2517 Add support for startCreatedTime and endCreatedTime filters for coord and bundles (abhishekbafna via jaydeepvishwakarma)


Project: http://git-wip-us.apache.org/repos/asf/oozie/repo
Commit: http://git-wip-us.apache.org/repos/asf/oozie/commit/0754451d
Tree: http://git-wip-us.apache.org/repos/asf/oozie/tree/0754451d
Diff: http://git-wip-us.apache.org/repos/asf/oozie/diff/0754451d

Branch: refs/heads/master
Commit: 0754451daf5a7c3bdbc401bb245611a1da13731e
Parents: 1b46fd9
Author: jvishwakarma <jv...@walmartlabs.com>
Authored: Wed Aug 24 00:11:30 2016 +0530
Committer: jvishwakarma <jv...@walmartlabs.com>
Committed: Wed Aug 24 00:11:30 2016 +0530

----------------------------------------------------------------------
 .../org/apache/oozie/CoordinatorEngine.java     |   5 +-
 .../jpa/BundleJobInfoGetJPAExecutor.java        |   2 +-
 .../jpa/CoordJobInfoGetJPAExecutor.java         |   2 +-
 .../jpa/WorkflowsJobGetJPAExecutor.java         |  13 +--
 .../apache/oozie/store/StoreStatusFilter.java   | 117 ++++++++++++++++++-
 .../org/apache/oozie/util/JobsFilterUtils.java  |   3 +
 .../org/apache/oozie/client/TestOozieCLI.java   |  10 +-
 .../jpa/TestBundleJobInfoGetJPAExecutor.java    |  70 +++++++++++
 .../jpa/TestCoordJobInfoGetJPAExecutor.java     |  95 +++++++++++++++
 docs/src/site/twiki/WebServicesAPI.twiki        |   4 +-
 release-log.txt                                 |   1 +
 11 files changed, 306 insertions(+), 16 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/oozie/blob/0754451d/core/src/main/java/org/apache/oozie/CoordinatorEngine.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/oozie/CoordinatorEngine.java b/core/src/main/java/org/apache/oozie/CoordinatorEngine.java
index 2301908..cec6347 100644
--- a/core/src/main/java/org/apache/oozie/CoordinatorEngine.java
+++ b/core/src/main/java/org/apache/oozie/CoordinatorEngine.java
@@ -611,6 +611,8 @@ public class CoordinatorEngine extends BaseEngine {
         FILTER_NAMES.add(OozieClient.FILTER_FREQUENCY);
         FILTER_NAMES.add(OozieClient.FILTER_UNIT);
         FILTER_NAMES.add(OozieClient.FILTER_SORT_BY);
+        FILTER_NAMES.add(OozieClient.FILTER_CREATED_TIME_START);
+        FILTER_NAMES.add(OozieClient.FILTER_CREATED_TIME_END);
     }
 
     /**
@@ -722,7 +724,8 @@ public class CoordinatorEngine extends BaseEngine {
                         throw new CoordinatorEngineException(ErrorCode.E0420, filter,
                                 "elements must be semicolon-separated name=value pairs");
                     }
-                    if (!FILTER_NAMES.contains(pair[0].toLowerCase())) {
+                    pair[0] = pair[0].toLowerCase();
+                    if (!FILTER_NAMES.contains(pair[0])) {
                         throw new CoordinatorEngineException(ErrorCode.E0420, filter, XLog.format("invalid name [{0}]",
                                 pair[0]));
                     }

http://git-wip-us.apache.org/repos/asf/oozie/blob/0754451d/core/src/main/java/org/apache/oozie/executor/jpa/BundleJobInfoGetJPAExecutor.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/oozie/executor/jpa/BundleJobInfoGetJPAExecutor.java b/core/src/main/java/org/apache/oozie/executor/jpa/BundleJobInfoGetJPAExecutor.java
index dace4e8..f4fe0ef 100644
--- a/core/src/main/java/org/apache/oozie/executor/jpa/BundleJobInfoGetJPAExecutor.java
+++ b/core/src/main/java/org/apache/oozie/executor/jpa/BundleJobInfoGetJPAExecutor.java
@@ -80,7 +80,7 @@ public class BundleJobInfoGetJPAExecutor implements JPAExecutor<BundleJobInfo> {
     public BundleJobInfo execute(EntityManager em) throws JPAExecutorException {
         List<String> orArray = new ArrayList<String>();
         List<String> colArray = new ArrayList<String>();
-        List<String> valArray = new ArrayList<String>();
+        List<Object> valArray = new ArrayList<Object>();
         StringBuilder sb = new StringBuilder("");
         String orderBy = DEFAULT_ORDER_BY;
 

http://git-wip-us.apache.org/repos/asf/oozie/blob/0754451d/core/src/main/java/org/apache/oozie/executor/jpa/CoordJobInfoGetJPAExecutor.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/oozie/executor/jpa/CoordJobInfoGetJPAExecutor.java b/core/src/main/java/org/apache/oozie/executor/jpa/CoordJobInfoGetJPAExecutor.java
index 8fcb1e6..8ae070e 100644
--- a/core/src/main/java/org/apache/oozie/executor/jpa/CoordJobInfoGetJPAExecutor.java
+++ b/core/src/main/java/org/apache/oozie/executor/jpa/CoordJobInfoGetJPAExecutor.java
@@ -66,7 +66,7 @@ public class CoordJobInfoGetJPAExecutor implements JPAExecutor<CoordinatorJobInf
     public CoordinatorJobInfo execute(EntityManager em) throws JPAExecutorException {
         List<String> orArray = new ArrayList<String>();
         List<String> colArray = new ArrayList<String>();
-        List<String> valArray = new ArrayList<String>();
+        List<Object> valArray = new ArrayList<Object>();
         StringBuilder sb = new StringBuilder("");
         String orderBy = DEFAULT_ORDER_BY;
 

http://git-wip-us.apache.org/repos/asf/oozie/blob/0754451d/core/src/main/java/org/apache/oozie/executor/jpa/WorkflowsJobGetJPAExecutor.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/oozie/executor/jpa/WorkflowsJobGetJPAExecutor.java b/core/src/main/java/org/apache/oozie/executor/jpa/WorkflowsJobGetJPAExecutor.java
index 5cde60e..3c03267 100644
--- a/core/src/main/java/org/apache/oozie/executor/jpa/WorkflowsJobGetJPAExecutor.java
+++ b/core/src/main/java/org/apache/oozie/executor/jpa/WorkflowsJobGetJPAExecutor.java
@@ -18,9 +18,7 @@
 
 package org.apache.oozie.executor.jpa;
 
-import java.io.IOException;
 import java.sql.Timestamp;
-import java.text.ParseException;
 import java.util.ArrayList;
 import java.util.Date;
 import java.util.List;
@@ -343,21 +341,21 @@ public class WorkflowsJobGetJPAExecutor implements JPAExecutor<WorkflowsInfo> {
                 case 'd':
                     offset = Integer.parseInt(time.substring(0, time.length() - 1));
                     if(offset > 0) {
-                        throw new IllegalArgumentException("offset must be minus from currentTime");
+                        throw new IllegalArgumentException("offset must be minus from currentTime.");
                     }
                     createdTime = org.apache.commons.lang.time.DateUtils.addDays(new Date(), offset);
                     break;
                 case 'h':
                     offset =  Integer.parseInt(time.substring(0, time.length() - 1));
                     if(offset > 0) {
-                        throw new IllegalArgumentException("offset must be minus from currentTime");
+                        throw new IllegalArgumentException("offset must be minus from currentTime.");
                     }
                     createdTime = org.apache.commons.lang.time.DateUtils.addHours(new Date(), offset);
                     break;
                 case 'm':
                     offset =  Integer.parseInt(time.substring(0, time.length() - 1));
                     if(offset > 0) {
-                        throw new IllegalArgumentException("offset must be minus from currentTime");
+                        throw new IllegalArgumentException("offset must be minus from currentTime.");
                     }
                     createdTime = org.apache.commons.lang.time.DateUtils.addMinutes(new Date(), offset);
                     break;
@@ -365,13 +363,14 @@ public class WorkflowsJobGetJPAExecutor implements JPAExecutor<WorkflowsInfo> {
                     createdTime = DateUtils.parseDateUTC(time);
                     break;
                 default:
-                    throw new IllegalArgumentException("Unsupported time format " + time);
+                    throw new IllegalArgumentException("Unsupported time format: " + time + StoreStatusFilter.TIME_FORMAT);
             }
         } else {
-            throw new IllegalArgumentException("the format of createdTime is wrong: " + time);
+            throw new IllegalArgumentException("The format of time is wrong: " + time + StoreStatusFilter.TIME_FORMAT);
         }
         return createdTime;
     }
+
     private WorkflowJobBean getBeanForWorkflowFromArray(Object[] arr) {
 
         WorkflowJobBean wfBean = new WorkflowJobBean();

http://git-wip-us.apache.org/repos/asf/oozie/blob/0754451d/core/src/main/java/org/apache/oozie/store/StoreStatusFilter.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/oozie/store/StoreStatusFilter.java b/core/src/main/java/org/apache/oozie/store/StoreStatusFilter.java
index ebdbaa4..fb1db29 100644
--- a/core/src/main/java/org/apache/oozie/store/StoreStatusFilter.java
+++ b/core/src/main/java/org/apache/oozie/store/StoreStatusFilter.java
@@ -18,29 +18,41 @@
 
 package org.apache.oozie.store;
 
+import java.sql.Timestamp;
+import java.util.Date;
 import java.util.List;
 import java.util.Map;
 
 import org.apache.oozie.ErrorCode;
 import org.apache.oozie.client.OozieClient;
 import org.apache.oozie.executor.jpa.JPAExecutorException;
+import org.apache.oozie.util.DateUtils;
 import org.apache.oozie.util.XLog;
 
 public class StoreStatusFilter {
-    public static final String coordSeletStr = "Select w.id, w.appName, w.statusStr, w.user, w.group, w.startTimestamp, w.endTimestamp, w.appPath, w.concurrency, w.frequency, w.lastActionTimestamp, w.nextMaterializedTimestamp, w.createdTimestamp, w.timeUnitStr, w.timeZone, w.timeOut from CoordinatorJobBean w";
+    public static final String coordSeletStr = "Select w.id, w.appName, w.statusStr, w.user, w.group, w.startTimestamp, " +
+            "w.endTimestamp, w.appPath, w.concurrency, w.frequency, w.lastActionTimestamp, w.nextMaterializedTimestamp, " +
+            "w.createdTimestamp, w.timeUnitStr, w.timeZone, w.timeOut from CoordinatorJobBean w";
 
     public static final String coordCountStr = "Select count(w) from CoordinatorJobBean w";
 
-    public static final String wfSeletStr = "Select w.id, w.appName, w.statusStr, w.run, w.user, w.group, w.createdTimestamp, w.startTimestamp, w.lastModifiedTimestamp, w.endTimestamp from WorkflowJobBean w";
+    public static final String wfSeletStr = "Select w.id, w.appName, w.statusStr, w.run, w.user, w.group, w.createdTimestamp, " +
+            "w.startTimestamp, w.lastModifiedTimestamp, w.endTimestamp from WorkflowJobBean w";
 
     public static final String wfCountStr = "Select count(w) from WorkflowJobBean w";
 
-    public static final String bundleSeletStr = "Select w.id, w.appName, w.appPath, w.conf, w.statusStr, w.kickoffTimestamp, w.startTimestamp, w.endTimestamp, w.pauseTimestamp, w.createdTimestamp, w.user, w.group, w.timeUnitStr, w.timeOut from BundleJobBean w";
+    public static final String bundleSeletStr = "Select w.id, w.appName, w.appPath, w.conf, w.statusStr, w.kickoffTimestamp, " +
+            "w.startTimestamp, w.endTimestamp, w.pauseTimestamp, w.createdTimestamp, w.user, w.group, w.timeUnitStr, " +
+            "w.timeOut from BundleJobBean w";
 
     public static final String bundleCountStr = "Select count(w) from BundleJobBean w";
 
+    public static final String TIME_FORMAT = " Specify time either in UTC format (yyyy-MM-dd'T'HH:mm'Z') or " +
+            "a offset value in days/hours/minutes e.g. (-2d/h/m) from the current time.";
+
+
     public static void filter(Map<String, List<String>> filter, List<String> orArray, List<String> colArray,
-            List<String> valArray, StringBuilder sb, String seletStr, String countStr) {
+           List<Object> valArray, StringBuilder sb, String seletStr, String countStr) throws JPAExecutorException {
         boolean isStatus = false;
         boolean isAppName = false;
         boolean isUser = false;
@@ -249,12 +261,109 @@ public class StoreStatusFilter {
                                 colArray.add(colVar);
                             }
                         }
+                        else if (entry.getKey().equalsIgnoreCase(OozieClient.FILTER_CREATED_TIME_START)) {
+                            List<String> values = filter.get(OozieClient.FILTER_CREATED_TIME_START);
+                            colName = "createdTimestampStart";
+                            if (values.size() > 1) {
+                                throw new JPAExecutorException(ErrorCode.E0302,
+                                        "cannot specify multiple startcreatedtime");
+                            }
+                            colVar = colName;
+                            colVar = colVar + index;
+                            if (!isEnabled) {
+                                sb.append(seletStr).append(" where w.createdTimestamp >= :" + colVar);
+                                isEnabled = true;
+                            }
+                            else {
+                                sb.append(" and w.createdTimestamp >= :" + colVar);
+                            }
+                            index++;
+                            Date createdTime = null;
+                            try {
+                                createdTime = parseCreatedTimeString(values.get(0));
+                            }
+                            catch (Exception e) {
+                                throw new JPAExecutorException(ErrorCode.E0302, e.getMessage());
+                            }
+                            Timestamp createdTimeStamp = new Timestamp(createdTime.getTime());
+                            valArray.add(createdTimeStamp);
+                            orArray.add(colName);
+                            colArray.add(colVar);
+
+                        }
+                        else if (entry.getKey().equalsIgnoreCase(OozieClient.FILTER_CREATED_TIME_END)) {
+                            List<String> values = filter.get(OozieClient.FILTER_CREATED_TIME_END);
+                            colName = "createdTimestampEnd";
+                            if (values.size() > 1) {
+                                throw new JPAExecutorException(ErrorCode.E0302,
+                                        "cannot specify multiple endcreatedtime");
+                            }
+                            colVar = colName;
+                            colVar = colVar + index;
+                            if (!isEnabled) {
+                                sb.append(seletStr).append(" where w.createdTimestamp <= :" + colVar);
+                                isEnabled = true;
+                            }
+                            else {
+                                sb.append(" and w.createdTimestamp <= :" + colVar);
+                            }
+                            index++;
+                            Date createdTime = null;
+                            try {
+                                createdTime = parseCreatedTimeString(values.get(0));
+                            }
+                            catch (Exception e) {
+                                throw new JPAExecutorException(ErrorCode.E0302, e.getMessage());
+                            }
+                            Timestamp createdTimeStamp = new Timestamp(createdTime.getTime());
+                            valArray.add(createdTimeStamp);
+                            orArray.add(colName);
+                            colArray.add(colVar);
+                        }
                     }
                 }
             }
         }
     }
 
+    private static Date parseCreatedTimeString(String time) throws Exception{
+        Date createdTime = null;
+        int offset = 0;
+        if (Character.isLetter(time.charAt(time.length() - 1))) {
+            switch (time.charAt(time.length() - 1)) {
+                case 'd':
+                    offset = Integer.parseInt(time.substring(0, time.length() - 1));
+                    if(offset > 0) {
+                        throw new IllegalArgumentException("offset must be minus from currentTime.");
+                    }
+                    createdTime = org.apache.commons.lang.time.DateUtils.addDays(new Date(), offset);
+                    break;
+                case 'h':
+                    offset =  Integer.parseInt(time.substring(0, time.length() - 1));
+                    if(offset > 0) {
+                        throw new IllegalArgumentException("offset must be minus from currentTime.");
+                    }
+                    createdTime = org.apache.commons.lang.time.DateUtils.addHours(new Date(), offset);
+                    break;
+                case 'm':
+                    offset =  Integer.parseInt(time.substring(0, time.length() - 1));
+                    if(offset > 0) {
+                        throw new IllegalArgumentException("offset must be minus from currentTime.");
+                    }
+                    createdTime = org.apache.commons.lang.time.DateUtils.addMinutes(new Date(), offset);
+                    break;
+                case 'Z':
+                    createdTime = DateUtils.parseDateUTC(time);
+                    break;
+                default:
+                    throw new IllegalArgumentException("Unsupported time format: " + time + TIME_FORMAT);
+            }
+        } else {
+            throw new IllegalArgumentException("The format of time is wrong: " + time + TIME_FORMAT);
+        }
+        return createdTime;
+    }
+
     public static String getSortBy(Map<String, List<String>> filter, String sortByStr) throws JPAExecutorException {
         if (filter.containsKey(OozieClient.FILTER_SORT_BY)) {
             List<String> values = filter.get(OozieClient.FILTER_SORT_BY);

http://git-wip-us.apache.org/repos/asf/oozie/blob/0754451d/core/src/main/java/org/apache/oozie/util/JobsFilterUtils.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/oozie/util/JobsFilterUtils.java b/core/src/main/java/org/apache/oozie/util/JobsFilterUtils.java
index 90c772f..18df836 100644
--- a/core/src/main/java/org/apache/oozie/util/JobsFilterUtils.java
+++ b/core/src/main/java/org/apache/oozie/util/JobsFilterUtils.java
@@ -44,6 +44,8 @@ public class JobsFilterUtils {
         FILTER_NAMES.add(OozieClient.FILTER_STATUS);
         FILTER_NAMES.add(OozieClient.FILTER_ID);
         FILTER_NAMES.add(OozieClient.FILTER_SORT_BY);
+        FILTER_NAMES.add(OozieClient.FILTER_CREATED_TIME_START);
+        FILTER_NAMES.add(OozieClient.FILTER_CREATED_TIME_END);
     }
 
     public static Map<String, List<String>> parseFilter(String filter) throws ServletException{
@@ -58,6 +60,7 @@ public class JobsFilterUtils {
                         throw new XServletException(HttpServletResponse.SC_BAD_REQUEST, ErrorCode.E0420,
                                 "filter elements must be semicolon-separated name=value pairs");
                     }
+                    pair[0] = pair[0].toLowerCase();
                     if (!FILTER_NAMES.contains(pair[0])) {
                         throw new XServletException(HttpServletResponse.SC_BAD_REQUEST, ErrorCode.E0420,
                                 "filter name: " + pair[0] + " is invalid");

http://git-wip-us.apache.org/repos/asf/oozie/blob/0754451d/core/src/test/java/org/apache/oozie/client/TestOozieCLI.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/oozie/client/TestOozieCLI.java b/core/src/test/java/org/apache/oozie/client/TestOozieCLI.java
index 10498cb..a30baaa 100644
--- a/core/src/test/java/org/apache/oozie/client/TestOozieCLI.java
+++ b/core/src/test/java/org/apache/oozie/client/TestOozieCLI.java
@@ -31,7 +31,6 @@ import java.util.concurrent.Callable;
 
 import org.apache.hadoop.conf.Configuration;
 import org.apache.hadoop.fs.Path;
-import org.apache.oozie.BaseEngine;
 import org.apache.oozie.BuildInfo;
 import org.apache.oozie.cli.CLIParser;
 import org.apache.oozie.cli.OozieCLI;
@@ -920,6 +919,15 @@ public class TestOozieCLI extends DagServletTestCase {
                 assertEquals(0, new OozieCLI().run(args));
                 assertEquals(RestConstants.JOBS_FILTER_PARAM, MockDagEngineService.did);
 
+                args = new String[] { "jobs", "-filter",
+                        "startcreatedtime=-10d;endcreatedtime=-20m", "-jobtype", "coord", "-oozie", oozieUrl };
+                assertEquals(0, new OozieCLI().run(args));
+                assertEquals(RestConstants.JOBS_FILTER_PARAM, MockDagEngineService.did);
+
+                args = new String[] { "jobs", "-filter",
+                        "startcreatedtime=-10d;endcreatedtime=-20m", "-jobtype", "bundle", "-oozie", oozieUrl };
+                assertEquals(0, new OozieCLI().run(args));
+                assertEquals(RestConstants.JOBS_FILTER_PARAM, MockDagEngineService.did);
                 return null;
             }
         });

http://git-wip-us.apache.org/repos/asf/oozie/blob/0754451d/core/src/test/java/org/apache/oozie/executor/jpa/TestBundleJobInfoGetJPAExecutor.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/oozie/executor/jpa/TestBundleJobInfoGetJPAExecutor.java b/core/src/test/java/org/apache/oozie/executor/jpa/TestBundleJobInfoGetJPAExecutor.java
index 14bbbbb..0b1f644 100644
--- a/core/src/test/java/org/apache/oozie/executor/jpa/TestBundleJobInfoGetJPAExecutor.java
+++ b/core/src/test/java/org/apache/oozie/executor/jpa/TestBundleJobInfoGetJPAExecutor.java
@@ -19,12 +19,15 @@
 package org.apache.oozie.executor.jpa;
 
 import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Date;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
 import org.apache.oozie.BundleJobBean;
 import org.apache.oozie.BundleJobInfo;
+import org.apache.oozie.client.BundleJob;
 import org.apache.oozie.client.Job;
 import org.apache.oozie.client.OozieClient;
 import org.apache.oozie.service.JPAService;
@@ -61,6 +64,73 @@ public class TestBundleJobInfoGetJPAExecutor extends XDataTestCase {
         _testGetJobInfoForId(bundleJob1.getId());
     }
 
+    public void testGetJobInfoForStartCreatedTime() throws Exception {
+        BundleJobBean bundleJob1 = addRecordToBundleJobTable(BundleJob.Status.PREP, false);
+        BundleJobBean bundleJob2 = addRecordToBundleJobTable(BundleJob.Status.KILLED, false);
+        Date createTime1 = DateUtils.parseDateUTC("2012-01-01T10:00Z");
+        Date createTime2 = DateUtils.parseDateUTC("2012-01-05T10:00Z");
+        bundleJob1.setCreatedTime(createTime1);
+        bundleJob2.setCreatedTime(createTime2);
+        BundleJobQueryExecutor.getInstance().executeUpdate(BundleJobQueryExecutor.BundleJobQuery.UPDATE_BUNDLE_JOB, bundleJob1);
+        BundleJobQueryExecutor.getInstance().executeUpdate(BundleJobQueryExecutor.BundleJobQuery.UPDATE_BUNDLE_JOB, bundleJob2);
+
+        JPAService jpaService = Services.get().get(JPAService.class);
+        assertNotNull(jpaService);
+        Map<String, List<String>> filter = new HashMap<String, List<String>>();
+        BundleJobInfoGetJPAExecutor BundleInfoGetCmd = new BundleJobInfoGetJPAExecutor(filter, 1, 20);
+        BundleJobInfo ret = jpaService.execute(BundleInfoGetCmd);
+        assertNotNull(ret);
+        assertEquals(2, ret.getBundleJobs().size());
+        filter.clear();
+
+        filter.put(OozieClient.FILTER_CREATED_TIME_START, Arrays.asList("2012-01-02T10:00Z"));
+        BundleInfoGetCmd = new BundleJobInfoGetJPAExecutor(filter, 1, 20);
+        ret = jpaService.execute(BundleInfoGetCmd);
+        assertNotNull(ret);
+        assertEquals(1, ret.getBundleJobs().size());
+        BundleJobBean jobBean = ret.getBundleJobs().get(0);
+        assertEquals(bundleJob2.getStatus(), jobBean.getStatus());
+        assertEquals(bundleJob2.getCreatedTime(), jobBean.getCreatedTime());
+    }
+
+    public void testGetJobInfoForEndCreatedTime() throws Exception {
+        BundleJobBean bundleJob1 = addRecordToBundleJobTable(BundleJob.Status.RUNNING, false);
+        BundleJobBean bundleJob2 = addRecordToBundleJobTable(BundleJob.Status.KILLED, false);
+        BundleJobBean bundleJob3 = addRecordToBundleJobTable(BundleJob.Status.FAILED, false);
+        Date createTime1 = DateUtils.parseDateUTC("2012-01-03T10:00Z");
+        Date createTime2 = DateUtils.parseDateUTC("2012-01-05T10:00Z");
+        Date createTime3 = DateUtils.parseDateUTC("2012-01-010T10:00Z");
+        bundleJob1.setCreatedTime(createTime1);
+        bundleJob2.setCreatedTime(createTime2);
+        bundleJob3.setCreatedTime(createTime3);
+        BundleJobQueryExecutor.getInstance().executeUpdate(BundleJobQueryExecutor.BundleJobQuery.UPDATE_BUNDLE_JOB, bundleJob1);
+        BundleJobQueryExecutor.getInstance().executeUpdate(BundleJobQueryExecutor.BundleJobQuery.UPDATE_BUNDLE_JOB, bundleJob2);
+        BundleJobQueryExecutor.getInstance().executeUpdate(BundleJobQueryExecutor.BundleJobQuery.UPDATE_BUNDLE_JOB, bundleJob3);
+
+        JPAService jpaService = Services.get().get(JPAService.class);
+        assertNotNull(jpaService);
+        Map<String, List<String>> filter = new HashMap<String, List<String>>();
+        BundleJobInfoGetJPAExecutor bundleInfoGetCmd = new BundleJobInfoGetJPAExecutor(filter, 1, 20);
+        BundleJobInfo ret = jpaService.execute(bundleInfoGetCmd);
+        assertNotNull(ret);
+        assertEquals(3, ret.getBundleJobs().size());
+        filter.clear();
+
+        filter.put(OozieClient.FILTER_CREATED_TIME_START, Arrays.asList("2012-01-02T10:00Z"));
+        filter.put(OozieClient.FILTER_CREATED_TIME_END, Arrays.asList("2012-01-07T10:00Z"));
+        bundleInfoGetCmd = new BundleJobInfoGetJPAExecutor(filter, 1, 20);
+        ret = jpaService.execute(bundleInfoGetCmd);
+        assertNotNull(ret);
+        assertEquals(2, ret.getBundleJobs().size());
+        // default, expected order of results is by createTime DESC
+        BundleJobBean jobBean = ret.getBundleJobs().get(0);
+        assertEquals(bundleJob2.getStatus(), jobBean.getStatus());
+        assertEquals(bundleJob2.getCreatedTime(), jobBean.getCreatedTime());
+        BundleJobBean jobBean1 = ret.getBundleJobs().get(1);
+        assertEquals(bundleJob1.getStatus(), jobBean1.getStatus());
+        assertEquals(bundleJob1.getCreatedTime(), jobBean1.getCreatedTime());
+    }
+
     private void _testGetJobInfoForStatus() throws Exception {
         JPAService jpaService = Services.get().get(JPAService.class);
         assertNotNull(jpaService);

http://git-wip-us.apache.org/repos/asf/oozie/blob/0754451d/core/src/test/java/org/apache/oozie/executor/jpa/TestCoordJobInfoGetJPAExecutor.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/oozie/executor/jpa/TestCoordJobInfoGetJPAExecutor.java b/core/src/test/java/org/apache/oozie/executor/jpa/TestCoordJobInfoGetJPAExecutor.java
index e98b146..7d468f1 100644
--- a/core/src/test/java/org/apache/oozie/executor/jpa/TestCoordJobInfoGetJPAExecutor.java
+++ b/core/src/test/java/org/apache/oozie/executor/jpa/TestCoordJobInfoGetJPAExecutor.java
@@ -19,16 +19,20 @@
 package org.apache.oozie.executor.jpa;
 
 import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Date;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
 import org.apache.oozie.CoordinatorJobBean;
 import org.apache.oozie.CoordinatorJobInfo;
+import org.apache.oozie.ErrorCode;
 import org.apache.oozie.client.CoordinatorJob;
 import org.apache.oozie.client.OozieClient;
 import org.apache.oozie.service.JPAService;
 import org.apache.oozie.service.Services;
+import org.apache.oozie.store.StoreStatusFilter;
 import org.apache.oozie.test.XDataTestCase;
 import org.apache.oozie.util.DateUtils;
 
@@ -62,6 +66,97 @@ public class TestCoordJobInfoGetJPAExecutor extends XDataTestCase {
         _testGetJobInfoForFrequencyAndUnit();
     }
 
+    public void testGetJobInfoForStartCreatedTime() throws Exception {
+        CoordinatorJobBean coordinatorJob1 = addRecordToCoordJobTable(CoordinatorJob.Status.RUNNING, false, false);
+        CoordinatorJobBean coordinatorJob2 = addRecordToCoordJobTable(CoordinatorJob.Status.KILLED, false, false);
+        Date createTime1 = DateUtils.parseDateUTC("2012-01-01T10:00Z");
+        Date createTime2 = DateUtils.parseDateUTC("2012-01-05T10:00Z");
+        coordinatorJob1.setCreatedTime(createTime1);
+        coordinatorJob2.setCreatedTime(createTime2);
+        CoordJobQueryExecutor.getInstance().executeUpdate(CoordJobQueryExecutor.CoordJobQuery.UPDATE_COORD_JOB, coordinatorJob1);
+        CoordJobQueryExecutor.getInstance().executeUpdate(CoordJobQueryExecutor.CoordJobQuery.UPDATE_COORD_JOB, coordinatorJob2);
+
+        JPAService jpaService = Services.get().get(JPAService.class);
+        assertNotNull(jpaService);
+        Map<String, List<String>> filter = new HashMap<String, List<String>>();
+        CoordJobInfoGetJPAExecutor coordInfoGetCmd = new CoordJobInfoGetJPAExecutor(filter, 1, 20);
+        CoordinatorJobInfo ret = jpaService.execute(coordInfoGetCmd);
+        assertNotNull(ret);
+        assertEquals(2, ret.getCoordJobs().size());
+        filter.clear();
+
+        filter.put(OozieClient.FILTER_CREATED_TIME_START, Arrays.asList("2012-01-02T10:00Z"));
+        coordInfoGetCmd = new CoordJobInfoGetJPAExecutor(filter, 1, 20);
+        ret = jpaService.execute(coordInfoGetCmd);
+        assertNotNull(ret);
+        assertEquals(1, ret.getCoordJobs().size());
+        CoordinatorJobBean jobBean = ret.getCoordJobs().get(0);
+        assertEquals(coordinatorJob2.getStatus(), jobBean.getStatus());
+        assertEquals(coordinatorJob2.getCreatedTime(), jobBean.getCreatedTime());
+    }
+
+    public void testGetJobInfoForEndCreatedTime() throws Exception {
+        CoordinatorJobBean coordinatorJob1 = addRecordToCoordJobTable(CoordinatorJob.Status.RUNNING, false, false);
+        CoordinatorJobBean coordinatorJob2 = addRecordToCoordJobTable(CoordinatorJob.Status.KILLED, false, false);
+        CoordinatorJobBean coordinatorJob3 = addRecordToCoordJobTable(CoordinatorJob.Status.FAILED, false, false);
+        Date createTime1 = DateUtils.parseDateUTC("2012-01-03T10:00Z");
+        Date createTime2 = DateUtils.parseDateUTC("2012-01-05T10:00Z");
+        Date createTime3 = DateUtils.parseDateUTC("2012-01-010T10:00Z");
+        coordinatorJob1.setCreatedTime(createTime1);
+        coordinatorJob2.setCreatedTime(createTime2);
+        coordinatorJob3.setCreatedTime(createTime3);
+        CoordJobQueryExecutor.getInstance().executeUpdate(CoordJobQueryExecutor.CoordJobQuery.UPDATE_COORD_JOB, coordinatorJob1);
+        CoordJobQueryExecutor.getInstance().executeUpdate(CoordJobQueryExecutor.CoordJobQuery.UPDATE_COORD_JOB, coordinatorJob2);
+        CoordJobQueryExecutor.getInstance().executeUpdate(CoordJobQueryExecutor.CoordJobQuery.UPDATE_COORD_JOB, coordinatorJob3);
+
+        JPAService jpaService = Services.get().get(JPAService.class);
+        assertNotNull(jpaService);
+        Map<String, List<String>> filter = new HashMap<String, List<String>>();
+        CoordJobInfoGetJPAExecutor coordInfoGetCmd = new CoordJobInfoGetJPAExecutor(filter, 1, 20);
+        CoordinatorJobInfo ret = jpaService.execute(coordInfoGetCmd);
+        assertNotNull(ret);
+        assertEquals(3, ret.getCoordJobs().size());
+        filter.clear();
+
+        filter.put(OozieClient.FILTER_CREATED_TIME_START, Arrays.asList("2012-01-02T10:00Z"));
+        filter.put(OozieClient.FILTER_CREATED_TIME_END, Arrays.asList("2012-01-07T10:00Z"));
+        coordInfoGetCmd = new CoordJobInfoGetJPAExecutor(filter, 1, 20);
+        ret = jpaService.execute(coordInfoGetCmd);
+        assertNotNull(ret);
+        assertEquals(2, ret.getCoordJobs().size());
+        // default, expected order of results is by createTime DESC
+        CoordinatorJobBean jobBean = ret.getCoordJobs().get(0);
+        assertEquals(coordinatorJob2.getStatus(), jobBean.getStatus());
+        assertEquals(coordinatorJob2.getCreatedTime(), jobBean.getCreatedTime());
+        CoordinatorJobBean jobBean1 = ret.getCoordJobs().get(1);
+        assertEquals(coordinatorJob1.getStatus(), jobBean1.getStatus());
+        assertEquals(coordinatorJob1.getCreatedTime(), jobBean1.getCreatedTime());
+    }
+
+    public void testGetJobInfoForWrongTimeFormat() throws Exception {
+        addRecordToCoordJobTable(CoordinatorJob.Status.SUCCEEDED, false, false);
+        addRecordToCoordJobTable(CoordinatorJob.Status.RUNNING, false, false);
+
+        JPAService jpaService = Services.get().get(JPAService.class);
+        assertNotNull(jpaService);
+        Map<String, List<String>> filter = new HashMap<String, List<String>>();
+        CoordJobInfoGetJPAExecutor coordInfoGetCmd = new CoordJobInfoGetJPAExecutor(filter, 1, 20);
+        CoordinatorJobInfo ret = jpaService.execute(coordInfoGetCmd);
+        assertNotNull(ret);
+        assertEquals(2, ret.getCoordJobs().size());
+        filter.clear();
+
+        filter.put(OozieClient.FILTER_CREATED_TIME_START, Arrays.asList("2012-01-02T10:00"));
+        coordInfoGetCmd = new CoordJobInfoGetJPAExecutor(filter, 1, 20);
+        try {
+            jpaService.execute(coordInfoGetCmd);
+            fail("This should not happen. Check the createdTime passed.");
+        } catch (JPAExecutorException e) {
+            assertEquals(e.getErrorCode(), ErrorCode.E0302);
+            assertTrue(e.getMessage().contains(StoreStatusFilter.TIME_FORMAT));
+        }
+    }
+
     private void _testGetJobInfoForStatus() throws Exception {
         JPAService jpaService = Services.get().get(JPAService.class);
         assertNotNull(jpaService);

http://git-wip-us.apache.org/repos/asf/oozie/blob/0754451d/docs/src/site/twiki/WebServicesAPI.twiki
----------------------------------------------------------------------
diff --git a/docs/src/site/twiki/WebServicesAPI.twiki b/docs/src/site/twiki/WebServicesAPI.twiki
index 66293a5..13e1691 100644
--- a/docs/src/site/twiki/WebServicesAPI.twiki
+++ b/docs/src/site/twiki/WebServicesAPI.twiki
@@ -1676,7 +1676,9 @@ Additionally the =offset= and =len= parameters can be used for pagination. The s
 Moreover, the =jobtype= parameter could be used to determine what type of job is looking for.
 The valid values of job type are: =wf=, =coordinator= or =bundle=.
 
-startCreatedTime and endCreatedTime should be specified either in *ISO8601 (UTC)* format (*yyyy-MM-dd'T'HH:mm'Z'*) or a offset value in days or hours from the current time. For example, -2d means the current time - 2 days. -3h means the current time - 3 hours. -5m means the current time - 5 minutes
+startCreatedTime and endCreatedTime should be specified either in *ISO8601 (UTC)* format *(yyyy-MM-dd'T'HH:mm'Z')* or
+a offset value in days or hours or minutes from the current time. For example, -2d means the (current time - 2 days),
+-3h means the (current time - 3 hours), -5m means the (current time - 5 minutes).
 
 ---++++ Bulk modify jobs
 

http://git-wip-us.apache.org/repos/asf/oozie/blob/0754451d/release-log.txt
----------------------------------------------------------------------
diff --git a/release-log.txt b/release-log.txt
index fc3ad1c..326642a 100644
--- a/release-log.txt
+++ b/release-log.txt
@@ -1,5 +1,6 @@
 -- Oozie 4.3.0 release (trunk - unreleased)
 
+OOZIE-2517 Add support for startCreatedTime and endCreatedTime filters for coord and bundles (abhishekbafna via jaydeepvishwakarma)
 OOZIE-2589 CompletedActionXCommand is hardcoded to wrong priority (tm_linfly via rkanter)
 OOZIE-2081 WorkflowJob notification to include coordinator action id (seoeun25 via rkanter)
 OOZIE-2036 Drop support for Java 1.6 (gezapeti via jaydeepvishwakarma)