http://git-wip-us.apache.org/repos/asf/hadoop/blob/f2e62207/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-timelineservice/src/main/java/org/apache/hadoop/yarn/server/timelineservice/reader/TimelineReaderWebServices.java
----------------------------------------------------------------------
diff --git 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-timelineservice/src/main/java/org/apache/hadoop/yarn/server/timelineservice/reader/TimelineReaderWebServices.java
 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-timelineservice/src/main/java/org/apache/hadoop/yarn/server/timelineservice/reader/TimelineReaderWebServices.java
index a054ee5..7a70de8 100644
--- 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-timelineservice/src/main/java/org/apache/hadoop/yarn/server/timelineservice/reader/TimelineReaderWebServices.java
+++ 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-timelineservice/src/main/java/org/apache/hadoop/yarn/server/timelineservice/reader/TimelineReaderWebServices.java
@@ -18,17 +18,12 @@
 
 package org.apache.hadoop.yarn.server.timelineservice.reader;
 
-import java.io.IOException;
 import java.text.DateFormat;
 import java.text.ParseException;
 import java.text.SimpleDateFormat;
 import java.util.Collections;
 import java.util.Date;
-import java.util.EnumSet;
-import java.util.HashMap;
-import java.util.HashSet;
 import java.util.Locale;
-import java.util.Map;
 import java.util.Set;
 import java.util.TimeZone;
 
@@ -51,10 +46,11 @@ import 
org.apache.hadoop.classification.InterfaceAudience.Private;
 import org.apache.hadoop.classification.InterfaceStability.Unstable;
 import org.apache.hadoop.security.UserGroupInformation;
 import org.apache.hadoop.util.Time;
+import org.apache.hadoop.yarn.api.records.timelineservice.FlowActivityEntity;
+import org.apache.hadoop.yarn.api.records.timelineservice.FlowRunEntity;
 import org.apache.hadoop.yarn.api.records.timeline.TimelineAbout;
 import org.apache.hadoop.yarn.api.records.timelineservice.TimelineEntity;
 import org.apache.hadoop.yarn.api.records.timelineservice.TimelineEntityType;
-import org.apache.hadoop.yarn.server.timeline.GenericObjectMapper;
 import 
org.apache.hadoop.yarn.server.timelineservice.storage.TimelineReader.Field;
 import org.apache.hadoop.yarn.util.timeline.TimelineUtils;
 import org.apache.hadoop.yarn.webapp.BadRequestException;
@@ -63,7 +59,7 @@ import org.apache.hadoop.yarn.webapp.NotFoundException;
 import com.google.common.annotations.VisibleForTesting;
 import com.google.inject.Singleton;
 
-/** REST end point for Timeline Reader */
+/** REST end point for Timeline Reader. */
 @Private
 @Unstable
 @Singleton
@@ -167,117 +163,6 @@ public class TimelineReaderWebServices {
     }
   }
 
-  private static Set<String> parseValuesStr(String str, String delimiter) {
-    if (str == null || str.isEmpty()) {
-      return null;
-    }
-    Set<String> strSet = new HashSet<String>();
-    String[] strs = str.split(delimiter);
-    for (String aStr : strs) {
-      strSet.add(aStr.trim());
-    }
-    return strSet;
-  }
-
-  @SuppressWarnings("unchecked")
-  private static <T> void parseKeyValues(Map<String,T> map, String str,
-      String pairsDelim, String keyValuesDelim, boolean stringValue,
-      boolean multipleValues) {
-    String[] pairs = str.split(pairsDelim);
-    for (String pair : pairs) {
-      if (pair == null || pair.trim().isEmpty()) {
-        continue;
-      }
-      String[] pairStrs = pair.split(keyValuesDelim);
-      if (pairStrs.length < 2) {
-        continue;
-      }
-      if (!stringValue) {
-        try {
-          Object value =
-              GenericObjectMapper.OBJECT_READER.readValue(pairStrs[1].trim());
-          map.put(pairStrs[0].trim(), (T) value);
-        } catch (IOException e) {
-          map.put(pairStrs[0].trim(), (T) pairStrs[1].trim());
-        }
-      } else {
-        String key = pairStrs[0].trim();
-        if (multipleValues) {
-          Set<String> values = new HashSet<String>();
-          for (int i = 1; i < pairStrs.length; i++) {
-            values.add(pairStrs[i].trim());
-          }
-          map.put(key, (T) values);
-        } else {
-          map.put(key, (T) pairStrs[1].trim());
-        }
-      }
-    }
-  }
-
-  private static Map<String, Set<String>> parseKeyStrValuesStr(String str,
-      String pairsDelim, String keyValuesDelim) {
-    if (str == null) {
-      return null;
-    }
-    Map<String, Set<String>> map = new HashMap<String, Set<String>>();
-    parseKeyValues(map, str,pairsDelim, keyValuesDelim, true, true);
-    return map;
-  }
-
-  private static Map<String, String> parseKeyStrValueStr(String str,
-      String pairsDelim, String keyValDelim) {
-    if (str == null) {
-      return null;
-    }
-    Map<String, String> map = new HashMap<String, String>();
-    parseKeyValues(map, str, pairsDelim, keyValDelim, true, false);
-    return map;
-  }
-
-  private static Map<String, Object> parseKeyStrValueObj(String str,
-      String pairsDelim, String keyValDelim) {
-    if (str == null) {
-      return null;
-    }
-    Map<String, Object> map = new HashMap<String, Object>();
-    parseKeyValues(map, str, pairsDelim, keyValDelim, false, false);
-    return map;
-  }
-
-  private static EnumSet<Field> parseFieldsStr(String str, String delimiter) {
-    if (str == null) {
-      return null;
-    }
-    String[] strs = str.split(delimiter);
-    EnumSet<Field> fieldList = EnumSet.noneOf(Field.class);
-    for (String s : strs) {
-      fieldList.add(Field.valueOf(s.trim().toUpperCase()));
-    }
-    return fieldList;
-  }
-
-  private static Long parseLongStr(String str) {
-    return str == null ? null : Long.parseLong(str.trim());
-  }
-
-  private static String parseStr(String str) {
-    return str == null ? null : str.trim();
-  }
-
-  private static UserGroupInformation getUser(HttpServletRequest req) {
-    String remoteUser = req.getRemoteUser();
-    UserGroupInformation callerUGI = null;
-    if (remoteUser != null) {
-      callerUGI = UserGroupInformation.createRemoteUser(remoteUser);
-    }
-    return callerUGI;
-  }
-
-  private static String getUserName(UserGroupInformation callerUGI) {
-    return ((callerUGI != null) ? callerUGI.getUserName().trim() : "");
-  }
-
   private TimelineReaderManager getTimelineReaderManager() {
     return (TimelineReaderManager)
         ctxt.getAttribute(TimelineReaderServer.TIMELINE_READER_MANAGER_ATTR);
@@ -294,6 +179,10 @@ public class TimelineReaderWebServices {
     } else if (e instanceof IllegalArgumentException) {
       throw new BadRequestException(e.getMessage() == null ?
           "Requested Invalid Field." : e.getMessage());
+    } else if (e instanceof NotFoundException) {
+      throw (NotFoundException)e;
+    } else if (e instanceof BadRequestException) {
+      throw (BadRequestException)e;
     } else {
       LOG.error("Error while processing REST request", e);
       throw new WebApplicationException(e,
@@ -303,6 +192,11 @@ public class TimelineReaderWebServices {
 
   /**
    * Return the description of the timeline reader web services.
+   *
+   * @param req Servlet request.
+   * @param res Servlet response.
+   *
+   * @return information about the cluster including timeline version.
    */
   @GET
   @Produces(MediaType.APPLICATION_JSON)
@@ -314,11 +208,188 @@ public class TimelineReaderWebServices {
   }
 
   /**
+   * Return a single entity for a given entity type and UID which is a 
delimited
+   * string containing clusterid, userid, flow name, flowrun id and app id.
+   *
+   * @param req Servlet request.
+   * @param res Servlet response.
+   * @param uId a delimited string containing clusterid, userid, flow name,
+   *     flowrun id and app id which are extracted from UID and then used to
+   *     query backend(Mandatory path param).
+   * @param limit Number of entities to return(Optional query param).
+   * @param createdTimeStart If specified, matched entities should not be
+   *     created before this timestamp(Optional query param).
+   * @param createdTimeEnd If specified, matched entities should not be created
+   *     after this timestamp(Optional query param).
+   * @param relatesTo If specified, matched entities should relate to given
+   *     entities associated with a entity type. relatesto is a comma separated
+   *     list in the format [entitytype]:[entityid1]:[entityid2]... (Optional
+   *     query param).
+   * @param isRelatedTo If specified, matched entities should be related to
+   *     given entities associated with a entity type. relatesto is a comma
+   *     separated list in the format [entitytype]:[entityid1]:[entityid2]...
+   *     (Optional query param).
+   * @param infofilters If specified, matched entities should have exact 
matches
+   *     to the given info represented as key-value pairs. This is represented
+   *     as infofilters=info1:value1,info2:value2... (Optional query param).
+   * @param conffilters If specified, matched entities should have exact 
matches
+   *     to the given configs represented as key-value pairs. This is
+   *     represented as conffilters=conf1:value1,conf2:value2... (Optional 
query
+   *     param).
+   * @param metricfilters If specified, matched entities should contain the
+   *     given metrics. This is represented as
+   *     metricfilters=metricid1, metricid2... (Optional query param).
+   * @param eventfilters If specified, matched entities should contain the 
given
+   *     events. This is represented as eventfilters=eventid1, eventid2...
+   * @param fields Specifies which fields of the entity object to retrieve, see
+   *     {@link Field}. All fields will be retrieved if fields=ALL. If not
+   *     specified, 4 fields i.e. entity type, id and created time is returned
+   *     (Optional query param).
+   *
+   * @return If successful, a HTTP 200(OK) response having a JSON representing
+   *     a set of {@link TimelineEntity} instances of the given entity type is
+   *     returned.
+   *     On failures,
+   *     If any problem occurs in parsing request or UID is incorrect,
+   *     HTTP 400(Bad Request) is returned.
+   *     For all other errors while retrieving data, HTTP 500(Internal Server
+   *     Error) is returned.
+   */
+  @GET
+  @Path("/app-uid/{uid}/entities/{entitytype}")
+  @Produces(MediaType.APPLICATION_JSON)
+  public Set<TimelineEntity> getEntities(
+      @Context HttpServletRequest req,
+      @Context HttpServletResponse res,
+      @PathParam("uid") String uId,
+      @PathParam("entitytype") String entityType,
+      @QueryParam("limit") String limit,
+      @QueryParam("createdtimestart") String createdTimeStart,
+      @QueryParam("createdtimeend") String createdTimeEnd,
+      @QueryParam("relatesto") String relatesTo,
+      @QueryParam("isrelatedto") String isRelatedTo,
+      @QueryParam("infofilters") String infofilters,
+      @QueryParam("conffilters") String conffilters,
+      @QueryParam("metricfilters") String metricfilters,
+      @QueryParam("eventfilters") String eventfilters,
+      @QueryParam("fields") String fields) {
+    String url = req.getRequestURI() +
+        (req.getQueryString() == null ? "" :
+            QUERY_STRING_SEP + req.getQueryString());
+    UserGroupInformation callerUGI =
+        TimelineReaderWebServicesUtils.getUser(req);
+    LOG.info("Received URL " + url + " from user " +
+        TimelineReaderWebServicesUtils.getUserName(callerUGI));
+    long startTime = Time.monotonicNow();
+    init(res);
+    TimelineReaderManager timelineReaderManager = getTimelineReaderManager();
+    Set<TimelineEntity> entities = null;
+    try {
+      TimelineReaderContext context =
+          TimelineUIDConverter.APPLICATION_UID.decodeUID(uId);
+      if (context == null) {
+        throw new BadRequestException("Incorrect UID " +  uId);
+      }
+      entities = timelineReaderManager.getEntities(
+          TimelineReaderWebServicesUtils.parseStr(context.getUserId()),
+          TimelineReaderWebServicesUtils.parseStr(context.getClusterId()),
+          TimelineReaderWebServicesUtils.parseStr(context.getFlowName()),
+          context.getFlowRunId(),
+          TimelineReaderWebServicesUtils.parseStr(context.getAppId()),
+          TimelineReaderWebServicesUtils.parseStr(entityType),
+          TimelineReaderWebServicesUtils.parseLongStr(limit),
+          TimelineReaderWebServicesUtils.parseLongStr(createdTimeStart),
+          TimelineReaderWebServicesUtils.parseLongStr(createdTimeEnd),
+          TimelineReaderWebServicesUtils.parseKeyStrValuesStr(
+          relatesTo, COMMA_DELIMITER, COLON_DELIMITER),
+          TimelineReaderWebServicesUtils.parseKeyStrValuesStr(
+          isRelatedTo, COMMA_DELIMITER, COLON_DELIMITER),
+          TimelineReaderWebServicesUtils.parseKeyStrValueObj(
+          infofilters, COMMA_DELIMITER, COLON_DELIMITER),
+          TimelineReaderWebServicesUtils.parseKeyStrValueStr(
+          conffilters, COMMA_DELIMITER, COLON_DELIMITER),
+          TimelineReaderWebServicesUtils.parseValuesStr(
+           metricfilters, COMMA_DELIMITER),
+          TimelineReaderWebServicesUtils.parseValuesStr(
+          eventfilters, COMMA_DELIMITER),
+          TimelineReaderWebServicesUtils.parseFieldsStr(
+          fields, COMMA_DELIMITER));
+    } catch (Exception e) {
+      handleException(e, url, startTime,
+          "createdTime start/end or limit or flowrunid");
+    }
+    long endTime = Time.monotonicNow();
+    if (entities == null) {
+      entities = Collections.emptySet();
+    }
+    LOG.info("Processed URL " + url +
+        " (Took " + (endTime - startTime) + " ms.)");
+    return entities;
+  }
+
+  /**
    * Return a set of entities that match the given parameters. Cluster ID is 
not
-   * provided by client so default cluster ID has to be taken.
+   * provided by client so default cluster ID has to be taken. If userid, flow
+   * name and flowrun id which are optional query parameters are not specified,
+   * they will be queried based on app id and default cluster id from the flow
+   * context information stored in underlying storage implementation. If number
+   * of matching entities are more than the limit, most recent entities till 
the
+   * limit is reached, will be returned.
+   *
+   * @param req Servlet request.
+   * @param res Servlet response.
+   * @param appId Application id to which the entities to be queried belong to(
+   *     Mandatory path param).
+   * @param entityType Type of entities(Mandatory path param).
+   * @param userId User id which should match for the entities(Optional query
+   *     param)
+   * @param flowName Flow name which should match for the entities(Optional
+   *     query param).
+   * @param flowRunId Run id which should match for the entities(Optional query
+   *     param).
+   * @param limit Number of entities to return(Optional query param).
+   * @param createdTimeStart If specified, matched entities should not be
+   *     created before this timestamp(Optional query param).
+   * @param createdTimeEnd If specified, matched entities should not be created
+   *     after this timestamp(Optional query param).
+   * @param relatesTo If specified, matched entities should relate to given
+   *     entities associated with a entity type. relatesto is a comma separated
+   *     list in the format [entitytype]:[entityid1]:[entityid2]... (Optional
+   *     query param).
+   * @param isRelatedTo If specified, matched entities should be related to
+   *     given entities associated with a entity type. relatesto is a comma
+   *     separated list in the format [entitytype]:[entityid1]:[entityid2]...
+   *     (Optional query param).
+   * @param infofilters If specified, matched entities should have exact 
matches
+   *     to the given info represented as key-value pairs. This is represented
+   *     as infofilters=info1:value1,info2:value2... (Optional query param).
+   * @param conffilters If specified, matched entities should have exact 
matches
+   *     to the given configs represented as key-value pairs. This is
+   *     represented as conffilters=conf1:value1,conf2:value2... (Optional 
query
+   *     param).
+   * @param metricfilters If specified, matched entities should contain the
+   *     given metrics. This is represented as
+   *     metricfilters=metricid1, metricid2... (Optional query param).
+   * @param eventfilters If specified, matched entities should contain the 
given
+   *     events. This is represented as eventfilters=eventid1, eventid2...
+   * @param fields Specifies which fields of the entity object to retrieve, see
+   *     {@link Field}. All fields will be retrieved if fields=ALL. If not
+   *     specified, 4 fields i.e. entity type, id, created time is returned
+   *     (Optional query param).
+   *
+   * @return If successful, a HTTP 200(OK) response having a JSON representing
+   *     a set of {@link TimelineEntity} instances of the given entity type is
+   *     returned.
+   *     On failures,
+   *     If any problem occurs in parsing request, HTTP 400(Bad Request) is
+   *     returned.
+   *     If flow context information cannot be retrieved, HTTP 404(Not Found)
+   *     is returned.
+   *     For all other errors while retrieving data, HTTP 500(Internal Server
+   *     Error) is returned.
    */
   @GET
-  @Path("/entities/{appid}/{entitytype}/")
+  @Path("/apps/{appid}/entities/{entitytype}")
   @Produces(MediaType.APPLICATION_JSON)
   public Set<TimelineEntity> getEntities(
       @Context HttpServletRequest req,
@@ -337,7 +408,7 @@ public class TimelineReaderWebServices {
       @QueryParam("conffilters") String conffilters,
       @QueryParam("metricfilters") String metricfilters,
       @QueryParam("eventfilters") String eventfilters,
-       @QueryParam("fields") String fields) {
+      @QueryParam("fields") String fields) {
     return getEntities(req, res, null, appId, entityType, userId, flowName,
         flowRunId, limit, createdTimeStart, createdTimeEnd, relatesTo,
         isRelatedTo, infofilters, conffilters, metricfilters, eventfilters,
@@ -345,10 +416,69 @@ public class TimelineReaderWebServices {
   }
 
   /**
-   * Return a set of entities that match the given parameters.
+   * Return a set of entities that match the given parameters. If userid, flow
+   * name and flowrun id which are optional query parameters are not specified,
+   * they will be queried based on app id and cluster id from the flow context
+   * information stored in underlying storage implementation. If number of
+   * matching entities are more than the limit, most recent entities till the
+   * limit is reached, will be returned.
+   *
+   * @param req Servlet request.
+   * @param res Servlet response.
+   * @param clusterId Cluster id to which the entities to be queried belong to(
+   *     Mandatory path param).
+   * @param appId Application id to which the entities to be queried belong to(
+   *     Mandatory path param).
+   * @param entityType Type of entities(Mandatory path param).
+   * @param userId User id which should match for the entities(Optional query
+   *     param)
+   * @param flowName Flow name which should match for the entities(Optional
+   *     query param).
+   * @param flowRunId Run id which should match for the entities(Optional query
+   *     param).
+   * @param limit Number of entities to return(Optional query param).
+   * @param createdTimeStart If specified, matched entities should not be
+   *     created before this timestamp(Optional query param).
+   * @param createdTimeEnd If specified, matched entities should not be created
+   *     after this timestamp(Optional query param).
+   * @param relatesTo If specified, matched entities should relate to given
+   *     entities associated with a entity type. relatesto is a comma separated
+   *     list in the format [entitytype]:[entityid1]:[entityid2]... (Optional
+   *     query param).
+   * @param isRelatedTo If specified, matched entities should be related to
+   *     given entities associated with a entity type. relatesto is a comma
+   *     separated list in the format [entitytype]:[entityid1]:[entityid2]...
+   *     (Optional query param).
+   * @param infofilters If specified, matched entities should have exact 
matches
+   *     to the given info represented as key-value pairs. This is represented
+   *     as infofilters=info1:value1,info2:value2... (Optional query param).
+   * @param conffilters If specified, matched entities should have exact 
matches
+   *     to the given configs represented as key-value pairs. This is
+   *     represented as conffilters=conf1:value1,conf2:value2... (Optional 
query
+   *     param).
+   * @param metricfilters If specified, matched entities should contain the
+   *     given metrics. This is represented as
+   *     metricfilters=metricid1, metricid2... (Optional query param).
+   * @param eventfilters If specified, matched entities should contain the 
given
+   *     events. This is represented as eventfilters=eventid1, eventid2...
+   * @param fields Specifies which fields of the entity object to retrieve, see
+   *     {@link Field}. All fields will be retrieved if fields=ALL. If not
+   *     specified, 4 fields i.e. entity type, id, created time is returned
+   *     (Optional query param).
+   *
+   * @return If successful, a HTTP 200(OK) response having a JSON representing
+   *     a set of {@link TimelineEntity} instances of the given entity type is
+   *     returned.
+   *     On failures,
+   *     If any problem occurs in parsing request, HTTP 400(Bad Request) is
+   *     returned.
+   *     If flow context information cannot be retrieved, HTTP 404(Not Found)
+   *     is returned.
+   *     For all other errors while retrieving data, HTTP 500(Internal Server
+   *     Error) is returned.
    */
   @GET
-  @Path("/entities/{clusterid}/{appid}/{entitytype}/")
+  @Path("/clusters/{clusterid}/apps/{appid}/entities/{entitytype}")
   @Produces(MediaType.APPLICATION_JSON)
   public Set<TimelineEntity> getEntities(
       @Context HttpServletRequest req,
@@ -372,25 +502,39 @@ public class TimelineReaderWebServices {
     String url = req.getRequestURI() +
         (req.getQueryString() == null ? "" :
             QUERY_STRING_SEP + req.getQueryString());
-    UserGroupInformation callerUGI = getUser(req);
-    LOG.info("Received URL " + url + " from user " + getUserName(callerUGI));
+    UserGroupInformation callerUGI =
+        TimelineReaderWebServicesUtils.getUser(req);
+    LOG.info("Received URL " + url + " from user " +
+        TimelineReaderWebServicesUtils.getUserName(callerUGI));
     long startTime = Time.monotonicNow();
     init(res);
     TimelineReaderManager timelineReaderManager = getTimelineReaderManager();
     Set<TimelineEntity> entities = null;
     try {
       entities = timelineReaderManager.getEntities(
-          parseStr(userId), parseStr(clusterId), parseStr(flowName),
-          parseLongStr(flowRunId), parseStr(appId), parseStr(entityType),
-          parseLongStr(limit), parseLongStr(createdTimeStart),
-          parseLongStr(createdTimeEnd),
-          parseKeyStrValuesStr(relatesTo, COMMA_DELIMITER, COLON_DELIMITER),
-          parseKeyStrValuesStr(isRelatedTo, COMMA_DELIMITER, COLON_DELIMITER),
-          parseKeyStrValueObj(infofilters, COMMA_DELIMITER, COLON_DELIMITER),
-          parseKeyStrValueStr(conffilters, COMMA_DELIMITER, COLON_DELIMITER),
-          parseValuesStr(metricfilters, COMMA_DELIMITER),
-          parseValuesStr(eventfilters, COMMA_DELIMITER),
-          parseFieldsStr(fields, COMMA_DELIMITER));
+          TimelineReaderWebServicesUtils.parseStr(userId),
+          TimelineReaderWebServicesUtils.parseStr(clusterId),
+          TimelineReaderWebServicesUtils.parseStr(flowName),
+          TimelineReaderWebServicesUtils.parseLongStr(flowRunId),
+          TimelineReaderWebServicesUtils.parseStr(appId),
+          TimelineReaderWebServicesUtils.parseStr(entityType),
+          TimelineReaderWebServicesUtils.parseLongStr(limit),
+          TimelineReaderWebServicesUtils.parseLongStr(createdTimeStart),
+          TimelineReaderWebServicesUtils.parseLongStr(createdTimeEnd),
+          TimelineReaderWebServicesUtils.parseKeyStrValuesStr(
+          relatesTo, COMMA_DELIMITER, COLON_DELIMITER),
+          TimelineReaderWebServicesUtils.parseKeyStrValuesStr(
+          isRelatedTo, COMMA_DELIMITER, COLON_DELIMITER),
+          TimelineReaderWebServicesUtils.parseKeyStrValueObj(
+          infofilters, COMMA_DELIMITER, COLON_DELIMITER),
+          TimelineReaderWebServicesUtils.parseKeyStrValueStr(
+          conffilters, COMMA_DELIMITER, COLON_DELIMITER),
+          TimelineReaderWebServicesUtils.parseValuesStr(
+          metricfilters, COMMA_DELIMITER),
+          TimelineReaderWebServicesUtils.parseValuesStr(
+          eventfilters, COMMA_DELIMITER),
+          TimelineReaderWebServicesUtils.parseFieldsStr(
+          fields, COMMA_DELIMITER));
     } catch (Exception e) {
       handleException(e, url, startTime,
           "createdTime start/end or limit or flowrunid");
@@ -405,11 +549,110 @@ public class TimelineReaderWebServices {
   }
 
   /**
+   * Return a single entity for given UID which is a delimited string 
containing
+   * clusterid, userid, flow name, flowrun id, app id, entity type and 
entityid.
+   *
+   * @param req Servlet request.
+   * @param res Servlet response.
+   * @param uId a delimited string containing clusterid, userid, flow name,
+   *     flowrun id, app id, entity type and entity id which are extracted from
+   *     UID and then used to query backend(Mandatory path param).
+   * @param fields Specifies which fields of the entity object to retrieve, see
+   *     {@link Field}. All fields will be retrieved if fields=ALL. If not
+   *     specified, 4 fields i.e. entity type, id, created time is returned
+   *     (Optional query param).
+   *
+   * @return If successful, a HTTP 200(OK) response having a JSON representing 
a
+   *     {@link TimelineEntity} instance is returned.
+   *     On failures,
+   *     If any problem occurs in parsing request or UID is incorrect,
+   *     HTTP 400(Bad Request) is returned.
+   *     If entity for the given entity id cannot be found, HTTP 404(Not Found)
+   *     is returned.
+   *     For all other errors while retrieving data, HTTP 500(Internal Server
+   *     Error) is returned.
+   */
+  @GET
+  @Path("/entity-uid/{uid}/")
+  @Produces(MediaType.APPLICATION_JSON)
+  public TimelineEntity getEntity(
+      @Context HttpServletRequest req,
+      @Context HttpServletResponse res,
+      @PathParam("uid") String uId,
+      @QueryParam("fields") String fields) {
+    String url = req.getRequestURI() +
+        (req.getQueryString() == null ? "" :
+            QUERY_STRING_SEP + req.getQueryString());
+    UserGroupInformation callerUGI =
+        TimelineReaderWebServicesUtils.getUser(req);
+    LOG.info("Received URL " + url + " from user " +
+        TimelineReaderWebServicesUtils.getUserName(callerUGI));
+    long startTime = Time.monotonicNow();
+    init(res);
+    TimelineReaderManager timelineReaderManager = getTimelineReaderManager();
+    TimelineEntity entity = null;
+    try {
+      TimelineReaderContext context =
+          TimelineUIDConverter.GENERIC_ENTITY_UID.decodeUID(uId);
+      if (context == null) {
+        throw new BadRequestException("Incorrect UID " +  uId);
+      }
+      entity = timelineReaderManager.getEntity(context.getUserId(),
+          context.getClusterId(), context.getFlowName(), 
context.getFlowRunId(),
+          context.getAppId(), context.getEntityType(), context.getEntityId(),
+          TimelineReaderWebServicesUtils.parseFieldsStr(
+          fields, COMMA_DELIMITER));
+    } catch (Exception e) {
+      handleException(e, url, startTime, "flowrunid");
+    }
+    long endTime = Time.monotonicNow();
+    if (entity == null) {
+      LOG.info("Processed URL " + url + " but entity not found" + " (Took " +
+          (endTime - startTime) + " ms.)");
+      throw new NotFoundException("Timeline entity with uid: " + uId +
+          "is not found");
+    }
+    LOG.info("Processed URL " + url +
+        " (Took " + (endTime - startTime) + " ms.)");
+    return entity;
+  }
+
+  /**
    * Return a single entity of the given entity type and Id. Cluster ID is not
-   * provided by client so default cluster ID has to be taken.
+   * provided by client so default cluster ID has to be taken. If userid, flow
+   * name and flowrun id which are optional query parameters are not specified,
+   * they will be queried based on app id and default cluster id from the flow
+   * context information stored in underlying storage implementation.
+   *
+   * @param req Servlet request.
+   * @param res Servlet response.
+   * @param appId Application id to which the entity to be queried belongs to(
+   *     Mandatory path param).
+   * @param entityType Type of entity(Mandatory path param).
+   * @param entityId Id of the entity to be fetched(Mandatory path param).
+   * @param userId User id which should match for the entity(Optional query
+   *     param).
+   * @param flowName Flow name which should match for the entity(Optional query
+   *     param).
+   * @param flowRunId Run id which should match for the entity(Optional query
+   *     param).
+   * @param fields Specifies which fields of the entity object to retrieve, see
+   *     {@link Field}. All fields will be retrieved if fields=ALL. If not
+   *     specified, 4 fields i.e. entity type, id, created time is returned
+   *     (Optional query param).
+   *
+   * @return If successful, a HTTP 200(OK) response having a JSON representing 
a
+   *     {@link TimelineEntity} instance is returned.
+   *     On failures,
+   *     If any problem occurs in parsing request, HTTP 400(Bad Request) is
+   *     returned.
+   *     If flow context information cannot be retrieved or entity for the 
given
+   *     entity id cannot be found, HTTP 404(Not Found) is returned.
+   *     For all other errors while retrieving data, HTTP 500(Internal Server
+   *     Error) is returned.
    */
   @GET
-  @Path("/entity/{appid}/{entitytype}/{entityid}/")
+  @Path("/apps/{appid}/entities/{entitytype}/{entityid}/")
   @Produces(MediaType.APPLICATION_JSON)
   public TimelineEntity getEntity(
       @Context HttpServletRequest req,
@@ -426,10 +669,42 @@ public class TimelineReaderWebServices {
   }
 
   /**
-   * Return a single entity of the given entity type and Id.
+   * Return a single entity of the given entity type and Id. If userid, 
flowname
+   * and flowrun id which are optional query parameters are not specified, they
+   * will be queried based on app id and cluster id from the flow context
+   * information stored in underlying storage implementation.
+   *
+   * @param req Servlet request.
+   * @param res Servlet response.
+   * @param clusterId Cluster id to which the entity to be queried belongs to(
+   *     Mandatory path param).
+   * @param appId Application id to which the entity to be queried belongs to(
+   *     Mandatory path param).
+   * @param entityType Type of entity(Mandatory path param).
+   * @param entityId Id of the entity to be fetched(Mandatory path param).
+   * @param userId User id which should match for the entity(Optional query
+   *     param).
+   * @param flowName Flow name which should match for the entity(Optional query
+   *     param).
+   * @param flowRunId Run id which should match for the entity(Optional query
+   *     param).
+   * @param fields Specifies which fields of the entity object to retrieve, see
+   *     {@link Field}. All fields will be retrieved if fields=ALL. If not
+   *     specified, 4 fields i.e. entity type, id and created time is returned
+   *     (Optional query param).
+   *
+   * @return If successful, a HTTP 200(OK) response having a JSON representing 
a
+   *     {@link TimelineEntity} instance is returned.
+   *     On failures,
+   *     If any problem occurs in parsing request, HTTP 400(Bad Request) is
+   *     returned.
+   *     If flow context information cannot be retrieved or entity for the 
given
+   *     entity id cannot be found, HTTP 404(Not Found) is returned.
+   *     For all other errors while retrieving data, HTTP 500(Internal Server
+   *     Error) is returned.
    */
   @GET
-  @Path("/entity/{clusterid}/{appid}/{entitytype}/{entityid}/")
+  @Path("/clusters/{clusterid}/apps/{appid}/entities/{entitytype}/{entityid}/")
   @Produces(MediaType.APPLICATION_JSON)
   public TimelineEntity getEntity(
       @Context HttpServletRequest req,
@@ -445,17 +720,25 @@ public class TimelineReaderWebServices {
     String url = req.getRequestURI() +
         (req.getQueryString() == null ? "" :
             QUERY_STRING_SEP + req.getQueryString());
-    UserGroupInformation callerUGI = getUser(req);
-    LOG.info("Received URL " + url + " from user " + getUserName(callerUGI));
+    UserGroupInformation callerUGI =
+        TimelineReaderWebServicesUtils.getUser(req);
+    LOG.info("Received URL " + url + " from user " +
+        TimelineReaderWebServicesUtils.getUserName(callerUGI));
     long startTime = Time.monotonicNow();
     init(res);
     TimelineReaderManager timelineReaderManager = getTimelineReaderManager();
     TimelineEntity entity = null;
+    String type = TimelineReaderWebServicesUtils.parseStr(entityType);
+    String id = TimelineReaderWebServicesUtils.parseStr(entityId);
     try {
       entity = timelineReaderManager.getEntity(
-          parseStr(userId), parseStr(clusterId), parseStr(flowName),
-          parseLongStr(flowRunId), parseStr(appId), parseStr(entityType),
-          parseStr(entityId), parseFieldsStr(fields, COMMA_DELIMITER));
+          TimelineReaderWebServicesUtils.parseStr(userId),
+          TimelineReaderWebServicesUtils.parseStr(clusterId),
+          TimelineReaderWebServicesUtils.parseStr(flowName),
+          TimelineReaderWebServicesUtils.parseLongStr(flowRunId),
+          TimelineReaderWebServicesUtils.parseStr(appId), type, id,
+          TimelineReaderWebServicesUtils.parseFieldsStr(
+          fields, COMMA_DELIMITER));
     } catch (Exception e) {
       handleException(e, url, startTime, "flowrunid");
     }
@@ -463,8 +746,8 @@ public class TimelineReaderWebServices {
     if (entity == null) {
       LOG.info("Processed URL " + url + " but entity not found" + " (Took " +
           (endTime - startTime) + " ms.)");
-      throw new NotFoundException("Timeline entity {id: " + parseStr(entityId) 
+
-          ", type: " + parseStr(entityType) + " } is not found");
+      throw new NotFoundException("Timeline entity {id: " + id + ", type: " +
+          type + " } is not found");
     }
     LOG.info("Processed URL " + url +
         " (Took " + (endTime - startTime) + " ms.)");
@@ -472,50 +755,155 @@ public class TimelineReaderWebServices {
   }
 
   /**
-   * Return a single flow run for the given user, flow id and run id.
+   * Return a single flow run for given UID which is a delimited string
+   * containing clusterid, userid, flow name and flowrun id.
+   *
+   * @param req Servlet request.
+   * @param res Servlet response.
+   * @param uId a delimited string containing clusterid, userid, flow name and
+   *     flowrun id which are extracted from UID and then used to query backend
+   *     (Mandatory path param).
+   *
+   * @return If successful, a HTTP 200(OK) response having a JSON representing 
a
+   *     {@link FlowRunEntity} instance is returned. By default, all metrics 
for
+   *     the flow run will be returned.
+   *     On failures,
+   *     If any problem occurs in parsing request or UID is incorrect,
+   *     HTTP 400(Bad Request) is returned.
+   *     If flow run for the given flow run id cannot be found, HTTP 404
+   *     (Not Found) is returned.
+   *     For all other errors while retrieving data, HTTP 500(Internal Server
+   *     Error) is returned.
+   */
+  @GET
+  @Path("/run-uid/{uid}/")
+  @Produces(MediaType.APPLICATION_JSON)
+  public TimelineEntity getFlowRun(
+      @Context HttpServletRequest req,
+      @Context HttpServletResponse res,
+      @PathParam("uid") String uId) {
+    String url = req.getRequestURI() +
+        (req.getQueryString() == null ? "" :
+            QUERY_STRING_SEP + req.getQueryString());
+    UserGroupInformation callerUGI =
+        TimelineReaderWebServicesUtils.getUser(req);
+    LOG.info("Received URL " + url + " from user " +
+        TimelineReaderWebServicesUtils.getUserName(callerUGI));
+    long startTime = Time.monotonicNow();
+    init(res);
+    TimelineReaderManager timelineReaderManager = getTimelineReaderManager();
+    TimelineEntity entity = null;
+    try {
+      TimelineReaderContext context =
+          TimelineUIDConverter.FLOWRUN_UID.decodeUID(uId);
+      if (context == null) {
+        throw new BadRequestException("Incorrect UID " +  uId);
+      }
+      entity = timelineReaderManager.getEntity(context.getUserId(),
+          context.getClusterId(), context.getFlowName(), 
context.getFlowRunId(),
+          null, TimelineEntityType.YARN_FLOW_RUN.toString(), null, null);
+    } catch (Exception e) {
+      handleException(e, url, startTime, "flowrunid");
+    }
+    long endTime = Time.monotonicNow();
+    if (entity == null) {
+      LOG.info("Processed URL " + url + " but flowrun not found (Took " +
+          (endTime - startTime) + " ms.)");
+      throw new NotFoundException("Flowrun with uid: " + uId + "is not found");
+    }
+    LOG.info("Processed URL " + url +
+        " (Took " + (endTime - startTime) + " ms.)");
+    return entity;
+  }
+
+  /**
+   * Return a single flow run for the given user, flow name and run id.
    * Cluster ID is not provided by client so default cluster ID has to be 
taken.
+   *
+   * @param req Servlet request.
+   * @param res Servlet response.
+   * @param userId User id representing the user who ran the flow run(Mandatory
+   *     path param).
+   * @param flowName Flow name to which the flow run to be queried belongs to(
+   *     Mandatory path param).
+   * @param flowRunId Id of the flow run to be queried(Mandatory path param).
+   *
+   * @return If successful, a HTTP 200(OK) response having a JSON representing 
a
+   *     {@link FlowRunEntity} instance is returned. By default, all metrics 
for
+   *     the flow run will be returned.
+   *     On failures,
+   *     If any problem occurs in parsing request, HTTP 400(Bad Request) is
+   *     returned.
+   *     If flow run for the given flow run id cannot be found, HTTP 404
+   *     (Not Found) is returned.
+   *     For all other errors while retrieving data, HTTP 500(Internal Server
+   *     Error) is returned.
    */
   @GET
-  @Path("/flowrun/{userid}/{flowname}/{flowrunid}/")
+  @Path("/users/{userid}/flows/{flowname}/runs/{flowrunid}/")
   @Produces(MediaType.APPLICATION_JSON)
   public TimelineEntity getFlowRun(
       @Context HttpServletRequest req,
       @Context HttpServletResponse res,
       @PathParam("userid") String userId,
       @PathParam("flowname") String flowName,
-      @PathParam("flowrunid") String flowRunId,
-      @QueryParam("fields") String fields) {
-    return getFlowRun(req, res, userId, null, flowName, flowRunId, fields);
+      @PathParam("flowrunid") String flowRunId) {
+    return getFlowRun(req, res, null, userId, flowName, flowRunId);
   }
 
   /**
-   * Return a single flow run for the given user, cluster, flow id and run id.
+   * Return a single flow run for the given user, cluster, flow name and run 
id.
+   *
+   * @param req Servlet request.
+   * @param res Servlet response.
+   * @param clusterId Cluster id to which the flow run to be queried belong to(
+   *     Mandatory path param).
+   * @param userId User id representing the user who ran the flow run(Mandatory
+   *     path param).
+   * @param flowName Flow name to which the flow run to be queried belongs to(
+   *     Mandatory path param).
+   * @param flowRunId Id of the flow run to be queried(Mandatory path param).
+   *
+   * @return If successful, a HTTP 200(OK) response having a JSON representing 
a
+   *     {@link FlowRunEntity} instance is returned. By default, all metrics 
for
+   *     the flow run will be returned.
+   *     On failures,
+   *     If any problem occurs in parsing request, HTTP 400(Bad Request) is
+   *     returned.
+   *     If flow run for the given flow run id cannot be found, HTTP 404
+   *     (Not Found) is returned.
+   *     For all other errors while retrieving data, HTTP 500(Internal Server
+   *     Error) is returned.
    */
   @GET
-  @Path("/flowrun/{userid}/{clusterid}/{flowname}/{flowrunid}/")
+  @Path("/clusters/{clusterid}/users/{userid}/flows/{flowname}/"
+      + "runs/{flowrunid}/")
   @Produces(MediaType.APPLICATION_JSON)
   public TimelineEntity getFlowRun(
       @Context HttpServletRequest req,
       @Context HttpServletResponse res,
-      @PathParam("userid") String userId,
       @PathParam("clusterid") String clusterId,
+      @PathParam("userid") String userId,
       @PathParam("flowname") String flowName,
-      @PathParam("flowrunid") String flowRunId,
-      @QueryParam("fields") String fields) {
+      @PathParam("flowrunid") String flowRunId) {
     String url = req.getRequestURI() +
         (req.getQueryString() == null ? "" :
             QUERY_STRING_SEP + req.getQueryString());
-    UserGroupInformation callerUGI = getUser(req);
-    LOG.info("Received URL " + url + " from user " + getUserName(callerUGI));
+    UserGroupInformation callerUGI =
+        TimelineReaderWebServicesUtils.getUser(req);
+    LOG.info("Received URL " + url + " from user " +
+        TimelineReaderWebServicesUtils.getUserName(callerUGI));
     long startTime = Time.monotonicNow();
     init(res);
     TimelineReaderManager timelineReaderManager = getTimelineReaderManager();
     TimelineEntity entity = null;
     try {
-      entity = timelineReaderManager.getEntity(parseStr(userId),
-          parseStr(clusterId), parseStr(flowName), parseLongStr(flowRunId), 
null,
-          TimelineEntityType.YARN_FLOW_RUN.toString(), null,
-          parseFieldsStr(fields, COMMA_DELIMITER));
+      entity = timelineReaderManager.getEntity(
+          TimelineReaderWebServicesUtils.parseStr(userId),
+          TimelineReaderWebServicesUtils.parseStr(clusterId),
+          TimelineReaderWebServicesUtils.parseStr(flowName),
+          TimelineReaderWebServicesUtils.parseLongStr(flowRunId),
+          null, TimelineEntityType.YARN_FLOW_RUN.toString(), null, null);
     } catch (Exception e) {
       handleException(e, url, startTime, "flowrunid");
     }
@@ -523,8 +911,10 @@ public class TimelineReaderWebServices {
     if (entity == null) {
       LOG.info("Processed URL " + url + " but flowrun not found (Took " +
           (endTime - startTime) + " ms.)");
-      throw new NotFoundException("Flow run {flow id: " + parseStr(flowName) +
-          ", run id: " + parseLongStr(flowRunId) + " } is not found");
+      throw new NotFoundException("Flow run {flow name: " +
+          TimelineReaderWebServicesUtils.parseStr(flowName) + ", run id: " +
+          TimelineReaderWebServicesUtils.parseLongStr(flowRunId) +
+          " } is not found");
     }
     LOG.info("Processed URL " + url +
         " (Took " + (endTime - startTime) + " ms.)");
@@ -532,11 +922,112 @@ public class TimelineReaderWebServices {
   }
 
   /**
-   * Return a set of flows runs for the given user and flow id.
+   * Return a list of flow runs for given UID which is a delimited string
+   * containing clusterid, userid and flow name.
+   *
+   * @param req Servlet request.
+   * @param res Servlet response.
+   * @param uId a delimited string containing clusterid, userid, and flow name
+   *     which are extracted from UID and then used to query backend(Mandatory
+   *     path param).
+   * @param flowName Flow name to which the flow runs to be queried belongs to(
+   *     Mandatory path param).
+   * @param limit Number of flow runs to return(Optional query param).
+   * @param createdTimeStart If specified, matched flow runs should not be
+   *     created before this timestamp(Optional query param).
+   * @param createdTimeEnd If specified, matched flow runs should not be 
created
+   *     after this timestamp(Optional query param).
+   * @param fields Specifies which fields to retrieve, see {@link Field}.
+   *     All fields will be retrieved if fields=ALL. Fields other than METRICS
+   *     have no meaning for this REST endpoint. If not specified, all fields
+   *     other than metrics are returned(Optional query param).
+   *
+   * @return If successful, a HTTP 200(OK) response having a JSON representing 
a
+   *     set of {@link FlowRunEntity} instances for the given flow are 
returned.
+   *     On failures,
+   *     If any problem occurs in parsing request or UID is incorrect,
+   *     HTTP 400(Bad Request) is returned.
+   *     For all other errors while retrieving data, HTTP 500(Internal Server
+   *     Error) is returned.
+   */
+  @GET
+  @Path("/flow-uid/{uid}/runs/")
+  @Produces(MediaType.APPLICATION_JSON)
+  public Set<TimelineEntity> getFlowRuns(
+      @Context HttpServletRequest req,
+      @Context HttpServletResponse res,
+      @PathParam("uid") String uId,
+      @QueryParam("limit") String limit,
+      @QueryParam("createdtimestart") String createdTimeStart,
+      @QueryParam("createdtimeend") String createdTimeEnd,
+      @QueryParam("fields") String fields) {
+    String url = req.getRequestURI() +
+        (req.getQueryString() == null ? "" :
+            QUERY_STRING_SEP + req.getQueryString());
+    UserGroupInformation callerUGI =
+        TimelineReaderWebServicesUtils.getUser(req);
+    LOG.info("Received URL " + url + " from user " +
+        TimelineReaderWebServicesUtils.getUserName(callerUGI));
+    long startTime = Time.monotonicNow();
+    init(res);
+    TimelineReaderManager timelineReaderManager = getTimelineReaderManager();
+    Set<TimelineEntity> entities = null;
+    try {
+      TimelineReaderContext context =
+          TimelineUIDConverter.FLOW_UID.decodeUID(uId);
+      if (context == null) {
+        throw new BadRequestException("Incorrect UID " +  uId);
+      }
+      entities = timelineReaderManager.getEntities(context.getUserId(),
+          context.getClusterId(), context.getFlowName(), null, null,
+          TimelineEntityType.YARN_FLOW_RUN.toString(),
+          TimelineReaderWebServicesUtils.parseLongStr(limit),
+          TimelineReaderWebServicesUtils.parseLongStr(createdTimeStart),
+          TimelineReaderWebServicesUtils.parseLongStr(createdTimeEnd),
+          null, null, null, null, null, null, TimelineReaderWebServicesUtils.
+          parseFieldsStr(fields, COMMA_DELIMITER));
+    } catch (Exception e) {
+      handleException(e, url, startTime, "createdTime start/end or limit");
+    }
+    long endTime = Time.monotonicNow();
+    if (entities == null) {
+      entities = Collections.emptySet();
+    }
+    LOG.info("Processed URL " + url +
+        " (Took " + (endTime - startTime) + " ms.)");
+    return entities;
+  }
+
+  /**
+   * Return a set of flows runs for the given user and flow name.
    * Cluster ID is not provided by client so default cluster ID has to be 
taken.
+   *
+   * @param req Servlet request.
+   * @param res Servlet response.
+   * @param userId User id representing the user who ran the flow runs(
+   *     Mandatory path param)
+   * @param flowName Flow name to which the flow runs to be queried belongs to(
+   *     Mandatory path param).
+   * @param limit Number of flow runs to return(Optional query param).
+   * @param createdTimeStart If specified, matched flow runs should not be
+   *     created before this timestamp(Optional query param).
+   * @param createdTimeEnd If specified, matched flow runs should not be 
created
+   *     after this timestamp(Optional query param).
+   * @param fields Specifies which fields to retrieve, see {@link Field}.
+   *     All fields will be retrieved if fields=ALL. Fields other than METRICS
+   *     have no meaning for this REST endpoint. If not specified, all fields
+   *     other than metrics are returned(Optional query param).
+   *
+   * @return If successful, a HTTP 200(OK) response having a JSON representing 
a
+   *     set of {@link FlowRunEntity} instances for the given flow are 
returned.
+   *     On failures,
+   *     If any problem occurs in parsing request, HTTP 400(Bad Request) is
+   *     returned.
+   *     For all other errors while retrieving data, HTTP 500(Internal Server
+   *     Error) is returned.
    */
   @GET
-  @Path("/flowruns/{userid}/{flowname}/")
+  @Path("/users/{userid}/flows/{flowname}/runs/")
   @Produces(MediaType.APPLICATION_JSON)
   public Set<TimelineEntity> getFlowRuns(
       @Context HttpServletRequest req,
@@ -547,21 +1038,47 @@ public class TimelineReaderWebServices {
       @QueryParam("createdtimestart") String createdTimeStart,
       @QueryParam("createdtimeend") String createdTimeEnd,
       @QueryParam("fields") String fields) {
-    return getFlowRuns(req, res, userId, null, flowName, limit, 
createdTimeStart,
-        createdTimeEnd, fields);
+    return getFlowRuns(req, res, null, userId, flowName, limit,
+        createdTimeStart, createdTimeEnd, fields);
   }
 
   /**
-   * Return a set of flow runs for the given user, cluster and flow id.
+   * Return a set of flows runs for the given cluster, user and flow name.
+   *
+   * @param req Servlet request.
+   * @param res Servlet response.
+   * @param clusterId Cluster id to which the flow runs to be queried belong 
to(
+   *     Mandatory path param).
+   * @param userId User id representing the user who ran the flow runs(
+   *     Mandatory path param)
+   * @param flowName Flow name to which the flow runs to be queried belongs to(
+   *     Mandatory path param).
+   * @param limit Number of flow runs to return(Optional query param).
+   * @param createdTimeStart If specified, matched flow runs should not be
+   *     created before this timestamp(Optional query param).
+   * @param createdTimeEnd If specified, matched flow runs should not be 
created
+   *     after this timestamp(Optional query param).
+   * @param fields Specifies which fields to retrieve, see {@link Field}.
+   *     All fields will be retrieved if fields=ALL. Fields other than METRICS
+   *     have no meaning for this REST endpoint. If not specified, all fields
+   *     other than metrics are returned(Optional query param).
+   *
+   * @return If successful, a HTTP 200(OK) response having a JSON representing 
a
+   *     set of {@link FlowRunEntity} instances for the given flow are 
returned.
+   *     On failures,
+   *     If any problem occurs in parsing request, HTTP 400(Bad Request) is
+   *     returned.
+   *     For all other errors while retrieving data, HTTP 500(Internal Server
+   *     Error) is returned.
    */
   @GET
-  @Path("/flowruns/{userid}/{clusterid}/{flowname}/")
+  @Path("/clusters/{clusterid}/users/{userid}/flows/{flowname}/runs/")
   @Produces(MediaType.APPLICATION_JSON)
   public Set<TimelineEntity> getFlowRuns(
       @Context HttpServletRequest req,
       @Context HttpServletResponse res,
-      @PathParam("userid") String userId,
       @PathParam("clusterid") String clusterId,
+      @PathParam("userid") String userId,
       @PathParam("flowname") String flowName,
       @QueryParam("limit") String limit,
       @QueryParam("createdtimestart") String createdTimeStart,
@@ -570,18 +1087,24 @@ public class TimelineReaderWebServices {
     String url = req.getRequestURI() +
         (req.getQueryString() == null ? "" :
             QUERY_STRING_SEP + req.getQueryString());
-    UserGroupInformation callerUGI = getUser(req);
-    LOG.info("Received URL " + url + " from user " + getUserName(callerUGI));
+    UserGroupInformation callerUGI =
+        TimelineReaderWebServicesUtils.getUser(req);
+    LOG.info("Received URL " + url + " from user " +
+        TimelineReaderWebServicesUtils.getUserName(callerUGI));
     long startTime = Time.monotonicNow();
     init(res);
     TimelineReaderManager timelineReaderManager = getTimelineReaderManager();
     Set<TimelineEntity> entities = null;
     try {
       entities = timelineReaderManager.getEntities(
-          parseStr(userId), parseStr(clusterId), parseStr(flowName), null, 
null,
-          TimelineEntityType.YARN_FLOW_RUN.toString(), parseLongStr(limit),
-          parseLongStr(createdTimeStart), parseLongStr(createdTimeEnd),
-          null, null, null, null, null, null,
+          TimelineReaderWebServicesUtils.parseStr(userId),
+          TimelineReaderWebServicesUtils.parseStr(clusterId),
+          TimelineReaderWebServicesUtils.parseStr(flowName), null, null,
+          TimelineEntityType.YARN_FLOW_RUN.toString(),
+          TimelineReaderWebServicesUtils.parseLongStr(limit),
+          TimelineReaderWebServicesUtils.parseLongStr(createdTimeStart),
+          TimelineReaderWebServicesUtils.parseLongStr(createdTimeEnd),
+          null, null, null, null, null, null, TimelineReaderWebServicesUtils.
           parseFieldsStr(fields, COMMA_DELIMITER));
     } catch (Exception e) {
       handleException(e, url, startTime, "createdTime start/end or limit");
@@ -596,20 +1119,35 @@ public class TimelineReaderWebServices {
   }
 
   /**
-   * Return a list of flows. Cluster ID is not provided by client so default
-   * cluster ID has to be taken. daterange, if specified is given as
-   * "[startdate]-[enddate]"(i.e. start and end date separated by -) or
-   * single date. Dates are interpreted in yyyyMMdd format and are assumed to
-   * be in GMT. If a single date is specified, all flows active on that date 
are
-   * returned. If both startdate and enddate is given, all flows active between
-   * start and end date will be returned. If only startdate is given, flows
-   * active on and after startdate are returned. If only enddate is given, 
flows
-   * active on and before enddate are returned.
-   * For example :
-   * "daterange=20150711" returns flows active on 20150711.
-   * "daterange=20150711-20150714" returns flows active between these 2 dates.
-   * "daterange=20150711-" returns flows active on and after 20150711.
-   * "daterange=-20150711" returns flows active on and before 20150711.
+   * Return a list of active flows. Cluster ID is not provided by client so
+   * default cluster ID has to be taken.
+   *
+   * @param req Servlet request.
+   * @param res Servlet response.
+   * @param limit Number of flows to return(Optional query param).
+   * @param dateRange If specified is given as "[startdate]-[enddate]"(i.e.
+   *     start and end date separated by "-") or single date. Dates are
+   *     interpreted in yyyyMMdd format and are assumed to be in GMT(Optional
+   *     query param).
+   *     If a single date is specified, all flows active on that date are
+   *     returned. If both startdate and enddate is given, all flows active
+   *     between start and end date will be returned. If only startdate is
+   *     given, flows active on and after startdate are returned. If only
+   *     enddate is given, flows active on and before enddate are returned.
+   *     For example :
+   *     "daterange=20150711" returns flows active on 20150711.
+   *     "daterange=20150711-20150714" returns flows active between these
+   *     2 dates.
+   *     "daterange=20150711-" returns flows active on and after 20150711.
+   *     "daterange=-20150711" returns flows active on and before 20150711.
+   *
+   * @return If successful, a HTTP 200(OK) response having a JSON representing 
a
+   *     set of {@link FlowActivityEntity} instances are returned.
+   *     On failures,
+   *     If any problem occurs in parsing request, HTTP 400(Bad Request) is
+   *     returned.
+   *     For all other errors while retrieving data, HTTP 500(Internal Server
+   *     Error) is returned.
    */
   @GET
   @Path("/flows/")
@@ -618,41 +1156,58 @@ public class TimelineReaderWebServices {
       @Context HttpServletRequest req,
       @Context HttpServletResponse res,
       @QueryParam("limit") String limit,
-      @QueryParam("daterange") String dateRange,
-      @QueryParam("fields") String fields) {
-    return getFlows(req, res, null, limit, dateRange, fields);
+      @QueryParam("daterange") String dateRange) {
+    return getFlows(req, res, null, limit, dateRange);
   }
 
   /**
-   * Return a list of flows for a given cluster id. daterange, if specified is
-   * given as "[startdate]-[enddate]"(i.e. start and end date separated by -) 
or
-   * single date. Dates are interpreted in yyyyMMdd format and are assumed to
-   * be in GMT. If a single date is specified, all flows active on that date 
are
-   * returned. If both startdate and enddate is given, all flows active between
-   * start and end date will be returned. If only startdate is given, flows
-   * active on and after startdate are returned. If only enddate is given, 
flows
-   * active on and before enddate are returned.
-   * For example :
-   * "daterange=20150711" returns flows active on 20150711.
-   * "daterange=20150711-20150714" returns flows active between these 2 dates.
-   * "daterange=20150711-" returns flows active on and after 20150711.
-   * "daterange=-20150711" returns flows active on and before 20150711.
+   * Return a list of active flows for a given cluster id.
+   *
+   * @param req Servlet request.
+   * @param res Servlet response.
+   * @param clusterId Cluster id to which the flows to be queried belong to(
+   *     Mandatory path param).
+   * @param limit Number of flows to return(Optional query param).
+   * @param dateRange If specified is given as "[startdate]-[enddate]"(i.e.
+   *     start and end date separated by "-") or single date. Dates are
+   *     interpreted in yyyyMMdd format and are assumed to be in GMT(Optional
+   *     query param).
+   *     If a single date is specified, all flows active on that date are
+   *     returned. If both startdate and enddate is given, all flows active
+   *     between start and end date will be returned. If only startdate is
+   *     given, flows active on and after startdate are returned. If only
+   *     enddate is given, flows active on and before enddate are returned.
+   *     For example :
+   *     "daterange=20150711" returns flows active on 20150711.
+   *     "daterange=20150711-20150714" returns flows active between these
+   *     2 dates.
+   *     "daterange=20150711-" returns flows active on and after 20150711.
+   *     "daterange=-20150711" returns flows active on and before 20150711.
+   *
+   * @return If successful, a HTTP 200(OK) response having a JSON representing 
a
+   *     set of {@link FlowActivityEntity} instances are returned.
+   *     On failures,
+   *     If any problem occurs in parsing request, HTTP 400(Bad Request) is
+   *     returned.
+   *     For all other errors while retrieving data, HTTP 500(Internal Server
+   *     Error) is returned.
    */
   @GET
-  @Path("/flows/{clusterid}/")
+  @Path("/clusters/{clusterid}/flows/")
   @Produces(MediaType.APPLICATION_JSON)
   public Set<TimelineEntity> getFlows(
       @Context HttpServletRequest req,
       @Context HttpServletResponse res,
       @PathParam("clusterid") String clusterId,
       @QueryParam("limit") String limit,
-      @QueryParam("daterange") String dateRange,
-      @QueryParam("fields") String fields) {
+      @QueryParam("daterange") String dateRange) {
     String url = req.getRequestURI() +
         (req.getQueryString() == null ? "" :
             QUERY_STRING_SEP + req.getQueryString());
-    UserGroupInformation callerUGI = getUser(req);
-    LOG.info("Received URL " + url + " from user " + getUserName(callerUGI));
+    UserGroupInformation callerUGI =
+        TimelineReaderWebServicesUtils.getUser(req);
+    LOG.info("Received URL " + url + " from user " +
+        TimelineReaderWebServicesUtils.getUserName(callerUGI));
     long startTime = Time.monotonicNow();
     init(res);
     TimelineReaderManager timelineReaderManager = getTimelineReaderManager();
@@ -660,10 +1215,10 @@ public class TimelineReaderWebServices {
     try {
       DateRange range = parseDateRange(dateRange);
       entities = timelineReaderManager.getEntities(
-          null, parseStr(clusterId), null, null, null,
-          TimelineEntityType.YARN_FLOW_ACTIVITY.toString(), 
parseLongStr(limit),
-          range.dateStart, range.dateEnd, null, null, null, null, null, null,
-          parseFieldsStr(fields, COMMA_DELIMITER));
+          null, TimelineReaderWebServicesUtils.parseStr(clusterId), null, null,
+          null, TimelineEntityType.YARN_FLOW_ACTIVITY.toString(),
+          TimelineReaderWebServicesUtils.parseLongStr(limit), range.dateStart,
+          range.dateEnd, null, null, null, null, null, null, null);
     } catch (Exception e) {
       handleException(e, url, startTime, "limit");
     }
@@ -677,11 +1232,105 @@ public class TimelineReaderWebServices {
   }
 
   /**
-   * Return a single app for given app id. Cluster ID is not provided by
-   * client so default cluster ID has to be taken.
+   * Return a single app for given UID which is a delimited string containing
+   * clusterid, userid, flow name, flowrun id and app id.
+   *
+   * @param req Servlet request.
+   * @param res Servlet response.
+   * @param uId a delimited string containing clusterid, userid, flow name, 
flow
+   *     run id and app id which are extracted from UID and then used to query
+   *     backend(Mandatory path param).
+   * @param fields Specifies which fields of the app entity object to retrieve,
+   *     see {@link Field}. All fields will be retrieved if fields=ALL. If not
+   *     specified, 4 fields i.e. entity type(equivalent to YARN_APPLICATION),
+   *     app id and app created time is returned(Optional query param).
+   *
+   * @return If successful, a HTTP 200(OK) response having a JSON representing 
a
+   *     {@link TimelineEntity} instance is returned.
+   *     On failures,
+   *     If any problem occurs in parsing request or UID is incorrect,
+   *     HTTP 400(Bad Request) is returned.
+   *     If app for the given app id cannot be found, HTTP 404(Not Found) is
+   *     returned.
+   *     For all other errors while retrieving data, HTTP 500(Internal Server
+   *     Error) is returned.
+   */
+  @GET
+  @Path("/app-uid/{uid}/")
+  @Produces(MediaType.APPLICATION_JSON)
+  public TimelineEntity getApp(
+      @Context HttpServletRequest req,
+      @Context HttpServletResponse res,
+      @PathParam("uid") String uId,
+      @QueryParam("fields") String fields) {
+    String url = req.getRequestURI() +
+        (req.getQueryString() == null ? "" :
+            QUERY_STRING_SEP + req.getQueryString());
+    UserGroupInformation callerUGI =
+        TimelineReaderWebServicesUtils.getUser(req);
+    LOG.info("Received URL " + url + " from user " +
+        TimelineReaderWebServicesUtils.getUserName(callerUGI));
+    long startTime = Time.monotonicNow();
+    init(res);
+    TimelineReaderManager timelineReaderManager = getTimelineReaderManager();
+    TimelineEntity entity = null;
+    try {
+      TimelineReaderContext context =
+          TimelineUIDConverter.APPLICATION_UID.decodeUID(uId);
+      if (context == null) {
+        throw new BadRequestException("Incorrect UID " +  uId);
+      }
+      entity = timelineReaderManager.getEntity(context.getUserId(),
+          context.getClusterId(), context.getFlowName(), 
context.getFlowRunId(),
+          context.getAppId(), TimelineEntityType.YARN_APPLICATION.toString(),
+          null, TimelineReaderWebServicesUtils.parseFieldsStr(
+          fields, COMMA_DELIMITER));
+    } catch (Exception e) {
+      handleException(e, url, startTime, "flowrunid");
+    }
+    long endTime = Time.monotonicNow();
+    if (entity == null) {
+      LOG.info("Processed URL " + url + " but app not found" + " (Took " +
+          (endTime - startTime) + " ms.)");
+      throw new NotFoundException("App with uid " + uId + " not found");
+    }
+    LOG.info("Processed URL " + url +
+        " (Took " + (endTime - startTime) + " ms.)");
+    return entity;
+  }
+
+  /**
+   * Return a single app for given app id. Cluster ID is not provided by client
+   * client so default cluster ID has to be taken. If userid, flow name and 
flow
+   * run id which are optional query parameters are not specified, they will be
+   * queried based on app id and cluster id from the flow context information
+   * stored in underlying storage implementation.
+   *
+   * @param req Servlet request.
+   * @param res Servlet response.
+   * @param appId Application id to be queried(Mandatory path param).
+   * @param flowName Flow name which should match for the app(Optional query
+   *     param).
+   * @param flowRunId Run id which should match for the app(Optional query
+   *     param).
+   * @param userId User id which should match for the app(Optional query 
param).
+   * @param fields Specifies which fields of the app entity object to retrieve,
+   *     see {@link Field}. All fields will be retrieved if fields=ALL. If not
+   *     specified, 4 fields i.e. entity type(equivalent to YARN_APPLICATION),
+   *     app id and app created time is returned(Optional query param).
+   *
+   * @return If successful, a HTTP 200(OK) response having a JSON representing 
a
+   *     {@link TimelineEntity} instance is returned.
+   *     On failures,
+   *     If any problem occurs in parsing request, HTTP 400(Bad Request) is
+   *     returned.
+   *     If flow context information cannot be retrieved or app for the given
+   *     app id cannot be found, HTTP 404(Not Found) is returned.
+   *     For all other errors while retrieving data, HTTP 500(Internal Server
+   *     Error) is returned.
    */
   @GET
-  @Path("/app/{appid}/")
+  @Path("/apps/{appid}/")
   @Produces(MediaType.APPLICATION_JSON)
   public TimelineEntity getApp(
       @Context HttpServletRequest req,
@@ -695,10 +1344,38 @@ public class TimelineReaderWebServices {
   }
 
   /**
-   * Return a single app for given cluster id and app id.
+   * Return a single app for given cluster id and app id. If userid, flow name
+   * and flowrun id which are optional query parameters are not specified, they
+   * will be queried based on app id and cluster id from the flow context
+   * information stored in underlying storage implementation.
+   *
+   * @param req Servlet request.
+   * @param res Servlet response.
+   * @param clusterId Cluster id to which the app to be queried belong to(
+   *     Mandatory path param).
+   * @param appId Application id to be queried(Mandatory path param).
+   * @param flowName Flow name which should match for the app(Optional query
+   *     param).
+   * @param flowRunId Run id which should match for the app(Optional query
+   *     param).
+   * @param userId User id which should match for the app(Optional query 
param).
+   * @param fields Specifies which fields of the app entity object to retrieve,
+   *     see {@link Field}. All fields will be retrieved if fields=ALL. If not
+   *     specified, 4 fields i.e. entity type(equivalent to YARN_APPLICATION),
+   *     app id and app created time is returned(Optional query param).
+   *
+   * @return If successful, a HTTP 200(OK) response having a JSON representing 
a
+   *     {@link TimelineEntity} instance is returned.
+   *     On failures,
+   *     If any problem occurs in parsing request, HTTP 400(Bad Request) is
+   *     returned.
+   *     If flow context information cannot be retrieved or app for the given
+   *     app id cannot be found, HTTP 404(Not Found) is returned.
+   *     For all other errors while retrieving data, HTTP 500(Internal Server
+   *     Error) is returned.
    */
   @GET
-  @Path("/app/{clusterid}/{appid}/")
+  @Path("/clusters/{clusterid}/apps/{appid}/")
   @Produces(MediaType.APPLICATION_JSON)
   public TimelineEntity getApp(
       @Context HttpServletRequest req,
@@ -712,17 +1389,24 @@ public class TimelineReaderWebServices {
     String url = req.getRequestURI() +
         (req.getQueryString() == null ? "" :
             QUERY_STRING_SEP + req.getQueryString());
-    UserGroupInformation callerUGI = getUser(req);
-    LOG.info("Received URL " + url + " from user " + getUserName(callerUGI));
+    UserGroupInformation callerUGI =
+        TimelineReaderWebServicesUtils.getUser(req);
+    LOG.info("Received URL " + url + " from user " +
+        TimelineReaderWebServicesUtils.getUserName(callerUGI));
     long startTime = Time.monotonicNow();
     init(res);
     TimelineReaderManager timelineReaderManager = getTimelineReaderManager();
     TimelineEntity entity = null;
     try {
-      entity = timelineReaderManager.getEntity(parseStr(userId),
-          parseStr(clusterId), parseStr(flowName), parseLongStr(flowRunId),
-          parseStr(appId), TimelineEntityType.YARN_APPLICATION.toString(), 
null,
-          parseFieldsStr(fields, COMMA_DELIMITER));
+      entity = timelineReaderManager.getEntity(
+          TimelineReaderWebServicesUtils.parseStr(userId),
+          TimelineReaderWebServicesUtils.parseStr(clusterId),
+          TimelineReaderWebServicesUtils.parseStr(flowName),
+          TimelineReaderWebServicesUtils.parseLongStr(flowRunId),
+          TimelineReaderWebServicesUtils.parseStr(appId),
+          TimelineEntityType.YARN_APPLICATION.toString(), null,
+          TimelineReaderWebServicesUtils.parseFieldsStr(
+          fields, COMMA_DELIMITER));
     } catch (Exception e) {
       handleException(e, url, startTime, "flowrunid");
     }
@@ -738,13 +1422,180 @@ public class TimelineReaderWebServices {
   }
 
   /**
-   * Return a list of apps for given user, flow id and flow run id. Cluster ID
+   * Return a list of apps for given UID which is a delimited string containing
+   * clusterid, userid, flow name and flowrun id. If number of matching apps 
are
+   * more than the limit, most recent apps till the limit is reached, will be
+   * returned.
+   *
+   * @param req Servlet request.
+   * @param res Servlet response.
+   * @param uId a delimited string containing clusterid, userid, flow name and
+   *     flowrun id which are extracted from UID and then used to query 
backend.
+   *     (Mandatory path param).
+   * @param limit Number of apps to return(Optional query param).
+   * @param createdTimeStart If specified, matched apps should not be created
+   *     before this timestamp(Optional query param).
+   * @param createdTimeEnd If specified, matched apps should not be created
+   *     after this timestamp(Optional query param).
+   * @param relatesTo If specified, matched apps should relate to given
+   *     entities associated with a entity type. relatesto is a comma separated
+   *     list in the format [entitytype]:[entityid1]:[entityid2]... (Optional
+   *     query param).
+   * @param isRelatedTo If specified, matched apps should be related to given
+   *     entities associated with a entity type. relatesto is a comma separated
+   *     list in the format [entitytype]:[entityid1]:[entityid2]... (Optional
+   *     query param).
+   * @param infofilters If specified, matched apps should have exact matches
+   *     to the given info represented as key-value pairs. This is represented
+   *     as infofilters=info1:value1,info2:value2... (Optional query param).
+   * @param conffilters If specified, matched apps should have exact matches
+   *     to the given configs represented as key-value pairs. This is
+   *     represented as conffilters=conf1:value1,conf2:value2... (Optional 
query
+   *     param).
+   * @param metricfilters If specified, matched apps should contain the given
+   *     metrics. This is represented as metricfilters=metricid1, metricid2...
+   *     (Optional query param).
+   * @param eventfilters If specified, matched apps should contain the given
+   *     events. This is represented as eventfilters=eventid1, eventid2...
+   * @param fields Specifies which fields of the app entity object to retrieve,
+   *     see {@link Field}. All fields will be retrieved if fields=ALL. If not
+   *     specified, 4 fields i.e. entity type(equivalent to YARN_APPLICATION),
+   *     app id and app created time is returned(Optional query param).
+   *
+   * @return If successful, a HTTP 200(OK) response having a JSON representing
+   *     a set of {@link TimelineEntity} instances representing apps is
+   *     returned.
+   *     On failures,
+   *     If any problem occurs in parsing request or UID is incorrect,
+   *     HTTP 400(Bad Request) is returned.
+   *     For all other errors while retrieving data, HTTP 500(Internal Server
+   *     Error) is returned.
+   */
+  @GET
+  @Path("/run-uid/{uid}/apps")
+  @Produces(MediaType.APPLICATION_JSON)
+  public Set<TimelineEntity> getFlowRunApps(
+      @Context HttpServletRequest req,
+      @Context HttpServletResponse res,
+      @PathParam("uid") String uId,
+      @QueryParam("limit") String limit,
+      @QueryParam("createdtimestart") String createdTimeStart,
+      @QueryParam("createdtimeend") String createdTimeEnd,
+      @QueryParam("relatesto") String relatesTo,
+      @QueryParam("isrelatedto") String isRelatedTo,
+      @QueryParam("infofilters") String infofilters,
+      @QueryParam("conffilters") String conffilters,
+      @QueryParam("metricfilters") String metricfilters,
+      @QueryParam("eventfilters") String eventfilters,
+      @QueryParam("fields") String fields) {
+    String url = req.getRequestURI() +
+        (req.getQueryString() == null ? "" :
+            QUERY_STRING_SEP + req.getQueryString());
+    UserGroupInformation callerUGI =
+        TimelineReaderWebServicesUtils.getUser(req);
+    LOG.info("Received URL " + url + " from user " +
+        TimelineReaderWebServicesUtils.getUserName(callerUGI));
+    long startTime = Time.monotonicNow();
+    init(res);
+    TimelineReaderManager timelineReaderManager = getTimelineReaderManager();
+    Set<TimelineEntity> entities = null;
+    try {
+      TimelineReaderContext context =
+          TimelineUIDConverter.FLOWRUN_UID.decodeUID(uId);
+      if (context == null) {
+        throw new BadRequestException("Incorrect UID " +  uId);
+      }
+      entities = timelineReaderManager.getEntities(
+          TimelineReaderWebServicesUtils.parseStr(context.getUserId()),
+          TimelineReaderWebServicesUtils.parseStr(context.getClusterId()),
+          TimelineReaderWebServicesUtils.parseStr(context.getFlowName()),
+          context.getFlowRunId(),
+          TimelineReaderWebServicesUtils.parseStr(context.getAppId()),
+          TimelineEntityType.YARN_APPLICATION.toString(),
+          TimelineReaderWebServicesUtils.parseLongStr(limit),
+          TimelineReaderWebServicesUtils.parseLongStr(createdTimeStart),
+          TimelineReaderWebServicesUtils.parseLongStr(createdTimeEnd),
+          TimelineReaderWebServicesUtils.parseKeyStrValuesStr(
+          relatesTo, COMMA_DELIMITER, COLON_DELIMITER),
+          TimelineReaderWebServicesUtils.parseKeyStrValuesStr(
+          isRelatedTo, COMMA_DELIMITER, COLON_DELIMITER),
+          TimelineReaderWebServicesUtils.parseKeyStrValueObj(
+          infofilters, COMMA_DELIMITER, COLON_DELIMITER),
+          TimelineReaderWebServicesUtils.parseKeyStrValueStr(
+          conffilters, COMMA_DELIMITER, COLON_DELIMITER),
+          TimelineReaderWebServicesUtils.parseValuesStr(
+          metricfilters, COMMA_DELIMITER),
+          TimelineReaderWebServicesUtils.parseValuesStr(
+          eventfilters, COMMA_DELIMITER),
+          TimelineReaderWebServicesUtils.parseFieldsStr(
+          fields, COMMA_DELIMITER));
+    } catch (Exception e) {
+      handleException(e, url, startTime,
+          "createdTime start/end or limit or flowrunid");
+    }
+    long endTime = Time.monotonicNow();
+    if (entities == null) {
+      entities = Collections.emptySet();
+    }
+    LOG.info("Processed URL " + url +
+        " (Took " + (endTime - startTime) + " ms.)");
+    return entities;
+  }
+
+  /**
+   * Return a list of apps for given user, flow name and flow run id. Cluster 
ID
    * is not provided by client so default cluster ID has to be taken. If number
    * of matching apps are more than the limit, most recent apps till the limit
    * is reached, will be returned.
+   *
+   * @param req Servlet request.
+   * @param res Servlet response.
+   * @param userId User id which should match for the apps(Mandatory path 
param)
+   * @param flowName Flow name which should match for the apps(Mandatory path
+   *     param).
+   * @param flowRunId Run id which should match for the apps(Mandatory path
+   *     param).
+   * @param limit Number of apps to return(Optional query param).
+   * @param createdTimeStart If specified, matched apps should not be created
+   *     before this timestamp(Optional query param).
+   * @param createdTimeEnd If specified, matched apps should not be created
+   *     after this timestamp(Optional query param).
+   * @param relatesTo If specified, matched apps should relate to given
+   *     entities associated with a entity type. relatesto is a comma separated
+   *     list in the format [entitytype]:[entityid1]:[entityid2]... (Optional
+   *     query param).
+   * @param isRelatedTo If specified, matched apps should be related to given
+   *     entities associated with a entity type. relatesto is a comma separated
+   *     list in the format [entitytype]:[entityid1]:[entityid2]... (Optional
+   *     query param).
+   * @param infofilters If specified, matched apps should have exact matches
+   *     to the given info represented as key-value pairs. This is represented
+   *     as infofilters=info1:value1,info2:value2... (Optional query param).
+   * @param conffilters If specified, matched apps should have exact matches
+   *     to the given configs represented as key-value pairs. This is
+   *     represented as conffilters=conf1:value1,conf2:value2... (Optional 
query
+   *     param).
+   * @param metricfilters If specified, matched apps should contain the given
+   *     metrics. This is represented as metricfilters=metricid1, metricid2...
+   *     (Optional query param).
+   * @param eventfilters If specified, matched apps should contain the given
+   *     events. This is represented as eventfilters=eventid1, eventid2...
+   * @param fields Specifies which fields of the app entity object to retrieve,
+   *     see {@link Field}. All fields will be retrieved if fields=ALL. If not
+   *     specified, 4 fields i.e. entity type(equivalent to YARN_APPLICATION),
+   *     app id and app created time is returned(Optional query param).
+   *
+   * @return If successful, a HTTP 200(OK) response having a JSON representing
+   *     a set of {@link TimelineEntity} instances representing apps is
+   *     returned.
+   *     On failures,
+   *     If any problem occurs in parsing request, HTTP 400(Bad Request) is
+   *     returned.
+   *     For all other errors while retrieving data, HTTP 500(Internal Server
+   *     Error) is returned.
    */
   @GET
-  @Path("/flowrunapps/{userid}/{flowname}/{flowrunid}/")
+  @Path("/users/{userid}/flows/{flowname}/runs/{flowrunid}/apps/")
   @Produces(MediaType.APPLICATION_JSON)
   public Set<TimelineEntity> getFlowRunApps(
       @Context HttpServletRequest req,
@@ -770,18 +1621,67 @@ public class TimelineReaderWebServices {
   }
 
   /**
-   * Return a list of apps for a given user, cluster id, flow id and flow run
+   * Return a list of apps for a given user, cluster id, flow name and flow run
    * id. If number of matching apps are more than the limit, most recent apps
    * till the limit is reached, will be returned.
+   *
+   * @param req Servlet request.
+   * @param res Servlet response.
+   * @param clusterId Cluster id to which the apps to be queried belong to
+   *     (Mandatory path param).
+   * @param userId User id which should match for the apps(Mandatory path 
param)
+   * @param flowName Flow name which should match for the apps(Mandatory path
+   *     param).
+   * @param flowRunId Run id which should match for the apps(Mandatory path
+   *     param).
+   * @param limit Number of apps to return(Optional query param).
+   * @param createdTimeStart If specified, matched apps should not be created
+   *     before this timestamp(Optional query param).
+   * @param createdTimeEnd If specified, matched apps should not be created
+   *     after this timestamp(Optional query param).
+   * @param relatesTo If specified, matched apps should relate to given
+   *     entities associated with a entity type. relatesto is a comma separated
+   *     list in the format [entitytype]:[entityid1]:[entityid2]... (Optional
+   *     query param).
+   * @param isRelatedTo If specified, matched apps should be related to given
+   *     entities associated with a entity type. relatesto is a comma separated
+   *     list in the format [entitytype]:[entityid1]:[entityid2]... (Optional
+   *     query param).
+   * @param infofilters If specified, matched apps should have exact matches
+   *     to the given info represented as key-value pairs. This is represented
+   *     as infofilters=info1:value1,info2:value2... (Optional query param).
+   * @param conffilters If specified, matched apps should have exact matches
+   *     to the given configs represented as key-value pairs. This is
+   *     represented as conffilters=conf1:value1,conf2:value2... (Optional 
query
+   *     param).
+   * @param metricfilters If specified, matched apps should contain the given
+   *     metrics. This is represented as metricfilters=metricid1, metricid2...
+   *     (Optional query param).
+   * @param eventfilters If specified, matched apps should contain the given
+   *     events. This is represented as eventfilters=eventid1, eventid2...
+   * @param fields Specifies which fields of the app entity object to retrieve,
+   *     see {@link Field}. All fields will be retrieved if fields=ALL. If not
+   *     specified, 4 fields i.e. entity type(equivalent to YARN_APPLICATION),
+   *     app id and app created time is returned(Optional query param).
+   *
+   * @return If successful, a HTTP 200(OK) response having a JSON representing
+   *     a set of {@link TimelineEntity} instances representing apps is
+   *     returned.
+   *     On failures,
+   *     If any problem occurs in parsing request, HTTP 400(Bad Request) is
+   *     returned.
+   *     For all other errors while retrieving data, HTTP 500(Internal Server
+   *     Error) is returned.
    */
   @GET
-  @Path("/flowrunapps/{userid}/{clusterid}/{flowname}/{flowrunid}/")
+  @Path("/clusters/{clusterid}/users/{userid}/flows/{flowname}/runs/"
+      + "{flowrunid}/apps/")
   @Produces(MediaType.APPLICATION_JSON)
   public Set<TimelineEntity> getFlowRunApps(
       @Context HttpServletRequest req,
       @Context HttpServletResponse res,
-      @PathParam("userid") String userId,
       @PathParam("clusterid") String clusterId,
+      @PathParam("userid") String userId,
       @PathParam("flowname") String flowName,
       @PathParam("flowrunid") String flowRunId,
       @QueryParam("limit") String limit,
@@ -802,13 +1702,57 @@ public class TimelineReaderWebServices {
   }
 
   /**
-   * Return a list of apps for given user and flow id. Cluster ID is not
+   * Return a list of apps for given user and flow name. Cluster ID is not
    * provided by client so default cluster ID has to be taken. If number of
    * matching apps are more than the limit, most recent apps till the limit is
    * reached, will be returned.
+   *
+   * @param req Servlet request.
+   * @param res Servlet response.
+   * @param userId User id which should match for the apps(Mandatory path 
param)
+   * @param flowName Flow name which should match for the apps(Mandatory path
+   *     param).
+   * @param limit Number of apps to return(Optional query param).
+   * @param createdTimeStart If specified, matched apps should not be created
+   *     before this timestamp(Optional query param).
+   * @param createdTimeEnd If specified, matched apps should not be created
+   *     after this timestamp(Optional query param).
+   * @param relatesTo If specified, matched apps should relate to given
+   *     entities associated with a entity type. relatesto is a comma separated
+   *     list in the format [entitytype]:[entityid1]:[entityid2]... (Optional
+   *     query param).
+   * @param isRelatedTo If specified, matched apps should be related to given
+   *     entities associated with a entity type. relatesto is a comma separated
+   *     list in the format [entitytype]:[entityid1]:[entityid2]... (Optional
+   *     query param).
+   * @param infofilters If specified, matched apps should have exact matches
+   *     to the given info represented as key-value pairs. This is represented
+   *     as infofilters=info1:value1,info2:value2... (Optional query param).
+   * @param conffilters If specified, matched apps should have exact matches
+   *     to the given configs represented as key-value pairs. This is
+   *     represented as conffilters=conf1:value1,conf2:value2... (Optional 
query
+   *     param).
+   * @param metricfilters If specified, matched apps should contain the given
+   *     metrics. This is represented as metricfilters=metricid1, metricid2...
+   *     (Optional query param).
+   * @param eventfilters If specified, matched apps should contain the given
+   *     events. This is represented as eventfilters=eventid1, eventid2...
+   * @param fields Specifies which fields of the app entity object to retrieve,
+   *     see {@link Field}. All fields will be retrieved if fields=ALL. If not
+   *     specified, 4 fields i.e. entity type(equivalent to YARN_APPLICATION),
+   *     app id and app created time is returned(Optional query param).
+   *
+   * @return If successful, a HTTP 200(OK) response having a JSON representing
+   *     a set of {@link TimelineEntity} instances representing apps is
+   *     returned.
+   *     On failures,
+   *     If any problem occurs in parsing request, HTTP 400(Bad Request) is
+   *     returned.
+   *     For all other errors while retrieving data, HTTP 500(Internal Server
+   *     Error) is returned.
    */
   @GET
-  @Path("/flowapps/{userid}/{flowname}/")
+  @Path("/users/{userid}/flows/{flowname}/apps/")
   @Produces(MediaType.APPLICATION_JSON)
   public Set<TimelineEntity> getFlowApps(
       @Context HttpServletRequest req,
@@ -832,18 +1776,65 @@ public class TimelineReaderWebServices {
   }
 
   /**
-   * Return a list of apps for a given user, cluster id and flow id. If number
+   * Return a list of apps for a given user, cluster id and flow name. If 
number
    * of matching apps are more than the limit, most recent apps till the limit
-   * is reached, will be returned.
+   * is reached, will be returned. If number of matching apps are more than the
+   * limit, most recent apps till the limit is reached, will be returned.
+   *
+   * @param req Servlet request.
+   * @param res Servlet response.
+   * @param clusterId Cluster id to which the apps to be queried belong to
+   *     (Mandatory path param).
+   * @param userId User id which should match for the apps(Mandatory path 
param)
+   * @param flowName Flow name which should match for the apps(Mandatory path
+   *     param).
+   * @param limit Number of apps to return(Optional query param).
+   * @param createdTimeStart If specified, matched apps should not be created
+   *     before this timestamp(Optional query param).
+   * @param createdTimeEnd If specified, matched apps should not be created
+   *     after this timestamp(Optional query param).
+   * @param relatesTo If specified, matched apps should relate to given
+   *     entities associated with a entity type. relatesto is a comma separated
+   *     list in the format [entitytype]:[entityid1]:[entityid2]... (Optional
+   *     query param).
+   * @param isRelatedTo If specified, matched apps should be related to given
+   *     entities associated with a entity type. relatesto is a comma separated
+   *     list in the format [entitytype]:[entityid1]:[entityid2]... (Optional
+   *     query param).
+   * @param infofilters If specified, matched apps should have exact matches
+   *     to the given info represented as key-value pairs. This is represented
+   *     as infofilters=info1:value1,info2:value2... (Optional query param).
+   * @param conffilters If specified, matched apps should have exact matches
+   *     to the given configs represented as key-value pairs. This is
+   *     represented as conffilters=conf1:value1,conf2:value2... (Optional 
query
+   *     param).
+   * @param metricfilters If specified, matched apps should contain the given
+   *     metrics. This is represented as metricfilters=metricid1, metricid2...
+   *     (Optional query param).
+   * @param eventfilters If specified, matched apps should contain the given
+   *     events. This is represented as eventfilters=eventid1, eventid2...
+   * 

<TRUNCATED>

Reply via email to