Merge remote-tracking branch 'upstream/development' into development
diff --git a/react-components/oodt_opsui_sample_app/src/App.js b/react-components/oodt_opsui_sample_app/src/App.js
index 2e34f02..0522ea9 100644
--- a/react-components/oodt_opsui_sample_app/src/App.js
+++ b/react-components/oodt_opsui_sample_app/src/App.js
@@ -12,6 +12,7 @@
       <BrowserRouter>
         <SnackbarProvider
           maxSnack={3}
+          autoHideDuration={3000}
           anchorOrigin={{
             vertical: "top",
             horizontal: "center",
diff --git a/react-components/oodt_opsui_sample_app/src/components/fileManager/Product/Product.js b/react-components/oodt_opsui_sample_app/src/components/fileManager/Product/Product.js
index 8b52ddf..3e62d6b 100644
--- a/react-components/oodt_opsui_sample_app/src/components/fileManager/Product/Product.js
+++ b/react-components/oodt_opsui_sample_app/src/components/fileManager/Product/Product.js
@@ -70,7 +70,6 @@
 class Product extends Component {
   constructor(props) {
     super(props);
-    this.snackBarRef = React.createRef();
     this.loadProduct = this.loadProduct.bind(this);
     this.removeProduct = this.removeProduct.bind(this);
   }
@@ -95,21 +94,21 @@
   }
 
   removeProduct() {
-    let result = window.confirm("Are you Sure to Remove the Product " +this.state.selectedProductId + "?")
+    let result = window.confirm("Are you Sure to Remove the Product " +this.props.productId + "?")
     if (result) {
       fmservice
-        .removeProductById(this.state.selectedProductId)
+        .removeProductById(this.props.productId)
         .then((isDeleted) => {
-          this.props.enqueueSnackbar("Sucessfully removed productID: " + this.state.selectedProductId,{
+          this.props.enqueueSnackbar("Sucessfully removed productID: " + this.props.productId,{
             variant: "success"
           })
-          this.props.history.push("/product")
           this.setState({
-            selectedProductId: "",
             productData: {},
             productMetaData: {},
             productRefData: {},
           });
+          this.props.onClose()
+          this.props.history.push("/products")
         })
         .catch((err) => {
           console.error(err);
diff --git a/react-components/oodt_opsui_sample_app/src/components/fileManager/ProductList/ProductList.js b/react-components/oodt_opsui_sample_app/src/components/fileManager/ProductList/ProductList.js
index a45e26b..599ec4c 100644
--- a/react-components/oodt_opsui_sample_app/src/components/fileManager/ProductList/ProductList.js
+++ b/react-components/oodt_opsui_sample_app/src/components/fileManager/ProductList/ProductList.js
@@ -104,6 +104,7 @@
     totalProductCount: 0,
     productTypeArray: [],
     isQueryTimedOut: true,
+    noProductsText: "Loading..."
   };
 
   componentDidMount() {
@@ -121,14 +122,18 @@
 
   onProductDrawerClose = () => {
     this.props.history.push("/products")
+    this.loadNextProducts()
   }
 
-  // TODO
   onProductSearch = (productName) => {
     fmservice.getProductPage({
       productName: productName
     }).then(productPage => {
         let productsArr = productPage.products.product
+        if (typeof(productsArr) === "undefined"){
+          this.setState({noProductsText: "No products"})
+          return;
+        }
         if (!Array.isArray(productsArr)) {
           productsArr = [productsArr]
         }
@@ -164,6 +169,10 @@
         // and returns an array of products when the object count is more than 1.
         // This check converts object to array to avoid this problem
         // Need to fix this in the backend
+        if (typeof(productsArr) === "undefined"){
+          this.setState({noProductsText: "No products"})
+          return;
+        }
         if (!Array.isArray(productsArr)) {
           productsArr = [productsArr]
         }
@@ -239,7 +248,7 @@
                    <TableCell></TableCell>
                    <TableCell>
                    <div className={classes.progress}>
-                    <CircularProgress />
+                   <p>{this.state.noProductsText}</p>
                   </div>
                    </TableCell>
                    <TableCell></TableCell>
@@ -262,7 +271,7 @@
                 count={this.state.totalProductCount}
                 page={this.state.currentProductPage}
                 onChangePage={this.handleChangePage}
-                rowsPerPage={this.state.productDetailsArray.length}
+                rowsPerPage={20}
                 rowsPerPageOptions={[]}
               />
             </Grid>
diff --git a/react-components/oodt_opsui_sample_app/src/components/workflowManager/NewWorkflow/NewWorkflow.js b/react-components/oodt_opsui_sample_app/src/components/workflowManager/NewWorkflow/NewWorkflow.js
new file mode 100644
index 0000000..7b06dd6
--- /dev/null
+++ b/react-components/oodt_opsui_sample_app/src/components/workflowManager/NewWorkflow/NewWorkflow.js
@@ -0,0 +1,125 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import React, { Component } from "react";
+import {
+  MenuItem,
+  InputLabel,
+  Button,
+  FormControl,
+  withStyles,
+  Select,
+} from "@material-ui/core";
+import * as wmservice from "services/wmservice";
+import {withSnackbar} from "notistack"
+
+const styles = (theme) => ({
+  root: {
+    paddingBottom: "2%",
+    paddingTop: "1%",
+    minHeight: "10vh",
+    display: "flex",
+    alignItems: "center",
+  },
+  formControl: {
+    minWidth: "30%",
+  },
+  selectEmpty: {
+    marginTop: theme.spacing(2),
+  },
+  button: {
+    marginLeft: theme.spacing(1),
+    padding: theme.spacing(1),
+  },
+});
+
+class NewWorkflow extends Component {
+  state = {
+    selectedEvent: "",
+    workflowEvents: [],
+    isSubmitted: false,
+  };
+
+  componentDidMount() {
+    wmservice
+      .getRegisteredEvents()
+      .then((eventsArr) => {
+        this.setState({
+          selectedEvent: eventsArr[0],
+          workflowEvents: eventsArr || [],
+        });
+      })
+      .catch((err) => console.error(err));
+  }
+
+  handleEventChange = (e) => {
+    this.setState({ selectedEvent: e.target.value });
+  };
+
+  triggerWorkflow = () => {
+    this.setState({isSubmitted: true})
+    wmservice
+      .handleEvent(this.state.selectedEvent)
+      .then((isOk) => {
+        this.setState({isSubmitted: false})
+        this.props.enqueueSnackbar("Event " + this.state.selectedEvent +" triggered successfully",{
+          variant: "success"
+        })
+        this.setState({isSubmitted: false})
+      })
+      .catch((err) => {
+        console.error(err)
+        this.props.enqueueSnackbar("Error occured when triggering event "+this.state.selectedEvent,{
+          variant: "error"
+        })
+        this.setState({isSubmitted: false})
+      });
+  };
+
+  render() {
+    const { classes } = this.props;
+
+    return (
+      <div className={classes.root}>
+        <FormControl variant="outlined" className={classes.formControl}>
+          <InputLabel>Event name</InputLabel>
+          <Select
+            value={this.state.selectedEvent}
+            onChange={this.handleEventChange}
+            label="Workflow event"
+          >
+            {this.state.workflowEvents.map((event) => {
+              return <MenuItem value={event}>{event}</MenuItem>;
+            })}
+          </Select>
+        </FormControl>
+
+        <Button
+          variant="contained"
+          onClick={this.triggerWorkflow}
+          color="primary"
+          disabled={this.state.isSubmitted}
+          className={classes.button}
+        >
+          Trigger workflow
+        </Button>
+      </div>
+    );
+  }
+}
+
+export default withStyles(styles)(withSnackbar(NewWorkflow));
\ No newline at end of file
diff --git a/react-components/oodt_opsui_sample_app/src/components/workflowManager/NewWorkflow/index.js b/react-components/oodt_opsui_sample_app/src/components/workflowManager/NewWorkflow/index.js
new file mode 100644
index 0000000..5c85fba
--- /dev/null
+++ b/react-components/oodt_opsui_sample_app/src/components/workflowManager/NewWorkflow/index.js
@@ -0,0 +1,21 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// Import the WorkflowList component from this folder and send it down to ./components/index.js
+import NewWorkflow from "./NewWorkflow";
+
+export {NewWorkflow};
\ No newline at end of file
diff --git a/react-components/oodt_opsui_sample_app/src/components/workflowManager/WorkflowList/WorkflowList.js b/react-components/oodt_opsui_sample_app/src/components/workflowManager/WorkflowList/WorkflowList.js
index 49af77a..5b1dd2f 100644
--- a/react-components/oodt_opsui_sample_app/src/components/workflowManager/WorkflowList/WorkflowList.js
+++ b/react-components/oodt_opsui_sample_app/src/components/workflowManager/WorkflowList/WorkflowList.js
@@ -16,7 +16,7 @@
  */
 
 import React, { Component } from "react";
-import { Button, withStyles } from "@material-ui/core";
+import { Button, withStyles, TablePagination, Typography, Grid } from "@material-ui/core";
 import Table from "@material-ui/core/Table";
 import TableBody from "@material-ui/core/TableBody";
 import TableCell from "@material-ui/core/TableCell";
@@ -24,14 +24,15 @@
 import TableRow from "@material-ui/core/TableRow";
 import Paper from "@material-ui/core/Paper";
 import PropTypes from "prop-types";
-import { wmconnection } from "constants/connection";
+import * as wmservice from "services/wmservice"
+import {NewWorkflow} from "components/workflowManager/NewWorkflow"
 import CircularProgress from "@material-ui/core/CircularProgress";
 
 const styles = theme => ({
   root: {
     width: "100%",
     marginTop: 0,
-    overflowX: "auto"
+    padding: 20
   },
   table: {
     minWidth: 650
@@ -40,98 +41,94 @@
     margin: 2
   },
   loading: {
-    textAlign: "center",
-    display: "block",
-    position: "relative"
+    display: "flex",
+    width: "100%",
+    justifyContent: "center"
   }
 });
 
 class WorkflowList extends Component {
-  constructor(props) {
-    super(props);
-    this.updateWorkflowStatus = this.updateWorkflowStatus.bind(this);
-    this.reloadWorkflow = this.reloadWorkflow.bind(this);
+  state = {
+    rows: [],
+    currentPage: 1,
+    totalPages: 0,
+    totalCount: 0,
+    workflowState: [],
+    noWorkflowsText: "Loading..."
+  };
+
+  componentDidMount() {
+    this.loadNextWorkflows()
   }
 
-  componentWillMount() {
-    wmconnection
-      .get("/workflow/firstpage")
-      .then(result => {
+  loadNextWorkflows = () => {
+    wmservice.getWorkflowList(this.state.currentPage).then(
+      workflowData => {
+        let workflowArr = workflowData.pageWorkflows
+        if (typeof(workflowArr) === "undefined"){
+          this.setState({noWorkflowsText: "No workflows found"})
+          return;
+        }
+        // Backend returns a product object when the object count is 1
+        // and returns an array of products when the object count is more than 1.
+        // This check converts object to array to avoid this problem
+        // Need to fix this in the backend
+        if (!Array.isArray(workflowArr)) {
+          workflowArr = [workflowArr]
+        }
         this.setState({
-          rows: result.data.workflowPageInstance.pageWorkflows
-        });
-        // console.log(this.state.rows)
-        console.log(this.state.rows[0].sharedContext.keyval[0].val);
-      })
-      .catch(error => {
-        console.log(error);
-      });
+          rows: workflowArr || [],
+          totalPages: workflowData.totalPages,
+          totalCount: workflowData.totalCount
+        })
+      }
+    ).catch(err => {
+      console.error(err)
+    })
   }
 
-  updateWorkflowStatus(workflowInstanceId, state) {
-    let result = window.confirm(
-      "Are you sure to change workflow " +
-        workflowInstanceId +
-        " state to " +
-        state
-    );
-    if (result) {
-      wmconnection
-        .post(
-          "/updatestatus/workflow?workflowInstanceId=" +
-            workflowInstanceId +
-            "&status=" +
-            state
-        )
-        .then(result => {
-          console.log("Success");
-          this.reloadWorkflow();
+  updateWorkflowStatus = (workflowInstanceId, state) => {
+    let result = window.confirm("Are you sure to change workflow " + workflowInstanceId + " state to " + state);
+    if(result){
+      wmservice.updateWorkflowStatus(workflowInstanceId, state)
+      .then((result) => {
+        wmservice.getWorkflowList().then(
+          workflows => {
+            this.setState({rows: workflows})
+          }
+        ).catch(err => {
+          console.error(err)
         })
-        .catch(error => {
-          console.log(error);
-        });
-    } else {
+      })
+      .catch((err) => console.error(err));
     }
   }
 
-  reloadWorkflow() {
-    wmconnection
-      .get("/workflow/firstpage")
-      .then(result => {
-        this.setState({
-          rows: result.data.workflowPageInstance.pageWorkflows
-        });
-        // console.log(this.state.rows)
-        console.log(this.state.rows[0].sharedContext.keyval[0].val);
-      })
-      .catch(error => {
-        console.log(error);
-      });
+  handleChangePage = (event,newPageNo) => {
+    this.setState({currentPage: newPageNo+1},() => this.loadNextWorkflows())
   }
 
-  state = {
-    rows: [],
-    workflowState: []
-  };
-
   render() {
     const { classes } = this.props;
     return (
       <Paper className={classes.root}>
+        <Typography variant="h6">New workflow</Typography>
+        <NewWorkflow />
+        
+        <Typography variant="h6">Past workflows</Typography>
         <Table className={classes.table}>
           <TableHead>
             <TableRow>
-              <TableCell>Workflow Instance Id</TableCell>
-              <TableCell align="center">Workflow Name</TableCell>
-              <TableCell align="center">Task Id</TableCell>
-              <TableCell align="center">Workflow State</TableCell>
-              <TableCell align="center">Actions</TableCell>
+              <TableCell><strong>Workflow Instance Id</strong></TableCell>
+              <TableCell align="center"><strong>Workflow Name</strong></TableCell>
+              <TableCell align="center"><strong>Task Id</strong></TableCell>
+              <TableCell align="center"><strong>Workflow State</strong></TableCell>
+              <TableCell align="center"><strong>Actions</strong></TableCell>
             </TableRow>
           </TableHead>
 
-          {this.state.rows.length > 0 && (
             <TableBody>
-              {this.state.rows.map(row => (
+              {this.state.rows.length > 0 && this.state.rows.map(row => (
                 <TableRow key={row.workflowInstanceId}>
                   <TableCell component="th" scope="row">
                     {row.workflowInstanceId}
@@ -189,13 +186,30 @@
                 </TableRow>
               ))}
             </TableBody>
-          )}
-          {this.state.rows.length === 0 && (
-            <TableBody className={classes.loading}>
-              <CircularProgress className={classes.progress} />
-            </TableBody>
-          )}
         </Table>
+        {this.state.rows.length === 0 && (
+                <div className={classes.loading}>
+                  <CircularProgress className={classes.progress} />
+                </div>                  
+          )}
+                  <Grid
+            style={{ width: "100%" }}
+            container
+            spacing={1}
+            direction="column"
+            alignItems="center"
+          >
+            <Grid item>
+              <TablePagination
+                component="div"
+                count={this.state.totalCount }
+                page={this.state.currentPage - 1}
+                onChangePage={this.handleChangePage}
+                rowsPerPage={20}
+                rowsPerPageOptions={[]}
+              />
+            </Grid>
+          </Grid>
       </Paper>
     );
   }
diff --git a/react-components/oodt_opsui_sample_app/src/services/wmservice.js b/react-components/oodt_opsui_sample_app/src/services/wmservice.js
new file mode 100644
index 0000000..a3a66c4
--- /dev/null
+++ b/react-components/oodt_opsui_sample_app/src/services/wmservice.js
@@ -0,0 +1,66 @@
+import { wmconnection } from "constants/connection";
+
+export const updateWorkflowStatus = (workflowInstanceId, state) => {
+  return new Promise((resolve, reject) => {
+    wmconnection
+      .post(
+        "/workflow/updatestatus?workflowInstanceId=" +
+          workflowInstanceId +
+          "&status=" +
+          state
+      )
+      .then((result) => {
+        resolve(result);
+      })
+      .catch((error) => {
+        reject(error);
+      });
+  });
+};
+
+export const getWorkflowList = (pageNo) => {
+  return new Promise((resolve, reject) => {
+    wmconnection
+      .get("/workflow/page",{
+        params: {
+          workflowPage: pageNo
+        }
+      })
+      .then((result) => {
+        resolve(result.data.workflowPageInstance);
+      })
+      .catch((error) => {
+        reject(error);
+      });
+  });
+};
+
+export const getRegisteredEvents = () => {
+  return new Promise((resolve, reject) => {
+    wmconnection
+      .get("/workflow/events")
+      .then((result) => {
+        resolve(result.data.workflowEvents.events);
+      })
+      .catch((error) => {
+        reject(error);
+      });
+  });
+}
+
+export const handleEvent = (eventName) => {
+  return new Promise((resolve, reject) => {
+    wmconnection
+      .post("/workflow/event",null,{
+        params: {
+          eventName: eventName
+        }
+      })
+      .then((result) => {
+        resolve(result);
+      })
+      .catch((error) => {
+        reject(error);
+      });
+  });
+}
\ No newline at end of file
diff --git a/react-components/swagger-implementations/workflow_manager.yaml b/react-components/swagger-implementations/workflow_manager.yaml
index 4f7c1b1..2c0345b 100644
--- a/react-components/swagger-implementations/workflow_manager.yaml
+++ b/react-components/swagger-implementations/workflow_manager.yaml
@@ -76,6 +76,65 @@
         404:
           description: workflows not Found
 
+  /workflow/page:
+    get:
+      tags:
+        - Workflows
+      summary: get workflow instance page
+      description: Retrieve the specified page of running/finished/paused Workflow Instances
+      operationId: findWorkflows
+      produces:
+        - application/json
+        - application/xml
+      parameters:
+        - in: query
+          name: workflowPage
+          schema:
+            type: integer
+          description: The page number of the desired workflow list page
+      responses:
+        200:
+          description: successful operation
+        404:
+          description: workflows not Found
+
+  /workflow/event:
+    post:
+      tags:
+        - Workflows
+      summary: Trigger workflow by event
+      description: Trigger the tasks in a configured workflow by a registered event 
+      operationId: triggerEvent
+      produces:
+        - application/json
+        - application/xml
+      parameters:
+        - in: query
+          name: eventName
+          schema:
+            type: string
+          description: The workflow event name to trigger workflow
+      responses:
+        200:
+          description: successful operation
+        404:
+          description: Error triggering the event
+
+  /workflow/events:
+    get:
+      tags:
+        - Workflows
+      summary: get events
+      description: Get all registered workflow events
+      operationId: findAllEvents
+      produces:
+        - application/json
+        - application/xml
+      responses:
+        200:
+          description: successful operation
+        404:
+          description: getting events failed
 
   /stop/workflow:
     post:
diff --git a/webapp/wmservices/src/main/java/org/apache/oodt/cas/wmservices/resources/WorkflowEventListResource.java b/webapp/wmservices/src/main/java/org/apache/oodt/cas/wmservices/resources/WorkflowEventListResource.java
new file mode 100644
index 0000000..9c24dff
--- /dev/null
+++ b/webapp/wmservices/src/main/java/org/apache/oodt/cas/wmservices/resources/WorkflowEventListResource.java
@@ -0,0 +1,31 @@
+package org.apache.oodt.cas.wmservices.resources;
+
+import org.apache.oodt.cas.workflow.structs.WorkflowInstancePage;
+
+import javax.xml.bind.annotation.*;
+import java.util.List;
+
+/**
+ * A JAX-RS resource representing a list of workflow events {@link List <String>}.
+ *
+ * @author pavinduLakshan (Pavindu Lakshan)
+ */
+@XmlRootElement(name = "workflowEvents")
+@XmlType(propOrder = {"eventList"})
+@XmlAccessorType(XmlAccessType.NONE)
+public class WorkflowEventListResource {
+    private List<String> eventList;
+
+    public WorkflowEventListResource(){
+
+    }
+
+    public WorkflowEventListResource(List<String> regEvents){
+        this.eventList = regEvents;
+    }
+
+    @XmlElement(name = "events")
+    public List<String> getEventList() {
+        return this.eventList;
+    }
+}
diff --git a/webapp/wmservices/src/main/java/org/apache/oodt/cas/wmservices/resources/WorkflowInstancePageResource.java b/webapp/wmservices/src/main/java/org/apache/oodt/cas/wmservices/resources/WorkflowInstancePageResource.java
index f47bac3..32a91fe 100644
--- a/webapp/wmservices/src/main/java/org/apache/oodt/cas/wmservices/resources/WorkflowInstancePageResource.java
+++ b/webapp/wmservices/src/main/java/org/apache/oodt/cas/wmservices/resources/WorkflowInstancePageResource.java
@@ -16,7 +16,7 @@
  * @author ngimhana (Nadeeshan Gimhana)
  */
 @XmlRootElement(name = "workflowPageInstance")
-@XmlType(propOrder = {"pageNum", "totalPages", "pageSize", "pageWorkflows"})
+@XmlType(propOrder = {"pageNum", "totalPages","totalWorkflowCount", "pageSize", "pageWorkflows"})
 @XmlAccessorType(XmlAccessType.NONE)
 public class WorkflowInstancePageResource {
 
@@ -24,6 +24,7 @@
   private int totalPages;
   private int pageSize;
   private List pageWorkflows;
+  private int totalWorkflowCount;
 
   /** Default constructor required by JAXB. */
   public WorkflowInstancePageResource() {}
@@ -33,11 +34,12 @@
    *
    * @param workflowInstancePage the workflowInstancePage associated with the resource
    */
-  public WorkflowInstancePageResource(WorkflowInstancePage workflowInstancePage) {
+  public WorkflowInstancePageResource(WorkflowInstancePage workflowInstancePage,int totalWorkflowCount) {
     this.pageNum = workflowInstancePage.getPageNum();
     this.totalPages = workflowInstancePage.getTotalPages();
     this.pageSize = workflowInstancePage.getPageSize();
     this.pageWorkflows = workflowInstancePage.getPageWorkflows();
+    this.totalWorkflowCount = totalWorkflowCount;
   }
 
   @XmlElement(name = "pageNum")
@@ -50,6 +52,11 @@
     return totalPages;
   }
 
+  @XmlElement(name = "totalCount")
+  public int getTotalWorkflowCount() {
+    return totalWorkflowCount;
+  }
+
   @XmlElement(name = "pageSize")
   public int getPageSize() {
     return pageSize;
diff --git a/webapp/wmservices/src/main/java/org/apache/oodt/cas/wmservices/resources/WorkflowInstanceResource.java b/webapp/wmservices/src/main/java/org/apache/oodt/cas/wmservices/resources/WorkflowInstanceResource.java
index 8d3e1b6..b6882a2 100755
--- a/webapp/wmservices/src/main/java/org/apache/oodt/cas/wmservices/resources/WorkflowInstanceResource.java
+++ b/webapp/wmservices/src/main/java/org/apache/oodt/cas/wmservices/resources/WorkflowInstanceResource.java
@@ -56,10 +56,12 @@
     this.workflowInstanceId = workflowInstance.getId();
     this.currentTaskId = workflowInstance.getCurrentTaskId();
     this.startDate = workflowInstance.getStartDate().toString();
-    this.endDate = workflowInstance.getEndDate().toString();
     this.timesBlocked = workflowInstance.getTimesBlocked();
     this.sharedContext = new MetadataResource(workflowInstance.getSharedContext());
     this.workflowState = new WorkflowStateResource(workflowInstance.getState());
+    if (workflowInstance.getEndDate() != null){
+      this.endDate = workflowInstance.getEndDate().toString();
+    }
   }
 
   @XmlElement(name = "workflowInstanceId")
diff --git a/webapp/wmservices/src/main/java/org/apache/oodt/cas/wmservices/services/WMJaxrsServiceV2.java b/webapp/wmservices/src/main/java/org/apache/oodt/cas/wmservices/services/WMJaxrsServiceV2.java
index 8fc78b5..400fbae 100644
--- a/webapp/wmservices/src/main/java/org/apache/oodt/cas/wmservices/services/WMJaxrsServiceV2.java
+++ b/webapp/wmservices/src/main/java/org/apache/oodt/cas/wmservices/services/WMJaxrsServiceV2.java
@@ -12,19 +12,20 @@
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.Response.Status;
+import org.apache.oodt.cas.metadata.Metadata;
 import org.apache.oodt.cas.wmservices.enums.ErrorType;
 import org.apache.oodt.cas.wmservices.exceptions.InternalServerErrorException;
 import org.apache.oodt.cas.wmservices.exceptions.NotFoundException;
-import org.apache.oodt.cas.wmservices.resources.WMRequestStatusResource;
-import org.apache.oodt.cas.wmservices.resources.WorkflowInstancePageResource;
-import org.apache.oodt.cas.wmservices.resources.WorkflowInstanceResource;
-import org.apache.oodt.cas.wmservices.resources.WorkflowManagerStatus;
+import org.apache.oodt.cas.wmservices.resources.*;
 import org.apache.oodt.cas.workflow.exceptions.WorkflowException;
 import org.apache.oodt.cas.workflow.structs.WorkflowInstance;
 import org.apache.oodt.cas.workflow.structs.WorkflowInstancePage;
 import org.apache.oodt.cas.workflow.system.WorkflowManagerClient;
 import org.slf4j.LoggerFactory;
 
+import java.util.Collections;
+import java.util.List;
+
 /**
  * Service class for Proposing Apache OODT-2.0 WorkflowManager REST-APIs This handles HTTP requests
  * and returns workflow manager entities JAX-RS resources converted to different formats.
@@ -79,6 +80,47 @@
   }
 
   /**
+   * returns all registered events
+   *
+   * @return events
+   */
+  @GET
+  @Path("events")
+  @Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
+  public WorkflowEventListResource getRegisteredEvents() {
+    try {
+      WorkflowManagerClient wmclient = getContextClient();
+      List events = wmclient.getRegisteredEvents();
+      WorkflowEventListResource eventResource = new WorkflowEventListResource(events);
+      return eventResource;
+    } catch (Exception e) {
+      logger.error("Error occurred when getting WM client", e);
+      throw new InternalServerErrorException("Unable to get WM client");
+    } 
+  }
+
+  /**
+   * trigger workflow by event
+   *
+   * @return isOk
+   */
+  @POST
+  @Path("event")
+  @Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
+  public Response handleEvent(
+          @QueryParam("eventName") String eventName
+  ) throws Exception {
+    try {
+      WorkflowManagerClient wmclient = getContextClient();
+      wmclient.sendEvent(eventName, new Metadata());
+      return Response.ok(true,MediaType.TEXT_PLAIN).build();
+    } catch (WorkflowException e) {
+      logger.error("Error occurred when getting WM client", e);
+      throw new InternalServerErrorException("Unable to get WM client");
+    }
+  }
+
+  /**
    * Gets an HTTP response that represents a {@link WorkflowInstance} from the workflow manager.
    *
    * @param workflowInstId the ID of the workflow Instance
@@ -116,7 +158,8 @@
     try {
       WorkflowManagerClient wmclient = getContextClient();
       WorkflowInstancePage firstPage = wmclient.getFirstPage();
-      WorkflowInstancePageResource firstPageResource = new WorkflowInstancePageResource(firstPage);
+      int totalWorkflowCount = wmclient.getNumWorkflowInstances();
+      WorkflowInstancePageResource firstPageResource = new WorkflowInstancePageResource(firstPage,totalWorkflowCount);
       return firstPageResource;
     } catch (Exception e) {
       throw new NotFoundException(e.getMessage());
@@ -124,6 +167,30 @@
   }
 
   /**
+   * Gets an HTTP response that represents a {@link WorkflowInstancePage} from the workflow manager.
+   * Gives the specified Page of WorkFlow Instances
+   *
+   * @return an HTTP response that represents a {@link WorkflowInstancePage} from the workflow
+   *     manager
+   */
+  @GET
+  @Path("page")
+  @Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
+  public WorkflowInstancePageResource getWorkflowPage(
+    @QueryParam("workflowPage") int pageNo
+  ) throws WebApplicationException {
+    try {
+      WorkflowManagerClient wmclient = getContextClient();
+      WorkflowInstancePage workflowPage = wmclient.paginateWorkflowInstances(pageNo);
+      int totalWorkflowCount = wmclient.getNumWorkflowInstances();
+      WorkflowInstancePageResource workflowPageResource = new WorkflowInstancePageResource(workflowPage,totalWorkflowCount);
+      return workflowPageResource;
+    } catch (Exception e) {
+      throw new NotFoundException(e.getMessage());
+    }
+  }
+
+  /**
    * This REST API stops a running {@link WorkflowInstance}.
    *
    * @param workflowInstanceId the ID of the workflow Instance